[Mesa-dev] [PATCH 2/2] glsl: calculate TOP_LEVEL_ARRAY_SIZE and STRIDE when adding resources

Samuel Iglesias Gonsálvez siglesias at igalia.com
Tue Oct 13 05:02:13 PDT 2015


Series is:

Reviewed-by: Samuel Iglesias Gonsálvez <siglesias at 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.palli at 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 */
> 


More information about the mesa-dev mailing list