From ae2ea5ec1f6630c2712ad48e8e03737b7efc74e7 Mon Sep 17 00:00:00 2001 From: Antia Puentes Date: Wed, 12 Sep 2018 13:51:57 +0200 Subject: nir/linker: Compute the offset for non-trivial uniform types. ARB_gl_spirv points that the offset must be explicit, however this is true for 'root' types. For complex types, like struct members or arrays of arraya, it needs to be computed. We are not using the offset stored in the gl_buffer_variables during the uniform blocks linking because currently we do not have a way to relate a gl_buffer_variable with its corresponding gl_uniform_storage. The GLSL path uses the name for that, but we can not rely on that because names are optional in SPIR-V. Notice that uniforms non-backed by a buffer object will have an offset equal to -1, like in the GLSL path. v2: add offset and var_is_in_block as per-variable state in nir_link_uniforms_state (Arcady) Reviewed-by: Caio Marcelo de Oliveira Filho --- src/compiler/glsl/gl_nir_link_uniforms.c | 33 ++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/compiler/glsl/gl_nir_link_uniforms.c b/src/compiler/glsl/gl_nir_link_uniforms.c index a17d13639d7..4a19ad81d75 100644 --- a/src/compiler/glsl/gl_nir_link_uniforms.c +++ b/src/compiler/glsl/gl_nir_link_uniforms.c @@ -247,6 +247,8 @@ struct nir_link_uniforms_state { unsigned shader_shadow_samplers; nir_variable *current_var; + int offset; + bool var_is_in_block; struct type_tree_entry *current_type; }; @@ -361,16 +363,26 @@ nir_link_uniform(struct gl_context *ctx, glsl_type_is_struct_or_ifc(glsl_get_array_element(type))))) { int location_count = 0; struct type_tree_entry *old_type = state->current_type; + unsigned int struct_base_offset = state->offset; state->current_type = old_type->children; for (unsigned i = 0; i < glsl_get_length(type); i++) { const struct glsl_type *field_type; - if (glsl_type_is_struct_or_ifc(type)) + if (glsl_type_is_struct_or_ifc(type)) { field_type = glsl_get_struct_field(type, i); - else + /* Use the offset inside the struct only for variables backed by + * a buffer object. For variables not backed by a buffer object, + * offset is -1. + */ + if (state->var_is_in_block) { + state->offset = + struct_base_offset + glsl_get_struct_field_offset(type, i); + } + } else { field_type = glsl_get_array_element(type); + } int entries = nir_link_uniform(ctx, prog, stage_program, stage, field_type, type, i, location, @@ -459,7 +471,7 @@ nir_link_uniform(struct gl_context *ctx, uniform->matrix_stride = -1; uniform->row_major = false; - if (nir_variable_is_in_block(state->current_var)) { + if (state->var_is_in_block) { uniform->array_stride = glsl_type_is_array(type) ? glsl_get_explicit_stride(type) : 0; @@ -473,16 +485,13 @@ nir_link_uniform(struct gl_context *ctx, } } - if (parent_type) - uniform->offset = glsl_get_struct_field_offset(parent_type, index_in_parent); - else - uniform->offset = 0; + uniform->offset = state->var_is_in_block ? state->offset : -1; 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. */ - if (nir_variable_is_in_block(state->current_var)) { + if (state->var_is_in_block) { struct gl_uniform_block *blocks = nir_variable_is_in_ssbo(state->current_var) ? prog->data->ShaderStorageBlocks : prog->data->UniformBlocks; @@ -496,6 +505,9 @@ nir_link_uniform(struct gl_context *ctx, } } assert(buffer_block_index >= 0); + + /* Compute the next offset. */ + state->offset += glsl_get_explicit_size(type, true); } uniform->block_index = buffer_block_index; @@ -620,6 +632,8 @@ gl_nir_link_uniforms(struct gl_context *ctx, var->data.location = prog->data->NumUniformStorage; state.current_var = var; + state.offset = 0; + state.var_is_in_block = nir_variable_is_in_block(var); /* * From ARB_program_interface spec, issue (16): @@ -656,8 +670,7 @@ gl_nir_link_uniforms(struct gl_context *ctx, * arrays of instance as a single block. */ const struct glsl_type *type = var->type; - if (nir_variable_is_in_block(var) && - glsl_type_is_array(type)) { + if (state.var_is_in_block && glsl_type_is_array(type)) { type = glsl_without_array(type); } -- cgit v1.2.3