summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2011-01-12 15:37:37 -0800
committerKenneth Graunke <[email protected]>2011-01-31 11:10:59 -0800
commit819d57fce94b20fa0d34da6f037f0a53c4a5bdc2 (patch)
treeea4c12c2a582e0f4a4119b4ace0bfecc5245d14b
parentc5a27b5939427bdc95c926b450ed3de1ff4baafb (diff)
glsl: Introduce a new "const_in" variable mode.
This annotation is for an "in" function parameter for which it is only legal to pass constant expressions. The only known example of this, currently, is the textureOffset functions. This should never be used for globals.
-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 b3635bf6867..b0f95dd73b6 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 cc508e2a424..fc356ba5275 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 878c1779d85..74a8b06b1a3 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 8db70119ec2..caee9296af9 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 630850048f6..82ccc722fa2 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 9ed3d23508a..af85e06ae0e 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 73da28faf4f..18a3e0fb0d9 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 3d1b8a2f703..c7fb62437db 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 147a6aea1ef..8eb1612f0a0 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 d69ca75fe03..599b21525de 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 a0449a7427a..2e7831dcbdb 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 ae77408dbea..1ef940f9c72 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)) {