aboutsummaryrefslogtreecommitdiffstats
path: root/src/glsl
diff options
context:
space:
mode:
authorPaul Berry <[email protected]>2013-10-21 21:09:47 -0700
committerPaul Berry <[email protected]>2013-10-24 22:01:19 -0700
commita49830b8f549c93cf92298048ffe00f931e0525d (patch)
treef222d584074dfbb57f580708ce5a6f75f5e08989 /src/glsl
parent4b97c581b4f85e1712c7900cb099c9d56babb05d (diff)
glsl: Account for interface block lowering in program_resource_visitor.
When program_resource_visitor visits variables that were created by lower_named_interface_blocks, it needs to do extra work to un-do the effects of lower_named_interface_blocks and construct the proper API names. Fixes piglit test spec/glsl-1.50/execution/interface-blocks-api-access-members. Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Ian Romanick <[email protected]> Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/link_uniforms.cpp58
1 files changed, 57 insertions, 1 deletions
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
index 4bd4034a0d6..ea71b3063ca 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -75,7 +75,63 @@ program_resource_visitor::process(ir_variable *var)
*/
/* Only strdup the name if we actually will need to modify it. */
- if (t->is_record() || (t->is_array() && t->fields.array->is_record())) {
+ if (var->from_named_ifc_block_array) {
+ /* lower_named_interface_blocks created this variable by lowering an
+ * interface block array to an array variable. For example if the
+ * original source code was:
+ *
+ * out Blk { vec4 bar } foo[3];
+ *
+ * Then the variable is now:
+ *
+ * out vec4 bar[3];
+ *
+ * We need to visit each array element using the names constructed like
+ * so:
+ *
+ * Blk[0].bar
+ * Blk[1].bar
+ * Blk[2].bar
+ */
+ assert(t->is_array());
+ const glsl_type *ifc_type = var->get_interface_type();
+ char *name = ralloc_strdup(NULL, ifc_type->name);
+ size_t name_length = strlen(name);
+ for (unsigned i = 0; i < t->length; i++) {
+ size_t new_length = name_length;
+ ralloc_asprintf_rewrite_tail(&name, &new_length, "[%u].%s", i,
+ var->name);
+ /* Note: row_major is only meaningful for uniform blocks, and
+ * lowering is only applied to non-uniform interface blocks, so we
+ * can safely pass false for row_major.
+ */
+ recursion(var->type, &name, new_length, false, NULL);
+ }
+ ralloc_free(name);
+ } else if (var->from_named_ifc_block_nonarray) {
+ /* lower_named_interface_blocks created this variable by lowering a
+ * named interface block (non-array) to an ordinary variable. For
+ * example if the original source code was:
+ *
+ * out Blk { vec4 bar } foo;
+ *
+ * Then the variable is now:
+ *
+ * out vec4 bar;
+ *
+ * We need to visit this variable using the name:
+ *
+ * Blk.bar
+ */
+ const glsl_type *ifc_type = var->get_interface_type();
+ char *name = ralloc_asprintf(NULL, "%s.%s", ifc_type->name, var->name);
+ /* Note: row_major is only meaningful for uniform blocks, and lowering
+ * is only applied to non-uniform interface blocks, so we can safely
+ * pass false for row_major.
+ */
+ recursion(var->type, &name, strlen(name), false, NULL);
+ ralloc_free(name);
+ } else if (t->is_record() || (t->is_array() && t->fields.array->is_record())) {
char *name = ralloc_strdup(NULL, var->name);
recursion(var->type, &name, strlen(name), false, NULL);
ralloc_free(name);