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 <kenn...@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); _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev