Mesa (master): glsl: fully split apart buffer block arrays

Timothy Arceri tarceri at kemper.freedesktop.org
Tue Apr 5 23:56:44 UTC 2016


Module: Mesa
Branch: master
Commit: f1293b2f9bc3a45c71941931edb5148d7b5f5a27
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f1293b2f9bc3a45c71941931edb5148d7b5f5a27

Author: Timothy Arceri <timothy.arceri at collabora.com>
Date:   Sun Apr  3 12:44:33 2016 +1000

glsl: fully split apart buffer block arrays

With this change we create the UBO and SSBO arrays separately from the
beginning rather than putting them into a combined array and splitting
it apart later.

A bug is with UBO and SSBO stage reference querying is also fixed as
we now use the block index to lookup the references in the separate arrays
not the combined buffer block array.

Reviewed-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>

---

 src/compiler/glsl/link_uniform_blocks.cpp       | 204 +++++++++++----------
 src/compiler/glsl/link_uniform_initializers.cpp |  17 +-
 src/compiler/glsl/link_uniforms.cpp             |  32 ++--
 src/compiler/glsl/linker.cpp                    | 225 +++++++++++-------------
 src/compiler/glsl/linker.h                      |   7 +-
 src/compiler/glsl/standalone_scaffolding.cpp    |   4 -
 src/mesa/main/mtypes.h                          |  50 +-----
 src/mesa/main/shader_query.cpp                  |   7 +-
 src/mesa/main/shaderapi.c                       |   2 +-
 src/mesa/main/shaderobj.c                       |  10 +-
 src/mesa/main/uniforms.c                        |   8 +-
 11 files changed, 270 insertions(+), 296 deletions(-)

diff --git a/src/compiler/glsl/link_uniform_blocks.cpp b/src/compiler/glsl/link_uniform_blocks.cpp
index c8fa181..586363d 100644
--- a/src/compiler/glsl/link_uniform_blocks.cpp
+++ b/src/compiler/glsl/link_uniform_blocks.cpp
@@ -291,13 +291,105 @@ resize_block_array(const glsl_type *type,
    }
 }
 
-unsigned
+static void
+create_buffer_blocks(void *mem_ctx, struct gl_context *ctx,
+                     struct gl_shader_program *prog,
+                     struct gl_uniform_block **out_blks, unsigned num_blocks,
+                     struct hash_table *block_hash, unsigned num_variables,
+                     bool create_ubo_blocks)
+{
+   if (num_blocks == 0) {
+      assert(num_variables == 0);
+      return;
+   }
+
+   assert(num_variables != 0);
+
+   /* Allocate storage to hold all of the information related to uniform
+    * blocks that can be queried through the API.
+    */
+   struct gl_uniform_block *blocks = ralloc_array(mem_ctx, gl_uniform_block, num_blocks);
+   gl_uniform_buffer_variable *variables =
+      ralloc_array(blocks, gl_uniform_buffer_variable, num_variables);
+
+   /* Add each variable from each uniform block to the API tracking
+    * structures.
+    */
+   ubo_visitor parcel(blocks, variables, num_variables);
+
+   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140)
+                 == unsigned(ubo_packing_std140));
+   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_SHARED)
+                 == unsigned(ubo_packing_shared));
+   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED)
+                 == unsigned(ubo_packing_packed));
+   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD430)
+                 == unsigned(ubo_packing_std430));
+
+   unsigned i = 0;
+   struct hash_entry *entry;
+   hash_table_foreach (block_hash, entry) {
+      const struct link_uniform_block_active *const b =
+         (const struct link_uniform_block_active *) entry->data;
+      const glsl_type *block_type = b->type;
+
+      if ((create_ubo_blocks && !b->is_shader_storage) ||
+          (!create_ubo_blocks && b->is_shader_storage)) {
+
+         if (b->array != NULL) {
+            unsigned binding_offset = 0;
+            char *name = ralloc_strdup(NULL,
+                                       block_type->without_array()->name);
+            size_t name_length = strlen(name);
+
+            assert(b->has_instance_name);
+            process_block_array(b->array, &name, name_length, blocks, &parcel,
+                                variables, b, &i, &binding_offset, ctx, prog);
+            ralloc_free(name);
+         } else {
+            blocks[i].Name = ralloc_strdup(blocks, block_type->name);
+            blocks[i].Uniforms = &variables[parcel.index];
+            blocks[i].Binding = (b->has_binding) ? b->binding : 0;
+            blocks[i].UniformBufferSize = 0;
+            blocks[i]._Packing =
+               gl_uniform_block_packing(block_type->interface_packing);
+
+            parcel.process(block_type,
+                           b->has_instance_name ? block_type->name : "");
+
+            blocks[i].UniformBufferSize = parcel.buffer_size;
+
+            /* Check SSBO size is lower than maximum supported size for SSBO
+             */
+            if (b->is_shader_storage &&
+                parcel.buffer_size > ctx->Const.MaxShaderStorageBlockSize) {
+               linker_error(prog, "shader storage block `%s' has size %d, "
+                            "which is larger than than the maximum allowed (%d)",
+                            block_type->name, parcel.buffer_size,
+                            ctx->Const.MaxShaderStorageBlockSize);
+            }
+            blocks[i].NumUniforms = (unsigned)(ptrdiff_t)
+               (&variables[parcel.index] - blocks[i].Uniforms);
+            i++;
+         }
+      }
+   }
+
+   *out_blks = blocks;
+
+   assert(parcel.index == num_variables);
+}
+
+void
 link_uniform_blocks(void *mem_ctx,
                     struct gl_context *ctx,
                     struct gl_shader_program *prog,
                     struct gl_shader **shader_list,
                     unsigned num_shaders,
-                    struct gl_uniform_block **blocks_ret)
+                    struct gl_uniform_block **ubo_blocks,
+                    unsigned *num_ubo_blocks,
+                    struct gl_uniform_block **ssbo_blocks,
+                    unsigned *num_ssbo_blocks)
 {
    /* This hash table will track all of the uniform blocks that have been
     * encountered.  Since blocks with the same block-name must be the same,
@@ -310,7 +402,7 @@ link_uniform_blocks(void *mem_ctx,
    if (block_hash == NULL) {
       _mesa_error_no_memory(__func__);
       linker_error(prog, "out of memory\n");
-      return 0;
+      return;
    }
 
    /* Determine which uniform blocks are active.
@@ -323,8 +415,8 @@ link_uniform_blocks(void *mem_ctx,
    /* Count the number of active uniform blocks.  Count the total number of
     * active slots in those uniform blocks.
     */
-   unsigned num_blocks = 0;
-   unsigned num_variables = 0;
+   unsigned num_ubo_variables = 0;
+   unsigned num_ssbo_variables = 0;
    count_block_size block_size;
    struct hash_entry *entry;
 
@@ -346,97 +438,31 @@ link_uniform_blocks(void *mem_ctx,
 
       if (b->array != NULL) {
          unsigned aoa_size = b->type->arrays_of_arrays_size();
-         num_blocks += aoa_size;
-         num_variables += aoa_size * block_size.num_active_uniforms;
-      } else {
-         num_blocks++;
-         num_variables += block_size.num_active_uniforms;
-      }
-
-   }
-
-   if (num_blocks == 0) {
-      assert(num_variables == 0);
-      _mesa_hash_table_destroy(block_hash, NULL);
-      return 0;
-   }
-
-   assert(num_variables != 0);
-
-   /* Allocate storage to hold all of the informatation related to uniform
-    * blocks that can be queried through the API.
-    */
-   gl_uniform_block *blocks =
-      ralloc_array(mem_ctx, gl_uniform_block, num_blocks);
-   gl_uniform_buffer_variable *variables =
-      ralloc_array(blocks, gl_uniform_buffer_variable, num_variables);
-
-   /* Add each variable from each uniform block to the API tracking
-    * structures.
-    */
-   unsigned i = 0;
-   ubo_visitor parcel(blocks, variables, num_variables);
-
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140)
-                 == unsigned(ubo_packing_std140));
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_SHARED)
-                 == unsigned(ubo_packing_shared));
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED)
-                 == unsigned(ubo_packing_packed));
-   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD430)
-                 == unsigned(ubo_packing_std430));
-
-   hash_table_foreach (block_hash, entry) {
-      const struct link_uniform_block_active *const b =
-         (const struct link_uniform_block_active *) entry->data;
-      const glsl_type *block_type = b->type;
-
-      if (b->array != NULL) {
-         unsigned binding_offset = 0;
-         char *name = ralloc_strdup(NULL, block_type->without_array()->name);
-         size_t name_length = strlen(name);
-
-         assert(b->has_instance_name);
-         process_block_array(b->array, &name, name_length, blocks, &parcel,
-                             variables, b, &i, &binding_offset, ctx, prog);
-         ralloc_free(name);
+         if (b->is_shader_storage) {
+            *num_ssbo_blocks += aoa_size;
+            num_ssbo_variables += aoa_size * block_size.num_active_uniforms;
+         } else {
+            *num_ubo_blocks += aoa_size;
+            num_ubo_variables += aoa_size * block_size.num_active_uniforms;
+         }
       } else {
-         blocks[i].Name = ralloc_strdup(blocks, block_type->name);
-         blocks[i].Uniforms = &variables[parcel.index];
-         blocks[i].Binding = (b->has_binding) ? b->binding : 0;
-         blocks[i].UniformBufferSize = 0;
-         blocks[i]._Packing =
-            gl_uniform_block_packing(block_type->interface_packing);
-
-         parcel.process(block_type,
-                        b->has_instance_name ? block_type->name : "");
-
-         blocks[i].UniformBufferSize = parcel.buffer_size;
-
-         /* Check SSBO size is lower than maximum supported size for SSBO */
-         if (b->is_shader_storage &&
-             parcel.buffer_size > ctx->Const.MaxShaderStorageBlockSize) {
-            linker_error(prog, "shader storage block `%s' has size %d, "
-                         "which is larger than than the maximum allowed (%d)",
-                         block_type->name,
-                         parcel.buffer_size,
-                         ctx->Const.MaxShaderStorageBlockSize);
+         if (b->is_shader_storage) {
+            (*num_ssbo_blocks)++;
+            num_ssbo_variables += block_size.num_active_uniforms;
+         } else {
+            (*num_ubo_blocks)++;
+            num_ubo_variables += block_size.num_active_uniforms;
          }
-         blocks[i].NumUniforms =
-            (unsigned)(ptrdiff_t)(&variables[parcel.index] - blocks[i].Uniforms);
-
-         blocks[i].IsShaderStorage = b->is_shader_storage;
-
-         i++;
       }
+
    }
 
-   assert(parcel.index == num_variables);
+   create_buffer_blocks(mem_ctx, ctx, prog, ubo_blocks, *num_ubo_blocks,
+                        block_hash, num_ubo_variables, true);
+   create_buffer_blocks(mem_ctx, ctx, prog, ssbo_blocks, *num_ssbo_blocks,
+                        block_hash, num_ssbo_variables, false);
 
    _mesa_hash_table_destroy(block_hash, NULL);
-
-   *blocks_ret = blocks;
-   return num_blocks;
 }
 
 bool
diff --git a/src/compiler/glsl/link_uniform_initializers.cpp b/src/compiler/glsl/link_uniform_initializers.cpp
index e5edf2e..c6346d5 100644
--- a/src/compiler/glsl/link_uniform_initializers.cpp
+++ b/src/compiler/glsl/link_uniform_initializers.cpp
@@ -154,11 +154,17 @@ set_opaque_binding(void *mem_ctx, gl_shader_program *prog,
 }
 
 void
-set_block_binding(gl_shader_program *prog, const char *block_name, int binding)
+set_block_binding(gl_shader_program *prog, const char *block_name,
+                  unsigned mode, int binding)
 {
-   for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) {
-      if (!strcmp(prog->BufferInterfaceBlocks[i].Name, block_name)) {
-         prog->BufferInterfaceBlocks[i].Binding = binding;
+   unsigned num_blocks = mode == ir_var_uniform ? prog->NumUniformBlocks :
+      prog->NumShaderStorageBlocks;
+   struct gl_uniform_block *blks = mode == ir_var_uniform ?
+      prog->UniformBlocks : prog->ShaderStorageBlocks;
+
+   for (unsigned i = 0; i < num_blocks; i++) {
+      if (!strcmp(blks[i].Name, block_name)) {
+         blks[i].Binding = binding;
          return;
       }
    }
@@ -308,11 +314,12 @@ link_set_uniform_initializers(struct gl_shader_program *prog,
                       *     each subsequent element takes the next consecutive
                       *     uniform block binding point."
                       */
-                     linker::set_block_binding(prog, name,
+                     linker::set_block_binding(prog, name, var->data.mode,
                                                var->data.binding + i);
                   }
                } else {
                   linker::set_block_binding(prog, iface_type->name,
+                                            var->data.mode,
                                             var->data.binding);
                }
             } else if (type->contains_atomic()) {
diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index 7d8a4b4..8db60a3 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -462,7 +462,7 @@ public:
 
       buffer_block_index = -1;
       if (var->is_in_buffer_block()) {
-         struct gl_uniform_block **blks = var->is_in_shader_storage_block() ?
+         struct gl_uniform_block *blks = var->is_in_shader_storage_block() ?
             prog->ShaderStorageBlocks : prog->UniformBlocks;
          unsigned num_blks = var->is_in_shader_storage_block() ?
             prog->NumShaderStorageBlocks : prog->NumUniformBlocks;
@@ -471,15 +471,15 @@ public:
             unsigned l = strlen(var->get_interface_type()->name);
 
             for (unsigned i = 0; i < num_blks; i++) {
-               if (strncmp(var->get_interface_type()->name, blks[i]->Name, l)
-                   == 0 && blks[i]->Name[l] == '[') {
+               if (strncmp(var->get_interface_type()->name, blks[i].Name, l)
+                   == 0 && blks[i].Name[l] == '[') {
                   buffer_block_index = i;
                   break;
                }
             }
          } else {
             for (unsigned i = 0; i < num_blks; i++) {
-               if (strcmp(var->get_interface_type()->name, blks[i]->Name) ==
+               if (strcmp(var->get_interface_type()->name, blks[i].Name) ==
                    0) {
                   buffer_block_index = i;
                   break;
@@ -500,7 +500,7 @@ public:
                     var->get_interface_type()->name);
          } else {
             const struct gl_uniform_block *const block =
-               blks[buffer_block_index];
+               &blks[buffer_block_index];
 
             assert(var->data.location != -1);
 
@@ -960,11 +960,16 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
          sentinel = '[';
       }
 
+      unsigned num_blocks = var->data.mode == ir_var_uniform ?
+         shader->NumUniformBlocks : shader->NumShaderStorageBlocks;
+      struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ?
+         shader->UniformBlocks : shader->ShaderStorageBlocks;
+
       const unsigned l = strlen(var->name);
-      for (unsigned i = 0; i < shader->NumBufferInterfaceBlocks; i++) {
-         for (unsigned j = 0; j < shader->BufferInterfaceBlocks[i]->NumUniforms; j++) {
+      for (unsigned i = 0; i < num_blocks; i++) {
+         for (unsigned j = 0; j < blks[i]->NumUniforms; j++) {
             if (sentinel) {
-               const char *begin = shader->BufferInterfaceBlocks[i]->Uniforms[j].Name;
+               const char *begin = blks[i]->Uniforms[j].Name;
                const char *end = strchr(begin, sentinel);
 
                if (end == NULL)
@@ -978,8 +983,7 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
                   var->data.location = j;
                   break;
                }
-            } else if (!strcmp(var->name,
-                               shader->BufferInterfaceBlocks[i]->Uniforms[j].Name)) {
+            } else if (!strcmp(var->name, blks[i]->Uniforms[j].Name)) {
                found = true;
                var->data.location = j;
                break;
@@ -1104,11 +1108,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
       sh->num_uniform_components = uniform_size.num_shader_uniform_components;
       sh->num_combined_uniform_components = sh->num_uniform_components;
 
-      for (unsigned i = 0; i < sh->NumBufferInterfaceBlocks; i++) {
-         if (!sh->BufferInterfaceBlocks[i]->IsShaderStorage) {
-            sh->num_combined_uniform_components +=
-               sh->BufferInterfaceBlocks[i]->UniformBufferSize / 4;
-         }
+      for (unsigned i = 0; i < sh->NumUniformBlocks; i++) {
+         sh->num_combined_uniform_components +=
+            sh->UniformBlocks[i]->UniformBufferSize / 4;
       }
    }
 
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index d9a681c..957efe5 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -1165,39 +1165,58 @@ cross_validate_uniforms(struct gl_shader_program *prog)
 }
 
 /**
- * Accumulates the array of prog->BufferInterfaceBlocks and checks that all
- * definitons of blocks agree on their contents.
+ * Accumulates the array of buffer blocks and checks that all definitions of
+ * blocks agree on their contents.
  */
 static bool
-interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
+interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog,
+                                         bool validate_ssbo)
 {
    int *InterfaceBlockStageIndex[MESA_SHADER_STAGES];
+   struct gl_uniform_block *blks = NULL;
+   unsigned *num_blks = validate_ssbo ? &prog->NumShaderStorageBlocks :
+      &prog->NumUniformBlocks;
 
-   unsigned max_num_uniform_blocks = 0;
+   unsigned max_num_buffer_blocks = 0;
    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
-      if (prog->_LinkedShaders[i])
-	 max_num_uniform_blocks += prog->_LinkedShaders[i]->NumBufferInterfaceBlocks;
+      if (prog->_LinkedShaders[i]) {
+         if (validate_ssbo) {
+            max_num_buffer_blocks +=
+               prog->_LinkedShaders[i]->NumShaderStorageBlocks;
+         } else {
+            max_num_buffer_blocks +=
+               prog->_LinkedShaders[i]->NumUniformBlocks;
+         }
+      }
    }
 
    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
       struct gl_shader *sh = prog->_LinkedShaders[i];
 
-      InterfaceBlockStageIndex[i] = new int[max_num_uniform_blocks];
-      for (unsigned int j = 0; j < max_num_uniform_blocks; j++)
+      InterfaceBlockStageIndex[i] = new int[max_num_buffer_blocks];
+      for (unsigned int j = 0; j < max_num_buffer_blocks; j++)
          InterfaceBlockStageIndex[i][j] = -1;
 
       if (sh == NULL)
 	 continue;
 
-      for (unsigned int j = 0; j < sh->NumBufferInterfaceBlocks; j++) {
-	 int index = link_cross_validate_uniform_block(prog,
-						       &prog->BufferInterfaceBlocks,
-						       &prog->NumBufferInterfaceBlocks,
-						       sh->BufferInterfaceBlocks[j]);
+      unsigned sh_num_blocks;
+      struct gl_uniform_block **sh_blks;
+      if (validate_ssbo) {
+         sh_num_blocks = prog->_LinkedShaders[i]->NumShaderStorageBlocks;
+         sh_blks = sh->ShaderStorageBlocks;
+      } else {
+         sh_num_blocks = prog->_LinkedShaders[i]->NumUniformBlocks;
+         sh_blks = sh->UniformBlocks;
+      }
+
+      for (unsigned int j = 0; j < sh_num_blocks; j++) {
+         int index = link_cross_validate_uniform_block(prog, &blks, num_blks,
+                                                       sh_blks[j]);
 
          if (index == -1) {
-            linker_error(prog, "uniform block `%s' has mismatching definitions\n",
-                         sh->BufferInterfaceBlocks[j]->Name);
+            linker_error(prog, "buffer block `%s' has mismatching "
+                         "definitions\n", sh_blks[j]->Name);
 
             for (unsigned k = 0; k <= i; k++) {
                delete[] InterfaceBlockStageIndex[k];
@@ -1213,16 +1232,18 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
     * FIXME: We should be able to free the per stage blocks here.
     */
    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
-      for (unsigned j = 0; j < prog->NumBufferInterfaceBlocks; j++) {
+      for (unsigned j = 0; j < *num_blks; j++) {
          int stage_index = InterfaceBlockStageIndex[i][j];
 
 	 if (stage_index != -1) {
 	    struct gl_shader *sh = prog->_LinkedShaders[i];
 
-            prog->BufferInterfaceBlocks[j].stageref |= (1 << i);
+            blks[j].stageref |= (1 << i);
+
+            struct gl_uniform_block **sh_blks = validate_ssbo ?
+               sh->ShaderStorageBlocks : sh->UniformBlocks;
 
-            sh->BufferInterfaceBlocks[stage_index] =
-               &prog->BufferInterfaceBlocks[j];
+            sh_blks[stage_index] = &blks[j];
 	 }
       }
    }
@@ -1231,6 +1252,11 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
       delete[] InterfaceBlockStageIndex[i];
    }
 
+   if (validate_ssbo)
+      prog->ShaderStorageBlocks = blks;
+   else
+      prog->UniformBlocks = blks;
+
    return true;
 }
 
@@ -2074,7 +2100,10 @@ link_intrastage_shaders(void *mem_ctx,
 			struct gl_shader **shader_list,
 			unsigned num_shaders)
 {
-   struct gl_uniform_block *uniform_blocks = NULL;
+   struct gl_uniform_block *ubo_blocks = NULL;
+   struct gl_uniform_block *ssbo_blocks = NULL;
+   unsigned num_ubo_blocks = 0;
+   unsigned num_ssbo_blocks = 0;
 
    /* Check that global variables defined in multiple shaders are consistent.
     */
@@ -2090,9 +2119,10 @@ link_intrastage_shaders(void *mem_ctx,
       return NULL;
 
    /* Link up uniform blocks defined within this stage. */
-   const unsigned num_uniform_blocks =
-      link_uniform_blocks(mem_ctx, ctx, prog, shader_list, num_shaders,
-                          &uniform_blocks);
+   link_uniform_blocks(mem_ctx, ctx, prog, shader_list, num_shaders,
+                       &ubo_blocks, &num_ubo_blocks, &ssbo_blocks,
+                       &num_ssbo_blocks);
+
    if (!prog->LinkStatus)
       return NULL;
 
@@ -2159,15 +2189,23 @@ link_intrastage_shaders(void *mem_ctx,
    linked->ir = new(linked) exec_list;
    clone_ir_list(mem_ctx, linked->ir, main->ir);
 
-   linked->BufferInterfaceBlocks =
-      ralloc_array(linked, gl_uniform_block *, num_uniform_blocks);
-
-   ralloc_steal(linked, uniform_blocks);
-   for (unsigned i = 0; i < num_uniform_blocks; i++) {
-      linked->BufferInterfaceBlocks[i] = &uniform_blocks[i];
+   /* Copy ubo blocks to linked shader list */
+   linked->UniformBlocks =
+      ralloc_array(linked, gl_uniform_block *, num_ubo_blocks);
+   ralloc_steal(linked, ubo_blocks);
+   for (unsigned i = 0; i < num_ubo_blocks; i++) {
+      linked->UniformBlocks[i] = &ubo_blocks[i];
    }
+   linked->NumUniformBlocks = num_ubo_blocks;
 
-   linked->NumBufferInterfaceBlocks = num_uniform_blocks;
+   /* Copy ssbo blocks to linked shader list */
+   linked->ShaderStorageBlocks =
+      ralloc_array(linked, gl_uniform_block *, num_ssbo_blocks);
+   ralloc_steal(linked, ssbo_blocks);
+   for (unsigned i = 0; i < num_ssbo_blocks; i++) {
+      linked->ShaderStorageBlocks[i] = &ssbo_blocks[i];
+   }
+   linked->NumShaderStorageBlocks = num_ssbo_blocks;
 
    link_fs_input_layout_qualifiers(prog, linked, shader_list, num_shaders);
    link_tcs_out_layout_qualifiers(prog, linked, shader_list, num_shaders);
@@ -2973,21 +3011,22 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
                    ctx->Const.MaxCombinedShaderStorageBlocks);
    }
 
-   for (unsigned i = 0; i < prog->NumBufferInterfaceBlocks; i++) {
-      /* Don't check SSBOs for Uniform Block Size */
-      if (!prog->BufferInterfaceBlocks[i].IsShaderStorage &&
-          prog->BufferInterfaceBlocks[i].UniformBufferSize > ctx->Const.MaxUniformBlockSize) {
+   for (unsigned i = 0; i < prog->NumUniformBlocks; i++) {
+      if (prog->UniformBlocks[i].UniformBufferSize >
+          ctx->Const.MaxUniformBlockSize) {
          linker_error(prog, "Uniform block %s too big (%d/%d)\n",
-                      prog->BufferInterfaceBlocks[i].Name,
-                      prog->BufferInterfaceBlocks[i].UniformBufferSize,
+                      prog->UniformBlocks[i].Name,
+                      prog->UniformBlocks[i].UniformBufferSize,
                       ctx->Const.MaxUniformBlockSize);
       }
+   }
 
-      if (prog->BufferInterfaceBlocks[i].IsShaderStorage &&
-          prog->BufferInterfaceBlocks[i].UniformBufferSize > ctx->Const.MaxShaderStorageBlockSize) {
+   for (unsigned i = 0; i < prog->NumShaderStorageBlocks; i++) {
+      if (prog->ShaderStorageBlocks[i].UniformBufferSize >
+          ctx->Const.MaxShaderStorageBlockSize) {
          linker_error(prog, "Shader storage block %s too big (%d/%d)\n",
-                      prog->BufferInterfaceBlocks[i].Name,
-                      prog->BufferInterfaceBlocks[i].UniformBufferSize,
+                      prog->ShaderStorageBlocks[i].Name,
+                      prog->ShaderStorageBlocks[i].UniformBufferSize,
                       ctx->Const.MaxShaderStorageBlockSize);
       }
    }
@@ -3295,8 +3334,8 @@ should_add_buffer_variable(struct gl_shader_program *shProg,
    if (type != GL_BUFFER_VARIABLE)
       return true;
 
-   for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
-      const char *block_name = shProg->BufferInterfaceBlocks[i].Name;
+   for (unsigned i = 0; i < shProg->NumShaderStorageBlocks; i++) {
+      const char *block_name = shProg->ShaderStorageBlocks[i].Name;
       block_name_len = strlen(block_name);
 
       const char *block_square_bracket = strchr(block_name, '[');
@@ -3805,8 +3844,8 @@ calculate_array_size_and_stride(struct gl_shader_program *shProg,
    char *var_name = get_top_level_name(uni->name);
    char *interface_name =
       get_top_level_name(uni->is_shader_storage ?
-                         shProg->ShaderStorageBlocks[block_index]->Name :
-                         shProg->UniformBlocks[block_index]->Name);
+                         shProg->ShaderStorageBlocks[block_index].Name :
+                         shProg->UniformBlocks[block_index].Name);
 
    if (strcmp(var_name, interface_name) == 0) {
       /* Deal with instanced array of SSBOs */
@@ -3947,8 +3986,8 @@ build_program_resource_list(struct gl_context *ctx,
       int block_index = shProg->UniformStorage[i].block_index;
       if (block_index != -1) {
          stageref |= is_shader_storage ?
-            shProg->ShaderStorageBlocks[block_index]->stageref :
-            shProg->UniformBlocks[block_index]->stageref;
+            shProg->ShaderStorageBlocks[block_index].stageref :
+            shProg->UniformBlocks[block_index].stageref;
       }
 
       GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM;
@@ -3965,12 +4004,17 @@ build_program_resource_list(struct gl_context *ctx,
          return;
    }
 
-   /* Add program uniform blocks and shader storage blocks. */
-   for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
-      bool is_shader_storage = shProg->BufferInterfaceBlocks[i].IsShaderStorage;
-      GLenum type = is_shader_storage ? GL_SHADER_STORAGE_BLOCK : GL_UNIFORM_BLOCK;
-      if (!add_program_resource(shProg, type,
-          &shProg->BufferInterfaceBlocks[i], 0))
+   /* Add program uniform blocks. */
+   for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
+      if (!add_program_resource(shProg, GL_UNIFORM_BLOCK,
+          &shProg->UniformBlocks[i], 0))
+         return;
+   }
+
+   /* Add program shader storage blocks. */
+   for (unsigned i = 0; i < shProg->NumShaderStorageBlocks; i++) {
+      if (!add_program_resource(shProg, GL_SHADER_STORAGE_BLOCK,
+          &shProg->ShaderStorageBlocks[i], 0))
          return;
    }
 
@@ -4116,49 +4160,6 @@ link_assign_subroutine_types(struct gl_shader_program *prog)
 }
 
 static void
-split_ubos_and_ssbos(void *mem_ctx,
-                     struct gl_uniform_block **s_blks,
-                     struct gl_uniform_block *p_blks,
-                     unsigned num_blocks,
-                     struct gl_uniform_block ***ubos,
-                     unsigned *num_ubos,
-                     struct gl_uniform_block ***ssbos,
-                     unsigned *num_ssbos)
-{
-   unsigned num_ubo_blocks = 0;
-   unsigned num_ssbo_blocks = 0;
-
-   /* Are we spliting the list of blocks for the shader or the program */
-   bool is_shader = p_blks == NULL;
-
-   for (unsigned i = 0; i < num_blocks; i++) {
-      if (is_shader ? s_blks[i]->IsShaderStorage : p_blks[i].IsShaderStorage)
-         num_ssbo_blocks++;
-      else
-         num_ubo_blocks++;
-   }
-
-   *ubos = ralloc_array(mem_ctx, gl_uniform_block *, num_ubo_blocks);
-   *num_ubos = 0;
-
-   *ssbos = ralloc_array(mem_ctx, gl_uniform_block *, num_ssbo_blocks);
-   *num_ssbos = 0;
-
-   for (unsigned i = 0; i < num_blocks; i++) {
-      struct gl_uniform_block *blk = is_shader ? s_blks[i] : &p_blks[i];
-      if (blk->IsShaderStorage) {
-         (*ssbos)[*num_ssbos] = blk;
-         (*num_ssbos)++;
-      } else {
-         (*ubos)[*num_ubos] = blk;
-         (*num_ubos)++;
-      }
-   }
-
-   assert(*num_ubos + *num_ssbos == num_blocks);
-}
-
-static void
 set_always_active_io(exec_list *ir, ir_variable_mode io_mode)
 {
    assert(io_mode == ir_var_shader_in || io_mode == ir_var_shader_out);
@@ -4498,7 +4499,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
    if (prog->SeparateShader)
       disable_varying_optimizations_for_sso(prog);
 
-   if (!interstage_cross_validate_uniform_blocks(prog))
+   /* Process UBOs */
+   if (!interstage_cross_validate_uniform_blocks(prog, false))
+      goto done;
+
+   /* Process SSBOs */
+   if (!interstage_cross_validate_uniform_blocks(prog, true))
       goto done;
 
    /* Do common optimization before assigning storage for attributes,
@@ -4695,33 +4701,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
                              has_xfb_qualifiers))
       goto done;
 
-   /* Split BufferInterfaceBlocks into UniformBlocks and ShaderStorageBlocks
-    * for gl_shader_program and gl_shader, so that drivers that need separate
-    * index spaces for each set can have that.
-    */
-   for (unsigned i = MESA_SHADER_VERTEX; i < MESA_SHADER_STAGES; i++) {
-      if (prog->_LinkedShaders[i] != NULL) {
-         gl_shader *sh = prog->_LinkedShaders[i];
-         split_ubos_and_ssbos(sh,
-                              sh->BufferInterfaceBlocks,
-                              NULL,
-                              sh->NumBufferInterfaceBlocks,
-                              &sh->UniformBlocks,
-                              &sh->NumUniformBlocks,
-                              &sh->ShaderStorageBlocks,
-                              &sh->NumShaderStorageBlocks);
-      }
-   }
-
-   split_ubos_and_ssbos(prog,
-                        NULL,
-                        prog->BufferInterfaceBlocks,
-                        prog->NumBufferInterfaceBlocks,
-                        &prog->UniformBlocks,
-                        &prog->NumUniformBlocks,
-                        &prog->ShaderStorageBlocks,
-                        &prog->NumShaderStorageBlocks);
-
    update_array_sizes(prog);
    link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue,
                                  num_explicit_uniform_locs,
diff --git a/src/compiler/glsl/linker.h b/src/compiler/glsl/linker.h
index 97144df..3a0ec8b 100644
--- a/src/compiler/glsl/linker.h
+++ b/src/compiler/glsl/linker.h
@@ -53,13 +53,16 @@ extern bool
 link_uniform_blocks_are_compatible(const gl_uniform_block *a,
 				   const gl_uniform_block *b);
 
-extern unsigned
+extern void
 link_uniform_blocks(void *mem_ctx,
                     struct gl_context *ctx,
                     struct gl_shader_program *prog,
                     struct gl_shader **shader_list,
                     unsigned num_shaders,
-                    struct gl_uniform_block **blocks_ret);
+                    struct gl_uniform_block **ubo_blocks,
+                    unsigned *num_ubo_blocks,
+                    struct gl_uniform_block **ssbo_blocks,
+                    unsigned *num_ssbo_blocks);
 
 bool
 validate_intrastage_arrays(struct gl_shader_program *prog,
diff --git a/src/compiler/glsl/standalone_scaffolding.cpp b/src/compiler/glsl/standalone_scaffolding.cpp
index 49b4a26..09d7d6e 100644
--- a/src/compiler/glsl/standalone_scaffolding.cpp
+++ b/src/compiler/glsl/standalone_scaffolding.cpp
@@ -105,10 +105,6 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg)
    ralloc_free(shProg->InfoLog);
    shProg->InfoLog = ralloc_strdup(shProg, "");
 
-   ralloc_free(shProg->BufferInterfaceBlocks);
-   shProg->BufferInterfaceBlocks = NULL;
-   shProg->NumBufferInterfaceBlocks = 0;
-
    ralloc_free(shProg->UniformBlocks);
    shProg->UniformBlocks = NULL;
    shProg->NumUniformBlocks = 0;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index b2060c2..dc73278 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2295,30 +2295,6 @@ struct gl_shader
     */
    unsigned num_combined_uniform_components;
 
-   /**
-    * This shader's uniform/ssbo block information.
-    *
-    * These fields are only set post-linking.
-    *
-    * BufferInterfaceBlocks is a list containing both UBOs and SSBOs. This is
-    * useful during the linking process so that we don't have to handle SSBOs
-    * specifically.
-    *
-    * UniformBlocks is a list of UBOs. This is useful for backends that need
-    * or prefer to see separate index spaces for UBOS and SSBOs like the GL
-    * API specifies.
-    *
-    * ShaderStorageBlocks is a list of SSBOs. This is useful for backends that
-    * need or prefer to see separate index spaces for UBOS and SSBOs like the
-    * GL API specifies.
-    *
-    * UniformBlocks and ShaderStorageBlocks only have pointers into
-    * BufferInterfaceBlocks so the actual resource information is not
-    * duplicated.
-    */
-   unsigned NumBufferInterfaceBlocks;
-   struct gl_uniform_block **BufferInterfaceBlocks;
-
    unsigned NumUniformBlocks;
    struct gl_uniform_block **UniformBlocks;
 
@@ -2804,33 +2780,11 @@ struct gl_shader_program
     */
    unsigned LastClipDistanceArraySize;
 
-   /**
-    * This shader's uniform/ssbo block information.
-    *
-    * BufferInterfaceBlocks is a list containing both UBOs and SSBOs. This is
-    * useful during the linking process so that we don't have to handle SSBOs
-    * specifically.
-    *
-    * UniformBlocks is a list of UBOs. This is useful for backends that need
-    * or prefer to see separate index spaces for UBOS and SSBOs like the GL
-    * API specifies.
-    *
-    * ShaderStorageBlocks is a list of SSBOs. This is useful for backends that
-    * need or prefer to see separate index spaces for UBOS and SSBOs like the
-    * GL API specifies.
-    *
-    * UniformBlocks and ShaderStorageBlocks only have pointers into
-    * BufferInterfaceBlocks so the actual resource information is not
-    * duplicated and are only set after linking.
-    */
-   unsigned NumBufferInterfaceBlocks;
-   struct gl_uniform_block *BufferInterfaceBlocks;
-
    unsigned NumUniformBlocks;
-   struct gl_uniform_block **UniformBlocks;
+   struct gl_uniform_block *UniformBlocks;
 
    unsigned NumShaderStorageBlocks;
-   struct gl_uniform_block **ShaderStorageBlocks;
+   struct gl_uniform_block *ShaderStorageBlocks;
 
    /**
     * Map of active uniform names to locations
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp
index 4ef6a81..2c1a6ee 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -925,8 +925,11 @@ is_resource_referenced(struct gl_shader_program *shProg,
    if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
       return RESOURCE_ATC(res)->StageReferences[stage];
 
-   if (res->Type == GL_UNIFORM_BLOCK || res->Type == GL_SHADER_STORAGE_BLOCK)
-      return shProg->BufferInterfaceBlocks[index].stageref & (1 << stage);
+   if (res->Type == GL_UNIFORM_BLOCK)
+      return shProg->UniformBlocks[index].stageref & (1 << stage);
+
+   if (res->Type == GL_SHADER_STORAGE_BLOCK)
+      return shProg->ShaderStorageBlocks[index].stageref & (1 << stage);
 
    return res->StageReferences & (1 << stage);
 }
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index ba26072..b28b5ce 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -727,7 +727,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname,
       for (i = 0; i < shProg->NumUniformBlocks; i++) {
 	 /* Add one for the terminating NUL character.
 	  */
-	 const GLint len = strlen(shProg->UniformBlocks[i]->Name) + 1;
+	 const GLint len = strlen(shProg->UniformBlocks[i].Name) + 1;
 
 	 if (len > max_len)
 	    max_len = len;
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 8b9166c..274cb12 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -292,9 +292,13 @@ _mesa_clear_shader_program_data(struct gl_shader_program *shProg)
    ralloc_free(shProg->InfoLog);
    shProg->InfoLog = ralloc_strdup(shProg, "");
 
-   ralloc_free(shProg->BufferInterfaceBlocks);
-   shProg->BufferInterfaceBlocks = NULL;
-   shProg->NumBufferInterfaceBlocks = 0;
+   ralloc_free(shProg->UniformBlocks);
+   shProg->UniformBlocks = NULL;
+   shProg->NumUniformBlocks = 0;
+
+   ralloc_free(shProg->ShaderStorageBlocks);
+   shProg->ShaderStorageBlocks = NULL;
+   shProg->NumShaderStorageBlocks = 0;
 
    ralloc_free(shProg->AtomicBuffers);
    shProg->AtomicBuffers = NULL;
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index 7dcbdcc..a9308d0 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -1016,13 +1016,13 @@ _mesa_UniformBlockBinding(GLuint program,
       return;
    }
 
-   if (shProg->UniformBlocks[uniformBlockIndex]->Binding !=
+   if (shProg->UniformBlocks[uniformBlockIndex].Binding !=
        uniformBlockBinding) {
 
       FLUSH_VERTICES(ctx, 0);
       ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
 
-      shProg->UniformBlocks[uniformBlockIndex]->Binding = uniformBlockBinding;
+      shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding;
    }
 }
 
@@ -1059,13 +1059,13 @@ _mesa_ShaderStorageBlockBinding(GLuint program,
       return;
    }
 
-   if (shProg->ShaderStorageBlocks[shaderStorageBlockIndex]->Binding !=
+   if (shProg->ShaderStorageBlocks[shaderStorageBlockIndex].Binding !=
        shaderStorageBlockBinding) {
 
       FLUSH_VERTICES(ctx, 0);
       ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
 
-      shProg->ShaderStorageBlocks[shaderStorageBlockIndex]->Binding =
+      shProg->ShaderStorageBlocks[shaderStorageBlockIndex].Binding =
          shaderStorageBlockBinding;
    }
 }




More information about the mesa-commit mailing list