glsl: Calculate UBO data at link-time
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 22 Jan 2013 06:09:16 +0000 (01:09 -0500)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 25 Jan 2013 14:07:36 +0000 (09:07 -0500)
Use the function added in the previous commit.

This temporarily causes gles3conform
uniform_buffer_object_index_of_not_active_block,
uniform_buffer_object_inherit_and_override_layouts, and
uniform_buffer_object_repeat_global_scope_layouts to assertion fail.
This is fixed in the next commit.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/glsl/ast_to_hir.cpp
src/glsl/link_uniforms.cpp
src/glsl/linker.cpp

index bf4130fa8c6e0d5059edb83cc194aa536be4d818..3272868ee8372e092af2041688533a8f00a005ff 100644 (file)
@@ -4187,25 +4187,6 @@ ast_struct_specifier::hir(exec_list *instructions,
    return NULL;
 }
 
-static struct gl_uniform_block *
-get_next_uniform_block(struct _mesa_glsl_parse_state *state)
-{
-   if (state->num_uniform_blocks >= state->uniform_block_array_size) {
-      state->uniform_block_array_size *= 2;
-      if (state->uniform_block_array_size <= 4)
-        state->uniform_block_array_size = 4;
-
-      state->uniform_blocks = reralloc(state,
-                                      state->uniform_blocks,
-                                      struct gl_uniform_block,
-                                      state->uniform_block_array_size);
-   }
-
-   memset(&state->uniform_blocks[state->num_uniform_blocks],
-         0, sizeof(*state->uniform_blocks));
-   return &state->uniform_blocks[state->num_uniform_blocks++];
-}
-
 ir_rvalue *
 ast_uniform_block::hir(exec_list *instructions,
                       struct _mesa_glsl_parse_state *state)
@@ -4216,17 +4197,15 @@ ast_uniform_block::hir(exec_list *instructions,
     * need to turn those into ir_variables with an association
     * with this uniform block.
     */
-   struct gl_uniform_block *ubo = get_next_uniform_block(state);
-   ubo->Name = ralloc_strdup(state->uniform_blocks, this->block_name);
-
+   enum glsl_interface_packing packing;
    if (this->layout.flags.q.shared) {
-      ubo->_Packing = ubo_packing_shared;
+      packing = GLSL_INTERFACE_PACKING_SHARED;
    } else if (this->layout.flags.q.packed) {
-      ubo->_Packing = ubo_packing_packed;
+      packing = GLSL_INTERFACE_PACKING_PACKED;
    } else {
       /* The default layout is std140.
        */
-      ubo->_Packing = ubo_packing_std140;
+      packing = GLSL_INTERFACE_PACKING_STD140;
    }
 
    bool block_row_major = this->layout.flags.q.row_major;
@@ -4241,17 +4220,10 @@ ast_uniform_block::hir(exec_list *instructions,
                                                true,
                                                block_row_major);
 
-   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));
-
    const glsl_type *block_type =
       glsl_type::get_interface_instance(fields,
                                         num_variables,
-                                        (enum glsl_interface_packing) ubo->_Packing,
+                                        packing,
                                         this->block_name);
 
    if (!state->symbols->add_type(block_type->name, block_type)) {
@@ -4310,24 +4282,6 @@ ast_uniform_block::hir(exec_list *instructions,
       }
    }
 
-   /* FINISHME: Eventually the rest of this code needs to be moved into the
-    * FINISHME: linker.
-    */
-   ubo->Uniforms = rzalloc_array(state->uniform_blocks,
-                                struct gl_uniform_buffer_variable,
-                                num_variables);
-
-   for (unsigned i = 0; i < num_variables; i++) {
-      struct gl_uniform_buffer_variable *ubo_var =
-         &ubo->Uniforms[ubo->NumUniforms++];
-
-      ubo_var->Name = ralloc_strdup(state->uniform_blocks, fields[i].name);
-      ubo_var->IndexName = ubo_var->Name;
-      ubo_var->Type = fields[i].type;
-      ubo_var->Offset = 0; /* Assigned at link time. */
-      ubo_var->RowMajor = fields[i].row_major;
-   }
-
    return NULL;
 }
 
index 68cafbf3946f184526090dcbe0b7aa33319623db..3e24842a0265076c958dfc1c73b382b57db20c43 100644 (file)
@@ -539,10 +539,41 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
 
       assert(var->mode == ir_var_uniform);
 
+      if (var->is_interface_instance()) {
+         var->location = 0;
+         continue;
+      }
+
       bool found = false;
+      char sentinel = '\0';
+
+      if (var->type->is_record()) {
+         sentinel = '.';
+      } else if (var->type->is_array()
+                 && var->type->fields.array->is_record()) {
+         sentinel = '[';
+      }
+
+      const unsigned l = strlen(var->name);
       for (unsigned i = 0; i < shader->NumUniformBlocks; i++) {
         for (unsigned j = 0; j < shader->UniformBlocks[i].NumUniforms; j++) {
-           if (!strcmp(var->name, shader->UniformBlocks[i].Uniforms[j].Name)) {
+            if (sentinel) {
+               const char *begin = shader->UniformBlocks[i].Uniforms[j].Name;
+               const char *end = strchr(begin, sentinel);
+
+               if (end == NULL)
+                  continue;
+
+               if (l != (end - begin))
+                  continue;
+
+               if (strncmp(var->name, begin, l) == 0) {
+                  found = true;
+                  var->location = j;
+                  break;
+               }
+            } else if (!strcmp(var->name,
+                               shader->UniformBlocks[i].Uniforms[j].Name)) {
               found = true;
               var->uniform_block = i;
               var->location = j;
@@ -614,13 +645,6 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
     */
    memset(prog->SamplerUnits, 0, sizeof(prog->SamplerUnits));
 
-   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
-      if (prog->_LinkedShaders[i] == NULL)
-        continue;
-
-      link_update_uniform_buffer_variables(prog->_LinkedShaders[i]);
-   }
-
    /* First pass: Count the uniform resources used by the user-defined
     * uniforms.  While this happens, each active uniform will have an index
     * assigned to it.
@@ -633,6 +657,8 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
       if (prog->_LinkedShaders[i] == NULL)
         continue;
 
+      link_update_uniform_buffer_variables(prog->_LinkedShaders[i]);
+
       /* Reset various per-shader target counts.
        */
       uniform_size.start_shader();
index a480dd0523fe4c9211578d6040542348a3eb6ca5..63ce178f44c48c53ac7f528c8ef404ed8a0b2954 100644 (file)
@@ -873,7 +873,6 @@ link_intrastage_shaders(void *mem_ctx,
                        unsigned num_shaders)
 {
    struct gl_uniform_block *uniform_blocks = NULL;
-   unsigned num_uniform_blocks = 0;
 
    /* Check that global variables defined in multiple shaders are consistent.
     */
@@ -881,23 +880,11 @@ link_intrastage_shaders(void *mem_ctx,
       return NULL;
 
    /* Check that uniform blocks between shaders for a stage agree. */
-   for (unsigned i = 0; i < num_shaders; i++) {
-      struct gl_shader *sh = shader_list[i];
-
-      for (unsigned j = 0; j < sh->NumUniformBlocks; j++) {
-        link_assign_uniform_block_offsets(sh);
-
-        int index = link_cross_validate_uniform_block(mem_ctx,
-                                                      &uniform_blocks,
-                                                      &num_uniform_blocks,
-                                                      &sh->UniformBlocks[j]);
-        if (index == -1) {
-           linker_error(prog, "uniform block `%s' has mismatching definitions",
-                        sh->UniformBlocks[j].Name);
-           return NULL;
-        }
-      }
-   }
+   const int num_uniform_blocks =
+      link_uniform_blocks(mem_ctx, prog, shader_list, num_shaders,
+                          &uniform_blocks);
+   if (num_uniform_blocks < 0)
+      return NULL;
 
    /* Check that there is only a single definition of each function signature
     * across all shaders.