Mesa (master): mesa: Expose GLSL interpolation qualifiers in gl_fragment_program.

Paul Berry stereotype441 at kemper.freedesktop.org
Thu Oct 27 17:08:48 PDT 2011


Module: Mesa
Branch: master
Commit: cf45949d6a896651a5f3864d3b195e26d59eee74
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=cf45949d6a896651a5f3864d3b195e26d59eee74

Author: Paul Berry <stereotype441 at gmail.com>
Date:   Tue Oct 25 18:06:37 2011 -0700

mesa: Expose GLSL interpolation qualifiers in gl_fragment_program.

This patch makes GLSL interpolation qualifiers visible to drivers via
the array InterpQualifier[] in gl_fragment_program, so that they can
easily be used by driver back-ends to select the correct interpolation
mode.

Previous to this patch, the GLSL compiler was using the enum
ir_variable_interpolation to represent interpolation types.  Rather
than make a duplicate enum in core mesa to represent the same thing, I
moved the enum into mtypes.h and renamed it to be more consistent with
the other enums defined there.

Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
Reviewed-by: Eric Anholt <eric at anholt.net>

---

 src/glsl/ast_to_hir.cpp                    |    8 ++--
 src/glsl/ir.cpp                            |    8 ++--
 src/glsl/ir.h                              |   10 ++----
 src/glsl/ir_reader.cpp                     |    6 ++--
 src/glsl/ir_set_program_inouts.cpp         |   47 ++++++++++++++++++++--------
 src/mesa/main/mtypes.h                     |   19 +++++++++++
 src/mesa/program/ir_to_mesa.cpp            |    2 +-
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp |    2 +-
 8 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 70afb67..d090d31 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -1962,11 +1962,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    }
 
    if (qual->flags.q.flat)
-      var->interpolation = ir_var_flat;
+      var->interpolation = INTERP_QUALIFIER_FLAT;
    else if (qual->flags.q.noperspective)
-      var->interpolation = ir_var_noperspective;
+      var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
    else
-      var->interpolation = ir_var_smooth;
+      var->interpolation = INTERP_QUALIFIER_SMOOTH;
 
    var->pixel_center_integer = qual->flags.q.pixel_center_integer;
    var->origin_upper_left = qual->flags.q.origin_upper_left;
@@ -2630,7 +2630,7 @@ ast_declarator_list::hir(exec_list *instructions,
           && state->current_function == NULL
           && var->type->is_integer()
           && var->mode == ir_var_out
-          && var->interpolation != ir_var_flat) {
+          && var->interpolation != INTERP_QUALIFIER_FLAT) {
 
          _mesa_glsl_error(&loc, state, "If a vertex output is an integer, "
                           "then it must be qualified with 'flat'");
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index d968890..046ce25 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1320,7 +1320,7 @@ ir_swizzle::variable_referenced() const
 ir_variable::ir_variable(const struct glsl_type *type, const char *name,
 			 ir_variable_mode mode)
    : max_array_access(0), read_only(false), centroid(false), invariant(false),
-     mode(mode), interpolation(ir_var_smooth)
+     mode(mode), interpolation(INTERP_QUALIFIER_SMOOTH)
 {
    this->ir_type = ir_type_variable;
    this->type = type;
@@ -1343,9 +1343,9 @@ const char *
 ir_variable::interpolation_string() const
 {
    switch (this->interpolation) {
-   case ir_var_smooth:        return "smooth";
-   case ir_var_flat:          return "flat";
-   case ir_var_noperspective: return "noperspective";
+   case INTERP_QUALIFIER_SMOOTH:        return "smooth";
+   case INTERP_QUALIFIER_FLAT:          return "flat";
+   case INTERP_QUALIFIER_NOPERSPECTIVE: return "noperspective";
    }
 
    assert(!"Should not get here.");
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index b707634..4ea8764 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -34,6 +34,7 @@
 #include "list.h"
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
+#include "main/mtypes.h"
 
 /**
  * \defgroup IR Intermediate representation nodes
@@ -227,12 +228,6 @@ enum ir_variable_mode {
    ir_var_temporary	/**< Temporary variable generated during compilation. */
 };
 
-enum ir_variable_interpolation {
-   ir_var_smooth = 0,
-   ir_var_flat,
-   ir_var_noperspective
-};
-
 /**
  * \brief Layout qualifiers for gl_FragDepth.
  *
@@ -1679,7 +1674,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_reader.cpp b/src/glsl/ir_reader.cpp
index afb06b3..e3a3ed9 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -405,11 +405,11 @@ ir_reader::read_declaration(s_expression *expr)
       } else if (strcmp(qualifier->value(), "inout") == 0) {
 	 var->mode = ir_var_inout;
       } else if (strcmp(qualifier->value(), "smooth") == 0) {
-	 var->interpolation = ir_var_smooth;
+	 var->interpolation = INTERP_QUALIFIER_SMOOTH;
       } else if (strcmp(qualifier->value(), "flat") == 0) {
-	 var->interpolation = ir_var_flat;
+	 var->interpolation = INTERP_QUALIFIER_FLAT;
       } else if (strcmp(qualifier->value(), "noperspective") == 0) {
-	 var->interpolation = ir_var_noperspective;
+	 var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
       } else {
 	 ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
 	 return NULL;
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
index ae3ef74..8c2bc30 100644
--- a/src/glsl/ir_set_program_inouts.cpp
+++ b/src/glsl/ir_set_program_inouts.cpp
@@ -26,6 +26,8 @@
  *
  * Sets the InputsRead and OutputsWritten of Mesa programs.
  *
+ * Additionally, for fragment shaders, sets the InterpQualifier array.
+ *
  * 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 +44,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 +65,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 +81,19 @@ 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;
+            fprog->InterpQualifier[var->location + offset + i] =
+               (glsl_interp_qualifier) var->interpolation;
+         }
+      } else if (var->mode == ir_var_system_value) {
+         prog->SystemValuesRead |= bitfield;
+      } else {
+	 prog->OutputsWritten |= bitfield;
+      }
    }
 }
 
@@ -93,9 +106,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 +136,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 +167,17 @@ 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) {
+      memset(((gl_fragment_program *) prog)->InterpQualifier, 0,
+             sizeof(((gl_fragment_program *) prog)->InterpQualifier));
+   }
    visit_list_elements(&v, instructions);
 }
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 4117686..9410e3f 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1790,6 +1790,18 @@ typedef enum
 } gl_system_value;
 
 
+/**
+ * The possible interpolation qualifiers that can be applied to a fragment
+ * shader input in GLSL.
+ */
+enum glsl_interp_qualifier
+{
+   INTERP_QUALIFIER_SMOOTH,
+   INTERP_QUALIFIER_FLAT,
+   INTERP_QUALIFIER_NOPERSPECTIVE
+};
+
+
 /** Vertex and fragment instructions */
 struct prog_instruction;
 struct gl_program_parameter_list;
@@ -1890,6 +1902,13 @@ struct gl_fragment_program
    GLboolean OriginUpperLeft;
    GLboolean PixelCenterInteger;
    enum gl_frag_depth_layout FragDepthLayout;
+
+   /**
+    * GLSL interpolation qualifier associated with each fragment shader input.
+    * For inputs that do not have an interpolation qualifier specified in
+    * GLSL, the value is INTERP_QUALIFIER_SMOOTH.
+    */
+   enum glsl_interp_qualifier InterpQualifier[FRAG_ATTRIB_MAX];
 };
 
 
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index bdbb6b9..93563bd 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -3191,7 +3191,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 145bd7d..67a1b51 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);



More information about the mesa-commit mailing list