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 <sigles...@igalia.com>

Including TOP_LEVEL_ARRAY_SIZE and TOP_LEVEL_ARRAY_STRIDE
queries.

Signed-off-by: Samuel Iglesias Gonsalvez <sigles...@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.pa...@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@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to