glsl: fix shader storage block member rules when adding program resources
authorSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Wed, 21 Oct 2015 07:46:48 +0000 (09:46 +0200)
committerSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Fri, 23 Oct 2015 11:12:43 +0000 (13:12 +0200)
Commit f24e5e did not take into account arrays of named shader
storage blocks.

Fixes 20 dEQP-GLES31.functional.ssbo.* tests:

dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.shared_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.packed_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.std140_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.per_block_buffer.std430_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.single_buffer.shared_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.single_buffer.packed_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.single_buffer.std140_instance_array
dEQP-GLES31.functional.ssbo.layout.single_struct_array.single_buffer.std430_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.shared_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.packed_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.std140_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.per_block_buffer.std430_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.single_buffer.shared_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.single_buffer.packed_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.single_buffer.std140_instance_array
dEQP-GLES31.functional.ssbo.layout.single_nested_struct_array.single_buffer.std430_instance_array
dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.2
dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.29
dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.33
dEQP-GLES31.functional.ssbo.layout.random.all_shared_buffer.3

V2:
- Rename some variables (Timothy)

Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
src/glsl/linker.cpp

index 07ea0e0c7e56e918d7702372c73aa45464246b8f..424b92a1783b9a7bf4c5aab271a25ad695d2aa01 100644 (file)
@@ -3137,7 +3137,8 @@ should_add_buffer_variable(struct gl_shader_program *shProg,
                            GLenum type, const char *name)
 {
    bool found_interface = false;
-   const char *block_name = NULL;
+   unsigned block_name_len = 0;
+   const char *block_name_dot = strchr(name, '.');
 
    /* These rules only apply to buffer variables. So we return
     * true for the rest of types.
@@ -3146,8 +3147,28 @@ should_add_buffer_variable(struct gl_shader_program *shProg,
       return true;
 
    for (unsigned i = 0; i < shProg->NumBufferInterfaceBlocks; i++) {
-      block_name = shProg->BufferInterfaceBlocks[i].Name;
-      if (strncmp(block_name, name, strlen(block_name)) == 0) {
+      const char *block_name = shProg->BufferInterfaceBlocks[i].Name;
+      block_name_len = strlen(block_name);
+
+      const char *block_square_bracket = strchr(block_name, '[');
+      if (block_square_bracket) {
+         /* The block is part of an array of named interfaces,
+          * for the name comparison we ignore the "[x]" part.
+          */
+         block_name_len -= strlen(block_square_bracket);
+      }
+
+      if (block_name_dot) {
+         /* Check if the variable name starts with the interface
+          * name. The interface name (if present) should have the
+          * length than the interface block name we are comparing to.
+          */
+         unsigned len = strlen(name) - strlen(block_name_dot);
+         if (len != block_name_len)
+            continue;
+      }
+
+      if (strncmp(block_name, name, block_name_len) == 0) {
          found_interface = true;
          break;
       }
@@ -3157,7 +3178,7 @@ should_add_buffer_variable(struct gl_shader_program *shProg,
     * including the dot that follows it.
     */
    if (found_interface)
-      name = name + strlen(block_name) + 1;
+      name = name + block_name_len + 1;
 
    /* From: ARB_program_interface_query extension:
     *
@@ -3166,14 +3187,14 @@ should_add_buffer_variable(struct gl_shader_program *shProg,
     *   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 *struct_first_dot = strchr(name, '.');
    const char *first_square_bracket = strchr(name, '[');
 
    /* The buffer variable is on top level and it is not an array */
    if (!first_square_bracket) {
       return true;
    /* The shader storage block member is a struct, then generate the entry */
-   } else if (first_dot && first_dot < first_square_bracket) {
+   } else if (struct_first_dot && struct_first_dot < first_square_bracket) {
       return true;
    } else {
       /* Shader storage block member is an array, only generate an entry for the