From ARB_program_interface_query:

"For an active shader storage block member declared as an array, an
 entry will be generated only for the first array element, regardless
 of its type. For arrays of aggregate types, the enumeration rules are
 applied recursively for the single enumerated array element."

Signed-off-by: Samuel Iglesias Gonsalvez <sigles...@igalia.com>
---
 src/glsl/linker.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index be04f5b..8cc9350 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -3134,6 +3134,57 @@ check_explicit_uniform_locations(struct gl_context *ctx,
 }
 
 static bool
+should_add_buffer_variable(struct gl_shader_program *shProg,
+                           GLenum type, const char *name)
+{
+   bool found_interface = false;
+   const char *block_name = NULL;
+
+   assert(type == GL_BUFFER_VARIABLE);
+
+   for (unsigned i = 0; i < shProg->NumUniformShaderStorageBlocks; i++) {
+      block_name = shProg->UniformBlocks[i].Name;
+      if (strncmp(block_name, name, strlen(block_name)) == 0) {
+         found_interface = true;
+         break;
+      }
+   }
+
+   /* We remove the interface name from the buffer variable name,
+    * including the dot that follows it.
+    */
+   if (found_interface)
+      name = name + strlen(block_name) + 1;
+
+   /* From: ARB_program_interface_query extension:
+    *
+    *  "For an active shader storage block member declared as an array, an
+    *   entry will be generated only for the first array element, regardless
+    *   of its type.  For arrays of aggregate types, the enumeration rules are
+    *   applied recursively for the single enumerated array element.
+    */
+   const char *first_dot = strchr(name, '.');
+   const char *first_square_bracket = strchr(name, '[');
+
+   /* The buffer variable is on top level and it is not an array or struct */
+   if (!first_square_bracket && !first_dot) {
+      return true;
+   /* The shader storage block member is a struct, then generate the entry */
+   } else if ((!first_square_bracket ||
+               (first_dot && first_dot < first_square_bracket))) {
+      return true;
+   } else {
+      /* Shader storage block member is an array, only generate an entry for 
the
+       * first array element.
+       */
+      if (strncmp(first_square_bracket, "[0]", 3) == 0)
+         return true;
+   }
+
+   return false;
+}
+
+static bool
 add_program_resource(struct gl_shader_program *prog, GLenum type,
                      const void *data, uint8_t stages)
 {
@@ -3408,6 +3459,11 @@ build_program_resource_list(struct gl_shader_program 
*shProg)
 
       bool is_shader_storage =  shProg->UniformStorage[i].is_shader_storage;
       GLenum type = is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM;
+      if (is_shader_storage &&
+          !should_add_buffer_variable(shProg, type,
+                                      shProg->UniformStorage[i].name))
+         continue;
+
       if (!add_program_resource(shProg, type,
                                 &shProg->UniformStorage[i], stageref))
          return;
-- 
2.1.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to