[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