Mesa (master): glsl: Fix interstage uniform interface block link error detection.
Paul Berry
stereotype441 at kemper.freedesktop.org
Thu Nov 21 23:25:32 UTC 2013
Module: Mesa
Branch: master
Commit: 544e3129c5addeb6c9539339782dd54616ef0499
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=544e3129c5addeb6c9539339782dd54616ef0499
Author: Paul Berry <stereotype441 at gmail.com>
Date: Fri Nov 15 14:23:45 2013 -0800
glsl: Fix interstage uniform interface block link error detection.
Previously, we checked for interstage uniform interface block link
errors in validate_interstage_interface_blocks(), which is only called
on pairs of adjacent shader stages. Therefore, we failed to detect
uniform interface block mismatches between non-adjacent shader stages.
Before the introduction of geometry shaders, this wasn't a problem,
because the only supported shader stages were vertex and fragment
shaders, therefore they were always adjacent. However, now that we
allow a program to contain vertex, geometry, and fragment shaders,
that is no longer the case.
Fixes piglit test "skip-stage-uniform-block-array-size-mismatch".
Cc: "10.0" <mesa-stable at lists.freedesktop.org>
v2: Rename validate_interstage_interface_blocks() to
validate_interstage_inout_blocks() to reflect the fact that it no
longer validates uniform blocks.
Reviewed-by: Jordan Justen <jordan.l.justen at intel.com>
v3: Make validate_interstage_inout_blocks() skip uniform blocks.
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
---
src/glsl/link_interface_blocks.cpp | 75 +++++++++++++++++++++++-------------
src/glsl/linker.cpp | 9 +++-
src/glsl/linker.h | 10 +++-
3 files changed, 62 insertions(+), 32 deletions(-)
diff --git a/src/glsl/link_interface_blocks.cpp b/src/glsl/link_interface_blocks.cpp
index 528d4a1..6900fa9 100644
--- a/src/glsl/link_interface_blocks.cpp
+++ b/src/glsl/link_interface_blocks.cpp
@@ -308,57 +308,78 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
}
void
-validate_interstage_interface_blocks(struct gl_shader_program *prog,
- const gl_shader *producer,
- const gl_shader *consumer)
+validate_interstage_inout_blocks(struct gl_shader_program *prog,
+ const gl_shader *producer,
+ const gl_shader *consumer)
{
- interface_block_definitions inout_interfaces;
- interface_block_definitions uniform_interfaces;
+ interface_block_definitions definitions;
const bool extra_array_level = consumer->Type == GL_GEOMETRY_SHADER;
- /* Add non-output interfaces from the consumer to the symbol table. */
+ /* Add input interfaces from the consumer to the symbol table. */
foreach_list(node, consumer->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
- if (!var || !var->get_interface_type() || var->mode == ir_var_shader_out)
+ if (!var || !var->get_interface_type() || var->mode != ir_var_shader_in)
continue;
- interface_block_definitions *definitions = var->mode == ir_var_uniform ?
- &uniform_interfaces : &inout_interfaces;
- definitions->store(interface_block_definition(var));
+ definitions.store(interface_block_definition(var));
}
- /* Verify that the producer's interfaces match. */
+ /* Verify that the producer's output interfaces match. */
foreach_list(node, producer->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
- if (!var || !var->get_interface_type() || var->mode == ir_var_shader_in)
+ if (!var || !var->get_interface_type() || var->mode != ir_var_shader_out)
continue;
- interface_block_definitions *definitions = var->mode == ir_var_uniform ?
- &uniform_interfaces : &inout_interfaces;
interface_block_definition *consumer_def =
- definitions->lookup(var->get_interface_type()->name);
+ definitions.lookup(var->get_interface_type()->name);
/* The consumer doesn't use this output block. Ignore it. */
if (consumer_def == NULL)
continue;
const interface_block_definition producer_def(var);
- bool match;
- if (var->mode == ir_var_uniform) {
- /* Uniform matching rules are the same for interstage and intrastage
- * linking.
- */
- match = intrastage_match(consumer_def, &producer_def,
- (ir_variable_mode) var->mode);
- } else {
- match = interstage_match(&producer_def, consumer_def,
- extra_array_level);
- }
- if (!match) {
+ if (!interstage_match(&producer_def, consumer_def, extra_array_level)) {
linker_error(prog, "definitions of interface block `%s' do not "
"match\n", var->get_interface_type()->name);
return;
}
}
}
+
+
+void
+validate_interstage_uniform_blocks(struct gl_shader_program *prog,
+ gl_shader **stages, int num_stages)
+{
+ interface_block_definitions definitions;
+
+ for (int i = 0; i < num_stages; i++) {
+ if (stages[i] == NULL)
+ continue;
+
+ const gl_shader *stage = stages[i];
+ foreach_list(node, stage->ir) {
+ ir_variable *var = ((ir_instruction *) node)->as_variable();
+ if (!var || !var->get_interface_type() || var->mode != ir_var_uniform)
+ continue;
+
+ interface_block_definition *old_def =
+ definitions.lookup(var->get_interface_type()->name);
+ const interface_block_definition new_def(var);
+ if (old_def == NULL) {
+ definitions.store(new_def);
+ } else {
+ /* Interstage uniform matching rules are the same as intrastage
+ * uniform matchin rules (for uniforms, it is as though all
+ * shaders are in the same shader stage).
+ */
+ if (!intrastage_match(old_def, &new_def, ir_var_uniform)) {
+ linker_error(prog, "definitions of interface block `%s' do not "
+ "match\n", var->get_interface_type()->name);
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 1d53b65..fac186a 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -2154,8 +2154,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
if (prog->_LinkedShaders[i] == NULL)
continue;
- validate_interstage_interface_blocks(prog, prog->_LinkedShaders[prev],
- prog->_LinkedShaders[i]);
+ validate_interstage_inout_blocks(prog, prog->_LinkedShaders[prev],
+ prog->_LinkedShaders[i]);
if (!prog->LinkStatus)
goto done;
@@ -2168,6 +2168,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
prev = i;
}
+ /* Cross-validate uniform blocks between shader stages */
+ validate_interstage_uniform_blocks(prog, prog->_LinkedShaders,
+ MESA_SHADER_TYPES);
+ if (!prog->LinkStatus)
+ goto done;
for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
if (prog->_LinkedShaders[i] != NULL)
diff --git a/src/glsl/linker.h b/src/glsl/linker.h
index 7b1f6f9..130915d 100644
--- a/src/glsl/linker.h
+++ b/src/glsl/linker.h
@@ -65,9 +65,13 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
unsigned num_shaders);
void
-validate_interstage_interface_blocks(struct gl_shader_program *prog,
- const gl_shader *producer,
- const gl_shader *consumer);
+validate_interstage_inout_blocks(struct gl_shader_program *prog,
+ const gl_shader *producer,
+ const gl_shader *consumer);
+
+void
+validate_interstage_uniform_blocks(struct gl_shader_program *prog,
+ gl_shader **stages, int num_stages);
extern void
link_assign_atomic_counter_resources(struct gl_context *ctx,
More information about the mesa-commit
mailing list