aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp10
-rw-r--r--mesalib/src/glsl/ir.cpp24
-rw-r--r--mesalib/src/glsl/ir.h25
-rw-r--r--mesalib/src/glsl/ir_reader.cpp6
-rw-r--r--mesalib/src/glsl/ir_set_program_inouts.cpp47
5 files changed, 81 insertions, 31 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 70afb67df..fa6206e5e 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -1962,11 +1962,13 @@ 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 if (qual->flags.q.smooth)
+ var->interpolation = INTERP_QUALIFIER_SMOOTH;
else
- var->interpolation = ir_var_smooth;
+ var->interpolation = INTERP_QUALIFIER_NONE;
var->pixel_center_integer = qual->flags.q.pixel_center_integer;
var->origin_upper_left = qual->flags.q.origin_upper_left;
@@ -2630,7 +2632,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/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index d968890a2..ef7300e65 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/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_NONE)
{
this->ir_type = ir_type_variable;
this->type = type;
@@ -1343,9 +1343,10 @@ 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_NONE: return "no";
+ case INTERP_QUALIFIER_SMOOTH: return "smooth";
+ case INTERP_QUALIFIER_FLAT: return "flat";
+ case INTERP_QUALIFIER_NOPERSPECTIVE: return "noperspective";
}
assert(!"Should not get here.");
@@ -1353,6 +1354,21 @@ ir_variable::interpolation_string() const
}
+glsl_interp_qualifier
+ir_variable::determine_interpolation_mode(bool flat_shade)
+{
+ if (this->interpolation != INTERP_QUALIFIER_NONE)
+ return (glsl_interp_qualifier) this->interpolation;
+ int location = this->location;
+ bool is_gl_Color =
+ location == FRAG_ATTRIB_COL0 || location == FRAG_ATTRIB_COL1;
+ if (flat_shade && is_gl_Color)
+ return INTERP_QUALIFIER_FLAT;
+ else
+ return INTERP_QUALIFIER_SMOOTH;
+}
+
+
ir_function_signature::ir_function_signature(const glsl_type *return_type)
: return_type(return_type), is_defined(false), _function(NULL)
{
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index b707634ea..404d4cffa 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/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.
*
@@ -288,11 +283,26 @@ public:
* \return The string that would be used in a shader to specify \c
* mode will be returned.
*
+ * This function is used to generate error messages of the form "shader
+ * uses %s interpolation qualifier", so in the case where there is no
+ * interpolation qualifier, it returns "no".
+ *
* This function should only be used on a shader input or output variable.
*/
const char *interpolation_string() const;
/**
+ * Determine how this variable should be interpolated based on its
+ * interpolation qualifier (if present), whether it is gl_Color or
+ * gl_SecondaryColor, and whether flatshading is enabled in the current GL
+ * state.
+ *
+ * The return value will always be either INTERP_QUALIFIER_SMOOTH,
+ * INTERP_QUALIFIER_NOPERSPECTIVE, or INTERP_QUALIFIER_FLAT.
+ */
+ glsl_interp_qualifier determine_interpolation_mode(bool flat_shade);
+
+ /**
* Delcared name of the variable
*/
const char *name;
@@ -1679,7 +1689,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/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp
index afb06b3be..e3a3ed97d 100644
--- a/mesalib/src/glsl/ir_reader.cpp
+++ b/mesalib/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/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp
index ae3ef74c7..8c2bc30d6 100644
--- a/mesalib/src/glsl/ir_set_program_inouts.cpp
+++ b/mesalib/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);
}