This make more sense here as its lowering that uses the results of this function.
This allows us to call lower_ubo_reference() before assigning uniform locations which will be useful for converting to earlier NIR and performing optimisations before assigning uniform locations. --- src/compiler/glsl/link_uniforms.cpp | 126 ------------------------------ src/compiler/glsl/linker.cpp | 16 +++- src/compiler/glsl/lower_ubo_reference.cpp | 126 ++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 130 deletions(-) diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp index e2e8dd1..e4275fd 100644 --- a/src/compiler/glsl/link_uniforms.cpp +++ b/src/compiler/glsl/link_uniforms.cpp @@ -868,130 +868,6 @@ public: unsigned shader_shadow_samplers; }; -static bool -variable_is_referenced(ir_array_refcount_visitor &v, ir_variable *var) -{ - ir_array_refcount_entry *const entry = v.get_variable_entry(var); - - return entry->is_referenced; - -} - -/** - * Walks the IR and update the references to uniform blocks in the - * ir_variables to point at linked shader's list (previously, they - * would point at the uniform block list in one of the pre-linked - * shaders). - */ -static void -link_update_uniform_buffer_variables(struct gl_linked_shader *shader, - unsigned stage) -{ - ir_array_refcount_visitor v; - - v.run(shader->ir); - - foreach_in_list(ir_instruction, node, shader->ir) { - ir_variable *const var = node->as_variable(); - - if (var == NULL || !var->is_in_buffer_block()) - continue; - - assert(var->data.mode == ir_var_uniform || - var->data.mode == ir_var_shader_storage); - - unsigned num_blocks = var->data.mode == ir_var_uniform ? - shader->Program->info.num_ubos : shader->Program->info.num_ssbos; - struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ? - shader->Program->sh.UniformBlocks : - shader->Program->sh.ShaderStorageBlocks; - - if (var->is_interface_instance()) { - const ir_array_refcount_entry *const entry = v.get_variable_entry(var); - - if (entry->is_referenced) { - /* Since this is an interface instance, the instance type will be - * same as the array-stripped variable type. If the variable type - * is an array, then the block names will be suffixed with [0] - * through [n-1]. Unlike for non-interface instances, there will - * not be structure types here, so the only name sentinel that we - * have to worry about is [. - */ - assert(var->type->without_array() == var->get_interface_type()); - const char sentinel = var->type->is_array() ? '[' : '\0'; - - const ptrdiff_t len = strlen(var->get_interface_type()->name); - for (unsigned i = 0; i < num_blocks; i++) { - const char *const begin = blks[i]->Name; - const char *const end = strchr(begin, sentinel); - - if (end == NULL) - continue; - - if (len != (end - begin)) - continue; - - /* Even when a match is found, do not "break" here. This could - * be an array of instances, and all elements of the array need - * to be marked as referenced. - */ - if (strncmp(begin, var->get_interface_type()->name, len) == 0 && - (!var->type->is_array() || - entry->is_linearized_index_referenced(blks[i]->linearized_array_index))) { - blks[i]->stageref |= 1U << stage; - } - } - } - - var->data.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_array() - || var->type->without_array()->is_record())) { - sentinel = '['; - } - - const unsigned l = strlen(var->name); - for (unsigned i = 0; i < num_blocks; i++) { - for (unsigned j = 0; j < blks[i]->NumUniforms; j++) { - if (sentinel) { - const char *begin = blks[i]->Uniforms[j].Name; - const char *end = strchr(begin, sentinel); - - if (end == NULL) - continue; - - if ((ptrdiff_t) l != (end - begin)) - continue; - - found = strncmp(var->name, begin, l) == 0; - } else { - found = strcmp(var->name, blks[i]->Uniforms[j].Name) == 0; - } - - if (found) { - var->data.location = j; - - if (variable_is_referenced(v, var)) - blks[i]->stageref |= 1U << stage; - - break; - } - } - - if (found) - break; - } - assert(found); - } -} - /** * Combine the hidden uniform hash map with the uniform hash map so that the * hidden uniforms will be given indicies at the end of the uniform storage @@ -1320,8 +1196,6 @@ link_assign_uniform_locations(struct gl_shader_program *prog, if (sh == NULL) continue; - link_update_uniform_buffer_variables(sh, i); - /* Reset various per-shader target counts. */ uniform_size.start_shader(); diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index d7ed436..fa1062e 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -4619,6 +4619,18 @@ link_varyings_and_uniforms(unsigned first, unsigned last, return false; } + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; + + const struct gl_shader_compiler_options *options = + &ctx->Const.ShaderCompilerOptions[i]; + + if (options->LowerBufferInterfaceBlocks) + lower_ubo_reference(prog->_LinkedShaders[i], + options->ClampBlockIndicesToArrayBounds); + } + /* If there is no fragment shader we need to set transform feedback. * * For SSO we also need to assign output locations. We assign them here @@ -4740,10 +4752,6 @@ link_varyings_and_uniforms(unsigned first, unsigned last, const struct gl_shader_compiler_options *options = &ctx->Const.ShaderCompilerOptions[i]; - if (options->LowerBufferInterfaceBlocks) - lower_ubo_reference(prog->_LinkedShaders[i], - options->ClampBlockIndicesToArrayBounds); - if (i == MESA_SHADER_COMPUTE) lower_shared_reference(prog->_LinkedShaders[i], &prog->Comp.SharedSize); diff --git a/src/compiler/glsl/lower_ubo_reference.cpp b/src/compiler/glsl/lower_ubo_reference.cpp index bfaddac..8d10dcb 100644 --- a/src/compiler/glsl/lower_ubo_reference.cpp +++ b/src/compiler/glsl/lower_ubo_reference.cpp @@ -35,6 +35,7 @@ #include "lower_buffer_access.h" #include "ir_builder.h" +#include "ir_array_refcount.h" #include "main/macros.h" #include "glsl_parser_extras.h" @@ -1092,9 +1093,134 @@ lower_ubo_reference_visitor::visit_enter(ir_call *ir) } /* unnamed namespace */ +static bool +variable_is_referenced(ir_array_refcount_visitor &v, ir_variable *var) +{ + ir_array_refcount_entry *const entry = v.get_variable_entry(var); + + return entry->is_referenced; + +} + +/** + * Walks the IR and update the references to uniform blocks in the + * ir_variables to point at linked shader's list (previously, they + * would point at the uniform block list in one of the pre-linked + * shaders). + */ +static void +update_uniform_buffer_variables(struct gl_linked_shader *shader) +{ + ir_array_refcount_visitor v; + + v.run(shader->ir); + + foreach_in_list(ir_instruction, node, shader->ir) { + ir_variable *const var = node->as_variable(); + + if (var == NULL || !var->is_in_buffer_block()) + continue; + + assert(var->data.mode == ir_var_uniform || + var->data.mode == ir_var_shader_storage); + + unsigned num_blocks = var->data.mode == ir_var_uniform ? + shader->Program->info.num_ubos : shader->Program->info.num_ssbos; + struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ? + shader->Program->sh.UniformBlocks : + shader->Program->sh.ShaderStorageBlocks; + + if (var->is_interface_instance()) { + const ir_array_refcount_entry *const entry = v.get_variable_entry(var); + + if (entry->is_referenced) { + /* Since this is an interface instance, the instance type will be + * same as the array-stripped variable type. If the variable type + * is an array, then the block names will be suffixed with [0] + * through [n-1]. Unlike for non-interface instances, there will + * not be structure types here, so the only name sentinel that we + * have to worry about is [. + */ + assert(var->type->without_array() == var->get_interface_type()); + const char sentinel = var->type->is_array() ? '[' : '\0'; + + const ptrdiff_t len = strlen(var->get_interface_type()->name); + for (unsigned i = 0; i < num_blocks; i++) { + const char *const begin = blks[i]->Name; + const char *const end = strchr(begin, sentinel); + + if (end == NULL) + continue; + + if (len != (end - begin)) + continue; + + /* Even when a match is found, do not "break" here. This could + * be an array of instances, and all elements of the array need + * to be marked as referenced. + */ + if (strncmp(begin, var->get_interface_type()->name, len) == 0 && + (!var->type->is_array() || + entry->is_linearized_index_referenced(blks[i]->linearized_array_index))) { + blks[i]->stageref |= 1U << shader->Stage; + } + } + } + + var->data.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_array() + || var->type->without_array()->is_record())) { + sentinel = '['; + } + + const unsigned l = strlen(var->name); + for (unsigned i = 0; i < num_blocks; i++) { + for (unsigned j = 0; j < blks[i]->NumUniforms; j++) { + if (sentinel) { + const char *begin = blks[i]->Uniforms[j].Name; + const char *end = strchr(begin, sentinel); + + if (end == NULL) + continue; + + if ((ptrdiff_t) l != (end - begin)) + continue; + + found = strncmp(var->name, begin, l) == 0; + } else { + found = strcmp(var->name, blks[i]->Uniforms[j].Name) == 0; + } + + if (found) { + var->data.location = j; + + if (variable_is_referenced(v, var)) + blks[i]->stageref |= 1U << shader->Stage; + + break; + } + } + + if (found) + break; + } + assert(found); + } +} + void lower_ubo_reference(struct gl_linked_shader *shader, bool clamp_block_indices) { + update_uniform_buffer_variables(shader); + lower_ubo_reference_visitor v(shader, clamp_block_indices); /* Loop over the instructions lowering references, because we take -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev