[Mesa-dev] [PATCH v2 1/8] mesa: Expose GLSL interpolation qualifiers in gl_fragment_program.

Kenneth Graunke kenneth at whitecape.org
Wed Oct 26 12:02:40 PDT 2011


On 10/25/2011 08:38 PM, Paul Berry wrote:
> 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.
> ---
>  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;

If you want, you could actually just do:
this->is_fragment_shader = prog->Target == GL_FRAGMENT_PROGRAM_ARB;
and not actually bother to pass the extra flag everywhere.

Otherwise, looks good.  This patch is:
Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
(as is or with the change)

>        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 719dff3..bd5e020 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 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);



More information about the mesa-dev mailing list