summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ast_function.cpp9
-rw-r--r--src/glsl/ir.cpp17
-rw-r--r--src/glsl/ir.h1
-rw-r--r--src/glsl/ir_function.cpp1
-rw-r--r--src/glsl/ir_print_visitor.cpp2
-rw-r--r--src/glsl/ir_reader.cpp2
-rw-r--r--src/glsl/ir_variable.cpp1
-rw-r--r--src/glsl/linker.cpp1
-rw-r--r--src/glsl/lower_variable_index_to_cond_assign.cpp1
-rw-r--r--src/glsl/opt_constant_folding.cpp2
-rw-r--r--src/glsl/opt_function_inlining.cpp1
-rw-r--r--src/glsl/opt_tree_grafting.cpp2
12 files changed, 36 insertions, 4 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index b3635bf686..b0f95dd73b 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -132,6 +132,9 @@ match_function_by_name(exec_list *instructions, const char *name,
/* Verify that 'out' and 'inout' actual parameters are lvalues. This
* isn't done in ir_function::matching_signature because that function
* cannot generate the necessary diagnostics.
+ *
+ * Also, validate that 'const_in' formal parameters (an extension of our
+ * IR) correspond to ir_constant actual parameters.
*/
exec_list_iterator actual_iter = actual_parameters->iterator();
exec_list_iterator formal_iter = sig->parameters.iterator();
@@ -143,6 +146,12 @@ match_function_by_name(exec_list *instructions, const char *name,
assert(actual != NULL);
assert(formal != NULL);
+ if (formal->mode == ir_var_const_in && !actual->as_constant()) {
+ _mesa_glsl_error(loc, state,
+ "parameter `%s' must be a constant expression",
+ formal->name);
+ }
+
if ((formal->mode == ir_var_out)
|| (formal->mode == ir_var_inout)) {
const char *mode = NULL;
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index cc508e2a42..fc356ba527 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1379,6 +1379,21 @@ ir_function_signature::ir_function_signature(const glsl_type *return_type)
}
+static bool
+modes_match(unsigned a, unsigned b)
+{
+ if (a == b)
+ return true;
+
+ /* Accept "in" vs. "const in" */
+ if ((a == ir_var_const_in && b == ir_var_in) ||
+ (b == ir_var_const_in && a == ir_var_in))
+ return true;
+
+ return false;
+}
+
+
const char *
ir_function_signature::qualifiers_match(exec_list *params)
{
@@ -1391,7 +1406,7 @@ ir_function_signature::qualifiers_match(exec_list *params)
ir_variable *b = (ir_variable *)iter_b.get();
if (a->read_only != b->read_only ||
- a->mode != b->mode ||
+ !modes_match(a->mode, b->mode) ||
a->interpolation != b->interpolation ||
a->centroid != b->centroid) {
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 878c1779d8..74a8b06b1a 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -222,6 +222,7 @@ enum ir_variable_mode {
ir_var_in,
ir_var_out,
ir_var_inout,
+ ir_var_const_in, /**< "in" param that must be a constant expression */
ir_var_system_value, /**< Ex: front-face, instance-id, etc. */
ir_var_temporary /**< Temporary variable generated during compilation. */
};
diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
index 8db70119ec..caee9296af 100644
--- a/src/glsl/ir_function.cpp
+++ b/src/glsl/ir_function.cpp
@@ -123,6 +123,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
assert(0);
return -1;
+ case ir_var_const_in:
case ir_var_in:
score = type_compare(param->type, actual->type);
break;
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
index 630850048f..82ccc722fa 100644
--- a/src/glsl/ir_print_visitor.cpp
+++ b/src/glsl/ir_print_visitor.cpp
@@ -97,7 +97,7 @@ void ir_print_visitor::visit(ir_variable *ir)
const char *const cent = (ir->centroid) ? "centroid " : "";
const char *const inv = (ir->invariant) ? "invariant " : "";
const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
- "sys ", "temporary " };
+ "const_in ", "sys ", "temporary " };
const char *const interp[] = { "", "flat", "noperspective" };
printf("(%s%s%s%s) ",
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index 9ed3d23508..af85e06ae0 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -397,6 +397,8 @@ ir_reader::read_declaration(s_expression *expr)
var->mode = ir_var_auto;
} else if (strcmp(qualifier->value(), "in") == 0) {
var->mode = ir_var_in;
+ } else if (strcmp(qualifier->value(), "const_in") == 0) {
+ var->mode = ir_var_const_in;
} else if (strcmp(qualifier->value(), "out") == 0) {
var->mode = ir_var_out;
} else if (strcmp(qualifier->value(), "inout") == 0) {
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
index 73da28faf4..18a3e0fb0d 100644
--- a/src/glsl/ir_variable.cpp
+++ b/src/glsl/ir_variable.cpp
@@ -45,6 +45,7 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
switch (var->mode) {
case ir_var_auto:
case ir_var_in:
+ case ir_var_const_in:
case ir_var_uniform:
case ir_var_system_value:
var->read_only = true;
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 3d1b8a2f70..c7fb62437d 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -299,6 +299,7 @@ mode_string(const ir_variable *var)
case ir_var_out: return "shader output";
case ir_var_inout: return "shader inout";
+ case ir_var_const_in:
case ir_var_temporary:
default:
assert(!"Should not get here.");
diff --git a/src/glsl/lower_variable_index_to_cond_assign.cpp b/src/glsl/lower_variable_index_to_cond_assign.cpp
index 147a6aea1e..8eb1612f0a 100644
--- a/src/glsl/lower_variable_index_to_cond_assign.cpp
+++ b/src/glsl/lower_variable_index_to_cond_assign.cpp
@@ -255,6 +255,7 @@ public:
case ir_var_uniform:
return this->lower_uniforms;
case ir_var_in:
+ case ir_var_const_in:
return (var->location == -1) ? this->lower_temps : this->lower_inputs;
case ir_var_out:
return (var->location == -1) ? this->lower_temps : this->lower_outputs;
diff --git a/src/glsl/opt_constant_folding.cpp b/src/glsl/opt_constant_folding.cpp
index d69ca75fe0..599b21525d 100644
--- a/src/glsl/opt_constant_folding.cpp
+++ b/src/glsl/opt_constant_folding.cpp
@@ -122,7 +122,7 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir)
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
ir_variable *sig_param = (ir_variable *)sig_iter.get();
- if (sig_param->mode == ir_var_in) {
+ if (sig_param->mode == ir_var_in || sig_param->mode == ir_var_const_in) {
ir_rvalue *new_param = param_rval;
handle_rvalue(&new_param);
diff --git a/src/glsl/opt_function_inlining.cpp b/src/glsl/opt_function_inlining.cpp
index a0449a7427..2e7831dcbd 100644
--- a/src/glsl/opt_function_inlining.cpp
+++ b/src/glsl/opt_function_inlining.cpp
@@ -165,6 +165,7 @@ ir_call::generate_inline(ir_instruction *next_ir)
/* Move the actual param into our param variable if it's an 'in' type. */
if (parameters[i] && (sig_param->mode == ir_var_in ||
+ sig_param->mode == ir_var_const_in ||
sig_param->mode == ir_var_inout)) {
ir_assignment *assign;
diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp
index ae77408dbe..1ef940f9c7 100644
--- a/src/glsl/opt_tree_grafting.cpp
+++ b/src/glsl/opt_tree_grafting.cpp
@@ -195,7 +195,7 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir)
ir_rvalue *ir = (ir_rvalue *)iter.get();
ir_rvalue *new_ir = ir;
- if (sig_param->mode != ir_var_in)
+ if (sig_param->mode != ir_var_in && sig_param->mode != ir_var_const_in)
continue;
if (do_graft(&new_ir)) {