glsl: fix up location setting for variables pointing to a UBO's base

while linking uniforms, we might get a variable which is the only reference
to the ubo (i.e., offset 0), as determined by its type being the UBO's
interface_type, at which point we can assign the previously-gotten
block index to this variable's location

Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5831>
This commit is contained in:
Mike Blumenkrantz 2020-07-09 15:36:54 -04:00 committed by Marge Bot
parent ef0babab38
commit 47c358233d
1 changed files with 47 additions and 44 deletions

View File

@ -1727,54 +1727,57 @@ gl_nir_link_uniforms(struct gl_context *ctx,
}
}
if (!prog->data->spirv && state.var_is_in_block &&
glsl_without_array(state.current_var->type) != state.current_var->interface_type) {
if (!prog->data->spirv && state.var_is_in_block) {
if (glsl_without_array(state.current_var->type) != state.current_var->interface_type) {
/* this is nested at some offset inside the block */
bool found = false;
char sentinel = '\0';
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;
struct hash_entry *entry =
_mesa_hash_table_search(state.referenced_uniforms[shader_type], var->name);
if (entry)
blocks[i].stageref |= 1U << shader_type;
break;
}
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 = '[';
}
if (found)
break;
}
assert(found);
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;
struct hash_entry *entry =
_mesa_hash_table_search(state.referenced_uniforms[shader_type], var->name);
if (entry)
blocks[i].stageref |= 1U << shader_type;
break;
}
}
if (found)
break;
}
assert(found);
} else
/* this is the base block offset */
location = buffer_block_index;
assert(buffer_block_index >= 0);
const struct gl_uniform_block *const block =
&blocks[buffer_block_index];
assert(location != -1);