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 b3635bf6867b36d86d40414bf6936711f378cbec..b0f95dd73b65b706c783151173c548d410bd990f 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 cc508e2a424d352a38e37e659f6f4d38e3f0e7a7..fc356ba52752dac3a6ee9e8e74b0362c1c3fd904 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 878c1779d85fac9ebbdf2dffd30c41493e7f1e38..74a8b06b1a30bffd96347197675bf37afcc4766e 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 8db70119ec21c0f94c7e2a3d3642044446be65b6..caee9296af9e5c042a9aa8df80ee2de6bd5b6726 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 630850048f629a35b44cdb526e052297dc61a66a..82ccc722fa28762f4fe4fd60345450306fca9385 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 9ed3d23508a284d55c72f478302610119d85515b..af85e06ae0e4a2cda026c84b5aca30b7476d2373 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 73da28faf4f8e664e64699590b410fdc0a95728f..18a3e0fb0d9e120c0d2f1f0537708bd2c91e739b 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 3d1b8a2f70368e07dd10399630875f5401dfe5b9..c7fb62437db381d26c58a83ee70ec079a4b9f8e0 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 147a6aea1ef7ce706451702cabe9067f182afb7b..8eb1612f0a0da921fb6e3ee30b8bd56e211b4ef5 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 d69ca75fe03090f9a27f960040eddad40baa1397..599b21525de8a4c94b76b47ac929fd0d35b138bc 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 a0449a7427a74ddfcc5f662952cea9b2ee7f6728..2e7831dcbdbe6b4b75bb6c501351e0e98176e326 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 ae77408dbeaefd844e537e3d1086d6a7e2cb23a8..1ef940f9c72bc31cf72bac01783a36042650d58b 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)) {