[Mesa-dev] [PATCH 3/8] mesa: Add interpolation override bitfields.

Paul Berry stereotype441 at gmail.com
Mon Oct 24 14:38:41 PDT 2011


This patch adds the bitfields InterpOverridesFlat,
InterpOverridesSmooth, and InterpOverridesNoperspective to
gl_fragment_program.  These bitfields keep track of which fragment
shader inputs are overridden with the GLSL "flat", "smooth", and
"noperspective" interpolation qualifiers.

For GLSL fragment shaders, these fields are populated by the
do_set_program_inouts() function.  For non-GLSL fragment programs,
these bitfields are zero.

In addition, there are three new Mesa functions for determining how
fragment shader inputs should be interpolated, taking into account the
current shade model: _mesa_compute_frag_attribs_flat(),
_mesa_compute_frag_attribs_smooth(), and
_mesa_compute_frag_attribs_noperspective().  These functions are
equivalent to ir_variable::determine_interpolation_mode(), except that
they operate on all fragment shader inputs as a bitfield, rather than
a single fragment shader input by itself.
---
 src/glsl/ir.h                              |    3 +-
 src/glsl/ir_set_program_inouts.cpp         |   59 +++++++++++++++----
 src/mesa/main/mtypes.h                     |   83 ++++++++++++++++++++++++++++
 src/mesa/program/ir_to_mesa.cpp            |    2 +-
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp |    2 +-
 5 files changed, 133 insertions(+), 16 deletions(-)

diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 6262369..a9045df 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -1695,7 +1695,8 @@ extern bool
 ir_has_call(ir_instruction *ir);
 
 extern void
-do_set_program_inouts(exec_list *instructions, struct gl_program *prog);
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
+                      bool is_fragment_shader);
 
 extern char *
 prototype_string(const glsl_type *return_type, const char *name,
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
index ae3ef74..b865641 100644
--- a/src/glsl/ir_set_program_inouts.cpp
+++ b/src/glsl/ir_set_program_inouts.cpp
@@ -26,6 +26,10 @@
  *
  * Sets the InputsRead and OutputsWritten of Mesa programs.
  *
+ * Additionally, for fragment shaders, sets the bitfields
+ * InterpOverridesSmooth, InterpOverridesFlat, and
+ * InterpOverridesNoperspective.
+ *
  * Mesa programs (gl_program, not gl_shader_program) have a set of
  * flags indicating which varyings are read and written.  Computing
  * which are actually read from some sort of backend code can be
@@ -42,9 +46,11 @@
 
 class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
 public:
-   ir_set_program_inouts_visitor(struct gl_program *prog)
+   ir_set_program_inouts_visitor(struct gl_program *prog,
+                                 bool is_fragment_shader)
    {
       this->prog = prog;
+      this->is_fragment_shader = is_fragment_shader;
       this->ht = hash_table_ctor(0,
 				 hash_table_pointer_hash,
 				 hash_table_pointer_compare);
@@ -61,10 +67,12 @@ public:
 
    struct gl_program *prog;
    struct hash_table *ht;
+   bool is_fragment_shader;
 };
 
 static void
-mark(struct gl_program *prog, ir_variable *var, int offset, int len)
+mark(struct gl_program *prog, ir_variable *var, int offset, int len,
+     bool is_fragment_shader)
 {
    /* As of GLSL 1.20, varyings can only be floats, floating-point
     * vectors or matrices, or arrays of them.  For Mesa programs using
@@ -75,12 +83,28 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len)
     */
 
    for (int i = 0; i < len; i++) {
-      if (var->mode == ir_var_in)
-	 prog->InputsRead |= BITFIELD64_BIT(var->location + offset + i);
-      else if (var->mode == ir_var_system_value)
-         prog->SystemValuesRead |= (1 << (var->location + offset + i));
-      else
-	 prog->OutputsWritten |= BITFIELD64_BIT(var->location + offset + i);
+      GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i);
+      if (var->mode == ir_var_in) {
+	 prog->InputsRead |= bitfield;
+         if (is_fragment_shader) {
+            gl_fragment_program *fprog = (gl_fragment_program *) prog;
+            switch (var->interpolation) {
+            case ir_var_interp_smooth:
+               fprog->InterpOverridesSmooth |= bitfield;
+               break;
+            case ir_var_interp_flat:
+               fprog->InterpOverridesFlat |= bitfield;
+               break;
+            case ir_var_interp_noperspective:
+               fprog->InterpOverridesNoperspective |= bitfield;
+               break;
+            }
+         }
+      } else if (var->mode == ir_var_system_value) {
+         prog->SystemValuesRead |= bitfield;
+      } else {
+	 prog->OutputsWritten |= bitfield;
+      }
    }
 }
 
@@ -93,9 +117,11 @@ ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
 
    if (ir->type->is_array()) {
       mark(this->prog, ir->var, 0,
-	   ir->type->length * ir->type->fields.array->matrix_columns);
+	   ir->type->length * ir->type->fields.array->matrix_columns,
+           this->is_fragment_shader);
    } else {
-      mark(this->prog, ir->var, 0, ir->type->matrix_columns);
+      mark(this->prog, ir->var, 0, ir->type->matrix_columns,
+           this->is_fragment_shader);
    }
 
    return visit_continue;
@@ -121,7 +147,8 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
 	 width = deref_var->type->fields.array->matrix_columns;
       }
 
-      mark(this->prog, var, index->value.i[0] * width, width);
+      mark(this->prog, var, index->value.i[0] * width, width,
+           this->is_fragment_shader);
       return visit_continue_with_parent;
    }
 
@@ -151,12 +178,18 @@ ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
 }
 
 void
-do_set_program_inouts(exec_list *instructions, struct gl_program *prog)
+do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
+                      bool is_fragment_shader)
 {
-   ir_set_program_inouts_visitor v(prog);
+   ir_set_program_inouts_visitor v(prog, is_fragment_shader);
 
    prog->InputsRead = 0;
    prog->OutputsWritten = 0;
    prog->SystemValuesRead = 0;
+   if (is_fragment_shader) {
+      ((gl_fragment_program *) prog)->InterpOverridesSmooth = 0;
+      ((gl_fragment_program *) prog)->InterpOverridesFlat = 0;
+      ((gl_fragment_program *) prog)->InterpOverridesNoperspective = 0;
+   }
    visit_list_elements(&v, instructions);
 }
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 719dff3..6412c0b 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1890,10 +1890,93 @@ struct gl_fragment_program
    GLboolean OriginUpperLeft;
    GLboolean PixelCenterInteger;
    enum gl_frag_depth_layout FragDepthLayout;
+
+   /**
+    * Bitmask of input regs whose interpolation mode is overridden to "smooth"
+    * in GLSL IR.
+    */
+   GLbitfield64 InterpOverridesSmooth;
+
+   /**
+    * Bitmask of input regs whose interpolation mode is overridden to "flat"
+    * in GLSL IR.
+    */
+   GLbitfield64 InterpOverridesFlat;
+
+   /**
+    * Bitmask of input regs whose interpolation mode is overridden to
+    * "noperspective" in GLSL IR.
+    */
+   GLbitfield64 InterpOverridesNoperspective;
 };
 
 
 /**
+ * Compute a bitfield indicating which fragment shader attributes are to be
+ * flatshaded, based on whether the current state of shade_model is GL_FLAT,
+ * and the bitfields stored in gl_fragment_program.
+ *
+ * Bits cooresponding to fragment shader attributes that are not directly
+ * interpolated from vertex shader outputs (FRAG_BIT_WPOS, FRAG_BIT_FACE, and
+ * FRAG_BIT_PNTC) are always zero.  Bits corresponding to attributes that are
+ * not read by the fragment shader are always zero.
+ */
+static inline GLbitfield64
+_mesa_compute_frag_attribs_flat(GLboolean shade_model_flat,
+                                const struct gl_fragment_program *fprog)
+{
+   GLbitfield64 flat_shaded_attrs = 0;
+   if (shade_model_flat)
+      flat_shaded_attrs |= FRAG_BIT_COL0 | FRAG_BIT_COL1;
+   flat_shaded_attrs &= ~fprog->InterpOverridesSmooth;
+   flat_shaded_attrs |= fprog->InterpOverridesFlat;
+   flat_shaded_attrs &= ~fprog->InterpOverridesNoperspective;
+   return flat_shaded_attrs & fprog->Base.InputsRead;
+}
+
+/**
+ * Compute a bitfield indicating which fragment shader attributes are to be
+ * "smooth" (perspective) shaded, based on whether the current state of
+ * shade_model and the bitfields stored in gl_fragment_program.
+ *
+ * Bits cooresponding to fragment shader attributes that are not directly
+ * interpolated from vertex shader outputs (FRAG_BIT_WPOS, FRAG_BIT_FACE, and
+ * FRAG_BIT_PNTC) are always zero.  Bits corresponding to attributes that are
+ * not read by the fragment shader are always zero.
+ */
+static inline GLbitfield64
+_mesa_compute_frag_attribs_smooth(GLboolean shade_model_flat,
+                                  const struct gl_fragment_program *fprog)
+{
+   GLbitfield64 smooth_shaded_attrs =
+      ~(GLbitfield64) (FRAG_BIT_WPOS | FRAG_BIT_FACE | FRAG_BIT_PNTC);
+   if (shade_model_flat)
+      smooth_shaded_attrs &= ~(GLbitfield64) (FRAG_BIT_COL0 | FRAG_BIT_COL1);
+   smooth_shaded_attrs |= fprog->InterpOverridesSmooth;
+   smooth_shaded_attrs &= ~fprog->InterpOverridesFlat;
+   smooth_shaded_attrs &= ~fprog->InterpOverridesNoperspective;
+   return smooth_shaded_attrs & fprog->Base.InputsRead;
+}
+
+/**
+ * Compute a bitfield indicating which fragment shader attributes are to be
+ * "noperspective" shaded, based on the bitfields stored in
+ * gl_fragment_program.
+ *
+ * Bits cooresponding to fragment shader attributes that are not directly
+ * interpolated from vertex shader outputs (FRAG_BIT_WPOS, FRAG_BIT_FACE, and
+ * FRAG_BIT_PNTC) are always zero.  Bits corresponding to attributes that are
+ * not read by the fragment shader are always zero.
+ */
+static inline GLbitfield64
+_mesa_compute_frag_attribs_noperspective(const struct gl_fragment_program *
+                                         fprog)
+{
+   return fprog->InterpOverridesNoperspective & fprog->Base.InputsRead;
+}
+
+
+/**
  * State common to vertex and fragment programs.
  */
 struct gl_program_state
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index fecab50..0331ecb 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -3165,7 +3165,7 @@ get_mesa_program(struct gl_context *ctx,
    prog->Instructions = mesa_instructions;
    prog->NumInstructions = num_instructions;
 
-   do_set_program_inouts(shader->ir, prog);
+   do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER);
    count_resources(prog);
 
    check_resources(ctx, shader_program, prog);
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 35fd1ff..ab2e04f 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -4966,7 +4966,7 @@ get_mesa_program(struct gl_context *ctx,
    prog->Instructions = NULL;
    prog->NumInstructions = 0;
 
-   do_set_program_inouts(shader->ir, prog);
+   do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER);
    count_resources(v, prog);
 
    check_resources(ctx, shader_program, v, prog);
-- 
1.7.6.4



More information about the mesa-dev mailing list