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 Signed-off-by: Gregory Hainaut <gregory.hain...@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 2c45b9e..f3f7355 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -1650,6 +1650,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 43a2bf0..a91add9 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 a97b4ef..3a30d0c 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -3599,6 +3599,70 @@ link_assign_subroutine_types(struct gl_shader_program *prog) } } +static void +ir_set_always_active_io(exec_list *ir, ir_variable_mode io_mode) +{ + assert(mode == ir_var_shader_in || 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) { @@ -3858,6 +3922,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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev