aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTimothy Arceri <[email protected]>2020-01-17 12:07:11 +1100
committerMarge Bot <[email protected]>2020-03-06 23:22:14 +0000
commit8ffd09f3114233f742e8cfd142c74ea3477c4c59 (patch)
treed8182055ede3cd7b1b44a12eb60eb211991ab99e /src
parent76ce7752403912642cd00905f1d7a5f8bf21d219 (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.c96
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;