glsl: Introduce a new "const_in" variable mode.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 12 Jan 2011 23:37:37 +0000 (15:37 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 31 Jan 2011 19:10:59 +0000 (11:10 -0800)
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.

12 files changed:
src/glsl/ast_function.cpp
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_function.cpp
src/glsl/ir_print_visitor.cpp
src/glsl/ir_reader.cpp
src/glsl/ir_variable.cpp
src/glsl/linker.cpp
src/glsl/lower_variable_index_to_cond_assign.cpp
src/glsl/opt_constant_folding.cpp
src/glsl/opt_function_inlining.cpp
src/glsl/opt_tree_grafting.cpp

index b3635bf..b0f95dd 100644 (file)
@@ -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;
index cc508e2..fc356ba 100644 (file)
@@ -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) {
 
index 878c177..74a8b06 100644 (file)
@@ -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. */
 };
index 8db7011..caee929 100644 (file)
@@ -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;
index 6308500..82ccc72 100644 (file)
@@ -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) ",
index 9ed3d23..af85e06 100644 (file)
@@ -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) {
index 73da28f..18a3e0f 100644 (file)
@@ -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;
index 3d1b8a2..c7fb624 100644 (file)
@@ -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.");
index 147a6ae..8eb1612 100644 (file)
@@ -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;
index d69ca75..599b215 100644 (file)
@@ -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);
index a0449a7..2e7831d 100644 (file)
@@ -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;
 
index ae77408..1ef940f 100644 (file)
@@ -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)) {