Series is: Reviewed-by: Samuel Iglesias Gonsálvez <sigles...@igalia.com>
Thanks! Sam On 13/10/15 13:40, Tapani Pälli wrote: > Patch moves existing calculation code from shader_query.cpp to happen > during program resource list creation. > > No Piglit or CTS regressions were observed during testing. > > Signed-off-by: Tapani Pälli <tapani.pa...@intel.com> > --- > src/glsl/linker.cpp | 241 ++++++++++++++++++++++++++++++++++++++++ > src/mesa/main/shader_query.cpp | 244 > +---------------------------------------- > 2 files changed, 243 insertions(+), 242 deletions(-) > > diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp > index a97b4ef..3422fba 100644 > --- a/src/glsl/linker.cpp > +++ b/src/glsl/linker.cpp > @@ -3389,6 +3389,242 @@ add_packed_varyings(struct gl_shader_program *shProg, > int stage) > return true; > } > > +static char* > +get_top_level_name(const char *name) > +{ > + const char *first_dot = strchr(name, '.'); > + const char *first_square_bracket = strchr(name, '['); > + int name_size = 0; > + /* From ARB_program_interface_query spec: > + * > + * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying > the > + * number of active array elements of the top-level shader storage block > + * member containing to the active variable is written to <params>. If > the > + * top-level block member is not declared as an array, the value one is > + * written to <params>. If the top-level block member is an array with > no > + * declared size, the value zero is written to <params>. > + */ > + > + /* The buffer variable is on top level.*/ > + if (!first_square_bracket && !first_dot) > + name_size = strlen(name); > + else if ((!first_square_bracket || > + (first_dot && first_dot < first_square_bracket))) > + name_size = first_dot - name; > + else > + name_size = first_square_bracket - name; > + > + return strndup(name, name_size); > +} > + > +static char* > +get_var_name(const char *name) > +{ > + const char *first_dot = strchr(name, '.'); > + > + if (!first_dot) > + return strdup(name); > + > + return strndup(first_dot+1, strlen(first_dot) - 1); > +} > + > +static bool > +is_top_level_shader_storage_block_member(const char* name, > + const char* interface_name, > + const char* field_name) > +{ > + bool result = false; > + > + /* If the given variable is already a top-level shader storage > + * block member, then return array_size = 1. > + * We could have two possibilities: if we have an instanced > + * shader storage block or not instanced. > + * > + * For the first, we check create a name as it was in top level and > + * compare it with the real name. If they are the same, then > + * the variable is already at top-level. > + * > + * Full instanced name is: interface name + '.' + var name + > + * NULL character > + */ > + int name_length = strlen(interface_name) + 1 + strlen(field_name) + 1; > + char *full_instanced_name = (char *) calloc(name_length, sizeof(char)); > + if (!full_instanced_name) { > + fprintf(stderr, "%s: Cannot allocate space for name\n", __func__); > + return false; > + } > + > + snprintf(full_instanced_name, name_length, "%s.%s", > + interface_name, field_name); > + > + /* Check if its top-level shader storage block member of an > + * instanced interface block, or of a unnamed interface block. > + */ > + if (strcmp(name, full_instanced_name) == 0 || > + strcmp(name, field_name) == 0) > + result = true; > + > + free(full_instanced_name); > + return result; > +} > + > +static void > +calculate_array_size(struct gl_shader_program *shProg, > + struct gl_uniform_storage *uni) > +{ > + int block_index = uni->block_index; > + int array_size = -1; > + char *var_name = get_top_level_name(uni->name); > + char *interface_name = > + get_top_level_name(shProg->UniformBlocks[block_index].Name); > + > + if (strcmp(var_name, interface_name) == 0) { > + /* Deal with instanced array of SSBOs */ > + char *temp_name = get_var_name(uni->name); > + free(var_name); > + var_name = get_top_level_name(temp_name); > + free(temp_name); > + } > + > + for (unsigned i = 0; i < shProg->NumShaders; i++) { > + if (shProg->Shaders[i] == NULL) > + continue; > + > + const gl_shader *stage = shProg->Shaders[i]; > + foreach_in_list(ir_instruction, node, stage->ir) { > + ir_variable *var = node->as_variable(); > + if (!var || !var->get_interface_type() || > + var->data.mode != ir_var_shader_storage) > + continue; > + > + const glsl_type *interface = var->get_interface_type(); > + > + if (strcmp(interface_name, interface->name) != 0) > + continue; > + > + for (unsigned i = 0; i < interface->length; i++) { > + const glsl_struct_field *field = &interface->fields.structure[i]; > + if (strcmp(field->name, var_name) != 0) > + continue; > + /* From GL_ARB_program_interface_query spec: > + * > + * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer > + * identifying the number of active array elements of the > top-level > + * shader storage block member containing to the active variable > is > + * written to <params>. If the top-level block member is not > + * declared as an array, the value one is written to <params>. > If > + * the top-level block member is an array with no declared size, > + * the value zero is written to <params>. > + */ > + if (is_top_level_shader_storage_block_member(uni->name, > + interface_name, > + var_name)) > + array_size = 1; > + else if (field->type->is_unsized_array()) > + array_size = 0; > + else if (field->type->is_array()) > + array_size = field->type->length; > + else > + array_size = 1; > + > + goto found_top_level_array_size; > + } > + } > + } > +found_top_level_array_size: > + free(interface_name); > + free(var_name); > + uni->top_level_array_size = array_size; > +} > + > +static void > +calculate_array_stride(struct gl_shader_program *shProg, > + struct gl_uniform_storage *uni) > +{ > + int block_index = uni->block_index; > + int array_stride = -1; > + char *var_name = get_top_level_name(uni->name); > + char *interface_name = > + get_top_level_name(shProg->UniformBlocks[block_index].Name); > + > + if (strcmp(var_name, interface_name) == 0) { > + /* Deal with instanced array of SSBOs */ > + char *temp_name = get_var_name(uni->name); > + free(var_name); > + var_name = get_top_level_name(temp_name); > + free(temp_name); > + } > + > + for (unsigned i = 0; i < shProg->NumShaders; i++) { > + if (shProg->Shaders[i] == NULL) > + continue; > + > + const gl_shader *stage = shProg->Shaders[i]; > + foreach_in_list(ir_instruction, node, stage->ir) { > + ir_variable *var = node->as_variable(); > + if (!var || !var->get_interface_type() || > + var->data.mode != ir_var_shader_storage) > + continue; > + > + const glsl_type *interface = var->get_interface_type(); > + > + if (strcmp(interface_name, interface->name) != 0) { > + continue; > + } > + > + for (unsigned i = 0; i < interface->length; i++) { > + const glsl_struct_field *field = &interface->fields.structure[i]; > + if (strcmp(field->name, var_name) != 0) > + continue; > + /* From GL_ARB_program_interface_query: > + * > + * "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer > + * identifying the stride between array elements of the > top-level > + * shader storage block member containing the active variable is > + * written to <params>. For top-level block members declared as > + * arrays, the value written is the difference, in basic machine > + * units, between the offsets of the active variable for > + * consecutive elements in the top-level array. For top-level > + * block members not declared as an array, zero is written to > + * <params>." > + */ > + if (field->type->is_array()) { > + const enum glsl_matrix_layout matrix_layout = > + glsl_matrix_layout(field->matrix_layout); > + bool row_major = matrix_layout == > GLSL_MATRIX_LAYOUT_ROW_MAJOR; > + const glsl_type *array_type = field->type->fields.array; > + > + if (is_top_level_shader_storage_block_member(uni->name, > + interface_name, > + var_name)) { > + array_stride = 0; > + goto found_top_level_array_stride; > + } > + if (interface->interface_packing != > GLSL_INTERFACE_PACKING_STD430) { > + if (array_type->is_record() || array_type->is_array()) { > + array_stride = array_type->std140_size(row_major); > + array_stride = glsl_align(array_stride, 16); > + } else { > + unsigned element_base_align = 0; > + element_base_align = > array_type->std140_base_alignment(row_major); > + array_stride = MAX2(element_base_align, 16); > + } > + } else { > + array_stride = array_type->std430_array_stride(row_major); > + } > + } else { > + array_stride = 0; > + } > + goto found_top_level_array_stride; > + } > + } > + } > +found_top_level_array_stride: > + free(interface_name); > + free(var_name); > + uni->top_level_array_stride = array_stride; > +} > + > /** > * Builds up a list of program resources that point to existing > * resource data. > @@ -3473,6 +3709,11 @@ build_program_resource_list(struct gl_shader_program > *shProg) > shProg->UniformStorage[i].name)) > continue; > > + if (is_shader_storage) { > + calculate_array_size(shProg, &shProg->UniformStorage[i]); > + calculate_array_stride(shProg, &shProg->UniformStorage[i]); > + } > + > if (!add_program_resource(shProg, type, > &shProg->UniformStorage[i], stageref)) > return; > diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp > index 324e1a6..8182d3d 100644 > --- a/src/mesa/main/shader_query.cpp > +++ b/src/mesa/main/shader_query.cpp > @@ -839,244 +839,6 @@ program_resource_location(struct gl_shader_program > *shProg, > } > } > > -static char* > -get_top_level_name(const char *name) > -{ > - const char *first_dot = strchr(name, '.'); > - const char *first_square_bracket = strchr(name, '['); > - int name_size = 0; > - /* From ARB_program_interface_query spec: > - * > - * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer identifying > the > - * number of active array elements of the top-level shader storage block > - * member containing to the active variable is written to <params>. If > the > - * top-level block member is not declared as an array, the value one is > - * written to <params>. If the top-level block member is an array with > no > - * declared size, the value zero is written to <params>. > - */ > - > - /* The buffer variable is on top level.*/ > - if (!first_square_bracket && !first_dot) > - name_size = strlen(name); > - else if ((!first_square_bracket || > - (first_dot && first_dot < first_square_bracket))) > - name_size = first_dot - name; > - else > - name_size = first_square_bracket - name; > - > - return strndup(name, name_size); > -} > - > -static char* > -get_var_name(const char *name) > -{ > - const char *first_dot = strchr(name, '.'); > - > - if (!first_dot) > - return strdup(name); > - > - return strndup(first_dot+1, strlen(first_dot) - 1); > -} > - > -static bool > -is_top_level_shader_storage_block_member(const char* name, > - const char* interface_name, > - const char* field_name) > -{ > - bool result = false; > - > - /* If the given variable is already a top-level shader storage > - * block member, then return array_size = 1. > - * We could have two possibilities: if we have an instanced > - * shader storage block or not instanced. > - * > - * For the first, we check create a name as it was in top level and > - * compare it with the real name. If they are the same, then > - * the variable is already at top-level. > - * > - * Full instanced name is: interface name + '.' + var name + > - * NULL character > - */ > - int name_length = strlen(interface_name) + 1 + strlen(field_name) + 1; > - char *full_instanced_name = (char *) calloc(name_length, sizeof(char)); > - if (!full_instanced_name) { > - fprintf(stderr, "%s: Cannot allocate space for name\n", __func__); > - return false; > - } > - > - snprintf(full_instanced_name, name_length, "%s.%s", > - interface_name, field_name); > - > - /* Check if its top-level shader storage block member of an > - * instanced interface block, or of a unnamed interface block. > - */ > - if (strcmp(name, full_instanced_name) == 0 || > - strcmp(name, field_name) == 0) > - result = true; > - > - free(full_instanced_name); > - return result; > -} > - > -static GLint > -program_resource_top_level_array_size(struct gl_shader_program *shProg, > - struct gl_program_resource *res, > - const char *name) > -{ > - int block_index = RESOURCE_UNI(res)->block_index; > - int array_size = -1; > - char *var_name = get_top_level_name(name); > - char *interface_name = > - get_top_level_name(shProg->UniformBlocks[block_index].Name); > - > - if (strcmp(var_name, interface_name) == 0) { > - /* Deal with instanced array of SSBOs */ > - char *temp_name = get_var_name(name); > - free(var_name); > - var_name = get_top_level_name(temp_name); > - free(temp_name); > - } > - > - for (unsigned i = 0; i < shProg->NumShaders; i++) { > - if (shProg->Shaders[i] == NULL) > - continue; > - > - const gl_shader *stage = shProg->Shaders[i]; > - foreach_in_list(ir_instruction, node, stage->ir) { > - ir_variable *var = node->as_variable(); > - if (!var || !var->get_interface_type() || > - var->data.mode != ir_var_shader_storage) > - continue; > - > - const glsl_type *interface = var->get_interface_type(); > - > - if (strcmp(interface_name, interface->name) != 0) > - continue; > - > - for (unsigned i = 0; i < interface->length; i++) { > - const glsl_struct_field *field = &interface->fields.structure[i]; > - if (strcmp(field->name, var_name) != 0) > - continue; > - /* From GL_ARB_program_interface_query spec: > - * > - * "For the property TOP_LEVEL_ARRAY_SIZE, a single integer > - * identifying the number of active array elements of the > top-level > - * shader storage block member containing to the active variable > is > - * written to <params>. If the top-level block member is not > - * declared as an array, the value one is written to <params>. > If > - * the top-level block member is an array with no declared size, > - * the value zero is written to <params>. > - */ > - if (is_top_level_shader_storage_block_member(name, > - interface_name, > - var_name)) > - array_size = 1; > - else if (field->type->is_unsized_array()) > - array_size = 0; > - else if (field->type->is_array()) > - array_size = field->type->length; > - else > - array_size = 1; > - > - goto found_top_level_array_size; > - } > - } > - } > -found_top_level_array_size: > - free(interface_name); > - free(var_name); > - return array_size; > -} > - > -static GLint > -program_resource_top_level_array_stride(struct gl_shader_program *shProg, > - struct gl_program_resource *res, > - const char *name) > -{ > - int block_index = RESOURCE_UNI(res)->block_index; > - int array_stride = -1; > - char *var_name = get_top_level_name(name); > - char *interface_name = > - get_top_level_name(shProg->UniformBlocks[block_index].Name); > - > - if (strcmp(var_name, interface_name) == 0) { > - /* Deal with instanced array of SSBOs */ > - char *temp_name = get_var_name(name); > - free(var_name); > - var_name = get_top_level_name(temp_name); > - free(temp_name); > - } > - > - for (unsigned i = 0; i < shProg->NumShaders; i++) { > - if (shProg->Shaders[i] == NULL) > - continue; > - > - const gl_shader *stage = shProg->Shaders[i]; > - foreach_in_list(ir_instruction, node, stage->ir) { > - ir_variable *var = node->as_variable(); > - if (!var || !var->get_interface_type() || > - var->data.mode != ir_var_shader_storage) > - continue; > - > - const glsl_type *interface = var->get_interface_type(); > - > - if (strcmp(interface_name, interface->name) != 0) { > - continue; > - } > - > - for (unsigned i = 0; i < interface->length; i++) { > - const glsl_struct_field *field = &interface->fields.structure[i]; > - if (strcmp(field->name, var_name) != 0) > - continue; > - /* From GL_ARB_program_interface_query: > - * > - * "For the property TOP_LEVEL_ARRAY_STRIDE, a single integer > - * identifying the stride between array elements of the > top-level > - * shader storage block member containing the active variable is > - * written to <params>. For top-level block members declared as > - * arrays, the value written is the difference, in basic machine > - * units, between the offsets of the active variable for > - * consecutive elements in the top-level array. For top-level > - * block members not declared as an array, zero is written to > - * <params>." > - */ > - if (field->type->is_array()) { > - const enum glsl_matrix_layout matrix_layout = > - glsl_matrix_layout(field->matrix_layout); > - bool row_major = matrix_layout == > GLSL_MATRIX_LAYOUT_ROW_MAJOR; > - const glsl_type *array_type = field->type->fields.array; > - > - if (is_top_level_shader_storage_block_member(name, > - interface_name, > - var_name)) { > - array_stride = 0; > - goto found_top_level_array_stride; > - } > - if (interface->interface_packing != > GLSL_INTERFACE_PACKING_STD430) { > - if (array_type->is_record() || array_type->is_array()) { > - array_stride = array_type->std140_size(row_major); > - array_stride = glsl_align(array_stride, 16); > - } else { > - unsigned element_base_align = 0; > - element_base_align = > array_type->std140_base_alignment(row_major); > - array_stride = MAX2(element_base_align, 16); > - } > - } else { > - array_stride = array_type->std430_array_stride(row_major); > - } > - } else { > - array_stride = 0; > - } > - goto found_top_level_array_stride; > - } > - } > - } > -found_top_level_array_stride: > - free(interface_name); > - free(var_name); > - return array_stride; > -} > - > /** > * Function implements following location queries: > * glGetUniformLocation > @@ -1444,14 +1206,12 @@ _mesa_program_resource_prop(struct gl_shader_program > *shProg, > > case GL_TOP_LEVEL_ARRAY_SIZE: > VALIDATE_TYPE(GL_BUFFER_VARIABLE); > - *val = program_resource_top_level_array_size(shProg, res, > - > _mesa_program_resource_name(res)); > + *val = RESOURCE_UNI(res)->top_level_array_size; > return 1; > > case GL_TOP_LEVEL_ARRAY_STRIDE: > VALIDATE_TYPE(GL_BUFFER_VARIABLE); > - *val = program_resource_top_level_array_stride(shProg, res, > - > _mesa_program_resource_name(res)); > + *val = RESOURCE_UNI(res)->top_level_array_stride; > return 1; > > /* GL_ARB_tessellation_shader */ > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev