diff options
author | Timothy Arceri <[email protected]> | 2020-01-17 12:07:11 +1100 |
---|---|---|
committer | Marge Bot <[email protected]> | 2020-03-06 23:22:14 +0000 |
commit | 8ffd09f3114233f742e8cfd142c74ea3477c4c59 (patch) | |
tree | d8182055ede3cd7b1b44a12eb60eb211991ab99e /src | |
parent | 76ce7752403912642cd00905f1d7a5f8bf21d219 (diff) |
glsl: find the base offset for block members from unnamed blocks
These block member have been split into individual vars so we need
to set the correct offsets for each member in the new glsl nir
linker. We also take this opportunity to set the correct location
for the variable.
Reviewed-by: Alejandro Piñeiro <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4050>
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/glsl/gl_nir_link_uniforms.c | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/src/compiler/glsl/gl_nir_link_uniforms.c b/src/compiler/glsl/gl_nir_link_uniforms.c index 88154cd6fcb..868a2642a43 100644 --- a/src/compiler/glsl/gl_nir_link_uniforms.c +++ b/src/compiler/glsl/gl_nir_link_uniforms.c @@ -1030,6 +1030,101 @@ gl_nir_link_uniforms(struct gl_context *ctx, build_type_tree_for_type(type); state.current_type = type_tree; + int location = var->data.location; + + if (!prog->data->spirv && state.var_is_in_block && + glsl_without_array(state.current_var->type) != state.current_var->interface_type) { + + int buffer_block_index = -1; + /* If the uniform is inside a uniform block determine its block index by + * comparing the bindings, we can not use names. + */ + struct gl_uniform_block *blocks = nir_variable_is_in_ssbo(state.current_var) ? + prog->data->ShaderStorageBlocks : prog->data->UniformBlocks; + int num_blocks = nir_variable_is_in_ssbo(state.current_var) ? + prog->data->NumShaderStorageBlocks : prog->data->NumUniformBlocks; + + bool is_interface_array = + glsl_without_array(state.current_var->type) == state.current_var->interface_type && + glsl_type_is_array(state.current_var->type); + + const char *ifc_name = + glsl_get_type_name(state.current_var->interface_type); + + if (is_interface_array) { + unsigned l = strlen(ifc_name); + for (unsigned i = 0; i < num_blocks; i++) { + if (strncmp(ifc_name, blocks[i].Name, l) == 0 && + blocks[i].Name[l] == '[') { + buffer_block_index = i; + + blocks[i].stageref |= 1U << shader_type; + } + } + } else { + for (unsigned i = 0; i < num_blocks; i++) { + if (strcmp(ifc_name, blocks[i].Name) == 0) { + buffer_block_index = i; + + blocks[i].stageref |= 1U << shader_type; + break; + } + } + } + + bool found = false; + char sentinel = '\0'; + + if (glsl_type_is_struct(state.current_var->type)) { + sentinel = '.'; + } else if (glsl_type_is_array(state.current_var->type) && + (glsl_type_is_array(glsl_get_array_element(state.current_var->type)) + || glsl_type_is_struct(glsl_without_array(state.current_var->type)))) { + sentinel = '['; + } + + const unsigned l = strlen(state.current_var->name); + for (unsigned i = 0; i < num_blocks; i++) { + for (unsigned j = 0; j < blocks[i].NumUniforms; j++) { + if (sentinel) { + const char *begin = blocks[i].Uniforms[j].Name; + const char *end = strchr(begin, sentinel); + + if (end == NULL) + continue; + + if ((ptrdiff_t) l != (end - begin)) + continue; + found = strncmp(state.current_var->name, begin, l) == 0; + } else { + found = strcmp(state.current_var->name, blocks[i].Uniforms[j].Name) == 0; + } + + if (found) { + location = j; + + blocks[i].stageref |= 1U << shader_type; + + break; + } + } + + if (found) + break; + } + assert(found); + + const struct gl_uniform_block *const block = + &blocks[buffer_block_index]; + assert(location != -1); + + const struct gl_uniform_buffer_variable *const ubo_var = + &block->Uniforms[location]; + + state.offset = ubo_var->Offset; + var->data.location = location; + } + /* Check if the uniform has been processed already for * other stage. If so, validate they are compatible and update * the active stage mask. @@ -1041,7 +1136,6 @@ gl_nir_link_uniforms(struct gl_context *ctx, continue; } - int location = var->data.location; /* From now on the variable’s location will be its uniform index */ if (!state.var_is_in_block) var->data.location = prog->data->NumUniformStorage; |