[Mesa-dev] [PATCH 2/3] glsl: move update_uniform_buffer_variables() to lower UBO

Timothy Arceri timothy.arceri at collabora.com
Thu Dec 29 02:40:01 UTC 2016


This make more sense here as its lowering that uses the results of
this function.

This allows us to call lower_ubo_reference() before assigning uniform
locations which will be useful for converting to earlier NIR and
performing optimisations before assigning uniform locations.
---
 src/compiler/glsl/link_uniforms.cpp       | 126 ------------------------------
 src/compiler/glsl/linker.cpp              |  16 +++-
 src/compiler/glsl/lower_ubo_reference.cpp | 126 ++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+), 130 deletions(-)

diff --git a/src/compiler/glsl/link_uniforms.cpp b/src/compiler/glsl/link_uniforms.cpp
index e2e8dd1..e4275fd 100644
--- a/src/compiler/glsl/link_uniforms.cpp
+++ b/src/compiler/glsl/link_uniforms.cpp
@@ -868,130 +868,6 @@ public:
    unsigned shader_shadow_samplers;
 };
 
-static bool
-variable_is_referenced(ir_array_refcount_visitor &v, ir_variable *var)
-{
-   ir_array_refcount_entry *const entry = v.get_variable_entry(var);
-
-   return entry->is_referenced;
-
-}
-
-/**
- * Walks the IR and update the references to uniform blocks in the
- * ir_variables to point at linked shader's list (previously, they
- * would point at the uniform block list in one of the pre-linked
- * shaders).
- */
-static void
-link_update_uniform_buffer_variables(struct gl_linked_shader *shader,
-                                     unsigned stage)
-{
-   ir_array_refcount_visitor v;
-
-   v.run(shader->ir);
-
-   foreach_in_list(ir_instruction, node, shader->ir) {
-      ir_variable *const var = node->as_variable();
-
-      if (var == NULL || !var->is_in_buffer_block())
-         continue;
-
-      assert(var->data.mode == ir_var_uniform ||
-             var->data.mode == ir_var_shader_storage);
-
-      unsigned num_blocks = var->data.mode == ir_var_uniform ?
-         shader->Program->info.num_ubos : shader->Program->info.num_ssbos;
-      struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ?
-         shader->Program->sh.UniformBlocks :
-         shader->Program->sh.ShaderStorageBlocks;
-
-      if (var->is_interface_instance()) {
-         const ir_array_refcount_entry *const entry = v.get_variable_entry(var);
-
-         if (entry->is_referenced) {
-            /* Since this is an interface instance, the instance type will be
-             * same as the array-stripped variable type.  If the variable type
-             * is an array, then the block names will be suffixed with [0]
-             * through [n-1].  Unlike for non-interface instances, there will
-             * not be structure types here, so the only name sentinel that we
-             * have to worry about is [.
-             */
-            assert(var->type->without_array() == var->get_interface_type());
-            const char sentinel = var->type->is_array() ? '[' : '\0';
-
-            const ptrdiff_t len = strlen(var->get_interface_type()->name);
-            for (unsigned i = 0; i < num_blocks; i++) {
-               const char *const begin = blks[i]->Name;
-               const char *const end = strchr(begin, sentinel);
-
-               if (end == NULL)
-                  continue;
-
-               if (len != (end - begin))
-                  continue;
-
-               /* Even when a match is found, do not "break" here.  This could
-                * be an array of instances, and all elements of the array need
-                * to be marked as referenced.
-                */
-               if (strncmp(begin, var->get_interface_type()->name, len) == 0 &&
-                   (!var->type->is_array() ||
-                    entry->is_linearized_index_referenced(blks[i]->linearized_array_index))) {
-                  blks[i]->stageref |= 1U << stage;
-               }
-            }
-         }
-
-         var->data.location = 0;
-         continue;
-      }
-
-      bool found = false;
-      char sentinel = '\0';
-
-      if (var->type->is_record()) {
-         sentinel = '.';
-      } else if (var->type->is_array() && (var->type->fields.array->is_array()
-                 || var->type->without_array()->is_record())) {
-         sentinel = '[';
-      }
-
-      const unsigned l = strlen(var->name);
-      for (unsigned i = 0; i < num_blocks; i++) {
-         for (unsigned j = 0; j < blks[i]->NumUniforms; j++) {
-            if (sentinel) {
-               const char *begin = blks[i]->Uniforms[j].Name;
-               const char *end = strchr(begin, sentinel);
-
-               if (end == NULL)
-                  continue;
-
-               if ((ptrdiff_t) l != (end - begin))
-                  continue;
-
-               found = strncmp(var->name, begin, l) == 0;
-            } else {
-               found = strcmp(var->name, blks[i]->Uniforms[j].Name) == 0;
-            }
-
-            if (found) {
-               var->data.location = j;
-
-               if (variable_is_referenced(v, var))
-                  blks[i]->stageref |= 1U << stage;
-
-               break;
-            }
-         }
-
-         if (found)
-            break;
-      }
-      assert(found);
-   }
-}
-
 /**
  * Combine the hidden uniform hash map with the uniform hash map so that the
  * hidden uniforms will be given indicies at the end of the uniform storage
@@ -1320,8 +1196,6 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
       if (sh == NULL)
          continue;
 
-      link_update_uniform_buffer_variables(sh, i);
-
       /* Reset various per-shader target counts.
        */
       uniform_size.start_shader();
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index d7ed436..fa1062e 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -4619,6 +4619,18 @@ link_varyings_and_uniforms(unsigned first, unsigned last,
          return false;
    }
 
+   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+         continue;
+
+      const struct gl_shader_compiler_options *options =
+         &ctx->Const.ShaderCompilerOptions[i];
+
+      if (options->LowerBufferInterfaceBlocks)
+         lower_ubo_reference(prog->_LinkedShaders[i],
+                             options->ClampBlockIndicesToArrayBounds);
+   }
+
    /* If there is no fragment shader we need to set transform feedback.
     *
     * For SSO we also need to assign output locations.  We assign them here
@@ -4740,10 +4752,6 @@ link_varyings_and_uniforms(unsigned first, unsigned last,
       const struct gl_shader_compiler_options *options =
          &ctx->Const.ShaderCompilerOptions[i];
 
-      if (options->LowerBufferInterfaceBlocks)
-         lower_ubo_reference(prog->_LinkedShaders[i],
-                             options->ClampBlockIndicesToArrayBounds);
-
       if (i == MESA_SHADER_COMPUTE)
          lower_shared_reference(prog->_LinkedShaders[i],
                                 &prog->Comp.SharedSize);
diff --git a/src/compiler/glsl/lower_ubo_reference.cpp b/src/compiler/glsl/lower_ubo_reference.cpp
index bfaddac..8d10dcb 100644
--- a/src/compiler/glsl/lower_ubo_reference.cpp
+++ b/src/compiler/glsl/lower_ubo_reference.cpp
@@ -35,6 +35,7 @@
 
 #include "lower_buffer_access.h"
 #include "ir_builder.h"
+#include "ir_array_refcount.h"
 #include "main/macros.h"
 #include "glsl_parser_extras.h"
 
@@ -1092,9 +1093,134 @@ lower_ubo_reference_visitor::visit_enter(ir_call *ir)
 
 } /* unnamed namespace */
 
+static bool
+variable_is_referenced(ir_array_refcount_visitor &v, ir_variable *var)
+{
+   ir_array_refcount_entry *const entry = v.get_variable_entry(var);
+
+   return entry->is_referenced;
+
+}
+
+/**
+ * Walks the IR and update the references to uniform blocks in the
+ * ir_variables to point at linked shader's list (previously, they
+ * would point at the uniform block list in one of the pre-linked
+ * shaders).
+ */
+static void
+update_uniform_buffer_variables(struct gl_linked_shader *shader)
+{
+   ir_array_refcount_visitor v;
+
+   v.run(shader->ir);
+
+   foreach_in_list(ir_instruction, node, shader->ir) {
+      ir_variable *const var = node->as_variable();
+
+      if (var == NULL || !var->is_in_buffer_block())
+         continue;
+
+      assert(var->data.mode == ir_var_uniform ||
+             var->data.mode == ir_var_shader_storage);
+
+      unsigned num_blocks = var->data.mode == ir_var_uniform ?
+         shader->Program->info.num_ubos : shader->Program->info.num_ssbos;
+      struct gl_uniform_block **blks = var->data.mode == ir_var_uniform ?
+         shader->Program->sh.UniformBlocks :
+         shader->Program->sh.ShaderStorageBlocks;
+
+      if (var->is_interface_instance()) {
+         const ir_array_refcount_entry *const entry = v.get_variable_entry(var);
+
+         if (entry->is_referenced) {
+            /* Since this is an interface instance, the instance type will be
+             * same as the array-stripped variable type.  If the variable type
+             * is an array, then the block names will be suffixed with [0]
+             * through [n-1].  Unlike for non-interface instances, there will
+             * not be structure types here, so the only name sentinel that we
+             * have to worry about is [.
+             */
+            assert(var->type->without_array() == var->get_interface_type());
+            const char sentinel = var->type->is_array() ? '[' : '\0';
+
+            const ptrdiff_t len = strlen(var->get_interface_type()->name);
+            for (unsigned i = 0; i < num_blocks; i++) {
+               const char *const begin = blks[i]->Name;
+               const char *const end = strchr(begin, sentinel);
+
+               if (end == NULL)
+                  continue;
+
+               if (len != (end - begin))
+                  continue;
+
+               /* Even when a match is found, do not "break" here.  This could
+                * be an array of instances, and all elements of the array need
+                * to be marked as referenced.
+                */
+               if (strncmp(begin, var->get_interface_type()->name, len) == 0 &&
+                   (!var->type->is_array() ||
+                    entry->is_linearized_index_referenced(blks[i]->linearized_array_index))) {
+                  blks[i]->stageref |= 1U << shader->Stage;
+               }
+            }
+         }
+
+         var->data.location = 0;
+         continue;
+      }
+
+      bool found = false;
+      char sentinel = '\0';
+
+      if (var->type->is_record()) {
+         sentinel = '.';
+      } else if (var->type->is_array() && (var->type->fields.array->is_array()
+                 || var->type->without_array()->is_record())) {
+         sentinel = '[';
+      }
+
+      const unsigned l = strlen(var->name);
+      for (unsigned i = 0; i < num_blocks; i++) {
+         for (unsigned j = 0; j < blks[i]->NumUniforms; j++) {
+            if (sentinel) {
+               const char *begin = blks[i]->Uniforms[j].Name;
+               const char *end = strchr(begin, sentinel);
+
+               if (end == NULL)
+                  continue;
+
+               if ((ptrdiff_t) l != (end - begin))
+                  continue;
+
+               found = strncmp(var->name, begin, l) == 0;
+            } else {
+               found = strcmp(var->name, blks[i]->Uniforms[j].Name) == 0;
+            }
+
+            if (found) {
+               var->data.location = j;
+
+               if (variable_is_referenced(v, var))
+                  blks[i]->stageref |= 1U << shader->Stage;
+
+               break;
+            }
+         }
+
+         if (found)
+            break;
+      }
+      assert(found);
+   }
+}
+
 void
 lower_ubo_reference(struct gl_linked_shader *shader, bool clamp_block_indices)
 {
+   update_uniform_buffer_variables(shader);
+
    lower_ubo_reference_visitor v(shader, clamp_block_indices);
 
    /* Loop over the instructions lowering references, because we take
-- 
2.9.3



More information about the mesa-dev mailing list