From: Paul Berry Date: Wed, 26 Oct 2011 01:06:37 +0000 (-0700) Subject: mesa: Expose GLSL interpolation qualifiers in gl_fragment_program. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cf45949d6a896651a5f3864d3b195e26d59eee74;p=mesa.git 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 Reviewed-by: Kenneth Graunke Reviewed-by: Eric Anholt --- diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 70afb67dfc1..d090d311da8 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 d968890a2c9..046ce25f90c 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 b707634ea5a..4ea8764b68f 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 afb06b3beff..e3a3ed97d3a 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 ae3ef74c75e..8c2bc30d614 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 4117686414e..9410e3ff67a 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 bdbb6b93838..93563bdaa5b 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 145bd7dcd0c..67a1b513bda 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);