mesa/main: Fix UBO/SSBO ACTIVE_VARIABLES query (ARB_gl_spirv)
authorAntia Puentes <apuentes@igalia.com>
Tue, 18 Dec 2018 10:55:04 +0000 (11:55 +0100)
committerAlejandro Piñeiro <apinheiro@igalia.com>
Fri, 12 Jul 2019 21:42:41 +0000 (23:42 +0200)
When querying MAX_NUM_ACTIVE_VARIABLES, NUM_ACTIVE_VARIABLES and
ACTIVE_VARIABLES over SSBO and UBO interfaces, we filter the variables
which are active using the variable's name and looking for it in the
program resource list. If it is in the program resource list, the
variable will be considered active.

However due to ARB_gl_spirv where name reflection information is not
mandatory, we can use the UBO/SSBO binding and variable offset to
filter which variables which are active.

v2: use RESOURCE_UBO/UNI macros instead of direct castings, update
    comment (Alejandro)

v3: Change signature of _mesa_program_resource_find_active_variable
    to simplify calling it. Also, squash the fix for find_binding_offset
    for arrays of blocks (Arcady)

Signed-off-by: Antia Puentes <apuentes@igalia.com>
Signed-off-by: Alejandro Piñeiro <apinheiro@igalia.com>
Signed-off-by: Arcady Goldmints-Orlov <agoldmints@igalia.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/mesa/main/program_resource.c
src/mesa/main/shader_query.cpp
src/mesa/main/shaderapi.h

index fedd1f183ceb756a61aa919e6de6d02afa0836e1..c85988d21ffa9ebaa6a5a783931c1518da25fe29 100644 (file)
@@ -164,10 +164,12 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
                   shProg->data->ProgramResourceList[i].Data;
                GLint block_params = 0;
                for (unsigned j = 0; j < block->NumUniforms; j++) {
-                  const char *iname = block->Uniforms[j].IndexName;
                   struct gl_program_resource *uni =
-                     _mesa_program_resource_find_name(shProg, GL_BUFFER_VARIABLE,
-                                                      iname, NULL);
+                     _mesa_program_resource_find_active_variable(
+                        shProg,
+                        GL_BUFFER_VARIABLE,
+                        block,
+                        j);
                   if (!uni)
                      continue;
                   block_params++;
index e9b39b7ff8f496425741caaf11f2f663e5c11225..000e2a16ea7787f017410a3627a41d2304bf7edc 100644 (file)
@@ -638,6 +638,119 @@ _mesa_program_resource_find_name(struct gl_shader_program *shProg,
    return NULL;
 }
 
+/* Find an uniform or buffer variable program resource with an specific offset
+ * inside a block with an specific binding.
+ *
+ * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
+ */
+static struct gl_program_resource *
+program_resource_find_binding_offset(struct gl_shader_program *shProg,
+                                     GLenum programInterface,
+                                     const GLuint binding,
+                                     const GLint offset)
+{
+
+   /* First we need to get the BLOCK_INDEX from the BUFFER_BINDING */
+   GLenum blockInterface;
+
+   switch (programInterface) {
+   case GL_BUFFER_VARIABLE:
+      blockInterface = GL_SHADER_STORAGE_BLOCK;
+      break;
+   case GL_UNIFORM:
+      blockInterface = GL_UNIFORM_BLOCK;
+      break;
+   default:
+      assert("Invalid program interface");
+      return NULL;
+   }
+
+   int block_index = -1;
+   int starting_index = -1;
+   struct gl_program_resource *res = shProg->data->ProgramResourceList;
+
+   /* Blocks are added to the resource list in the same order that they are
+    * added to UniformBlocks/ShaderStorageBlocks. Furthermore, all the blocks
+    * of each type (UBO/SSBO) are contiguous, so we can infer block_index from
+    * the resource list.
+    */
+   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
+      if (res->Type != blockInterface)
+         continue;
+
+      /* Store the first index where a resource of the specific interface is. */
+      if (starting_index == -1)
+         starting_index = i;
+
+      const struct gl_uniform_block *block = RESOURCE_UBO(res);
+
+      if (block->Binding == binding) {
+         /* For arrays, or arrays of arrays of blocks, we want the resource
+          * for the block with base index. Most properties for members of each
+          * block are inherited from the block with the base index, including
+          * a uniform being active or not.
+          */
+         block_index = i - starting_index - block->linearized_array_index;
+         break;
+      }
+   }
+
+   if (block_index == -1)
+      return NULL;
+
+   /* We now look for the resource corresponding to the uniform or buffer
+    * variable using the BLOCK_INDEX and OFFSET.
+    */
+   res = shProg->data->ProgramResourceList;
+   for (unsigned i = 0; i < shProg->data->NumProgramResourceList; i++, res++) {
+      if (res->Type != programInterface)
+         continue;
+
+      const struct gl_uniform_storage *uniform = RESOURCE_UNI(res);
+
+      if (uniform->block_index == block_index && uniform->offset == offset) {
+         return res;
+      }
+   }
+
+   return NULL;
+}
+
+/* Checks if an uniform or buffer variable is in the active program resource
+ * list.
+ *
+ * It takes into accout that for variables coming from SPIR-V binaries their
+ * names could not be available (ARB_gl_spirv). In that case, it will use the
+ * the offset and the block binding to locate the resource.
+ *
+ * Valid interfaces are GL_BUFFER_VARIABLE and GL_UNIFORM.
+ */
+struct gl_program_resource *
+_mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
+                                            GLenum programInterface,
+                                            const gl_uniform_block *block,
+                                            unsigned index)
+{
+   struct gl_program_resource *res;
+   struct gl_uniform_buffer_variable uni = block->Uniforms[index];
+
+   assert(programInterface == GL_UNIFORM ||
+          programInterface == GL_BUFFER_VARIABLE);
+
+   if (uni.IndexName) {
+      res = _mesa_program_resource_find_name(shProg, programInterface, uni.IndexName,
+                                             NULL);
+   } else {
+      /* As the resource has no associated name (ARB_gl_spirv),
+       * we can use the UBO/SSBO binding and offset to find it.
+       */
+      res = program_resource_find_binding_offset(shProg, programInterface,
+                                                 block->Binding, uni.Offset);
+   }
+
+   return res;
+}
+
 static GLuint
 calc_resource_index(struct gl_shader_program *shProg,
                     struct gl_program_resource *res)
@@ -1039,10 +1152,13 @@ get_buffer_property(struct gl_shader_program *shProg,
       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_UNIFORM, iname,
-                                                NULL);
+               _mesa_program_resource_find_active_variable(
+                  shProg,
+                  GL_UNIFORM,
+                  RESOURCE_UBO(res),
+                  i);
+
             if (!uni)
                continue;
             (*val)++;
@@ -1051,10 +1167,13 @@ get_buffer_property(struct gl_shader_program *shProg,
       case GL_ACTIVE_VARIABLES: {
          unsigned num_values = 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_UNIFORM, iname,
-                                                NULL);
+               _mesa_program_resource_find_active_variable(
+                  shProg,
+                  GL_UNIFORM,
+                  RESOURCE_UBO(res),
+                  i);
+
             if (!uni)
                continue;
             *val++ =
@@ -1075,10 +1194,13 @@ get_buffer_property(struct gl_shader_program *shProg,
       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, NULL);
+               _mesa_program_resource_find_active_variable(
+                  shProg,
+                  GL_BUFFER_VARIABLE,
+                  RESOURCE_UBO(res),
+                  i);
+
             if (!uni)
                continue;
             (*val)++;
@@ -1087,10 +1209,13 @@ get_buffer_property(struct gl_shader_program *shProg,
       case GL_ACTIVE_VARIABLES: {
          unsigned num_values = 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, NULL);
+               _mesa_program_resource_find_active_variable(
+                  shProg,
+                  GL_BUFFER_VARIABLE,
+                  RESOURCE_UBO(res),
+                  i);
+
             if (!uni)
                continue;
             *val++ =
index a8227ecc969fed642ec45f1e235be8b1e6f5d677..73fa90bbae934e2f3fee53f333ca77fa187945da 100644 (file)
@@ -29,6 +29,7 @@
 
 
 #include "glheader.h"
+#include "main/mtypes.h"
 #include "compiler/shader_enums.h"
 
 #ifdef __cplusplus
@@ -296,6 +297,12 @@ extern struct gl_program_resource *
 _mesa_program_resource_find_index(struct gl_shader_program *shProg,
                                   GLenum programInterface, GLuint index);
 
+extern struct gl_program_resource *
+_mesa_program_resource_find_active_variable(struct gl_shader_program *shProg,
+                                            GLenum programInterface,
+                                            const struct gl_uniform_block *block,
+                                            unsigned index);
+
 extern bool
 _mesa_get_program_resource_name(struct gl_shader_program *shProg,
                                 GLenum programInterface, GLuint index,