From 514f8c7ec7cc1ab18be93cebb5b9bf970b1955a9 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 22 Jan 2013 01:09:16 -0500 Subject: [PATCH] glsl: Calculate UBO data at link-time 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 Reviewed-by: Jordan Justen --- src/glsl/ast_to_hir.cpp | 56 ++++---------------------------------- src/glsl/link_uniforms.cpp | 42 ++++++++++++++++++++++------ src/glsl/linker.cpp | 23 ++++------------ 3 files changed, 44 insertions(+), 77 deletions(-) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index bf4130fa8c6..3272868ee83 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -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; } diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 68cafbf3946..3e24842a026 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -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(); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index a480dd0523f..63ce178f44c 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -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. -- 2.30.2