[Mesa-dev] [PATCH v3 (part2) 49/56] main: Add SHADER_STORAGE_BLOCK and BUFFER_VARIABLE support for ARB_program_interface_query

Tapani Pälli tapani.palli at intel.com
Mon Aug 3 22:28:41 PDT 2015



On 07/31/2015 12:37 PM, Samuel Iglesias Gonsálvez wrote:
> On Fri, 2015-07-31 at 09:32 +0200, Samuel Iglesias Gonsálvez wrote:
>> On Fri, 2015-07-31 at 09:09 +0300, Tapani Pälli wrote:
>>> On 07/14/2015 10:46 AM, Iago Toral Quiroga wrote:
>>>> From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
>>>>
>>>> Including TOP_LEVEL_ARRAY_SIZE and TOP_LEVEL_ARRAY_STRIDE
>>>> queries.
>>>>
>>>> Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
>>>> ---
>>>>    src/glsl/ir_uniform.h            |   5 +
>>>>    src/glsl/link_uniforms.cpp       |  17 ++-
>>>>    src/glsl/linker.cpp              |  10 +-
>>>>    src/mesa/main/program_resource.c |   7 +-
>>>>    src/mesa/main/shader_query.cpp   | 265
>>>> +++++++++++++++++++++++++++++++++++++--
>>>>    5 files changed, 289 insertions(+), 15 deletions(-)
>>>>
>>>> diff --git a/src/glsl/ir_uniform.h b/src/glsl/ir_uniform.h
>>>> index e1b8014..71d894c 100644
>>>> --- a/src/glsl/ir_uniform.h
>>>> +++ b/src/glsl/ir_uniform.h
>>>> @@ -186,6 +186,11 @@ struct gl_uniform_storage {
>>>>        * This is a built-in uniform that should not be modified
>>>> through any gl API.
>>>>        */
>>>>       bool builtin;
>>>> +
>>>> +   /**
>>>> +    * This is a shader storage buffer variable, not an uniform.
>>>> +    */
>>>> +   bool is_shader_storage;
>>>>    };
>>>>
>>>>    #ifdef __cplusplus
>>>> diff --git a/src/glsl/link_uniforms.cpp
>>>> b/src/glsl/link_uniforms.cpp
>>>> index eefe7dc..29a8799 100644
>>>> --- a/src/glsl/link_uniforms.cpp
>>>> +++ b/src/glsl/link_uniforms.cpp
>>>> @@ -638,6 +638,9 @@ private:
>>>>          if (!this->uniforms[id].builtin)
>>>>             this->uniforms[id].storage = this->values;
>>>>
>>>> +      this->uniforms[id].is_shader_storage =
>>>> +         current_var->is_in_shader_storage_block();
>>>> +
>>>>          if (this->ubo_block_index != -1) {
>>>>    	 this->uniforms[id].block_index = this
>>>> ->ubo_block_index;
>>>>
>>>> @@ -647,8 +650,12 @@ private:
>>>>    	 this->ubo_byte_offset += type->std140_size(row_major);
>>>>
>>>>    	 if (type->is_array()) {
>>>> -	    this->uniforms[id].array_stride =
>>>> -	       glsl_align(type->fields.array
>>>> ->std140_size(row_major), 16);
>>>> +	    if (type->interface_packing ==
>>>> GLSL_INTERFACE_PACKING_STD430)
>>>> +	       this->uniforms[id].array_stride =
>>>> +		  type->fields.array->std430_size(row_major);
>>>> +	    else
>>>> +	       this->uniforms[id].array_stride =
>>>> +		  glsl_align(type->fields.array
>>>> ->std140_size(row_major), 16);
>>>>    	 } else {
>>>>    	    this->uniforms[id].array_stride = 0;
>>>>    	 }
>>>> @@ -659,7 +666,11 @@ private:
>>>>                const unsigned items = row_major ? matrix
>>>> ->matrix_columns : matrix->vector_elements;
>>>>
>>>>                assert(items <= 4);
>>>> -            this->uniforms[id].matrix_stride = glsl_align(items
>>>> *
>>>> N, 16);
>>>> +            if (type->interface_packing ==
>>>> GLSL_INTERFACE_PACKING_STD430)
>>>> +               this->uniforms[id].matrix_stride = items < 3 ?
>>>> items * N :
>>>> +
>>>>   glsl_align(items
>>>> * N, 16);
>>>> +            else
>>>> +               this->uniforms[id].matrix_stride =
>>>> glsl_align(items
>>>> * N, 16);
>>>>    	    this->uniforms[id].row_major = row_major;
>>>>    	 } else {
>>>>    	    this->uniforms[id].matrix_stride = 0;
>>>> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
>>>> index 330ef56..e82aa61 100644
>>>> --- a/src/glsl/linker.cpp
>>>> +++ b/src/glsl/linker.cpp
>>>> @@ -2852,14 +2852,18 @@ build_program_resource_list(struct
>>>> gl_context *ctx,
>>>>             }
>>>>          }
>>>>
>>>> -      if (!add_program_resource(shProg, GL_UNIFORM,
>>>> +      bool is_shader_storage =  shProg
>>>> ->UniformStorage[i].is_shader_storage;
>>>> +      GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE :
>>>> GL_UNIFORM;
>>>> +      if (!add_program_resource(shProg, type,
>>>>                                    &shProg->UniformStorage[i],
>>>> stageref))
>>>>             return;
>>>>       }
>>>>
>>>> -   /* Add program uniform blocks. */
>>>> +   /* Add program uniform blocks and shader storage blocks. */
>>>>       for (unsigned i = 0; i < shProg->NumUniformBlocks; i++) {
>>>> -      if (!add_program_resource(shProg, GL_UNIFORM_BLOCK,
>>>> +      bool is_shader_storage = shProg
>>>> ->UniformBlocks[i].IsShaderStorage;
>>>> +      GLenum type = is_shader_storage ? GL_SHADER_STORAGE_BLOCK
>>>> :
>>>> GL_UNIFORM_BLOCK;
>>>> +      if (!add_program_resource(shProg, type,
>>>>              &shProg->UniformBlocks[i], 0))
>>>>             return;
>>>>       }
>>>> diff --git a/src/mesa/main/program_resource.c
>>>> b/src/mesa/main/program_resource.c
>>>> index d857b84..0444e3b 100644
>>>> --- a/src/mesa/main/program_resource.c
>>>> +++ b/src/mesa/main/program_resource.c
>>>> @@ -40,6 +40,8 @@ supported_interface_enum(GLenum iface)
>>>>       case GL_PROGRAM_OUTPUT:
>>>>       case GL_TRANSFORM_FEEDBACK_VARYING:
>>>>       case GL_ATOMIC_COUNTER_BUFFER:
>>>> +   case GL_BUFFER_VARIABLE:
>>>> +   case GL_SHADER_STORAGE_BLOCK:
>>>>          return true;
>>>>       case GL_VERTEX_SUBROUTINE:
>>>>       case GL_TESS_CONTROL_SUBROUTINE:
>>>> @@ -53,8 +55,6 @@ supported_interface_enum(GLenum iface)
>>>>       case GL_GEOMETRY_SUBROUTINE_UNIFORM:
>>>>       case GL_FRAGMENT_SUBROUTINE_UNIFORM:
>>>>       case GL_COMPUTE_SUBROUTINE_UNIFORM:
>>>> -   case GL_BUFFER_VARIABLE:
>>>> -   case GL_SHADER_STORAGE_BLOCK:
>>>>       default:
>>>>          return false;
>>>>       }
>>>> @@ -116,6 +116,7 @@ _mesa_GetProgramInterfaceiv(GLuint program,
>>>> GLenum programInterface,
>>>>       case GL_MAX_NUM_ACTIVE_VARIABLES:
>>>>          switch (programInterface) {
>>>>          case GL_UNIFORM_BLOCK:
>>>> +      case GL_SHADER_STORAGE_BLOCK:
>>>>             for (i = 0, *params = 0; i < shProg
>>>> ->NumProgramResourceList; i++) {
>>>>                if (shProg->ProgramResourceList[i].Type ==
>>>> programInterface) {
>>>>                   struct gl_uniform_block *block =
>>>> @@ -220,12 +221,14 @@ _mesa_GetProgramResourceIndex(GLuint
>>>> program,
>>>> GLenum programInterface,
>>>>       case GL_PROGRAM_INPUT:
>>>>       case GL_PROGRAM_OUTPUT:
>>>>       case GL_UNIFORM:
>>>> +   case GL_BUFFER_VARIABLE:
>>>>       case GL_TRANSFORM_FEEDBACK_VARYING:
>>>>          /* Validate name syntax for array variables */
>>>>          if (!valid_program_resource_index_name(name))
>>>>             return GL_INVALID_INDEX;
>>>>          /* fall-through */
>>>>       case GL_UNIFORM_BLOCK:
>>>> +   case GL_SHADER_STORAGE_BLOCK:
>>>>          res = _mesa_program_resource_find_name(shProg,
>>>> programInterface, name);
>>>>          if (!res)
>>>>             return GL_INVALID_INDEX;
>>>> diff --git a/src/mesa/main/shader_query.cpp
>>>> b/src/mesa/main/shader_query.cpp
>>>> index a6246a3..2f1b8e2 100644
>>>> --- a/src/mesa/main/shader_query.cpp
>>>> +++ b/src/mesa/main/shader_query.cpp
>>>> @@ -482,6 +482,7 @@ _mesa_program_resource_name(struct
>>>> gl_program_resource *res)
>>>>       const ir_variable *var;
>>>>       switch (res->Type) {
>>>>       case GL_UNIFORM_BLOCK:
>>>> +   case GL_SHADER_STORAGE_BLOCK:
>>>>          return RESOURCE_UBO(res)->Name;
>>>>       case GL_TRANSFORM_FEEDBACK_VARYING:
>>>>          return RESOURCE_XFB(res)->Name;
>>>> @@ -496,6 +497,7 @@ _mesa_program_resource_name(struct
>>>> gl_program_resource *res)
>>>>       case GL_PROGRAM_OUTPUT:
>>>>          return RESOURCE_VAR(res)->name;
>>>>       case GL_UNIFORM:
>>>> +   case GL_BUFFER_VARIABLE:
>>>>          return RESOURCE_UNI(res)->name;
>>>>       default:
>>>>          assert(!"support for resource type not implemented");
>>>> @@ -515,9 +517,11 @@ _mesa_program_resource_array_size(struct
>>>> gl_program_resource *res)
>>>>       case GL_PROGRAM_OUTPUT:
>>>>          return RESOURCE_VAR(res)->data.max_array_access;
>>>>       case GL_UNIFORM:
>>>> +   case GL_BUFFER_VARIABLE:
>>>>          return RESOURCE_UNI(res)->array_elements;
>>>>       case GL_ATOMIC_COUNTER_BUFFER:
>>>>       case GL_UNIFORM_BLOCK:
>>>> +   case GL_SHADER_STORAGE_BLOCK:
>>>>          return 0;
>>>>       default:
>>>>          assert(!"support for resource type not implemented");
>>>> @@ -571,6 +575,8 @@ _mesa_program_resource_find_name(struct
>>>> gl_shader_program *shProg,
>>>>          case GL_TRANSFORM_FEEDBACK_VARYING:
>>>>          case GL_UNIFORM_BLOCK:
>>>>          case GL_UNIFORM:
>>>> +      case GL_SHADER_STORAGE_BLOCK:
>>>> +      case GL_BUFFER_VARIABLE:
>>>>             if (strncmp(rname, name, baselen) == 0) {
>>>>                /* Basename match, check if array or struct. */
>>>>                if (name[baselen] == '\0' ||
>>>> @@ -619,6 +625,7 @@ _mesa_program_resource_index(struct
>>>> gl_shader_program *shProg,
>>>>
>>>>       switch (res->Type) {
>>>>       case GL_UNIFORM_BLOCK:
>>>> +   case GL_SHADER_STORAGE_BLOCK:
>>>>          return RESOURCE_UBO(res)- shProg->UniformBlocks;
>>>>       case GL_ATOMIC_COUNTER_BUFFER:
>>>>          return RESOURCE_ATC(res) - shProg->AtomicBuffers;
>>>> @@ -644,6 +651,7 @@ _mesa_program_resource_find_index(struct
>>>> gl_shader_program *shProg,
>>>>          switch (res->Type) {
>>>>          case GL_UNIFORM_BLOCK:
>>>>          case GL_ATOMIC_COUNTER_BUFFER:
>>>> +      case GL_SHADER_STORAGE_BLOCK:
>>>>             if (_mesa_program_resource_index(shProg, res) ==
>>>> index)
>>>>                return res;
>>>>             break;
>>>> @@ -651,6 +659,7 @@ _mesa_program_resource_find_index(struct
>>>> gl_shader_program *shProg,
>>>>          case GL_PROGRAM_INPUT:
>>>>          case GL_PROGRAM_OUTPUT:
>>>>          case GL_UNIFORM:
>>>> +      case GL_BUFFER_VARIABLE:
>>>>             if (++idx == (int) index)
>>>>                return res;
>>>>             break;
>>>> @@ -785,6 +794,197 @@ 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 GL_shader_storage_buffer_object spec:
>
> Here it should be ARB_program_interface_query spec. I am going to
> change it.

OK

>>>> +    *
>>>> +    * "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);
>>>> +}
>>>
>>> I think instead of this function you should be able to do something
>>> along the lines of:
>>>
>>> const char *base_name_end;
>>> const char *base_name =
>>>      parse_program_resource_name(name, &base_name_end);
>>>
>>> return strndup(base_name, base_name_end - base_name);
>>>
>>
>> OK
>>
>
> I have checked this solution and it doesn't work:
> parse_program_resource_name() expects the name to be of an array
> element (i.e, last char is ']'). If this is not the case, it returns
> the same name written into 'out_base_name_end' and 'array_index' is -1.

Argh I see, sorry for leading to wrong tracks. Then I'm happy with the 
added function.

> Notice that the buffer variable used to query TOP_LEVEL_ARRAY_SIZE
> could not be an array element and we want to know the array size of the
> top-level shader storage block member containing that buffer variable.

Right, this makes sense. I was hoping we could utilize existing 
'parsing' logic but it seems it is not that generic as it makes the 
array assumption.

With the other small changes fixed this is

Reviewed-by: Tapani Pälli <tapani.palli at intel.com>


> See 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>."
>
> Sam
>
>>>> +
>>>> +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 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;
>>>> +         }
>>>
>>> strip { } for single line statement
>>>
>>
>> OK
>>
>>>> +
>>>> +         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 (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 (array_type->is_record()) {
>>>> +                  if (field->type->interface_packing ==
>>>> GLSL_INTERFACE_PACKING_STD430) {
>>>> +                     array_stride = array_type
>>>> ->std430_size(row_major);
>>>> +                  } else {
>>>> +                     array_stride = array_type
>>>> ->std140_size(row_major);
>>>> +                     array_stride = glsl_align(array_stride,
>>>> 16);
>>>> +                  }
>>>> +               } else {
>>>> +                  unsigned element_base_align = 0;
>>>> +                  if (field->type->interface_packing ==
>>>> GLSL_INTERFACE_PACKING_STD430) {
>>>> +                     array_stride = array_type
>>>> ->std430_base_alignment(row_major);
>>>> +                  } else {
>>>> +                     element_base_align = array_type
>>>> ->std140_base_alignment(row_major);
>>>> +                     array_stride = MAX2(element_base_align,
>>>> 16);
>>>> +                  }
>>>> +               }
>>>> +            } else {
>>>> +               array_stride = 0;
>>>> +            }
>>>> +            goto found_top_level_array_size;
>>>> +         }
>>>> +      }
>>>> +   }
>>>> +found_top_level_array_size:
>>>> +   free(var_name);
>>>> +   return array_stride;
>>>> +}
>>>> +
>>>>    /**
>>>>     * Function implements following location queries:
>>>>     *    glGetAttribLocation
>>>> @@ -857,7 +1057,7 @@ is_resource_referenced(struct
>>>> gl_shader_program *shProg,
>>>>       if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
>>>>          return RESOURCE_ATC(res)->StageReferences[stage];
>>>>
>>>> -   if (res->Type == GL_UNIFORM_BLOCK)
>>>> +   if (res->Type == GL_UNIFORM_BLOCK || res->Type ==
>>>> GL_SHADER_STORAGE_BLOCK)
>>>>          return shProg->UniformBlockStageIndex[stage][index] !=
>>>> -1;
>>>>
>>>>       return res->StageReferences & (1 << stage);
>>>> @@ -870,7 +1070,8 @@ get_buffer_property(struct gl_shader_program
>>>> *shProg,
>>>>    {
>>>>       GET_CURRENT_CONTEXT(ctx);
>>>>       if (res->Type != GL_UNIFORM_BLOCK &&
>>>> -       res->Type != GL_ATOMIC_COUNTER_BUFFER)
>>>> +       res->Type != GL_ATOMIC_COUNTER_BUFFER &&
>>>> +       res->Type != GL_SHADER_STORAGE_BLOCK)
>>>>          goto invalid_operation;
>>>>
>>>>       if (res->Type == GL_UNIFORM_BLOCK) {
>>>> @@ -904,6 +1105,37 @@ get_buffer_property(struct
>>>> gl_shader_program
>>>> *shProg,
>>>>             }
>>>>             return RESOURCE_UBO(res)->NumUniforms;
>>>>          }
>>>> +   } else if (res->Type == GL_SHADER_STORAGE_BLOCK) {
>>>> +      switch (prop) {
>>>> +      case GL_BUFFER_BINDING:
>>>> +         *val = RESOURCE_UBO(res)->Binding;
>>>> +         return 1;
>>>> +      case GL_BUFFER_DATA_SIZE:
>>>> +         *val = RESOURCE_UBO(res)->UniformBufferSize;
>>>> +         return 1;
>>>> +      case GL_NUM_ACTIVE_VARIABLES:
>>>> +         *val = 0;
>>>> +         for (unsigned i = 0; i < RESOURCE_UBO(res)
>>>> ->NumUniforms;
>>>> i++) {
>>>> +            const char *iname = RESOURCE_UBO(res)
>>>> ->Uniforms[i].IndexName;
>>>> +            struct gl_program_resource *uni =
>>>> +               _mesa_program_resource_find_name(shProg,
>>>> GL_BUFFER_VARIABLE, iname);
>>>> +            if (!uni)
>>>> +               continue;
>>>> +            (*val)++;
>>>> +         }
>>>> +         return 1;
>>>> +      case GL_ACTIVE_VARIABLES:
>>>> +         for (unsigned i = 0; i < RESOURCE_UBO(res)
>>>> ->NumUniforms;
>>>> i++) {
>>>> +            const char *iname = RESOURCE_UBO(res)
>>>> ->Uniforms[i].IndexName;
>>>> +            struct gl_program_resource *uni =
>>>> +               _mesa_program_resource_find_name(shProg,
>>>> GL_BUFFER_VARIABLE, iname);
>>>> +            if (!uni)
>>>> +               continue;
>>>> +            *val++ =
>>>> +               _mesa_program_resource_index(shProg, uni);
>>>> +         }
>>>> +         return RESOURCE_UBO(res)->NumUniforms;
>>>> +      }
>>>>       } else if (res->Type == GL_ATOMIC_COUNTER_BUFFER) {
>>>>          switch (prop) {
>>>>          case GL_BUFFER_BINDING:
>>>> @@ -942,6 +1174,10 @@ _mesa_program_resource_prop(struct
>>>> gl_shader_program *shProg,
>>>>       if (res->Type != type)\
>>>>          goto invalid_operation;
>>>>
>>>> +#define VALIDATE_TYPE_2(type1, type2)\
>>>> +   if (res->Type != type1 && res->Type != type2)\
>>>> +      goto invalid_operation;
>>>> +
>>>
>>>
>>> add undef for VALIDATE_TYPE2
>>>
>>
>> OK
>>
>> Thanks for the review!
>>
>> Sam
>>
>>>
>>>>       switch(prop) {
>>>>       case GL_NAME_LENGTH:
>>>>          if (res->Type == GL_ATOMIC_COUNTER_BUFFER)
>>>> @@ -953,6 +1189,7 @@ _mesa_program_resource_prop(struct
>>>> gl_shader_program *shProg,
>>>>       case GL_TYPE:
>>>>          switch (res->Type) {
>>>>          case GL_UNIFORM:
>>>> +      case GL_BUFFER_VARIABLE:
>>>>             *val = RESOURCE_UNI(res)->type->gl_type;
>>>>             return 1;
>>>>          case GL_PROGRAM_INPUT:
>>>> @@ -968,6 +1205,7 @@ _mesa_program_resource_prop(struct
>>>> gl_shader_program *shProg,
>>>>       case GL_ARRAY_SIZE:
>>>>          switch (res->Type) {
>>>>          case GL_UNIFORM:
>>>> +      case GL_BUFFER_VARIABLE:
>>>>                *val = MAX2(RESOURCE_UNI(res)->array_elements, 1);
>>>>                return 1;
>>>>          case GL_PROGRAM_INPUT:
>>>> @@ -981,23 +1219,23 @@ _mesa_program_resource_prop(struct
>>>> gl_shader_program *shProg,
>>>>             goto invalid_operation;
>>>>          }
>>>>       case GL_OFFSET:
>>>> -      VALIDATE_TYPE(GL_UNIFORM);
>>>> +      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
>>>>          *val = RESOURCE_UNI(res)->offset;
>>>>          return 1;
>>>>       case GL_BLOCK_INDEX:
>>>> -      VALIDATE_TYPE(GL_UNIFORM);
>>>> +      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
>>>>          *val = RESOURCE_UNI(res)->block_index;
>>>>          return 1;
>>>>       case GL_ARRAY_STRIDE:
>>>> -      VALIDATE_TYPE(GL_UNIFORM);
>>>> +      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
>>>>          *val = RESOURCE_UNI(res)->array_stride;
>>>>          return 1;
>>>>       case GL_MATRIX_STRIDE:
>>>> -      VALIDATE_TYPE(GL_UNIFORM);
>>>> +      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
>>>>          *val = RESOURCE_UNI(res)->matrix_stride;
>>>>          return 1;
>>>>       case GL_IS_ROW_MAJOR:
>>>> -      VALIDATE_TYPE(GL_UNIFORM);
>>>> +      VALIDATE_TYPE_2(GL_UNIFORM, GL_BUFFER_VARIABLE);
>>>>          *val = RESOURCE_UNI(res)->row_major;
>>>>          return 1;
>>>>       case GL_ATOMIC_COUNTER_BUFFER_INDEX:
>>>> @@ -1021,6 +1259,8 @@ _mesa_program_resource_prop(struct
>>>> gl_shader_program *shProg,
>>>>          case GL_PROGRAM_INPUT:
>>>>          case GL_PROGRAM_OUTPUT:
>>>>          case GL_UNIFORM_BLOCK:
>>>> +      case GL_BUFFER_VARIABLE:
>>>> +      case GL_SHADER_STORAGE_BLOCK:
>>>>          case GL_ATOMIC_COUNTER_BUFFER:
>>>>             *val = is_resource_referenced(shProg, res, index,
>>>>                                           stage_from_enum(prop));
>>>> @@ -1045,6 +1285,17 @@ _mesa_program_resource_prop(struct
>>>> gl_shader_program *shProg,
>>>>          *val = RESOURCE_VAR(res)->data.index;
>>>>          return 1;
>>>>
>>>> +   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));
>>>> +      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));
>>>> +      return 1;
>>>>       /* GL_ARB_tessellation_shader */
>>>>       case GL_IS_PER_PATCH:
>>>>       case GL_REFERENCED_BY_TESS_CONTROL_SHADER:
>>>>
>>> _______________________________________________
>>> mesa-dev mailing list
>>> mesa-dev at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list