[Mesa-dev] [RFC 1/4] glsl IR: add always_active_io attribute to ir_variable
Gregory Hainaut
gregory.hainaut at gmail.com
Sun Oct 25 07:01:34 PDT 2015
The value will be set in separate-shader program when an input/output
must remains active (i.e. deadcode removal isn't allowed because it will create
interface location/name-matching mismatch)
v3:
* Rename the attribute
* Use ir_variable directly instead of ir_variable_refcount_visitor
* Move the foreach IR code in the linker file
v4:
* Fix variable name in assert
Signed-off-by: Gregory Hainaut <gregory.hainaut at gmail.com>
---
src/glsl/ir.cpp | 1 +
src/glsl/ir.h | 7 +++++
src/glsl/linker.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+)
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index 8933b23..0c1430b 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1666,6 +1666,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
this->data.pixel_center_integer = false;
this->data.depth_layout = ir_depth_layout_none;
this->data.used = false;
+ this->data.always_active_io = false;
this->data.read_only = false;
this->data.centroid = false;
this->data.sample = false;
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 9c9f22d..0223665 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -658,6 +658,13 @@ public:
unsigned assigned:1;
/**
+ * When separate shader programs are enabled, only interstage
+ * variables can be safely removed of the shader interface. Others
+ * input/output must remains active.
+ */
+ unsigned always_active_io:1;
+
+ /**
* Enum indicating how the variable was declared. See
* ir_var_declaration_type.
*
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 424b92a..8455555 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -3896,6 +3896,70 @@ split_ubos_and_ssbos(void *mem_ctx,
assert(*num_ubos + *num_ssbos == num_blocks);
}
+static void
+ir_set_always_active_io(exec_list *ir, ir_variable_mode io_mode)
+{
+ assert(io_mode == ir_var_shader_in || io_mode == ir_var_shader_out);
+
+ foreach_in_list(ir_instruction, node, ir) {
+ ir_variable *const var = node->as_variable();
+
+ if (var == NULL || var->data.mode != io_mode)
+ continue;
+
+ var->data.always_active_io = true;
+ }
+}
+
+static void
+set_always_active_io(struct gl_shader_program *prog)
+{
+ unsigned first, last;
+ assert(prog->SeparateShader);
+
+ first = MESA_SHADER_STAGES;
+ last = 0;
+
+ /* Determine first and last stage. Excluding the compute stage */
+ for (unsigned i = 0; i < MESA_SHADER_COMPUTE; i++) {
+ if (!prog->_LinkedShaders[i])
+ continue;
+ if (first == MESA_SHADER_STAGES)
+ first = i;
+ last = i;
+ }
+
+ if (first == MESA_SHADER_STAGES)
+ return;
+
+ for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+ gl_shader *sh = prog->_LinkedShaders[stage];
+ if (!sh)
+ continue;
+
+ if (first == last) {
+ /* Single shader program: allowed inactive variable
+ * 1/ input of the VS
+ * 2/ output of the FS
+ */
+ if (stage != MESA_SHADER_VERTEX)
+ ir_set_always_active_io(sh->ir, ir_var_shader_in);
+ if (stage != MESA_SHADER_FRAGMENT)
+ ir_set_always_active_io(sh->ir, ir_var_shader_out);
+ } else {
+ /* Multiple shaders program: allowed inactive variable
+ * 1/ input of the VS
+ * 2/ output of the FS
+ * 3/ interstage variables
+ */
+ if (stage == first && stage != MESA_SHADER_VERTEX)
+ ir_set_always_active_io(sh->ir, ir_var_shader_in);
+ else if (stage == last && stage != MESA_SHADER_FRAGMENT)
+ ir_set_always_active_io(sh->ir, ir_var_shader_out);
+ }
+ }
+}
+
void
link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
{
@@ -4155,6 +4219,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
}
}
+
+ /**
+ * When separate shader programs are enabled, only interstage
+ * variables can be safely removed of the shader interface. Others
+ * input/output must remains active.
+ */
+ if (prog->SeparateShader)
+ set_always_active_io(prog);
+
if (!interstage_cross_validate_uniform_blocks(prog))
goto done;
--
2.1.4
More information about the mesa-dev
mailing list