[Mesa-dev] [RFC 1/4] glsl IR: add always_active_io attribute to ir_variable

Gregory Hainaut gregory.hainaut at gmail.com
Tue Oct 13 13:22:04 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

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 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



More information about the mesa-dev mailing list