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.
This commit is contained in:
@@ -132,6 +132,9 @@ match_function_by_name(exec_list *instructions, const char *name,
|
|||||||
/* Verify that 'out' and 'inout' actual parameters are lvalues. This
|
/* Verify that 'out' and 'inout' actual parameters are lvalues. This
|
||||||
* isn't done in ir_function::matching_signature because that function
|
* isn't done in ir_function::matching_signature because that function
|
||||||
* cannot generate the necessary diagnostics.
|
* 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 actual_iter = actual_parameters->iterator();
|
||||||
exec_list_iterator formal_iter = sig->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(actual != NULL);
|
||||||
assert(formal != 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)
|
if ((formal->mode == ir_var_out)
|
||||||
|| (formal->mode == ir_var_inout)) {
|
|| (formal->mode == ir_var_inout)) {
|
||||||
const char *mode = NULL;
|
const char *mode = NULL;
|
||||||
|
@@ -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 *
|
const char *
|
||||||
ir_function_signature::qualifiers_match(exec_list *params)
|
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();
|
ir_variable *b = (ir_variable *)iter_b.get();
|
||||||
|
|
||||||
if (a->read_only != b->read_only ||
|
if (a->read_only != b->read_only ||
|
||||||
a->mode != b->mode ||
|
!modes_match(a->mode, b->mode) ||
|
||||||
a->interpolation != b->interpolation ||
|
a->interpolation != b->interpolation ||
|
||||||
a->centroid != b->centroid) {
|
a->centroid != b->centroid) {
|
||||||
|
|
||||||
|
@@ -222,6 +222,7 @@ enum ir_variable_mode {
|
|||||||
ir_var_in,
|
ir_var_in,
|
||||||
ir_var_out,
|
ir_var_out,
|
||||||
ir_var_inout,
|
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_system_value, /**< Ex: front-face, instance-id, etc. */
|
||||||
ir_var_temporary /**< Temporary variable generated during compilation. */
|
ir_var_temporary /**< Temporary variable generated during compilation. */
|
||||||
};
|
};
|
||||||
|
@@ -123,6 +123,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
|
|||||||
assert(0);
|
assert(0);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
case ir_var_const_in:
|
||||||
case ir_var_in:
|
case ir_var_in:
|
||||||
score = type_compare(param->type, actual->type);
|
score = type_compare(param->type, actual->type);
|
||||||
break;
|
break;
|
||||||
|
@@ -97,7 +97,7 @@ void ir_print_visitor::visit(ir_variable *ir)
|
|||||||
const char *const cent = (ir->centroid) ? "centroid " : "";
|
const char *const cent = (ir->centroid) ? "centroid " : "";
|
||||||
const char *const inv = (ir->invariant) ? "invariant " : "";
|
const char *const inv = (ir->invariant) ? "invariant " : "";
|
||||||
const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
|
const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
|
||||||
"sys ", "temporary " };
|
"const_in ", "sys ", "temporary " };
|
||||||
const char *const interp[] = { "", "flat", "noperspective" };
|
const char *const interp[] = { "", "flat", "noperspective" };
|
||||||
|
|
||||||
printf("(%s%s%s%s) ",
|
printf("(%s%s%s%s) ",
|
||||||
|
@@ -397,6 +397,8 @@ ir_reader::read_declaration(s_expression *expr)
|
|||||||
var->mode = ir_var_auto;
|
var->mode = ir_var_auto;
|
||||||
} else if (strcmp(qualifier->value(), "in") == 0) {
|
} else if (strcmp(qualifier->value(), "in") == 0) {
|
||||||
var->mode = ir_var_in;
|
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) {
|
} else if (strcmp(qualifier->value(), "out") == 0) {
|
||||||
var->mode = ir_var_out;
|
var->mode = ir_var_out;
|
||||||
} else if (strcmp(qualifier->value(), "inout") == 0) {
|
} else if (strcmp(qualifier->value(), "inout") == 0) {
|
||||||
|
@@ -45,6 +45,7 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
|
|||||||
switch (var->mode) {
|
switch (var->mode) {
|
||||||
case ir_var_auto:
|
case ir_var_auto:
|
||||||
case ir_var_in:
|
case ir_var_in:
|
||||||
|
case ir_var_const_in:
|
||||||
case ir_var_uniform:
|
case ir_var_uniform:
|
||||||
case ir_var_system_value:
|
case ir_var_system_value:
|
||||||
var->read_only = true;
|
var->read_only = true;
|
||||||
|
@@ -299,6 +299,7 @@ mode_string(const ir_variable *var)
|
|||||||
case ir_var_out: return "shader output";
|
case ir_var_out: return "shader output";
|
||||||
case ir_var_inout: return "shader inout";
|
case ir_var_inout: return "shader inout";
|
||||||
|
|
||||||
|
case ir_var_const_in:
|
||||||
case ir_var_temporary:
|
case ir_var_temporary:
|
||||||
default:
|
default:
|
||||||
assert(!"Should not get here.");
|
assert(!"Should not get here.");
|
||||||
|
@@ -255,6 +255,7 @@ public:
|
|||||||
case ir_var_uniform:
|
case ir_var_uniform:
|
||||||
return this->lower_uniforms;
|
return this->lower_uniforms;
|
||||||
case ir_var_in:
|
case ir_var_in:
|
||||||
|
case ir_var_const_in:
|
||||||
return (var->location == -1) ? this->lower_temps : this->lower_inputs;
|
return (var->location == -1) ? this->lower_temps : this->lower_inputs;
|
||||||
case ir_var_out:
|
case ir_var_out:
|
||||||
return (var->location == -1) ? this->lower_temps : this->lower_outputs;
|
return (var->location == -1) ? this->lower_temps : this->lower_outputs;
|
||||||
|
@@ -122,7 +122,7 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir)
|
|||||||
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
|
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
|
||||||
ir_variable *sig_param = (ir_variable *)sig_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;
|
ir_rvalue *new_param = param_rval;
|
||||||
|
|
||||||
handle_rvalue(&new_param);
|
handle_rvalue(&new_param);
|
||||||
|
@@ -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. */
|
/* Move the actual param into our param variable if it's an 'in' type. */
|
||||||
if (parameters[i] && (sig_param->mode == ir_var_in ||
|
if (parameters[i] && (sig_param->mode == ir_var_in ||
|
||||||
|
sig_param->mode == ir_var_const_in ||
|
||||||
sig_param->mode == ir_var_inout)) {
|
sig_param->mode == ir_var_inout)) {
|
||||||
ir_assignment *assign;
|
ir_assignment *assign;
|
||||||
|
|
||||||
|
@@ -195,7 +195,7 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir)
|
|||||||
ir_rvalue *ir = (ir_rvalue *)iter.get();
|
ir_rvalue *ir = (ir_rvalue *)iter.get();
|
||||||
ir_rvalue *new_ir = ir;
|
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;
|
continue;
|
||||||
|
|
||||||
if (do_graft(&new_ir)) {
|
if (do_graft(&new_ir)) {
|
||||||
|
Reference in New Issue
Block a user