aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/ast.h1
-rw-r--r--mesalib/src/glsl/ast_array_index.cpp8
-rw-r--r--mesalib/src/glsl/ast_function.cpp86
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp298
-rw-r--r--mesalib/src/glsl/ast_type.cpp3
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp37
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp50
-rw-r--r--mesalib/src/glsl/glsl_lexer.ll2
-rw-r--r--mesalib/src/glsl/glsl_parser.yy17
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp24
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h14
-rw-r--r--mesalib/src/glsl/glsl_types.cpp5
-rw-r--r--mesalib/src/glsl/glsl_types.h6
-rw-r--r--mesalib/src/glsl/ir.cpp65
-rw-r--r--mesalib/src/glsl/ir.h373
-rw-r--r--mesalib/src/glsl/ir_clone.cpp35
-rwxr-xr-xmesalib/src/glsl/ir_constant_expression.cpp2
-rw-r--r--mesalib/src/glsl/ir_function.cpp2
-rw-r--r--mesalib/src/glsl/ir_hv_accept.cpp20
-rw-r--r--mesalib/src/glsl/ir_print_visitor.cpp27
-rw-r--r--mesalib/src/glsl/ir_reader.cpp42
-rw-r--r--mesalib/src/glsl/ir_set_program_inouts.cpp35
-rw-r--r--mesalib/src/glsl/ir_validate.cpp47
-rw-r--r--mesalib/src/glsl/link_atomics.cpp20
-rw-r--r--mesalib/src/glsl/link_functions.cpp10
-rw-r--r--mesalib/src/glsl/link_interface_blocks.cpp12
-rw-r--r--mesalib/src/glsl/link_uniform_initializers.cpp6
-rw-r--r--mesalib/src/glsl/link_uniforms.cpp20
-rw-r--r--mesalib/src/glsl/link_varyings.cpp98
-rw-r--r--mesalib/src/glsl/linker.cpp173
-rw-r--r--mesalib/src/glsl/loop_analysis.cpp196
-rw-r--r--mesalib/src/glsl/loop_analysis.h93
-rw-r--r--mesalib/src/glsl/loop_controls.cpp127
-rw-r--r--mesalib/src/glsl/loop_unroll.cpp318
-rw-r--r--mesalib/src/glsl/lower_clip_distance.cpp18
-rw-r--r--mesalib/src/glsl/lower_instructions.cpp4
-rw-r--r--mesalib/src/glsl/lower_named_interface_blocks.cpp21
-rw-r--r--mesalib/src/glsl/lower_output_reads.cpp2
-rw-r--r--mesalib/src/glsl/lower_packed_varyings.cpp21
-rw-r--r--mesalib/src/glsl/lower_ubo_reference.cpp2
-rw-r--r--mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp2
-rw-r--r--mesalib/src/glsl/opt_array_splitting.cpp4
-rw-r--r--mesalib/src/glsl/opt_constant_folding.cpp4
-rw-r--r--mesalib/src/glsl/opt_constant_propagation.cpp4
-rw-r--r--mesalib/src/glsl/opt_constant_variable.cpp4
-rw-r--r--mesalib/src/glsl/opt_copy_propagation.cpp4
-rw-r--r--mesalib/src/glsl/opt_copy_propagation_elements.cpp4
-rw-r--r--mesalib/src/glsl/opt_cse.cpp2
-rw-r--r--mesalib/src/glsl/opt_dead_builtin_varyings.cpp22
-rw-r--r--mesalib/src/glsl/opt_dead_code.cpp8
-rw-r--r--mesalib/src/glsl/opt_dead_code_local.cpp2
-rw-r--r--mesalib/src/glsl/opt_flip_matrices.cpp4
-rw-r--r--mesalib/src/glsl/opt_function_inlining.cpp14
-rw-r--r--mesalib/src/glsl/opt_structure_splitting.cpp4
-rw-r--r--mesalib/src/glsl/opt_tree_grafting.cpp10
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.h2
56 files changed, 1279 insertions, 1155 deletions
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h
index 9c43920a4..344277803 100644
--- a/mesalib/src/glsl/ast.h
+++ b/mesalib/src/glsl/ast.h
@@ -361,6 +361,7 @@ struct ast_type_qualifier {
unsigned in:1;
unsigned out:1;
unsigned centroid:1;
+ unsigned sample:1;
unsigned uniform:1;
unsigned smooth:1;
unsigned flat:1;
diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp
index f7b5e8350..a5f23206a 100644
--- a/mesalib/src/glsl/ast_array_index.cpp
+++ b/mesalib/src/glsl/ast_array_index.cpp
@@ -41,8 +41,8 @@ update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc,
{
if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) {
ir_variable *var = deref_var->var;
- if (idx > var->max_array_access) {
- var->max_array_access = idx;
+ if (idx > var->data.max_array_access) {
+ var->data.max_array_access = idx;
/* Check whether this access will, as a side effect, implicitly cause
* the size of a built-in array to be too large.
@@ -168,7 +168,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
if (array->type->is_unsized_array()) {
_mesa_glsl_error(&loc, state, "unsized array index must be constant");
} else if (array->type->fields.array->is_interface()
- && array->variable_referenced()->mode == ir_var_uniform) {
+ && array->variable_referenced()->data.mode == ir_var_uniform) {
/* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says:
*
* "All indexes used to index a uniform block array must be
@@ -184,7 +184,7 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
*/
ir_variable *v = array->whole_variable_referenced();
if (v != NULL)
- v->max_array_access = array->type->array_size() - 1;
+ v->data.max_array_access = array->type->array_size() - 1;
}
/* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index 2707522ef..e4c0fd1c4 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -123,7 +123,7 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
YYLTYPE loc = actual_ast->get_location();
/* Verify that 'const_in' parameters are ir_constants. */
- if (formal->mode == ir_var_const_in &&
+ if (formal->data.mode == ir_var_const_in &&
actual->ir_type != ir_type_constant) {
_mesa_glsl_error(&loc, state,
"parameter `in %s' must be a constant expression",
@@ -132,10 +132,10 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
}
/* Verify that 'out' and 'inout' actual parameters are lvalues. */
- if (formal->mode == ir_var_function_out
- || formal->mode == ir_var_function_inout) {
+ if (formal->data.mode == ir_var_function_out
+ || formal->data.mode == ir_var_function_inout) {
const char *mode = NULL;
- switch (formal->mode) {
+ switch (formal->data.mode) {
case ir_var_function_out: mode = "out"; break;
case ir_var_function_inout: mode = "inout"; break;
default: assert(false); break;
@@ -155,9 +155,9 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
ir_variable *var = actual->variable_referenced();
if (var)
- var->assigned = true;
+ var->data.assigned = true;
- if (var && var->read_only) {
+ if (var && var->data.read_only) {
_mesa_glsl_error(&loc, state,
"function parameter '%s %s' references the "
"read-only variable '%s'",
@@ -274,20 +274,20 @@ fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type,
}
/**
- * If a function call is generated, \c call_ir will point to it on exit.
- * Otherwise \c call_ir will be set to \c NULL.
+ * Generate a function call.
+ *
+ * For non-void functions, this returns a dereference of the temporary variable
+ * which stores the return value for the call. For void functions, this returns
+ * NULL.
*/
static ir_rvalue *
generate_call(exec_list *instructions, ir_function_signature *sig,
exec_list *actual_parameters,
- ir_call **call_ir,
struct _mesa_glsl_parse_state *state)
{
void *ctx = state;
exec_list post_call_conversions;
- *call_ir = NULL;
-
/* Perform implicit conversion of arguments. For out parameters, we need
* to place them in a temporary variable and do the conversion after the
* call takes place. Since we haven't emitted the call yet, we'll place
@@ -304,7 +304,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
assert(formal != NULL);
if (formal->type->is_numeric() || formal->type->is_boolean()) {
- switch (formal->mode) {
+ switch (formal->data.mode) {
case ir_var_const_in:
case ir_var_function_in: {
ir_rvalue *converted
@@ -316,7 +316,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
case ir_var_function_inout:
fix_parameter(ctx, actual, formal->type,
instructions, &post_call_conversions,
- formal->mode == ir_var_function_inout);
+ formal->data.mode == ir_var_function_inout);
break;
default:
assert (!"Illegal formal parameter mode");
@@ -421,6 +421,25 @@ done:
return sig;
}
+static void
+print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc,
+ ir_function *f)
+{
+ if (f == NULL)
+ return;
+
+ foreach_list (node, &f->signatures) {
+ ir_function_signature *sig = (ir_function_signature *) node;
+
+ if (sig->is_builtin() && !sig->is_builtin_available(state))
+ continue;
+
+ char *str = prototype_string(sig->return_type, f->name, &sig->parameters);
+ _mesa_glsl_error(loc, state, " %s", str);
+ ralloc_free(str);
+ }
+}
+
/**
* Raise a "no matching function" error, listing all possible overloads the
* compiler considered so developers can figure out what went wrong.
@@ -431,30 +450,23 @@ no_matching_function_error(const char *name,
exec_list *actual_parameters,
_mesa_glsl_parse_state *state)
{
- char *str = prototype_string(NULL, name, actual_parameters);
- _mesa_glsl_error(loc, state, "no matching function for call to `%s'", str);
- ralloc_free(str);
-
- const char *prefix = "candidates are: ";
+ gl_shader *sh = _mesa_glsl_get_builtin_function_shader();
- for (int i = -1; i < (int) state->num_builtins_to_link; i++) {
- glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols
- : state->symbols;
- ir_function *f = syms->get_function(name);
- if (f == NULL)
- continue;
-
- foreach_list (node, &f->signatures) {
- ir_function_signature *sig = (ir_function_signature *) node;
-
- if (sig->is_builtin() && !sig->is_builtin_available(state))
- continue;
+ if (state->symbols->get_function(name) == NULL
+ && (!state->uses_builtin_functions
+ || sh->symbols->get_function(name) == NULL)) {
+ _mesa_glsl_error(loc, state, "no function with name '%s'", name);
+ } else {
+ char *str = prototype_string(NULL, name, actual_parameters);
+ _mesa_glsl_error(loc, state,
+ "no matching function for call to `%s'; candidates are:",
+ str);
+ ralloc_free(str);
- str = prototype_string(sig->return_type, f->name, &sig->parameters);
- _mesa_glsl_error(loc, state, "%s%s", prefix, str);
- ralloc_free(str);
+ print_function_prototypes(state, loc, state->symbols->get_function(name));
- prefix = " ";
+ if (state->uses_builtin_functions) {
+ print_function_prototypes(state, loc, sh->symbols->get_function(name));
}
}
}
@@ -1651,7 +1663,7 @@ ast_function_expression::hir(exec_list *instructions,
} else {
const ast_expression *id = subexpressions[0];
const char *func_name = id->primary_expression.identifier;
- YYLTYPE loc = id->get_location();
+ YYLTYPE loc = get_location();
exec_list actual_parameters;
process_parameters(instructions, &actual_parameters, &this->expressions,
@@ -1660,7 +1672,6 @@ ast_function_expression::hir(exec_list *instructions,
ir_function_signature *sig =
match_function_by_name(func_name, &actual_parameters, state);
- ir_call *call = NULL;
ir_rvalue *value = NULL;
if (sig == NULL) {
no_matching_function_error(func_name, &loc, &actual_parameters, state);
@@ -1669,8 +1680,7 @@ ast_function_expression::hir(exec_list *instructions,
/* an error has already been emitted */
value = ir_rvalue::error_value(ctx);
} else {
- value = generate_call(instructions, sig, &actual_parameters,
- &call, state);
+ value = generate_call(instructions, sig, &actual_parameters, state);
}
return value;
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 43cf49745..3bc181e87 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -728,7 +728,7 @@ mark_whole_array_access(ir_rvalue *access)
ir_dereference_variable *deref = access->as_dereference_variable();
if (deref && deref->var) {
- deref->var->max_array_access = deref->type->length - 1;
+ deref->var->data.max_array_access = deref->type->length - 1;
}
}
@@ -767,7 +767,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
ir_variable *lhs_var = lhs->variable_referenced();
if (lhs_var)
- lhs_var->assigned = true;
+ lhs_var->data.assigned = true;
if (!error_emitted) {
if (non_lvalue_description != NULL) {
@@ -776,7 +776,7 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
non_lvalue_description);
error_emitted = true;
} else if (lhs->variable_referenced() != NULL
- && lhs->variable_referenced()->read_only) {
+ && lhs->variable_referenced()->data.read_only) {
_mesa_glsl_error(&lhs_loc, state,
"assignment to read-only variable '%s'",
lhs->variable_referenced()->name);
@@ -819,11 +819,11 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
assert(var != NULL);
- if (var->max_array_access >= unsigned(rhs->type->array_size())) {
+ if (var->data.max_array_access >= unsigned(rhs->type->array_size())) {
/* FINISHME: This should actually log the location of the RHS. */
_mesa_glsl_error(& lhs_loc, state, "array size must be > %u due to "
"previous access",
- var->max_array_access);
+ var->data.max_array_access);
}
var->type = glsl_type::get_array_instance(lhs->type->element_type(),
@@ -866,7 +866,7 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
ir_var_temporary);
instructions->push_tail(var);
- var->mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
instructions->push_tail(new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
lvalue));
@@ -1639,7 +1639,7 @@ ast_expression::hir(exec_list *instructions,
state->symbols->get_variable(this->primary_expression.identifier);
if (var != NULL) {
- var->used = true;
+ var->data.used = true;
result = new(ctx) ir_dereference_variable(var);
} else {
_mesa_glsl_error(& loc, state, "`%s' undeclared",
@@ -1860,7 +1860,7 @@ ast_fully_specified_type::glsl_type(const char **name,
if (type->base_type == GLSL_TYPE_FLOAT
&& state->es_shader
- && state->target == fragment_shader
+ && state->target == MESA_SHADER_FRAGMENT
&& this->qualifier.precision == ast_precision_none
&& state->symbols->get_variable("#default precision") == NULL) {
YYLTYPE loc = this->get_location();
@@ -1882,15 +1882,15 @@ ast_fully_specified_type::glsl_type(const char **name,
* this function will produce undefined results.
*/
static bool
-is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target)
+is_varying_var(ir_variable *var, gl_shader_type target)
{
switch (target) {
- case vertex_shader:
- return var->mode == ir_var_shader_out;
- case fragment_shader:
- return var->mode == ir_var_shader_in;
+ case MESA_SHADER_VERTEX:
+ return var->data.mode == ir_var_shader_out;
+ case MESA_SHADER_FRAGMENT:
+ return var->data.mode == ir_var_shader_in;
default:
- return var->mode == ir_var_shader_out || var->mode == ir_var_shader_in;
+ return var->data.mode == ir_var_shader_out || var->data.mode == ir_var_shader_in;
}
}
@@ -1941,7 +1941,7 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
ir_variable *var,
const ast_type_qualifier *qual)
{
- if (var->mode != ir_var_uniform) {
+ if (var->data.mode != ir_var_uniform) {
_mesa_glsl_error(loc, state,
"the \"binding\" qualifier only applies to uniforms");
return false;
@@ -1985,13 +1985,13 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
*/
unsigned limit = 0;
switch (state->target) {
- case vertex_shader:
+ case MESA_SHADER_VERTEX:
limit = ctx->Const.VertexProgram.MaxTextureImageUnits;
break;
- case geometry_shader:
+ case MESA_SHADER_GEOMETRY:
limit = ctx->Const.GeometryProgram.MaxTextureImageUnits;
break;
- case fragment_shader:
+ case MESA_SHADER_FRAGMENT:
limit = ctx->Const.FragmentProgram.MaxTextureImageUnits;
break;
}
@@ -2049,8 +2049,8 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual,
}
- if ((state->target == vertex_shader && mode == ir_var_shader_in) ||
- (state->target == fragment_shader && mode == ir_var_shader_out)) {
+ if ((state->target == MESA_SHADER_VERTEX && mode == ir_var_shader_in) ||
+ (state->target == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) {
_mesa_glsl_error(loc, state,
"interpolation qualifier `%s' cannot be applied to "
"vertex shader inputs or fragment shader outputs",
@@ -2077,8 +2077,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
* locations.
*/
switch (state->target) {
- case vertex_shader:
- if (var->mode == ir_var_shader_in) {
+ case MESA_SHADER_VERTEX:
+ if (var->data.mode == ir_var_shader_in) {
if (!state->check_explicit_attrib_location_allowed(loc, var))
return;
@@ -2088,14 +2088,14 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
fail = true;
break;
- case geometry_shader:
+ case MESA_SHADER_GEOMETRY:
_mesa_glsl_error(loc, state,
"geometry shader variables cannot be given "
"explicit locations");
return;
- case fragment_shader:
- if (var->mode == ir_var_shader_out) {
+ case MESA_SHADER_FRAGMENT:
+ if (var->data.mode == ir_var_shader_out) {
if (!state->check_explicit_attrib_location_allowed(loc, var))
return;
@@ -2112,7 +2112,7 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
mode_string(var),
_mesa_glsl_shader_target_name(state->target));
} else {
- var->explicit_location = true;
+ var->data.explicit_location = true;
/* This bit of silliness is needed because invalid explicit locations
* are supposed to be flagged during linking. Small negative values
@@ -2122,11 +2122,11 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
* ensures that negative values stay negative.
*/
if (qual->location >= 0) {
- var->location = (state->target == vertex_shader)
+ var->data.location = (state->target == MESA_SHADER_VERTEX)
? (qual->location + VERT_ATTRIB_GENERIC0)
: (qual->location + FRAG_RESULT_DATA0);
} else {
- var->location = qual->location;
+ var->data.location = qual->location;
}
if (qual->flags.q.explicit_index) {
@@ -2143,8 +2143,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
_mesa_glsl_error(loc, state,
"explicit index may only be 0 or 1");
} else {
- var->explicit_index = true;
- var->index = qual->index;
+ var->data.explicit_index = true;
+ var->data.index = qual->index;
}
}
}
@@ -2162,25 +2162,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i));
if (qual->flags.q.invariant) {
- if (var->used) {
+ if (var->data.used) {
_mesa_glsl_error(loc, state,
"variable `%s' may not be redeclared "
"`invariant' after being used",
var->name);
} else {
- var->invariant = 1;
+ var->data.invariant = 1;
}
}
if (qual->flags.q.constant || qual->flags.q.attribute
|| qual->flags.q.uniform
- || (qual->flags.q.varying && (state->target == fragment_shader)))
- var->read_only = 1;
+ || (qual->flags.q.varying && (state->target == MESA_SHADER_FRAGMENT)))
+ var->data.read_only = 1;
if (qual->flags.q.centroid)
- var->centroid = 1;
+ var->data.centroid = 1;
- if (qual->flags.q.attribute && state->target != vertex_shader) {
+ if (qual->flags.q.sample)
+ var->data.sample = 1;
+
+ if (qual->flags.q.attribute && state->target != MESA_SHADER_VERTEX) {
var->type = glsl_type::error_type;
_mesa_glsl_error(loc, state,
"`attribute' variables may not be declared in the "
@@ -2207,18 +2210,18 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
* the setting alone.
*/
if (qual->flags.q.in && qual->flags.q.out)
- var->mode = ir_var_function_inout;
+ var->data.mode = ir_var_function_inout;
else if (qual->flags.q.in)
- var->mode = is_parameter ? ir_var_function_in : ir_var_shader_in;
+ var->data.mode = is_parameter ? ir_var_function_in : ir_var_shader_in;
else if (qual->flags.q.attribute
- || (qual->flags.q.varying && (state->target == fragment_shader)))
- var->mode = ir_var_shader_in;
+ || (qual->flags.q.varying && (state->target == MESA_SHADER_FRAGMENT)))
+ var->data.mode = ir_var_shader_in;
else if (qual->flags.q.out)
- var->mode = is_parameter ? ir_var_function_out : ir_var_shader_out;
- else if (qual->flags.q.varying && (state->target == vertex_shader))
- var->mode = ir_var_shader_out;
+ var->data.mode = is_parameter ? ir_var_function_out : ir_var_shader_out;
+ else if (qual->flags.q.varying && (state->target == MESA_SHADER_VERTEX))
+ var->data.mode = ir_var_shader_out;
else if (qual->flags.q.uniform)
- var->mode = ir_var_uniform;
+ var->data.mode = ir_var_uniform;
if (!is_parameter && is_varying_var(var, state->target)) {
/* This variable is being used to link data between shader stages (in
@@ -2270,28 +2273,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
if (state->all_invariant && (state->current_function == NULL)) {
switch (state->target) {
- case vertex_shader:
- if (var->mode == ir_var_shader_out)
- var->invariant = true;
+ case MESA_SHADER_VERTEX:
+ if (var->data.mode == ir_var_shader_out)
+ var->data.invariant = true;
break;
- case geometry_shader:
- if ((var->mode == ir_var_shader_in)
- || (var->mode == ir_var_shader_out))
- var->invariant = true;
+ case MESA_SHADER_GEOMETRY:
+ if ((var->data.mode == ir_var_shader_in)
+ || (var->data.mode == ir_var_shader_out))
+ var->data.invariant = true;
break;
- case fragment_shader:
- if (var->mode == ir_var_shader_in)
- var->invariant = true;
+ case MESA_SHADER_FRAGMENT:
+ if (var->data.mode == ir_var_shader_in)
+ var->data.invariant = true;
break;
}
}
- var->interpolation =
- interpret_interpolation_qualifier(qual, (ir_variable_mode) var->mode,
+ var->data.interpolation =
+ interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode,
state, loc);
- var->pixel_center_integer = qual->flags.q.pixel_center_integer;
- var->origin_upper_left = qual->flags.q.origin_upper_left;
+ var->data.pixel_center_integer = qual->flags.q.pixel_center_integer;
+ var->data.origin_upper_left = qual->flags.q.origin_upper_left;
if ((qual->flags.q.origin_upper_left || qual->flags.q.pixel_center_integer)
&& (strcmp(var->name, "gl_FragCoord") != 0)) {
const char *const qual_string = (qual->flags.q.origin_upper_left)
@@ -2312,27 +2315,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
if (qual->flags.q.explicit_binding &&
validate_binding_qualifier(state, loc, var, qual)) {
- var->explicit_binding = true;
- var->binding = qual->binding;
+ var->data.explicit_binding = true;
+ var->data.binding = qual->binding;
}
if (var->type->contains_atomic()) {
- if (var->mode == ir_var_uniform) {
- if (var->explicit_binding) {
- unsigned *offset = &state->atomic_counter_offsets[var->binding];
+ if (var->data.mode == ir_var_uniform) {
+ if (var->data.explicit_binding) {
+ unsigned *offset =
+ &state->atomic_counter_offsets[var->data.binding];
if (*offset % ATOMIC_COUNTER_SIZE)
_mesa_glsl_error(loc, state,
"misaligned atomic counter offset");
- var->atomic.offset = *offset;
+ var->data.atomic.offset = *offset;
*offset += var->type->atomic_size();
} else {
_mesa_glsl_error(loc, state,
"atomic counters require explicit binding point");
}
- } else if (var->mode != ir_var_function_in) {
+ } else if (var->data.mode != ir_var_function_in) {
_mesa_glsl_error(loc, state, "atomic counters may only be declared as "
"function parameters or uniform-qualified "
"global variables");
@@ -2406,15 +2410,15 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
"gl_FragDepth");
}
if (qual->flags.q.depth_any)
- var->depth_layout = ir_depth_layout_any;
+ var->data.depth_layout = ir_depth_layout_any;
else if (qual->flags.q.depth_greater)
- var->depth_layout = ir_depth_layout_greater;
+ var->data.depth_layout = ir_depth_layout_greater;
else if (qual->flags.q.depth_less)
- var->depth_layout = ir_depth_layout_less;
+ var->data.depth_layout = ir_depth_layout_less;
else if (qual->flags.q.depth_unchanged)
- var->depth_layout = ir_depth_layout_unchanged;
+ var->data.depth_layout = ir_depth_layout_unchanged;
else
- var->depth_layout = ir_depth_layout_none;
+ var->data.depth_layout = ir_depth_layout_none;
if (qual->flags.q.std140 ||
qual->flags.q.packed ||
@@ -2475,10 +2479,10 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
const unsigned size = unsigned(var->type->array_size());
check_builtin_array_max_size(var->name, size, loc, state);
- if ((size > 0) && (size <= earlier->max_array_access)) {
+ if ((size > 0) && (size <= earlier->data.max_array_access)) {
_mesa_glsl_error(& loc, state, "array size must be > %u due to "
"previous access",
- earlier->max_array_access);
+ earlier->data.max_array_access);
}
earlier->type = var->type;
@@ -2488,12 +2492,12 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
state->is_version(150, 0))
&& strcmp(var->name, "gl_FragCoord") == 0
&& earlier->type == var->type
- && earlier->mode == var->mode) {
+ && earlier->data.mode == var->data.mode) {
/* Allow redeclaration of gl_FragCoord for ARB_fcc layout
* qualifiers.
*/
- earlier->origin_upper_left = var->origin_upper_left;
- earlier->pixel_center_integer = var->pixel_center_integer;
+ earlier->data.origin_upper_left = var->data.origin_upper_left;
+ earlier->data.pixel_center_integer = var->data.pixel_center_integer;
/* According to section 4.3.7 of the GLSL 1.30 spec,
* the following built-in varaibles can be redeclared with an
@@ -2513,41 +2517,41 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE loc,
|| strcmp(var->name, "gl_Color") == 0
|| strcmp(var->name, "gl_SecondaryColor") == 0)
&& earlier->type == var->type
- && earlier->mode == var->mode) {
- earlier->interpolation = var->interpolation;
+ && earlier->data.mode == var->data.mode) {
+ earlier->data.interpolation = var->data.interpolation;
/* Layout qualifiers for gl_FragDepth. */
} else if ((state->AMD_conservative_depth_enable ||
state->ARB_conservative_depth_enable)
&& strcmp(var->name, "gl_FragDepth") == 0
&& earlier->type == var->type
- && earlier->mode == var->mode) {
+ && earlier->data.mode == var->data.mode) {
/** From the AMD_conservative_depth spec:
* Within any shader, the first redeclarations of gl_FragDepth
* must appear before any use of gl_FragDepth.
*/
- if (earlier->used) {
+ if (earlier->data.used) {
_mesa_glsl_error(&loc, state,
"the first redeclaration of gl_FragDepth "
"must appear before any use of gl_FragDepth");
}
/* Prevent inconsistent redeclaration of depth layout qualifier. */
- if (earlier->depth_layout != ir_depth_layout_none
- && earlier->depth_layout != var->depth_layout) {
+ if (earlier->data.depth_layout != ir_depth_layout_none
+ && earlier->data.depth_layout != var->data.depth_layout) {
_mesa_glsl_error(&loc, state,
"gl_FragDepth: depth layout is declared here "
"as '%s, but it was previously declared as "
"'%s'",
- depth_layout_string(var->depth_layout),
- depth_layout_string(earlier->depth_layout));
+ depth_layout_string(var->data.depth_layout),
+ depth_layout_string(earlier->data.depth_layout));
}
- earlier->depth_layout = var->depth_layout;
+ earlier->data.depth_layout = var->data.depth_layout;
} else if (allow_all_redeclarations) {
- if (earlier->mode != var->mode) {
+ if (earlier->data.mode != var->data.mode) {
_mesa_glsl_error(&loc, state,
"redeclaration of `%s' with incorrect qualifiers",
var->name);
@@ -2582,7 +2586,7 @@ process_initializer(ir_variable *var, ast_declaration *decl,
* directly by an application via API commands, or indirectly by
* OpenGL."
*/
- if (var->mode == ir_var_uniform) {
+ if (var->data.mode == ir_var_uniform) {
state->check_version(120, 0, &initializer_loc,
"cannot initialize uniforms");
}
@@ -2592,11 +2596,11 @@ process_initializer(ir_variable *var, ast_declaration *decl,
"cannot initialize samplers");
}
- if ((var->mode == ir_var_shader_in) && (state->current_function == NULL)) {
+ if ((var->data.mode == ir_var_shader_in) && (state->current_function == NULL)) {
_mesa_glsl_error(& initializer_loc, state,
"cannot initialize %s shader input / %s",
_mesa_glsl_shader_target_name(state->target),
- (state->target == vertex_shader)
+ (state->target == MESA_SHADER_VERTEX)
? "attribute" : "varying");
}
@@ -2647,9 +2651,9 @@ process_initializer(ir_variable *var, ast_declaration *decl,
}
if (rhs && !rhs->type->is_error()) {
- bool temp = var->read_only;
+ bool temp = var->data.read_only;
if (type->qualifier.flags.q.constant)
- var->read_only = false;
+ var->data.read_only = false;
/* Never emit code to initialize a uniform.
*/
@@ -2664,7 +2668,7 @@ process_initializer(ir_variable *var, ast_declaration *decl,
initializer_type = rhs->type;
var->constant_initializer = rhs->constant_expression_value();
- var->has_initializer = true;
+ var->data.has_initializer = true;
/* If the declared variable is an unsized array, it must inherrit
* its full type from the initializer. A declaration such as
@@ -2688,7 +2692,7 @@ process_initializer(ir_variable *var, ast_declaration *decl,
*/
var->type = initializer_type;
- var->read_only = temp;
+ var->data.read_only = temp;
}
return result;
@@ -2840,23 +2844,23 @@ ast_declarator_list::hir(exec_list *instructions,
_mesa_glsl_error(& loc, state,
"undeclared variable `%s' cannot be marked "
"invariant", decl->identifier);
- } else if ((state->target == vertex_shader)
- && (earlier->mode != ir_var_shader_out)) {
+ } else if ((state->target == MESA_SHADER_VERTEX)
+ && (earlier->data.mode != ir_var_shader_out)) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, vertex shader "
"outputs only", decl->identifier);
- } else if ((state->target == fragment_shader)
- && (earlier->mode != ir_var_shader_in)) {
+ } else if ((state->target == MESA_SHADER_FRAGMENT)
+ && (earlier->data.mode != ir_var_shader_in)) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, fragment shader "
"inputs only", decl->identifier);
- } else if (earlier->used) {
+ } else if (earlier->data.used) {
_mesa_glsl_error(& loc, state,
"variable `%s' may not be redeclared "
"`invariant' after being used",
earlier->name);
} else {
- earlier->invariant = true;
+ earlier->data.invariant = true;
}
}
@@ -2940,7 +2944,7 @@ ast_declarator_list::hir(exec_list *instructions,
precision_names[this->type->qualifier.precision],
type_name);
}
- } else {
+ } else if (this->type->specifier->structure == NULL) {
_mesa_glsl_warning(&loc, state, "empty declaration");
}
}
@@ -3030,13 +3034,13 @@ ast_declarator_list::hir(exec_list *instructions,
& loc, false);
if (this->type->qualifier.flags.q.invariant) {
- if ((state->target == vertex_shader) &&
- var->mode != ir_var_shader_out) {
+ if ((state->target == MESA_SHADER_VERTEX) &&
+ var->data.mode != ir_var_shader_out) {
_mesa_glsl_error(& loc, state,
"`%s' cannot be marked invariant, vertex shader "
"outputs only", var->name);
- } else if ((state->target == fragment_shader) &&
- var->mode != ir_var_shader_in) {
+ } else if ((state->target == MESA_SHADER_FRAGMENT) &&
+ var->data.mode != ir_var_shader_in) {
/* FINISHME: Note that this doesn't work for invariant on
* a function signature inval
*/
@@ -3073,10 +3077,10 @@ ast_declarator_list::hir(exec_list *instructions,
"global scope%s",
mode, var->name, extra);
}
- } else if (var->mode == ir_var_shader_in) {
- var->read_only = true;
+ } else if (var->data.mode == ir_var_shader_in) {
+ var->data.read_only = true;
- if (state->target == vertex_shader) {
+ if (state->target == MESA_SHADER_VERTEX) {
bool error_emitted = false;
/* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
@@ -3131,7 +3135,7 @@ ast_declarator_list::hir(exec_list *instructions,
"cannot have array type")) {
error_emitted = true;
}
- } else if (state->target == geometry_shader) {
+ } else if (state->target == MESA_SHADER_GEOMETRY) {
/* From section 4.3.4 (Inputs) of the GLSL 1.50 spec:
*
* Geometry shader input variables get the per-vertex values
@@ -3180,11 +3184,11 @@ ast_declarator_list::hir(exec_list *instructions,
*/
if (state->is_version(130, 300) &&
var->type->contains_integer() &&
- var->interpolation != INTERP_QUALIFIER_FLAT &&
- ((state->target == fragment_shader && var->mode == ir_var_shader_in)
- || (state->target == vertex_shader && var->mode == ir_var_shader_out
+ var->data.interpolation != INTERP_QUALIFIER_FLAT &&
+ ((state->target == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in)
+ || (state->target == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out
&& state->es_shader))) {
- const char *var_type = (state->target == vertex_shader) ?
+ const char *var_type = (state->target == MESA_SHADER_VERTEX) ?
"vertex output" : "fragment input";
_mesa_glsl_error(&loc, state, "if a %s is (or contains) "
"an integer, then it must be qualified with 'flat'",
@@ -3241,14 +3245,14 @@ ast_declarator_list::hir(exec_list *instructions,
assert(i != NULL);
switch (state->target) {
- case vertex_shader:
+ case MESA_SHADER_VERTEX:
if (this->type->qualifier.flags.q.in) {
_mesa_glsl_error(&loc, state,
"qualifier '%s' cannot be applied to vertex "
"shader inputs", i);
}
break;
- case fragment_shader:
+ case MESA_SHADER_FRAGMENT:
if (this->type->qualifier.flags.q.out) {
_mesa_glsl_error(&loc, state,
"qualifier '%s' cannot be applied to fragment "
@@ -3271,12 +3275,20 @@ ast_declarator_list::hir(exec_list *instructions,
if (state->is_version(130, 300)
&& this->type->qualifier.flags.q.centroid
&& this->type->qualifier.flags.q.in
- && state->target == vertex_shader) {
+ && state->target == MESA_SHADER_VERTEX) {
_mesa_glsl_error(&loc, state,
"'centroid in' cannot be used in a vertex shader");
}
+ if (state->target == MESA_SHADER_VERTEX
+ && this->type->qualifier.flags.q.sample
+ && this->type->qualifier.flags.q.in) {
+
+ _mesa_glsl_error(&loc, state,
+ "'sample in' cannot be used in a vertex shader");
+ }
+
/* Section 4.3.6 of the GLSL 1.30 specification states:
* "It is an error to use centroid out in a fragment shader."
*
@@ -3284,7 +3296,7 @@ ast_declarator_list::hir(exec_list *instructions,
* "It is an error to use auxiliary storage qualifiers or interpolation
* qualifiers on an output in a fragment shader."
*/
- if (state->target == fragment_shader &&
+ if (state->target == MESA_SHADER_FRAGMENT &&
this->type->qualifier.flags.q.out &&
this->type->qualifier.has_auxiliary_storage()) {
_mesa_glsl_error(&loc, state,
@@ -3363,12 +3375,12 @@ ast_declarator_list::hir(exec_list *instructions,
false /* allow_all_redeclarations */);
if (earlier != NULL) {
if (strncmp(var->name, "gl_", 3) == 0 &&
- earlier->how_declared == ir_var_declared_in_block) {
+ earlier->data.how_declared == ir_var_declared_in_block) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared using "
"gl_PerVertex", var->name);
}
- earlier->how_declared = ir_var_declared_normally;
+ earlier->data.how_declared = ir_var_declared_normally;
}
if (decl->initializer != NULL) {
@@ -3548,7 +3560,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
* as out or inout function parameters, nor can they be assigned
* into."
*/
- if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out)
+ if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out)
&& type->contains_sampler()) {
_mesa_glsl_error(&loc, state, "out and inout parameters cannot contain samplers");
type = glsl_type::error_type;
@@ -3568,7 +3580,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
* So for GLSL 1.10, passing an array as an out or inout parameter is not
* allowed. This restriction is removed in GLSL 1.20, and in GLSL ES.
*/
- if ((var->mode == ir_var_function_inout || var->mode == ir_var_function_out)
+ if ((var->data.mode == ir_var_function_inout || var->data.mode == ir_var_function_out)
&& type->is_array()
&& !state->check_version(120, 100, &loc,
"arrays cannot be out or inout parameters")) {
@@ -3942,7 +3954,7 @@ ast_jump_statement::hir(exec_list *instructions,
}
case ast_discard:
- if (state->target != fragment_shader) {
+ if (state->target != MESA_SHADER_FRAGMENT) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state,
@@ -4480,7 +4492,7 @@ ast_type_specifier::hir(exec_list *instructions,
if (type->base_type == GLSL_TYPE_FLOAT
&& state->es_shader
- && state->target == fragment_shader) {
+ && state->target == MESA_SHADER_FRAGMENT) {
/* Section 4.5.3 (Default Precision Qualifiers) of the GLSL ES 1.00
* spec says:
*
@@ -4662,6 +4674,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
fields[i].interpolation =
interpret_interpolation_qualifier(qual, var_mode, state, &loc);
fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
+ fields[i].sample = qual->flags.q.sample ? 1 : 0;
if (qual->flags.q.row_major || qual->flags.q.column_major) {
if (!qual->flags.q.uniform) {
@@ -4782,7 +4795,7 @@ public:
virtual ir_visitor_status visit(ir_dereference_variable *ir)
{
- if (ir->var->mode == mode && ir->var->get_interface_type() == block) {
+ if (ir->var->data.mode == mode && ir->var->get_interface_type() == block) {
found = true;
return visit_stop;
}
@@ -4930,6 +4943,8 @@ ast_interface_block::hir(exec_list *instructions,
earlier_per_vertex->fields.structure[j].interpolation;
fields[i].centroid =
earlier_per_vertex->fields.structure[j].centroid;
+ fields[i].sample =
+ earlier_per_vertex->fields.structure[j].sample;
}
}
@@ -4980,7 +4995,7 @@ ast_interface_block::hir(exec_list *instructions,
* variable (or input block, see interface blocks below) needs to be
* declared as an array.
*/
- if (state->target == geometry_shader && !this->is_array &&
+ if (state->target == MESA_SHADER_GEOMETRY && !this->is_array &&
var_mode == ir_var_shader_in) {
_mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays");
}
@@ -5035,7 +5050,7 @@ ast_interface_block::hir(exec_list *instructions,
* geometry shader input.
*/
if (this->array_size == NULL &&
- (state->target != geometry_shader || !this->layout.flags.q.in)) {
+ (state->target != MESA_SHADER_GEOMETRY || !this->layout.flags.q.in)) {
_mesa_glsl_error(&loc, state,
"only geometry shader inputs may be unsized "
"instance block arrays");
@@ -5054,7 +5069,7 @@ ast_interface_block::hir(exec_list *instructions,
var_mode);
}
- if (state->target == geometry_shader && var_mode == ir_var_shader_in)
+ if (state->target == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
handle_geometry_shader_input_decl(state, loc, var);
if (ir_variable *earlier =
@@ -5063,7 +5078,7 @@ ast_interface_block::hir(exec_list *instructions,
_mesa_glsl_error(&loc, state, "`%s' redeclared",
this->instance_name);
}
- earlier->how_declared = ir_var_declared_normally;
+ earlier->data.how_declared = ir_var_declared_normally;
earlier->type = var->type;
earlier->reinit_interface_type(block_type);
delete var;
@@ -5082,8 +5097,9 @@ ast_interface_block::hir(exec_list *instructions,
new(state) ir_variable(fields[i].type,
ralloc_strdup(state, fields[i].name),
var_mode);
- var->interpolation = fields[i].interpolation;
- var->centroid = fields[i].centroid;
+ var->data.interpolation = fields[i].interpolation;
+ var->data.centroid = fields[i].centroid;
+ var->data.sample = fields[i].sample;
var->init_interface_type(block_type);
if (redeclaring_per_vertex) {
@@ -5094,11 +5110,11 @@ ast_interface_block::hir(exec_list *instructions,
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex can only "
"include built-in variables");
- } else if (earlier->how_declared == ir_var_declared_normally) {
+ } else if (earlier->data.how_declared == ir_var_declared_normally) {
_mesa_glsl_error(&loc, state,
"`%s' has already been redeclared", var->name);
} else {
- earlier->how_declared = ir_var_declared_in_block;
+ earlier->data.how_declared = ir_var_declared_in_block;
earlier->reinit_interface_type(block_type);
}
continue;
@@ -5111,8 +5127,8 @@ ast_interface_block::hir(exec_list *instructions,
* the UBO declaration itself doesn't get an ir_variable unless it
* has an instance name. This is ugly.
*/
- var->explicit_binding = this->layout.flags.q.explicit_binding;
- var->binding = this->layout.binding;
+ var->data.explicit_binding = this->layout.flags.q.explicit_binding;
+ var->data.binding = this->layout.binding;
state->symbols->add_variable(var);
instructions->push_tail(var);
@@ -5144,8 +5160,8 @@ ast_interface_block::hir(exec_list *instructions,
ir_variable *const var = ((ir_instruction *) node)->as_variable();
if (var != NULL &&
var->get_interface_type() == earlier_per_vertex &&
- var->mode == var_mode) {
- if (var->how_declared == ir_var_declared_normally) {
+ var->data.mode == var_mode) {
+ if (var->data.how_declared == ir_var_declared_normally) {
_mesa_glsl_error(&loc, state,
"redeclaration of gl_PerVertex cannot "
"follow a redeclaration of `%s'",
@@ -5200,7 +5216,7 @@ ast_gs_input_layout::hir(exec_list *instructions,
*/
foreach_list (node, instructions) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
- if (var == NULL || var->mode != ir_var_shader_in)
+ if (var == NULL || var->data.mode != ir_var_shader_in)
continue;
/* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an
@@ -5208,12 +5224,12 @@ ast_gs_input_layout::hir(exec_list *instructions,
*/
if (var->type->is_unsized_array()) {
- if (var->max_array_access >= num_vertices) {
+ if (var->data.max_array_access >= num_vertices) {
_mesa_glsl_error(&loc, state,
"this geometry shader input layout implies %u"
" vertices, but an access to element %u of input"
" `%s' already exists", num_vertices,
- var->max_array_access, var->name);
+ var->data.max_array_access, var->name);
} else {
var->type = glsl_type::get_array_instance(var->type->fields.array,
num_vertices);
@@ -5241,7 +5257,7 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
foreach_list(node, instructions) {
ir_variable *var = ((ir_instruction *)node)->as_variable();
- if (!var || !var->assigned)
+ if (!var || !var->data.assigned)
continue;
if (strcmp(var->name, "gl_FragColor") == 0)
@@ -5249,8 +5265,8 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
else if (strcmp(var->name, "gl_FragData") == 0)
gl_FragData_assigned = true;
else if (strncmp(var->name, "gl_", 3) != 0) {
- if (state->target == fragment_shader &&
- var->mode == ir_var_shader_out) {
+ if (state->target == MESA_SHADER_FRAGMENT &&
+ var->data.mode == ir_var_shader_out) {
user_defined_fs_output_assigned = true;
user_defined_fs_output = var;
}
@@ -5331,7 +5347,7 @@ remove_per_vertex_blocks(exec_list *instructions,
foreach_list_safe(node, instructions) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
if (var != NULL && var->get_interface_type() == per_vertex &&
- var->mode == mode) {
+ var->data.mode == mode) {
state->symbols->disable_variable(var->name);
var->remove();
}
diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp
index 2b088bf8b..d758bfa1f 100644
--- a/mesalib/src/glsl/ast_type.cpp
+++ b/mesalib/src/glsl/ast_type.cpp
@@ -90,7 +90,8 @@ ast_type_qualifier::has_storage() const
bool
ast_type_qualifier::has_auxiliary_storage() const
{
- return this->flags.q.centroid;
+ return this->flags.q.centroid
+ || this->flags.q.sample;
}
const char*
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index a45de091b..f22ace19d 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -77,7 +77,7 @@ always_available(const _mesa_glsl_parse_state *state)
static bool
compatibility_vs_only(const _mesa_glsl_parse_state *state)
{
- return state->target == vertex_shader &&
+ return state->target == MESA_SHADER_VERTEX &&
state->language_version <= 130 &&
!state->es_shader;
}
@@ -85,13 +85,13 @@ compatibility_vs_only(const _mesa_glsl_parse_state *state)
static bool
fs_only(const _mesa_glsl_parse_state *state)
{
- return state->target == fragment_shader;
+ return state->target == MESA_SHADER_FRAGMENT;
}
static bool
gs_only(const _mesa_glsl_parse_state *state)
{
- return state->target == geometry_shader;
+ return state->target == MESA_SHADER_GEOMETRY;
}
static bool
@@ -103,7 +103,7 @@ v110(const _mesa_glsl_parse_state *state)
static bool
v110_fs_only(const _mesa_glsl_parse_state *state)
{
- return !state->es_shader && state->target == fragment_shader;
+ return !state->es_shader && state->target == MESA_SHADER_FRAGMENT;
}
static bool
@@ -122,7 +122,7 @@ static bool
v130_fs_only(const _mesa_glsl_parse_state *state)
{
return state->is_version(130, 300) &&
- state->target == fragment_shader;
+ state->target == MESA_SHADER_FRAGMENT;
}
static bool
@@ -155,7 +155,7 @@ lod_exists_in_stage(const _mesa_glsl_parse_state *state)
* Since ARB_shader_texture_lod can only be enabled on desktop GLSL, we
* don't need to explicitly check state->es_shader.
*/
- return state->target == vertex_shader ||
+ return state->target == MESA_SHADER_VERTEX ||
state->is_version(130, 300) ||
state->ARB_shader_texture_lod_enable;
}
@@ -223,7 +223,7 @@ texture_array_lod(const _mesa_glsl_parse_state *state)
static bool
fs_texture_array(const _mesa_glsl_parse_state *state)
{
- return state->target == fragment_shader &&
+ return state->target == MESA_SHADER_FRAGMENT &&
state->EXT_texture_array_enable;
}
@@ -243,7 +243,7 @@ texture_multisample(const _mesa_glsl_parse_state *state)
static bool
fs_texture_cube_map_array(const _mesa_glsl_parse_state *state)
{
- return state->target == fragment_shader &&
+ return state->target == MESA_SHADER_FRAGMENT &&
(state->is_version(400, 0) ||
state->ARB_texture_cube_map_array_enable);
}
@@ -265,7 +265,7 @@ texture_query_levels(const _mesa_glsl_parse_state *state)
static bool
texture_query_lod(const _mesa_glsl_parse_state *state)
{
- return state->target == fragment_shader &&
+ return state->target == MESA_SHADER_FRAGMENT &&
state->ARB_texture_query_lod_enable;
}
@@ -292,7 +292,7 @@ texture_gather_only(const _mesa_glsl_parse_state *state)
static bool
fs_oes_derivatives(const _mesa_glsl_parse_state *state)
{
- return state->target == fragment_shader &&
+ return state->target == MESA_SHADER_FRAGMENT &&
(state->is_version(110, 300) ||
state->OES_standard_derivatives_enable);
}
@@ -318,7 +318,7 @@ tex3d(const _mesa_glsl_parse_state *state)
static bool
fs_tex3d(const _mesa_glsl_parse_state *state)
{
- return state->target == fragment_shader &&
+ return state->target == MESA_SHADER_FRAGMENT &&
(!state->es_shader || state->OES_texture_3D_enable);
}
@@ -357,8 +357,6 @@ public:
ir_function_signature *find(_mesa_glsl_parse_state *state,
const char *name, exec_list *actual_parameters);
-private:
- void *mem_ctx;
/**
* A shader to hold all the built-in signatures; created by this module.
*
@@ -368,6 +366,9 @@ private:
*/
gl_shader *shader;
+private:
+ void *mem_ctx;
+
/** Global variables used by built-in functions. */
ir_variable *gl_ModelViewProjectionMatrix;
ir_variable *gl_Vertex;
@@ -608,8 +609,7 @@ builtin_builder::find(_mesa_glsl_parse_state *state,
* that the "no matching signature" error will list potential candidates
* from the available built-ins.
*/
- state->builtins_to_link[0] = shader;
- state->num_builtins_to_link = 1;
+ state->uses_builtin_functions = true;
ir_function *f = shader->symbols->get_function(name);
if (f == NULL)
@@ -4020,4 +4020,11 @@ _mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
{
return builtins.find(state, name, actual_parameters);
}
+
+gl_shader *
+_mesa_glsl_get_builtin_function_shader()
+{
+ return builtins.shader;
+}
+
/** @} */
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index d57324c2f..ff9acb8d0 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -332,6 +332,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type,
this->fields[this->num_fields].location = slot;
this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE;
this->fields[this->num_fields].centroid = 0;
+ this->fields[this->num_fields].sample = 0;
this->num_fields++;
}
@@ -434,14 +435,14 @@ builtin_variable_generator::add_variable(const char *name,
enum ir_variable_mode mode, int slot)
{
ir_variable *var = new(symtab) ir_variable(type, name, mode);
- var->how_declared = ir_var_declared_implicitly;
+ var->data.how_declared = ir_var_declared_implicitly;
- switch (var->mode) {
+ switch (var->data.mode) {
case ir_var_auto:
case ir_var_shader_in:
case ir_var_uniform:
case ir_var_system_value:
- var->read_only = true;
+ var->data.read_only = true;
break;
case ir_var_shader_out:
break;
@@ -454,9 +455,9 @@ builtin_variable_generator::add_variable(const char *name,
break;
}
- var->location = slot;
- var->explicit_location = (slot >= 0);
- var->explicit_index = 0;
+ var->data.location = slot;
+ var->data.explicit_location = (slot >= 0);
+ var->data.explicit_index = 0;
/* Once the variable is created an initialized, add it to the symbol table
* and add the declaration to the IR stream.
@@ -523,7 +524,7 @@ builtin_variable_generator::add_const(const char *name, int value)
ir_var_auto, -1);
var->constant_value = new(var) ir_constant(value);
var->constant_initializer = new(var) ir_constant(value);
- var->has_initializer = true;
+ var->data.has_initializer = true;
return var;
}
@@ -792,9 +793,9 @@ builtin_variable_generator::generate_gs_special_vars()
*/
ir_variable *var;
var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn");
- var->interpolation = INTERP_QUALIFIER_FLAT;
+ var->data.interpolation = INTERP_QUALIFIER_FLAT;
var = add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID");
- var->interpolation = INTERP_QUALIFIER_FLAT;
+ var->data.interpolation = INTERP_QUALIFIER_FLAT;
}
@@ -812,7 +813,7 @@ builtin_variable_generator::generate_fs_special_vars()
if (state->is_version(150, 0)) {
ir_variable *var =
add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID");
- var->interpolation = INTERP_QUALIFIER_FLAT;
+ var->data.interpolation = INTERP_QUALIFIER_FLAT;
}
/* gl_FragColor and gl_FragData were deprecated starting in desktop GLSL
@@ -857,6 +858,10 @@ builtin_variable_generator::generate_fs_special_vars()
*/
add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask");
}
+
+ if (state->ARB_gpu_shader5_enable) {
+ add_system_value(SYSTEM_VALUE_SAMPLE_MASK_IN, array(int_t, 1), "gl_SampleMaskIn");
+ }
}
@@ -872,13 +877,13 @@ builtin_variable_generator::add_varying(int slot, const glsl_type *type,
const char *name_as_gs_input)
{
switch (state->target) {
- case geometry_shader:
+ case MESA_SHADER_GEOMETRY:
this->per_vertex_in.add_field(slot, type, name);
/* FALLTHROUGH */
- case vertex_shader:
+ case MESA_SHADER_VERTEX:
this->per_vertex_out.add_field(slot, type, name);
break;
- case fragment_shader:
+ case MESA_SHADER_FRAGMENT:
add_input(slot, type, name);
break;
}
@@ -896,7 +901,7 @@ builtin_variable_generator::generate_varyings()
add_varying(loc, type, name, name "In")
/* gl_Position and gl_PointSize are not visible from fragment shaders. */
- if (state->target != fragment_shader) {
+ if (state->target != MESA_SHADER_FRAGMENT) {
ADD_VARYING(VARYING_SLOT_POS, vec4_t, "gl_Position");
ADD_VARYING(VARYING_SLOT_PSIZ, float_t, "gl_PointSize");
}
@@ -909,7 +914,7 @@ builtin_variable_generator::generate_varyings()
if (compatibility) {
ADD_VARYING(VARYING_SLOT_TEX0, array(vec4_t, 0), "gl_TexCoord");
ADD_VARYING(VARYING_SLOT_FOGC, float_t, "gl_FogFragCoord");
- if (state->target == fragment_shader) {
+ if (state->target == MESA_SHADER_FRAGMENT) {
ADD_VARYING(VARYING_SLOT_COL0, vec4_t, "gl_Color");
ADD_VARYING(VARYING_SLOT_COL1, vec4_t, "gl_SecondaryColor");
} else {
@@ -921,13 +926,13 @@ builtin_variable_generator::generate_varyings()
}
}
- if (state->target == geometry_shader) {
+ if (state->target == MESA_SHADER_GEOMETRY) {
const glsl_type *per_vertex_in_type =
this->per_vertex_in.construct_interface_instance();
add_variable("gl_in", array(per_vertex_in_type, 0),
ir_var_shader_in, -1);
}
- if (state->target == vertex_shader || state->target == geometry_shader) {
+ if (state->target == MESA_SHADER_VERTEX || state->target == MESA_SHADER_GEOMETRY) {
const glsl_type *per_vertex_out_type =
this->per_vertex_out.construct_interface_instance();
const glsl_struct_field *fields = per_vertex_out_type->fields.structure;
@@ -935,8 +940,9 @@ builtin_variable_generator::generate_varyings()
ir_variable *var =
add_variable(fields[i].name, fields[i].type, ir_var_shader_out,
fields[i].location);
- var->interpolation = fields[i].interpolation;
- var->centroid = fields[i].centroid;
+ var->data.interpolation = fields[i].interpolation;
+ var->data.centroid = fields[i].centroid;
+ var->data.sample = fields[i].sample;
var->init_interface_type(per_vertex_out_type);
}
}
@@ -958,13 +964,13 @@ _mesa_glsl_initialize_variables(exec_list *instructions,
gen.generate_varyings();
switch (state->target) {
- case vertex_shader:
+ case MESA_SHADER_VERTEX:
gen.generate_vs_special_vars();
break;
- case geometry_shader:
+ case MESA_SHADER_GEOMETRY:
gen.generate_gs_special_vars();
break;
- case fragment_shader:
+ case MESA_SHADER_FRAGMENT:
gen.generate_fs_special_vars();
break;
}
diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll
index 822d70d6b..50875bf3b 100644
--- a/mesalib/src/glsl/glsl_lexer.ll
+++ b/mesalib/src/glsl/glsl_lexer.ll
@@ -520,7 +520,7 @@ readonly KEYWORD(0, 300, 0, 0, READONLY);
writeonly KEYWORD(0, 300, 0, 0, WRITEONLY);
resource KEYWORD(0, 300, 0, 0, RESOURCE);
patch KEYWORD(0, 300, 0, 0, PATCH);
-sample KEYWORD(0, 300, 0, 0, SAMPLE);
+sample KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE);
subroutine KEYWORD(0, 300, 0, 0, SUBROUTINE);
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 8ad7484fb..6cd129cae 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -1522,7 +1522,7 @@ type_qualifier:
{
if ($2.has_auxiliary_storage()) {
_mesa_glsl_error(&@1, state,
- "duplicate auxiliary storage qualifier (centroid)");
+ "duplicate auxiliary storage qualifier (centroid or sample)");
}
if (!state->ARB_shading_language_420pack_enable &&
@@ -1572,7 +1572,12 @@ auxiliary_storage_qualifier:
memset(& $$, 0, sizeof($$));
$$.flags.q.centroid = 1;
}
- /* TODO: "sample" and "patch" also go here someday. */
+ | SAMPLE
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.sample = 1;
+ }
+ /* TODO: "patch" also goes here someday. */
storage_qualifier:
CONST_TOK
@@ -2215,11 +2220,11 @@ basic_interface_block:
* "It is illegal to have an input block in a vertex shader
* or an output block in a fragment shader"
*/
- if ((state->target == vertex_shader) && $1.flags.q.in) {
+ if ((state->target == MESA_SHADER_VERTEX) && $1.flags.q.in) {
_mesa_glsl_error(& @1, state,
"`in' interface block is not allowed for "
"a vertex shader");
- } else if ((state->target == fragment_shader) && $1.flags.q.out) {
+ } else if ((state->target == MESA_SHADER_FRAGMENT) && $1.flags.q.out) {
_mesa_glsl_error(& @1, state,
"`out' interface block is not allowed for "
"a fragment shader");
@@ -2373,7 +2378,7 @@ layout_defaults:
{
void *ctx = state;
$$ = NULL;
- if (state->target != geometry_shader) {
+ if (state->target != MESA_SHADER_GEOMETRY) {
_mesa_glsl_error(& @1, state,
"input layout qualifiers only valid in "
"geometry shaders");
@@ -2401,7 +2406,7 @@ layout_defaults:
| layout_qualifier OUT_TOK ';'
{
- if (state->target != geometry_shader) {
+ if (state->target != MESA_SHADER_GEOMETRY) {
_mesa_glsl_error(& @1, state,
"out layout qualifiers only valid in "
"geometry shaders");
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index d76d94b7a..5f19368d8 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -58,9 +58,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
: ctx(_ctx), switch_state()
{
switch (target) {
- case GL_VERTEX_SHADER: this->target = vertex_shader; break;
- case GL_FRAGMENT_SHADER: this->target = fragment_shader; break;
- case GL_GEOMETRY_SHADER: this->target = geometry_shader; break;
+ case GL_VERTEX_SHADER: this->target = MESA_SHADER_VERTEX; break;
+ case GL_FRAGMENT_SHADER: this->target = MESA_SHADER_FRAGMENT; break;
+ case GL_GEOMETRY_SHADER: this->target = MESA_SHADER_GEOMETRY; break;
}
this->scanner = NULL;
@@ -76,7 +76,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->loop_nesting_ast = NULL;
this->struct_specifier_depth = 0;
- this->num_builtins_to_link = 0;
+
+ this->uses_builtin_functions = false;
/* Set default language version and extensions */
this->language_version = ctx->Const.ForceGLSLVersion ?
@@ -366,12 +367,12 @@ _mesa_glsl_shader_target_name(GLenum type)
* our internal enum into short stage names.
*/
const char *
-_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target)
+_mesa_glsl_shader_target_name(gl_shader_type target)
{
switch (target) {
- case vertex_shader: return "vertex";
- case fragment_shader: return "fragment";
- case geometry_shader: return "geometry";
+ case MESA_SHADER_VERTEX: return "vertex";
+ case MESA_SHADER_FRAGMENT: return "fragment";
+ case MESA_SHADER_GEOMETRY: return "geometry";
}
assert(!"Should not get here.");
@@ -877,6 +878,8 @@ _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
if (q->flags.q.centroid)
printf("centroid ");
+ if (q->flags.q.sample)
+ printf("sample ");
if (q->flags.q.uniform)
printf("uniform ");
if (q->flags.q.smooth)
@@ -1532,10 +1535,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
shader->InfoLog = state->info_log;
shader->Version = state->language_version;
shader->IsES = state->es_shader;
-
- memcpy(shader->builtins_to_link, state->builtins_to_link,
- sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
- shader->num_builtins_to_link = state->num_builtins_to_link;
+ shader->uses_builtin_functions = state->uses_builtin_functions;
if (shader->UniformBlocks)
ralloc_free(shader->UniformBlocks);
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index cb998d80e..7aa78d611 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -34,12 +34,6 @@
#include <stdlib.h>
#include "glsl_symbol_table.h"
-enum _mesa_glsl_parser_targets {
- vertex_shader,
- geometry_shader,
- fragment_shader
-};
-
struct gl_context;
struct glsl_switch_state {
@@ -175,7 +169,7 @@ struct _mesa_glsl_parse_state {
bool es_shader;
unsigned language_version;
- enum _mesa_glsl_parser_targets target;
+ gl_shader_type target;
/**
* Number of nested struct_specifier levels
@@ -365,9 +359,7 @@ struct _mesa_glsl_parse_state {
/** Extensions supported by the OpenGL implementation. */
const struct gl_extensions *extensions;
- /** Shaders containing built-in functions that are used for linking. */
- struct gl_shader *builtins_to_link[16];
- unsigned num_builtins_to_link;
+ bool uses_builtin_functions;
/**
* For geometry shaders, size of the most recently seen input declaration
@@ -437,7 +429,7 @@ extern bool _mesa_glsl_process_extension(const char *name, YYLTYPE *name_locp,
* Get the textual name of the specified shader target
*/
extern const char *
-_mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target);
+_mesa_glsl_shader_target_name(gl_shader_type target);
#endif /* __cplusplus */
diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp
index f74013096..12d4ac0ee 100644
--- a/mesalib/src/glsl/glsl_types.cpp
+++ b/mesalib/src/glsl/glsl_types.cpp
@@ -103,6 +103,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].location = fields[i].location;
this->fields.structure[i].interpolation = fields[i].interpolation;
this->fields.structure[i].centroid = fields[i].centroid;
+ this->fields.structure[i].sample = fields[i].sample;
this->fields.structure[i].row_major = fields[i].row_major;
}
}
@@ -130,6 +131,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
this->fields.structure[i].location = fields[i].location;
this->fields.structure[i].interpolation = fields[i].interpolation;
this->fields.structure[i].centroid = fields[i].centroid;
+ this->fields.structure[i].sample = fields[i].sample;
this->fields.structure[i].row_major = fields[i].row_major;
}
}
@@ -483,6 +485,9 @@ glsl_type::record_key_compare(const void *a, const void *b)
if (key1->fields.structure[i].centroid
!= key2->fields.structure[i].centroid)
return 1;
+ if (key1->fields.structure[i].sample
+ != key2->fields.structure[i].sample)
+ return 1;
}
return 0;
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index 96eee5e64..fb7c9288d 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -634,6 +634,12 @@ struct glsl_struct_field {
* in ir_variable::centroid). 0 otherwise.
*/
unsigned centroid:1;
+
+ /**
+ * For interface blocks, 1 if this variable uses sample interpolation (as
+ * in ir_variable::sample). 0 otherwise.
+ */
+ unsigned sample:1;
};
static inline unsigned int
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 64a2c5af9..8af58b847 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -1277,11 +1277,6 @@ ir_constant::is_basis() const
ir_loop::ir_loop()
{
this->ir_type = ir_type_loop;
- this->cmp = ir_unop_neg;
- this->from = NULL;
- this->to = NULL;
- this->increment = NULL;
- this->counter = NULL;
}
@@ -1364,7 +1359,7 @@ ir_dereference::is_lvalue() const
/* Every l-value derference chain eventually ends in a variable.
*/
- if ((var == NULL) || var->read_only)
+ if ((var == NULL) || var->data.read_only)
return false;
/* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
@@ -1584,29 +1579,36 @@ ir_swizzle::variable_referenced() const
ir_variable::ir_variable(const struct glsl_type *type, const char *name,
ir_variable_mode mode)
- : max_array_access(0), max_ifc_array_access(NULL),
- read_only(false), centroid(false), invariant(false),
- how_declared(ir_var_declared_normally), mode(mode),
- interpolation(INTERP_QUALIFIER_NONE), atomic()
+ : max_ifc_array_access(NULL)
{
this->ir_type = ir_type_variable;
this->type = type;
this->name = ralloc_strdup(this, name);
- this->explicit_location = false;
- this->has_initializer = false;
- this->location = -1;
- this->location_frac = 0;
+ this->data.explicit_location = false;
+ this->data.has_initializer = false;
+ this->data.location = -1;
+ this->data.location_frac = 0;
this->warn_extension = NULL;
this->constant_value = NULL;
this->constant_initializer = NULL;
- this->origin_upper_left = false;
- this->pixel_center_integer = false;
- this->depth_layout = ir_depth_layout_none;
- this->used = false;
+ this->data.origin_upper_left = false;
+ this->data.pixel_center_integer = false;
+ this->data.depth_layout = ir_depth_layout_none;
+ this->data.used = false;
+ this->data.read_only = false;
+ this->data.centroid = false;
+ this->data.sample = false;
+ this->data.invariant = false;
+ this->data.how_declared = ir_var_declared_normally;
+ this->data.mode = mode;
+ this->data.interpolation = INTERP_QUALIFIER_NONE;
+ this->data.max_array_access = 0;
+ this->data.atomic.buffer_index = 0;
+ this->data.atomic.offset = 0;
if (type != NULL) {
if (type->base_type == GLSL_TYPE_SAMPLER)
- this->read_only = true;
+ this->data.read_only = true;
if (type->is_interface())
this->init_interface_type(type);
@@ -1634,9 +1636,9 @@ interpolation_string(unsigned interpolation)
glsl_interp_qualifier
ir_variable::determine_interpolation_mode(bool flat_shade)
{
- if (this->interpolation != INTERP_QUALIFIER_NONE)
- return (glsl_interp_qualifier) this->interpolation;
- int location = this->location;
+ if (this->data.interpolation != INTERP_QUALIFIER_NONE)
+ return (glsl_interp_qualifier) this->data.interpolation;
+ int location = this->data.location;
bool is_gl_Color =
location == VARYING_SLOT_COL0 || location == VARYING_SLOT_COL1;
if (flat_shade && is_gl_Color)
@@ -1706,10 +1708,11 @@ ir_function_signature::qualifiers_match(exec_list *params)
ir_variable *a = (ir_variable *)iter_a.get();
ir_variable *b = (ir_variable *)iter_b.get();
- if (a->read_only != b->read_only ||
- !modes_match(a->mode, b->mode) ||
- a->interpolation != b->interpolation ||
- a->centroid != b->centroid) {
+ if (a->data.read_only != b->data.read_only ||
+ !modes_match(a->data.mode, b->data.mode) ||
+ a->data.interpolation != b->data.interpolation ||
+ a->data.centroid != b->data.centroid ||
+ a->data.sample != b->data.sample) {
/* parameter a's qualifiers don't match */
return a->name;
@@ -1729,12 +1732,6 @@ ir_function_signature::replace_parameters(exec_list *new_params)
* parameter information comes from the function prototype, it may either
* specify incorrect parameter names or not have names at all.
*/
- foreach_iter(exec_list_iterator, iter, parameters) {
- assert(((ir_instruction *) iter.get())->as_variable() != NULL);
-
- iter.remove();
- }
-
new_params->move_nodes_to(&parameters);
}
@@ -1899,9 +1896,9 @@ vertices_per_prim(GLenum prim)
const char *
mode_string(const ir_variable *var)
{
- switch (var->mode) {
+ switch (var->data.mode) {
case ir_var_auto:
- return (var->read_only) ? "global constant" : "global variable";
+ return (var->data.read_only) ? "global constant" : "global variable";
case ir_var_uniform:
return "uniform";
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 4f775da4b..780959b73 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -86,6 +86,7 @@ enum ir_node_type {
ir_type_max /**< maximum ir_type enum number, for validation */
};
+
/**
* Base class of all IR instructions
*/
@@ -402,7 +403,7 @@ public:
*/
inline bool is_in_uniform_block() const
{
- return this->mode == ir_var_uniform && this->interface_type != NULL;
+ return this->data.mode == ir_var_uniform && this->interface_type != NULL;
}
/**
@@ -502,13 +503,6 @@ public:
const char *name;
/**
- * Highest element accessed with a constant expression array index
- *
- * Not used for non-array variables.
- */
- unsigned max_array_access;
-
- /**
* For variables which satisfy the is_interface_instance() predicate, this
* points to an array of integers such that if the ith member of the
* interface block is an array, max_ifc_array_access[i] is the maximum
@@ -521,177 +515,189 @@ public:
*/
unsigned *max_ifc_array_access;
- /**
- * Is the variable read-only?
- *
- * This is set for variables declared as \c const, shader inputs,
- * and uniforms.
- */
- unsigned read_only:1;
- unsigned centroid:1;
- unsigned invariant:1;
-
- /**
- * Has this variable been used for reading or writing?
- *
- * Several GLSL semantic checks require knowledge of whether or not a
- * variable has been used. For example, it is an error to redeclare a
- * variable as invariant after it has been used.
- *
- * This is only maintained in the ast_to_hir.cpp path, not in
- * Mesa's fixed function or ARB program paths.
- */
- unsigned used:1;
-
- /**
- * Has this variable been statically assigned?
- *
- * This answers whether the variable was assigned in any path of
- * the shader during ast_to_hir. This doesn't answer whether it is
- * still written after dead code removal, nor is it maintained in
- * non-ast_to_hir.cpp (GLSL parsing) paths.
- */
- unsigned assigned:1;
-
- /**
- * Enum indicating how the variable was declared. See
- * ir_var_declaration_type.
- *
- * This is used to detect certain kinds of illegal variable redeclarations.
- */
- unsigned how_declared:2;
-
- /**
- * Storage class of the variable.
- *
- * \sa ir_variable_mode
- */
- unsigned mode:4;
-
- /**
- * Interpolation mode for shader inputs / outputs
- *
- * \sa ir_variable_interpolation
- */
- unsigned interpolation:2;
-
- /**
- * \name ARB_fragment_coord_conventions
- * @{
- */
- unsigned origin_upper_left:1;
- unsigned pixel_center_integer:1;
- /*@}*/
+ struct ir_variable_data {
- /**
- * Was the location explicitly set in the shader?
- *
- * If the location is explicitly set in the shader, it \b cannot be changed
- * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
- * no effect).
- */
- unsigned explicit_location:1;
- unsigned explicit_index:1;
-
- /**
- * Was an initial binding explicitly set in the shader?
- *
- * If so, constant_value contains an integer ir_constant representing the
- * initial binding point.
- */
- unsigned explicit_binding:1;
+ /**
+ * Is the variable read-only?
+ *
+ * This is set for variables declared as \c const, shader inputs,
+ * and uniforms.
+ */
+ unsigned read_only:1;
+ unsigned centroid:1;
+ unsigned sample:1;
+ unsigned invariant:1;
+
+ /**
+ * Has this variable been used for reading or writing?
+ *
+ * Several GLSL semantic checks require knowledge of whether or not a
+ * variable has been used. For example, it is an error to redeclare a
+ * variable as invariant after it has been used.
+ *
+ * This is only maintained in the ast_to_hir.cpp path, not in
+ * Mesa's fixed function or ARB program paths.
+ */
+ unsigned used:1;
+
+ /**
+ * Has this variable been statically assigned?
+ *
+ * This answers whether the variable was assigned in any path of
+ * the shader during ast_to_hir. This doesn't answer whether it is
+ * still written after dead code removal, nor is it maintained in
+ * non-ast_to_hir.cpp (GLSL parsing) paths.
+ */
+ unsigned assigned:1;
- /**
- * Does this variable have an initializer?
- *
- * This is used by the linker to cross-validiate initializers of global
- * variables.
- */
- unsigned has_initializer:1;
+ /**
+ * Enum indicating how the variable was declared. See
+ * ir_var_declaration_type.
+ *
+ * This is used to detect certain kinds of illegal variable redeclarations.
+ */
+ unsigned how_declared:2;
- /**
- * Is this variable a generic output or input that has not yet been matched
- * up to a variable in another stage of the pipeline?
- *
- * This is used by the linker as scratch storage while assigning locations
- * to generic inputs and outputs.
- */
- unsigned is_unmatched_generic_inout:1;
+ /**
+ * Storage class of the variable.
+ *
+ * \sa ir_variable_mode
+ */
+ unsigned mode:4;
- /**
- * If non-zero, then this variable may be packed along with other variables
- * into a single varying slot, so this offset should be applied when
- * accessing components. For example, an offset of 1 means that the x
- * component of this variable is actually stored in component y of the
- * location specified by \c location.
- */
- unsigned location_frac:2;
+ /**
+ * Interpolation mode for shader inputs / outputs
+ *
+ * \sa ir_variable_interpolation
+ */
+ unsigned interpolation:2;
- /**
- * Non-zero if this variable was created by lowering a named interface
- * block which was not an array.
- *
- * Note that this variable and \c from_named_ifc_block_array will never
- * both be non-zero.
- */
- unsigned from_named_ifc_block_nonarray:1;
+ /**
+ * \name ARB_fragment_coord_conventions
+ * @{
+ */
+ unsigned origin_upper_left:1;
+ unsigned pixel_center_integer:1;
+ /*@}*/
+
+ /**
+ * Was the location explicitly set in the shader?
+ *
+ * If the location is explicitly set in the shader, it \b cannot be changed
+ * by the linker or by the API (e.g., calls to \c glBindAttribLocation have
+ * no effect).
+ */
+ unsigned explicit_location:1;
+ unsigned explicit_index:1;
+
+ /**
+ * Was an initial binding explicitly set in the shader?
+ *
+ * If so, constant_value contains an integer ir_constant representing the
+ * initial binding point.
+ */
+ unsigned explicit_binding:1;
- /**
- * Non-zero if this variable was created by lowering a named interface
- * block which was an array.
- *
- * Note that this variable and \c from_named_ifc_block_nonarray will never
- * both be non-zero.
- */
- unsigned from_named_ifc_block_array:1;
+ /**
+ * Does this variable have an initializer?
+ *
+ * This is used by the linker to cross-validiate initializers of global
+ * variables.
+ */
+ unsigned has_initializer:1;
+
+ /**
+ * Is this variable a generic output or input that has not yet been matched
+ * up to a variable in another stage of the pipeline?
+ *
+ * This is used by the linker as scratch storage while assigning locations
+ * to generic inputs and outputs.
+ */
+ unsigned is_unmatched_generic_inout:1;
+
+ /**
+ * If non-zero, then this variable may be packed along with other variables
+ * into a single varying slot, so this offset should be applied when
+ * accessing components. For example, an offset of 1 means that the x
+ * component of this variable is actually stored in component y of the
+ * location specified by \c location.
+ */
+ unsigned location_frac:2;
+
+ /**
+ * Non-zero if this variable was created by lowering a named interface
+ * block which was not an array.
+ *
+ * Note that this variable and \c from_named_ifc_block_array will never
+ * both be non-zero.
+ */
+ unsigned from_named_ifc_block_nonarray:1;
+
+ /**
+ * Non-zero if this variable was created by lowering a named interface
+ * block which was an array.
+ *
+ * Note that this variable and \c from_named_ifc_block_nonarray will never
+ * both be non-zero.
+ */
+ unsigned from_named_ifc_block_array:1;
- /**
- * \brief Layout qualifier for gl_FragDepth.
- *
- * This is not equal to \c ir_depth_layout_none if and only if this
- * variable is \c gl_FragDepth and a layout qualifier is specified.
- */
- ir_depth_layout depth_layout;
+ /**
+ * \brief Layout qualifier for gl_FragDepth.
+ *
+ * This is not equal to \c ir_depth_layout_none if and only if this
+ * variable is \c gl_FragDepth and a layout qualifier is specified.
+ */
+ ir_depth_layout depth_layout;
+
+ /**
+ * Storage location of the base of this variable
+ *
+ * The precise meaning of this field depends on the nature of the variable.
+ *
+ * - Vertex shader input: one of the values from \c gl_vert_attrib.
+ * - Vertex shader output: one of the values from \c gl_varying_slot.
+ * - Geometry shader input: one of the values from \c gl_varying_slot.
+ * - Geometry shader output: one of the values from \c gl_varying_slot.
+ * - Fragment shader input: one of the values from \c gl_varying_slot.
+ * - Fragment shader output: one of the values from \c gl_frag_result.
+ * - Uniforms: Per-stage uniform slot number for default uniform block.
+ * - Uniforms: Index within the uniform block definition for UBO members.
+ * - Other: This field is not currently used.
+ *
+ * If the variable is a uniform, shader input, or shader output, and the
+ * slot has not been assigned, the value will be -1.
+ */
+ int location;
- /**
- * Storage location of the base of this variable
- *
- * The precise meaning of this field depends on the nature of the variable.
- *
- * - Vertex shader input: one of the values from \c gl_vert_attrib.
- * - Vertex shader output: one of the values from \c gl_varying_slot.
- * - Geometry shader input: one of the values from \c gl_varying_slot.
- * - Geometry shader output: one of the values from \c gl_varying_slot.
- * - Fragment shader input: one of the values from \c gl_varying_slot.
- * - Fragment shader output: one of the values from \c gl_frag_result.
- * - Uniforms: Per-stage uniform slot number for default uniform block.
- * - Uniforms: Index within the uniform block definition for UBO members.
- * - Other: This field is not currently used.
- *
- * If the variable is a uniform, shader input, or shader output, and the
- * slot has not been assigned, the value will be -1.
- */
- int location;
+ /**
+ * output index for dual source blending.
+ */
+ int index;
- /**
- * output index for dual source blending.
- */
- int index;
+ /**
+ * Initial binding point for a sampler or UBO.
+ *
+ * For array types, this represents the binding point for the first element.
+ */
+ int binding;
- /**
- * Initial binding point for a sampler or UBO.
- *
- * For array types, this represents the binding point for the first element.
- */
- int binding;
+ /**
+ * Location an atomic counter is stored at.
+ */
+ struct {
+ unsigned buffer_index;
+ unsigned offset;
+ } atomic;
+
+ /**
+ * Highest element accessed with a constant expression array index
+ *
+ * Not used for non-array variables.
+ */
+ unsigned max_array_access;
- /**
- * Location an atomic counter is stored at.
- */
- struct {
- unsigned buffer_index;
- unsigned offset;
- } atomic;
+ } data;
/**
* Built-in state that backs this uniform
@@ -1022,34 +1028,6 @@ public:
/** List of ir_instruction that make up the body of the loop. */
exec_list body_instructions;
-
- /**
- * \name Loop counter and controls
- *
- * Represents a loop like a FORTRAN \c do-loop.
- *
- * \note
- * If \c from and \c to are the same value, the loop will execute once.
- */
- /*@{*/
- ir_rvalue *from; /** Value of the loop counter on the first
- * iteration of the loop.
- */
- ir_rvalue *to; /** Value of the loop counter on the last
- * iteration of the loop.
- */
- ir_rvalue *increment;
- ir_variable *counter;
-
- /**
- * Comparison operation in the loop terminator.
- *
- * If any of the loop control fields are non-\c NULL, this field must be
- * one of \c ir_binop_less, \c ir_binop_greater, \c ir_binop_lequal,
- * \c ir_binop_gequal, \c ir_binop_equal, or \c ir_binop_nequal.
- */
- int cmp;
- /*@}*/
};
@@ -2344,6 +2322,9 @@ extern ir_function_signature *
_mesa_glsl_find_builtin_function(_mesa_glsl_parse_state *state,
const char *name, exec_list *actual_parameters);
+extern gl_shader *
+_mesa_glsl_get_builtin_function_shader(void);
+
extern void
_mesa_glsl_release_functions(void);
diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp
index 40ed33afc..4e5cf68ca 100644
--- a/mesalib/src/glsl/ir_clone.cpp
+++ b/mesalib/src/glsl/ir_clone.cpp
@@ -41,35 +41,19 @@ ir_variable *
ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
{
ir_variable *var = new(mem_ctx) ir_variable(this->type, this->name,
- (ir_variable_mode) this->mode);
+ (ir_variable_mode) this->data.mode);
- var->max_array_access = this->max_array_access;
+ var->data.max_array_access = this->data.max_array_access;
if (this->is_interface_instance()) {
var->max_ifc_array_access =
rzalloc_array(var, unsigned, this->interface_type->length);
memcpy(var->max_ifc_array_access, this->max_ifc_array_access,
this->interface_type->length * sizeof(unsigned));
}
- var->read_only = this->read_only;
- var->centroid = this->centroid;
- var->invariant = this->invariant;
- var->interpolation = this->interpolation;
- var->location = this->location;
- var->index = this->index;
- var->binding = this->binding;
- var->atomic.buffer_index = this->atomic.buffer_index;
- var->atomic.offset = this->atomic.offset;
+
+ memcpy(&var->data, &this->data, sizeof(var->data));
+
var->warn_extension = this->warn_extension;
- var->origin_upper_left = this->origin_upper_left;
- var->pixel_center_integer = this->pixel_center_integer;
- var->explicit_location = this->explicit_location;
- var->explicit_index = this->explicit_index;
- var->explicit_binding = this->explicit_binding;
- var->has_initializer = this->has_initializer;
- var->depth_layout = this->depth_layout;
- var->assigned = this->assigned;
- var->how_declared = this->how_declared;
- var->used = this->used;
var->num_state_slots = this->num_state_slots;
if (this->state_slots) {
@@ -157,20 +141,11 @@ ir_loop::clone(void *mem_ctx, struct hash_table *ht) const
{
ir_loop *new_loop = new(mem_ctx) ir_loop();
- if (this->from)
- new_loop->from = this->from->clone(mem_ctx, ht);
- if (this->to)
- new_loop->to = this->to->clone(mem_ctx, ht);
- if (this->increment)
- new_loop->increment = this->increment->clone(mem_ctx, ht);
- new_loop->counter = counter;
-
foreach_iter(exec_list_iterator, iter, this->body_instructions) {
ir_instruction *ir = (ir_instruction *)iter.get();
new_loop->body_instructions.push_tail(ir->clone(mem_ctx, ht));
}
- new_loop->cmp = this->cmp;
return new_loop;
}
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index 54bfe5832..c24d3c96b 100755
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -1576,7 +1576,7 @@ ir_dereference_variable::constant_expression_value(struct hash_table *variable_c
/* The constant_value of a uniform variable is its initializer,
* not the lifetime constant value of the uniform.
*/
- if (var->mode == ir_var_uniform)
+ if (var->data.mode == ir_var_uniform)
return NULL;
if (!var->constant_value)
diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp
index 53cf469d9..bd5318d23 100644
--- a/mesalib/src/glsl/ir_function.cpp
+++ b/mesalib/src/glsl/ir_function.cpp
@@ -66,7 +66,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
/* Try to find an implicit conversion from actual to param. */
inexact_match = true;
- switch ((enum ir_variable_mode)(param->mode)) {
+ switch ((enum ir_variable_mode)(param->data.mode)) {
case ir_var_auto:
case ir_var_uniform:
case ir_var_temporary:
diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp
index 941b25e97..2a1f70e5b 100644
--- a/mesalib/src/glsl/ir_hv_accept.cpp
+++ b/mesalib/src/glsl/ir_hv_accept.cpp
@@ -91,26 +91,6 @@ ir_loop::accept(ir_hierarchical_visitor *v)
if (s == visit_stop)
return s;
- if (s != visit_continue_with_parent) {
- if (this->from) {
- s = this->from->accept(v);
- if (s != visit_continue)
- return (s == visit_continue_with_parent) ? visit_continue : s;
- }
-
- if (this->to) {
- s = this->to->accept(v);
- if (s != visit_continue)
- return (s == visit_continue_with_parent) ? visit_continue : s;
- }
-
- if (this->increment) {
- s = this->increment->accept(v);
- if (s != visit_continue)
- return (s == visit_continue_with_parent) ? visit_continue : s;
- }
- }
-
return v->visit_leave(this);
}
diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp
index f85e573c4..01c5f7f1c 100644
--- a/mesalib/src/glsl/ir_print_visitor.cpp
+++ b/mesalib/src/glsl/ir_print_visitor.cpp
@@ -148,8 +148,9 @@ void ir_print_visitor::visit(ir_variable *ir)
{
printf("(declare ");
- const char *const cent = (ir->centroid) ? "centroid " : "";
- const char *const inv = (ir->invariant) ? "invariant " : "";
+ const char *const cent = (ir->data.centroid) ? "centroid " : "";
+ const char *const samp = (ir->data.sample) ? "sample " : "";
+ const char *const inv = (ir->data.invariant) ? "invariant " : "";
const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ",
"in ", "out ", "inout ",
"const_in ", "sys ", "temporary " };
@@ -157,8 +158,8 @@ void ir_print_visitor::visit(ir_variable *ir)
const char *const interp[] = { "", "smooth", "flat", "noperspective" };
STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT);
- printf("(%s%s%s%s) ",
- cent, inv, mode[ir->mode], interp[ir->interpolation]);
+ printf("(%s%s%s%s%s) ",
+ cent, samp, inv, mode[ir->data.mode], interp[ir->data.interpolation]);
print_type(ir->type);
printf(" %s)", unique_name(ir));
@@ -416,9 +417,9 @@ void ir_print_visitor::visit(ir_constant *ir)
if (ir->value.f[i] == 0.0f)
/* 0.0 == -0.0, so print with %f to get the proper sign. */
printf("%.1f", ir->value.f[i]);
- else if (abs(ir->value.f[i]) < 0.000001f)
+ else if (fabs(ir->value.f[i]) < 0.000001f)
printf("%a", ir->value.f[i]);
- else if (abs(ir->value.f[i]) > 1000000.0f)
+ else if (fabs(ir->value.f[i]) > 1000000.0f)
printf("%e", ir->value.f[i]);
else
printf("%f", ir->value.f[i]);
@@ -522,19 +523,7 @@ ir_print_visitor::visit(ir_if *ir)
void
ir_print_visitor::visit(ir_loop *ir)
{
- printf("(loop (");
- if (ir->counter != NULL)
- ir->counter->accept(this);
- printf(") (");
- if (ir->from != NULL)
- ir->from->accept(this);
- printf(") (");
- if (ir->to != NULL)
- ir->to->accept(this);
- printf(") (");
- if (ir->increment != NULL)
- ir->increment->accept(this);
- printf(") (\n");
+ printf("(loop (\n");
indentation++;
foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp
index 00e2db9a3..7970112ec 100644
--- a/mesalib/src/glsl/ir_reader.cpp
+++ b/mesalib/src/glsl/ir_reader.cpp
@@ -412,33 +412,35 @@ ir_reader::read_declaration(s_expression *expr)
// FINISHME: Check for duplicate/conflicting qualifiers.
if (strcmp(qualifier->value(), "centroid") == 0) {
- var->centroid = 1;
+ var->data.centroid = 1;
+ } else if (strcmp(qualifier->value(), "sample") == 0) {
+ var->data.sample = 1;
} else if (strcmp(qualifier->value(), "invariant") == 0) {
- var->invariant = 1;
+ var->data.invariant = 1;
} else if (strcmp(qualifier->value(), "uniform") == 0) {
- var->mode = ir_var_uniform;
+ var->data.mode = ir_var_uniform;
} else if (strcmp(qualifier->value(), "auto") == 0) {
- var->mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
} else if (strcmp(qualifier->value(), "in") == 0) {
- var->mode = ir_var_function_in;
+ var->data.mode = ir_var_function_in;
} else if (strcmp(qualifier->value(), "shader_in") == 0) {
- var->mode = ir_var_shader_in;
+ var->data.mode = ir_var_shader_in;
} else if (strcmp(qualifier->value(), "const_in") == 0) {
- var->mode = ir_var_const_in;
+ var->data.mode = ir_var_const_in;
} else if (strcmp(qualifier->value(), "out") == 0) {
- var->mode = ir_var_function_out;
+ var->data.mode = ir_var_function_out;
} else if (strcmp(qualifier->value(), "shader_out") == 0) {
- var->mode = ir_var_shader_out;
+ var->data.mode = ir_var_shader_out;
} else if (strcmp(qualifier->value(), "inout") == 0) {
- var->mode = ir_var_function_inout;
+ var->data.mode = ir_var_function_inout;
} else if (strcmp(qualifier->value(), "temporary") == 0) {
- var->mode = ir_var_temporary;
+ var->data.mode = ir_var_temporary;
} else if (strcmp(qualifier->value(), "smooth") == 0) {
- var->interpolation = INTERP_QUALIFIER_SMOOTH;
+ var->data.interpolation = INTERP_QUALIFIER_SMOOTH;
} else if (strcmp(qualifier->value(), "flat") == 0) {
- var->interpolation = INTERP_QUALIFIER_FLAT;
+ var->data.interpolation = INTERP_QUALIFIER_FLAT;
} else if (strcmp(qualifier->value(), "noperspective") == 0) {
- var->interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
+ var->data.interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
} else {
ir_read_error(expr, "unknown qualifier: %s", qualifier->value());
return NULL;
@@ -486,18 +488,16 @@ ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx)
ir_loop *
ir_reader::read_loop(s_expression *expr)
{
- s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body;
+ s_expression *s_body;
- s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body };
- if (!MATCH(expr, pat)) {
- ir_read_error(expr, "expected (loop <counter> <from> <to> "
- "<increment> <body>)");
+ s_pattern loop_pat[] = { "loop", s_body };
+ if (!MATCH(expr, loop_pat)) {
+ ir_read_error(expr, "expected (loop <body>)");
return NULL;
}
- // FINISHME: actually read the count/from/to fields.
-
ir_loop *loop = new(mem_ctx) ir_loop;
+
read_instructions(&loop->body_instructions, s_body, loop);
if (state->error) {
delete loop;
diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp
index ab23538c3..0b49eb2b6 100644
--- a/mesalib/src/glsl/ir_set_program_inouts.cpp
+++ b/mesalib/src/glsl/ir_set_program_inouts.cpp
@@ -27,7 +27,7 @@
* Sets the InputsRead and OutputsWritten of Mesa programs.
*
* Additionally, for fragment shaders, sets the InterpQualifier array, the
- * IsCentroid bitfield, and the UsesDFdy flag.
+ * IsCentroid and IsSample bitfields, and the UsesDFdy flag.
*
* Mesa programs (gl_program, not gl_shader_program) have a set of
* flags indicating which varyings are read and written. Computing
@@ -75,9 +75,9 @@ private:
static inline bool
is_shader_inout(ir_variable *var)
{
- return var->mode == ir_var_shader_in ||
- var->mode == ir_var_shader_out ||
- var->mode == ir_var_system_value;
+ return var->data.mode == ir_var_shader_in ||
+ var->data.mode == ir_var_shader_out ||
+ var->data.mode == ir_var_system_value;
}
static void
@@ -93,20 +93,24 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len,
*/
for (int i = 0; i < len; i++) {
- GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i);
- if (var->mode == ir_var_shader_in) {
+ GLbitfield64 bitfield =
+ BITFIELD64_BIT(var->data.location + var->data.index + offset + i);
+ if (var->data.mode == ir_var_shader_in) {
prog->InputsRead |= bitfield;
if (is_fragment_shader) {
gl_fragment_program *fprog = (gl_fragment_program *) prog;
- fprog->InterpQualifier[var->location + var->index + offset + i] =
- (glsl_interp_qualifier) var->interpolation;
- if (var->centroid)
+ fprog->InterpQualifier[var->data.location +
+ var->data.index + offset + i] =
+ (glsl_interp_qualifier) var->data.interpolation;
+ if (var->data.centroid)
fprog->IsCentroid |= bitfield;
+ if (var->data.sample)
+ fprog->IsSample |= bitfield;
}
- } else if (var->mode == ir_var_system_value) {
+ } else if (var->data.mode == ir_var_system_value) {
prog->SystemValuesRead |= bitfield;
} else {
- assert(var->mode == ir_var_shader_out);
+ assert(var->data.mode == ir_var_shader_out);
prog->OutputsWritten |= bitfield;
}
}
@@ -121,7 +125,7 @@ ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var)
{
const glsl_type *type = var->type;
if (this->shader_type == GL_GEOMETRY_SHADER &&
- var->mode == ir_var_shader_in && type->is_array()) {
+ var->data.mode == ir_var_shader_in && type->is_array()) {
type = type->fields.array;
}
@@ -160,7 +164,7 @@ ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var,
const glsl_type *type = var->type;
if (this->shader_type == GL_GEOMETRY_SHADER &&
- var->mode == ir_var_shader_in) {
+ var->data.mode == ir_var_shader_in) {
/* The only geometry shader input that is not an array is
* gl_PrimitiveIDIn, and in that case, this code will never be reached,
* because gl_PrimitiveIDIn can't be indexed into in array fashion.
@@ -242,7 +246,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
if (ir_dereference_variable * const deref_var =
inner_array->array->as_dereference_variable()) {
if (this->shader_type == GL_GEOMETRY_SHADER &&
- deref_var->var->mode == ir_var_shader_in) {
+ deref_var->var->data.mode == ir_var_shader_in) {
/* foo is a geometry shader input, so i is the vertex, and j the
* part of the input we're accessing.
*/
@@ -261,7 +265,7 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
ir->array->as_dereference_variable()) {
/* ir => foo[i], where foo is a variable. */
if (this->shader_type == GL_GEOMETRY_SHADER &&
- deref_var->var->mode == ir_var_shader_in) {
+ deref_var->var->data.mode == ir_var_shader_in) {
/* foo is a geometry shader input, so i is the vertex, and we're
* accessing the entire input.
*/
@@ -341,6 +345,7 @@ do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
gl_fragment_program *fprog = (gl_fragment_program *) prog;
memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier));
fprog->IsCentroid = 0;
+ fprog->IsSample = 0;
fprog->UsesDFdy = false;
fprog->UsesKill = false;
}
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index 13e41a089..4bbb3ce65 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -63,7 +63,6 @@ public:
virtual ir_visitor_status visit_enter(ir_if *ir);
- virtual ir_visitor_status visit_leave(ir_loop *ir);
virtual ir_visitor_status visit_enter(ir_function *ir);
virtual ir_visitor_status visit_leave(ir_function *ir);
virtual ir_visitor_status visit_enter(ir_function_signature *ir);
@@ -149,42 +148,6 @@ ir_validate::visit_enter(ir_if *ir)
ir_visitor_status
-ir_validate::visit_leave(ir_loop *ir)
-{
- if (ir->counter != NULL) {
- if ((ir->from == NULL) || (ir->to == NULL) || (ir->increment == NULL)) {
- printf("ir_loop has invalid loop controls:\n"
- " counter: %p\n"
- " from: %p\n"
- " to: %p\n"
- " increment: %p\n",
- (void *) ir->counter, (void *) ir->from, (void *) ir->to,
- (void *) ir->increment);
- abort();
- }
-
- if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) {
- printf("ir_loop has invalid comparitor %d\n", ir->cmp);
- abort();
- }
- } else {
- if ((ir->from != NULL) || (ir->to != NULL) || (ir->increment != NULL)) {
- printf("ir_loop has invalid loop controls:\n"
- " counter: %p\n"
- " from: %p\n"
- " to: %p\n"
- " increment: %p\n",
- (void *) ir->counter, (void *) ir->from, (void *) ir->to,
- (void *) ir->increment);
- abort();
- }
- }
-
- return visit_continue;
-}
-
-
-ir_visitor_status
ir_validate::visit_enter(ir_function *ir)
{
/* Function definitions cannot be nested.
@@ -679,9 +642,9 @@ ir_validate::visit(ir_variable *ir)
* to be out of bounds.
*/
if (ir->type->array_size() > 0) {
- if (ir->max_array_access >= ir->type->length) {
+ if (ir->data.max_array_access >= ir->type->length) {
printf("ir_variable has maximum access out of bounds (%d vs %d)\n",
- ir->max_array_access, ir->type->length - 1);
+ ir->data.max_array_access, ir->type->length - 1);
ir->print();
abort();
}
@@ -707,7 +670,7 @@ ir_validate::visit(ir_variable *ir)
}
}
- if (ir->constant_initializer != NULL && !ir->has_initializer) {
+ if (ir->constant_initializer != NULL && !ir->data.has_initializer) {
printf("ir_variable didn't have an initializer, but has a constant "
"initializer value.\n");
ir->print();
@@ -789,8 +752,8 @@ ir_validate::visit_enter(ir_call *ir)
printf("ir_call parameter type mismatch:\n");
goto dump_ir;
}
- if (formal_param->mode == ir_var_function_out
- || formal_param->mode == ir_var_function_inout) {
+ if (formal_param->data.mode == ir_var_function_out
+ || formal_param->data.mode == ir_var_function_inout) {
if (!actual_param->is_lvalue()) {
printf("ir_call out/inout parameters must be lvalues:\n");
goto dump_ir;
diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp
index 2466bbd79..33903ad54 100644
--- a/mesalib/src/glsl/link_atomics.cpp
+++ b/mesalib/src/glsl/link_atomics.cpp
@@ -73,16 +73,16 @@ namespace {
const active_atomic_counter *const first = (active_atomic_counter *) a;
const active_atomic_counter *const second = (active_atomic_counter *) b;
- return int(first->var->atomic.offset) - int(second->var->atomic.offset);
+ return int(first->var->data.atomic.offset) - int(second->var->data.atomic.offset);
}
bool
check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y)
{
- return ((x->atomic.offset >= y->atomic.offset &&
- x->atomic.offset < y->atomic.offset + y->type->atomic_size()) ||
- (y->atomic.offset >= x->atomic.offset &&
- y->atomic.offset < x->atomic.offset + x->type->atomic_size()));
+ return ((x->data.atomic.offset >= y->data.atomic.offset &&
+ x->data.atomic.offset < y->data.atomic.offset + y->type->atomic_size()) ||
+ (y->data.atomic.offset >= x->data.atomic.offset &&
+ y->data.atomic.offset < x->data.atomic.offset + x->type->atomic_size()));
}
active_atomic_buffer *
@@ -107,7 +107,7 @@ namespace {
unsigned id;
bool found = prog->UniformHash->get(id, var->name);
assert(found);
- active_atomic_buffer *buf = &buffers[var->binding];
+ active_atomic_buffer *buf = &buffers[var->data.binding];
/* If this is the first time the buffer is used, increment
* the counter of buffers used.
@@ -118,7 +118,7 @@ namespace {
buf->push_back(id, var);
buf->stage_references[i]++;
- buf->size = MAX2(buf->size, var->atomic.offset +
+ buf->size = MAX2(buf->size, var->data.atomic.offset +
var->type->atomic_size());
}
}
@@ -143,7 +143,7 @@ namespace {
linker_error(prog, "Atomic counter %s declared at offset %d "
"which is already in use.",
buffers[i].counters[j].var->name,
- buffers[i].counters[j].var->atomic.offset);
+ buffers[i].counters[j].var->data.atomic.offset);
}
}
}
@@ -190,9 +190,9 @@ link_assign_atomic_counter_resources(struct gl_context *ctx,
gl_uniform_storage *const storage = &prog->UniformStorage[id];
mab.Uniforms[j] = id;
- var->atomic.buffer_index = i;
+ var->data.atomic.buffer_index = i;
storage->atomic_buffer_index = i;
- storage->offset = var->atomic.offset;
+ storage->offset = var->data.atomic.offset;
storage->array_stride = (var->type->is_array() ?
var->type->element_type()->atomic_size() : 0);
}
diff --git a/mesalib/src/glsl/link_functions.cpp b/mesalib/src/glsl/link_functions.cpp
index 68aa62032..56f3f207e 100644
--- a/mesalib/src/glsl/link_functions.cpp
+++ b/mesalib/src/glsl/link_functions.cpp
@@ -201,8 +201,9 @@ public:
if (formal_param->type->is_array()) {
ir_dereference_variable *deref = actual_param->as_dereference_variable();
if (deref && deref->var && deref->var->type->is_array()) {
- deref->var->max_array_access =
- MAX2(formal_param->max_array_access, deref->var->max_array_access);
+ deref->var->data.max_array_access =
+ MAX2(formal_param->data.max_array_access,
+ deref->var->data.max_array_access);
}
}
}
@@ -234,8 +235,9 @@ public:
* we need to track the maximal access to the array as linking
* pulls more functions in that access the array.
*/
- var->max_array_access =
- MAX2(var->max_array_access, ir->var->max_array_access);
+ var->data.max_array_access =
+ MAX2(var->data.max_array_access,
+ ir->var->data.max_array_access);
if (var->type->length == 0 && ir->var->type->length != 0)
var->type = ir->var->type;
diff --git a/mesalib/src/glsl/link_interface_blocks.cpp b/mesalib/src/glsl/link_interface_blocks.cpp
index 6900fa94e..476963642 100644
--- a/mesalib/src/glsl/link_interface_blocks.cpp
+++ b/mesalib/src/glsl/link_interface_blocks.cpp
@@ -60,7 +60,7 @@ struct interface_block_definition
if (var->type->is_array())
array_size = var->type->length;
}
- explicitly_declared = (var->how_declared != ir_var_declared_implicitly);
+ explicitly_declared = (var->data.how_declared != ir_var_declared_implicitly);
}
/**
@@ -270,7 +270,7 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
continue;
interface_block_definitions *definitions;
- switch (var->mode) {
+ switch (var->data.mode) {
case ir_var_shader_in:
definitions = &in_interfaces;
break;
@@ -298,7 +298,7 @@ validate_intrastage_interface_blocks(struct gl_shader_program *prog,
*/
definitions->store(def);
} else if (!intrastage_match(prev_def, &def,
- (ir_variable_mode) var->mode)) {
+ (ir_variable_mode) var->data.mode)) {
linker_error(prog, "definitions of interface block `%s' do not"
" match\n", iface_type->name);
return;
@@ -318,7 +318,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
/* Add input interfaces from the consumer to the symbol table. */
foreach_list(node, consumer->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
- if (!var || !var->get_interface_type() || var->mode != ir_var_shader_in)
+ if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_in)
continue;
definitions.store(interface_block_definition(var));
@@ -327,7 +327,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
/* Verify that the producer's output interfaces match. */
foreach_list(node, producer->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
- if (!var || !var->get_interface_type() || var->mode != ir_var_shader_out)
+ if (!var || !var->get_interface_type() || var->data.mode != ir_var_shader_out)
continue;
interface_block_definition *consumer_def =
@@ -361,7 +361,7 @@ validate_interstage_uniform_blocks(struct gl_shader_program *prog,
const gl_shader *stage = stages[i];
foreach_list(node, stage->ir) {
ir_variable *var = ((ir_instruction *) node)->as_variable();
- if (!var || !var->get_interface_type() || var->mode != ir_var_uniform)
+ if (!var || !var->get_interface_type() || var->data.mode != ir_var_uniform)
continue;
interface_block_definition *old_def =
diff --git a/mesalib/src/glsl/link_uniform_initializers.cpp b/mesalib/src/glsl/link_uniform_initializers.cpp
index 786aaf0b4..04daa1760 100644
--- a/mesalib/src/glsl/link_uniform_initializers.cpp
+++ b/mesalib/src/glsl/link_uniform_initializers.cpp
@@ -224,15 +224,15 @@ link_set_uniform_initializers(struct gl_shader_program *prog)
foreach_list(node, shader->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (!var || var->mode != ir_var_uniform)
+ if (!var || var->data.mode != ir_var_uniform)
continue;
if (!mem_ctx)
mem_ctx = ralloc_context(NULL);
- if (var->explicit_binding) {
+ if (var->data.explicit_binding) {
linker::set_uniform_binding(mem_ctx, prog, var->name,
- var->type, var->binding);
+ var->type, var->data.binding);
} else if (var->constant_value) {
linker::set_uniform_initializer(mem_ctx, prog, var->name,
var->type, var->constant_value);
diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp
index 95e75d73d..1cbe80b2e 100644
--- a/mesalib/src/glsl/link_uniforms.cpp
+++ b/mesalib/src/glsl/link_uniforms.cpp
@@ -75,7 +75,7 @@ program_resource_visitor::process(ir_variable *var)
*/
/* Only strdup the name if we actually will need to modify it. */
- if (var->from_named_ifc_block_array) {
+ if (var->data.from_named_ifc_block_array) {
/* lower_named_interface_blocks created this variable by lowering an
* interface block array to an array variable. For example if the
* original source code was:
@@ -108,7 +108,7 @@ program_resource_visitor::process(ir_variable *var)
recursion(var->type, &name, new_length, false, NULL);
}
ralloc_free(name);
- } else if (var->from_named_ifc_block_nonarray) {
+ } else if (var->data.from_named_ifc_block_nonarray) {
/* lower_named_interface_blocks created this variable by lowering a
* named interface block (non-array) to an ordinary variable. For
* example if the original source code was:
@@ -408,10 +408,10 @@ public:
const struct gl_uniform_block *const block =
&prog->UniformBlocks[ubo_block_index];
- assert(var->location != -1);
+ assert(var->data.location != -1);
const struct gl_uniform_buffer_variable *const ubo_var =
- &block->Uniforms[var->location];
+ &block->Uniforms[var->data.location];
ubo_row_major = ubo_var->RowMajor;
ubo_byte_offset = ubo_var->Offset;
@@ -637,10 +637,10 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
if ((var == NULL) || !var->is_in_uniform_block())
continue;
- assert(var->mode == ir_var_uniform);
+ assert(var->data.mode == ir_var_uniform);
if (var->is_interface_instance()) {
- var->location = 0;
+ var->data.location = 0;
continue;
}
@@ -669,13 +669,13 @@ link_update_uniform_buffer_variables(struct gl_shader *shader)
if (strncmp(var->name, begin, l) == 0) {
found = true;
- var->location = j;
+ var->data.location = j;
break;
}
} else if (!strcmp(var->name,
shader->UniformBlocks[i].Uniforms[j].Name)) {
found = true;
- var->location = j;
+ var->data.location = j;
break;
}
}
@@ -767,7 +767,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
foreach_list(node, sh->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_uniform))
+ if ((var == NULL) || (var->data.mode != ir_var_uniform))
continue;
/* FINISHME: Update code to process built-in uniforms!
@@ -818,7 +818,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
foreach_list(node, prog->_LinkedShaders[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_uniform))
+ if ((var == NULL) || (var->data.mode != ir_var_uniform))
continue;
/* FINISHME: Update code to process built-in uniforms!
diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp
index be36b5f8f..229a4cb85 100644
--- a/mesalib/src/glsl/link_varyings.cpp
+++ b/mesalib/src/glsl/link_varyings.cpp
@@ -93,31 +93,43 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog,
/* Check that all of the qualifiers match between stages.
*/
- if (input->centroid != output->centroid) {
+ if (input->data.centroid != output->data.centroid) {
linker_error(prog,
"%s shader output `%s' %s centroid qualifier, "
"but %s shader input %s centroid qualifier\n",
_mesa_glsl_shader_target_name(producer_type),
output->name,
- (output->centroid) ? "has" : "lacks",
+ (output->data.centroid) ? "has" : "lacks",
_mesa_glsl_shader_target_name(consumer_type),
- (input->centroid) ? "has" : "lacks");
+ (input->data.centroid) ? "has" : "lacks");
return;
}
- if (input->invariant != output->invariant) {
+ if (input->data.sample != output->data.sample) {
+ linker_error(prog,
+ "%s shader output `%s' %s sample qualifier, "
+ "but %s shader input %s sample qualifier\n",
+ _mesa_glsl_shader_target_name(producer_type),
+ output->name,
+ (output->data.sample) ? "has" : "lacks",
+ _mesa_glsl_shader_target_name(consumer_type),
+ (input->data.sample) ? "has" : "lacks");
+ return;
+ }
+
+ if (input->data.invariant != output->data.invariant) {
linker_error(prog,
"%s shader output `%s' %s invariant qualifier, "
"but %s shader input %s invariant qualifier\n",
_mesa_glsl_shader_target_name(producer_type),
output->name,
- (output->invariant) ? "has" : "lacks",
+ (output->data.invariant) ? "has" : "lacks",
_mesa_glsl_shader_target_name(consumer_type),
- (input->invariant) ? "has" : "lacks");
+ (input->data.invariant) ? "has" : "lacks");
return;
}
- if (input->interpolation != output->interpolation) {
+ if (input->data.interpolation != output->data.interpolation) {
linker_error(prog,
"%s shader output `%s' specifies %s "
"interpolation qualifier, "
@@ -125,9 +137,9 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog,
"interpolation qualifier\n",
_mesa_glsl_shader_target_name(producer_type),
output->name,
- interpolation_string(output->interpolation),
+ interpolation_string(output->data.interpolation),
_mesa_glsl_shader_target_name(consumer_type),
- interpolation_string(input->interpolation));
+ interpolation_string(input->data.interpolation));
return;
}
}
@@ -143,11 +155,11 @@ cross_validate_front_and_back_color(struct gl_shader_program *prog,
GLenum consumer_type,
GLenum producer_type)
{
- if (front_color != NULL && front_color->assigned)
+ if (front_color != NULL && front_color->data.assigned)
cross_validate_types_and_qualifiers(prog, input, front_color,
consumer_type, producer_type);
- if (back_color != NULL && back_color->assigned)
+ if (back_color != NULL && back_color->data.assigned)
cross_validate_types_and_qualifiers(prog, input, back_color,
consumer_type, producer_type);
}
@@ -166,7 +178,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
foreach_list(node, producer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_shader_out))
+ if ((var == NULL) || (var->data.mode != ir_var_shader_out))
continue;
parameters.add_variable(var);
@@ -184,10 +196,10 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
foreach_list(node, consumer->ir) {
ir_variable *const input = ((ir_instruction *) node)->as_variable();
- if ((input == NULL) || (input->mode != ir_var_shader_in))
+ if ((input == NULL) || (input->data.mode != ir_var_shader_in))
continue;
- if (strcmp(input->name, "gl_Color") == 0 && input->used) {
+ if (strcmp(input->name, "gl_Color") == 0 && input->data.used) {
const ir_variable *const front_color =
parameters.get_variable("gl_FrontColor");
@@ -197,7 +209,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
cross_validate_front_and_back_color(prog, input,
front_color, back_color,
consumer->Type, producer->Type);
- } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->used) {
+ } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->data.used) {
const ir_variable *const front_color =
parameters.get_variable("gl_FrontSecondaryColor");
@@ -317,8 +329,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
assert(this->is_varying());
unsigned fine_location
- = this->matched_candidate->toplevel_var->location * 4
- + this->matched_candidate->toplevel_var->location_frac
+ = this->matched_candidate->toplevel_var->data.location * 4
+ + this->matched_candidate->toplevel_var->data.location_frac
+ this->matched_candidate->offset;
if (this->matched_candidate->type->is_array()) {
@@ -734,7 +746,7 @@ varying_matches::~varying_matches()
void
varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
{
- if (!producer_var->is_unmatched_generic_inout) {
+ if (!producer_var->data.is_unmatched_generic_inout) {
/* Either a location already exists for this variable (since it is part
* of fixed functionality), or it has already been recorded as part of a
* previous match.
@@ -752,12 +764,14 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
* regardless of where they appear. We can trivially satisfy that
* requirement by changing the interpolation type to flat here.
*/
- producer_var->centroid = false;
- producer_var->interpolation = INTERP_QUALIFIER_FLAT;
+ producer_var->data.centroid = false;
+ producer_var->data.sample = false;
+ producer_var->data.interpolation = INTERP_QUALIFIER_FLAT;
if (consumer_var) {
- consumer_var->centroid = false;
- consumer_var->interpolation = INTERP_QUALIFIER_FLAT;
+ consumer_var->data.centroid = false;
+ consumer_var->data.sample = false;
+ consumer_var->data.interpolation = INTERP_QUALIFIER_FLAT;
}
}
@@ -784,9 +798,9 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
this->matches[this->num_matches].producer_var = producer_var;
this->matches[this->num_matches].consumer_var = consumer_var;
this->num_matches++;
- producer_var->is_unmatched_generic_inout = 0;
+ producer_var->data.is_unmatched_generic_inout = 0;
if (consumer_var)
- consumer_var->is_unmatched_generic_inout = 0;
+ consumer_var->data.is_unmatched_generic_inout = 0;
}
@@ -838,12 +852,12 @@ varying_matches::store_locations(unsigned producer_base,
unsigned slot = generic_location / 4;
unsigned offset = generic_location % 4;
- producer_var->location = producer_base + slot;
- producer_var->location_frac = offset;
+ producer_var->data.location = producer_base + slot;
+ producer_var->data.location_frac = offset;
if (consumer_var) {
- assert(consumer_var->location == -1);
- consumer_var->location = consumer_base + slot;
- consumer_var->location_frac = offset;
+ assert(consumer_var->data.location == -1);
+ consumer_var->data.location = consumer_base + slot;
+ consumer_var->data.location_frac = offset;
}
}
}
@@ -873,9 +887,9 @@ varying_matches::compute_packing_class(ir_variable *var)
*
* Therefore, the packing class depends only on the interpolation type.
*/
- unsigned packing_class = var->centroid ? 1 : 0;
+ unsigned packing_class = var->data.centroid | (var->data.sample << 1);
packing_class *= 4;
- packing_class += var->interpolation;
+ packing_class += var->data.interpolation;
return packing_class;
}
@@ -933,8 +947,8 @@ is_varying_var(GLenum shaderType, const ir_variable *var)
{
/* Only fragment shaders will take a varying variable as an input */
if (shaderType == GL_FRAGMENT_SHADER &&
- var->mode == ir_var_shader_in) {
- switch (var->location) {
+ var->data.mode == ir_var_shader_in) {
+ switch (var->data.location) {
case VARYING_SLOT_POS:
case VARYING_SLOT_FACE:
case VARYING_SLOT_PNTC:
@@ -1082,7 +1096,7 @@ assign_varying_locations(struct gl_context *ctx,
ir_variable *const input_var =
((ir_instruction *) node)->as_variable();
- if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) {
+ if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
if (input_var->get_interface_type() != NULL) {
char *const iface_field_name =
ralloc_asprintf(mem_ctx, "%s.%s",
@@ -1101,7 +1115,7 @@ assign_varying_locations(struct gl_context *ctx,
foreach_list(node, producer->ir) {
ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
- if ((output_var == NULL) || (output_var->mode != ir_var_shader_out))
+ if ((output_var == NULL) || (output_var->data.mode != ir_var_shader_out))
continue;
tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
@@ -1121,7 +1135,7 @@ assign_varying_locations(struct gl_context *ctx,
(ir_variable *) hash_table_find(consumer_inputs, output_var->name);
}
- if (input_var && input_var->mode != ir_var_shader_in)
+ if (input_var && input_var->data.mode != ir_var_shader_in)
input_var = NULL;
if (input_var) {
@@ -1143,7 +1157,7 @@ assign_varying_locations(struct gl_context *ctx,
return false;
}
- if (matched_candidate->toplevel_var->is_unmatched_generic_inout)
+ if (matched_candidate->toplevel_var->data.is_unmatched_generic_inout)
matches.record(matched_candidate->toplevel_var, NULL);
}
@@ -1185,8 +1199,8 @@ assign_varying_locations(struct gl_context *ctx,
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (var && var->mode == ir_var_shader_in &&
- var->is_unmatched_generic_inout) {
+ if (var && var->data.mode == ir_var_shader_in &&
+ var->data.is_unmatched_generic_inout) {
if (prog->Version <= 120) {
/* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
*
@@ -1211,7 +1225,7 @@ assign_varying_locations(struct gl_context *ctx,
/* An 'in' variable is only really a shader input if its
* value is written by the previous stage.
*/
- var->mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
}
}
}
@@ -1229,7 +1243,7 @@ check_against_output_limit(struct gl_context *ctx,
foreach_list(node, producer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (var && var->mode == ir_var_shader_out &&
+ if (var && var->data.mode == ir_var_shader_out &&
is_varying_var(producer->Type, var)) {
output_vectors += var->type->count_attribute_slots();
}
@@ -1278,7 +1292,7 @@ check_against_input_limit(struct gl_context *ctx,
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (var && var->mode == ir_var_shader_in &&
+ if (var && var->data.mode == ir_var_shader_in &&
is_varying_var(consumer->Type, var)) {
input_vectors += var->type->count_attribute_slots();
}
diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp
index 1366077f7..a6133ea9c 100644
--- a/mesalib/src/glsl/linker.cpp
+++ b/mesalib/src/glsl/linker.cpp
@@ -114,8 +114,8 @@ public:
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
ir_variable *sig_param = (ir_variable *)sig_iter.get();
- if (sig_param->mode == ir_var_function_out ||
- sig_param->mode == ir_var_function_inout) {
+ if (sig_param->data.mode == ir_var_function_out ||
+ sig_param->data.mode == ir_var_function_inout) {
ir_variable *var = param_rval->variable_referenced();
if (var && strcmp(name, var->name) == 0) {
found = true;
@@ -198,7 +198,7 @@ public:
virtual ir_visitor_status visit(ir_variable *var)
{
- if (!var->type->is_array() || var->mode != ir_var_shader_in)
+ if (!var->type->is_array() || var->data.mode != ir_var_shader_in)
return visit_continue;
unsigned size = var->type->length;
@@ -217,16 +217,16 @@ public:
* array using an index too large for its actual size assigned at link
* time.
*/
- if (var->max_array_access >= this->num_vertices) {
+ if (var->data.max_array_access >= this->num_vertices) {
linker_error(this->prog, "geometry shader accesses element %i of "
"%s, but only %i input vertices\n",
- var->max_array_access, var->name, this->num_vertices);
+ var->data.max_array_access, var->name, this->num_vertices);
return visit_continue;
}
var->type = glsl_type::get_array_instance(var->type->element_type(),
this->num_vertices);
- var->max_array_access = this->num_vertices - 1;
+ var->data.max_array_access = this->num_vertices - 1;
return visit_continue;
}
@@ -379,9 +379,9 @@ link_invalidate_variable_locations(exec_list *ir)
* shader inputs (via layout(location=...)), and generic fragment shader
* outputs (also via layout(location=...)).
*/
- if (!var->explicit_location) {
- var->location = -1;
- var->location_frac = 0;
+ if (!var->data.explicit_location) {
+ var->data.location = -1;
+ var->data.location_frac = 0;
}
/* ir_variable::is_unmatched_generic_inout is used by the linker while
@@ -396,10 +396,10 @@ link_invalidate_variable_locations(exec_list *ir)
* GL_ARB_separate_shader_objects is supported. When that extension is
* implemented, this function will need some modifications.
*/
- if (!var->explicit_location) {
- var->is_unmatched_generic_inout = 1;
+ if (!var->data.explicit_location) {
+ var->data.is_unmatched_generic_inout = 1;
} else {
- var->is_unmatched_generic_inout = 0;
+ var->data.is_unmatched_generic_inout = 0;
}
}
}
@@ -580,13 +580,13 @@ cross_validate_globals(struct gl_shader_program *prog,
if (var == NULL)
continue;
- if (uniforms_only && (var->mode != ir_var_uniform))
+ if (uniforms_only && (var->data.mode != ir_var_uniform))
continue;
/* Don't cross validate temporaries that are at global scope. These
* will eventually get pulled into the shaders 'main'.
*/
- if (var->mode == ir_var_temporary)
+ if (var->data.mode == ir_var_temporary)
continue;
/* If a global with this name has already been seen, verify that the
@@ -619,17 +619,17 @@ cross_validate_globals(struct gl_shader_program *prog,
}
}
- if (var->explicit_location) {
- if (existing->explicit_location
- && (var->location != existing->location)) {
+ if (var->data.explicit_location) {
+ if (existing->data.explicit_location
+ && (var->data.location != existing->data.location)) {
linker_error(prog, "explicit locations for %s "
"`%s' have differing values\n",
mode_string(var), var->name);
return;
}
- existing->location = var->location;
- existing->explicit_location = true;
+ existing->data.location = var->data.location;
+ existing->data.explicit_location = true;
}
/* From the GLSL 4.20 specification:
@@ -638,21 +638,21 @@ cross_validate_globals(struct gl_shader_program *prog,
* opaque-uniform name. However, it is not an error to specify a
* binding on some but not all declarations for the same name"
*/
- if (var->explicit_binding) {
- if (existing->explicit_binding &&
- var->binding != existing->binding) {
+ if (var->data.explicit_binding) {
+ if (existing->data.explicit_binding &&
+ var->data.binding != existing->data.binding) {
linker_error(prog, "explicit bindings for %s "
"`%s' have differing values\n",
mode_string(var), var->name);
return;
}
- existing->binding = var->binding;
- existing->explicit_binding = true;
+ existing->data.binding = var->data.binding;
+ existing->data.explicit_binding = true;
}
if (var->type->contains_atomic() &&
- var->atomic.offset != existing->atomic.offset) {
+ var->data.atomic.offset != existing->data.atomic.offset) {
linker_error(prog, "offset specifications for %s "
"`%s' have differing values\n",
mode_string(var), var->name);
@@ -671,9 +671,9 @@ cross_validate_globals(struct gl_shader_program *prog,
* of qualifiers."
*/
if (strcmp(var->name, "gl_FragDepth") == 0) {
- bool layout_declared = var->depth_layout != ir_depth_layout_none;
+ bool layout_declared = var->data.depth_layout != ir_depth_layout_none;
bool layout_differs =
- var->depth_layout != existing->depth_layout;
+ var->data.depth_layout != existing->data.depth_layout;
if (layout_declared && layout_differs) {
linker_error(prog,
@@ -682,7 +682,7 @@ cross_validate_globals(struct gl_shader_program *prog,
"the same set of qualifiers.");
}
- if (var->used && layout_differs) {
+ if (var->data.used && layout_differs) {
linker_error(prog,
"If gl_FragDepth is redeclared with a layout "
"qualifier in any fragment shader, it must be "
@@ -734,8 +734,8 @@ cross_validate_globals(struct gl_shader_program *prog,
}
}
- if (var->has_initializer) {
- if (existing->has_initializer
+ if (var->data.has_initializer) {
+ if (existing->data.has_initializer
&& (var->constant_initializer == NULL
|| existing->constant_initializer == NULL)) {
linker_error(prog,
@@ -750,21 +750,27 @@ cross_validate_globals(struct gl_shader_program *prog,
* otherwise) will propagate the existence to the variable
* stored in the symbol table.
*/
- existing->has_initializer = true;
+ existing->data.has_initializer = true;
}
- if (existing->invariant != var->invariant) {
+ if (existing->data.invariant != var->data.invariant) {
linker_error(prog, "declarations for %s `%s' have "
"mismatching invariant qualifiers\n",
mode_string(var), var->name);
return;
}
- if (existing->centroid != var->centroid) {
+ if (existing->data.centroid != var->data.centroid) {
linker_error(prog, "declarations for %s `%s' have "
"mismatching centroid qualifiers\n",
mode_string(var), var->name);
return;
}
+ if (existing->data.sample != var->data.sample) {
+ linker_error(prog, "declarations for %s `%s` have "
+ "mismatching sample qualifiers\n",
+ mode_string(var), var->name);
+ return;
+ }
} else
variables.add_variable(var);
}
@@ -884,7 +890,7 @@ remap_variables(ir_instruction *inst, struct gl_shader *target,
virtual ir_visitor_status visit(ir_dereference_variable *ir)
{
- if (ir->var->mode == ir_var_temporary) {
+ if (ir->var->data.mode == ir_var_temporary) {
ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var);
assert(var != NULL);
@@ -958,13 +964,13 @@ move_non_declarations(exec_list *instructions, exec_node *last,
continue;
ir_variable *var = inst->as_variable();
- if ((var != NULL) && (var->mode != ir_var_temporary))
+ if ((var != NULL) && (var->data.mode != ir_var_temporary))
continue;
assert(inst->as_assignment()
|| inst->as_call()
|| inst->as_if() /* for initializers with the ?: operator */
- || ((var != NULL) && (var->mode == ir_var_temporary)));
+ || ((var != NULL) && (var->data.mode == ir_var_temporary)));
if (make_copies) {
inst = inst->clone(target, NULL);
@@ -1036,7 +1042,7 @@ public:
virtual ir_visitor_status visit(ir_variable *var)
{
- fixup_type(&var->type, var->max_array_access);
+ fixup_type(&var->type, var->data.max_array_access);
if (var->type->is_interface()) {
if (interface_contains_unsized_arrays(var->type)) {
const glsl_type *new_type =
@@ -1405,36 +1411,38 @@ link_intrastage_shaders(void *mem_ctx,
insertion_point, true, linked);
}
- /* Resolve initializers for global variables in the linked shader.
- */
- unsigned num_linking_shaders = num_shaders;
- for (unsigned i = 0; i < num_shaders; i++)
- num_linking_shaders += shader_list[i]->num_builtins_to_link;
+ /* Check if any shader needs built-in functions. */
+ bool need_builtins = false;
+ for (unsigned i = 0; i < num_shaders; i++) {
+ if (shader_list[i]->uses_builtin_functions) {
+ need_builtins = true;
+ break;
+ }
+ }
- gl_shader **linking_shaders =
- (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *));
+ bool ok;
+ if (need_builtins) {
+ /* Make a temporary array one larger than shader_list, which will hold
+ * the built-in function shader as well.
+ */
+ gl_shader **linking_shaders = (gl_shader **)
+ calloc(num_shaders + 1, sizeof(gl_shader *));
+ memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
+ linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
- memcpy(linking_shaders, shader_list,
- sizeof(linking_shaders[0]) * num_shaders);
+ ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
- unsigned idx = num_shaders;
- for (unsigned i = 0; i < num_shaders; i++) {
- memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link,
- sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link);
- idx += shader_list[i]->num_builtins_to_link;
+ free(linking_shaders);
+ } else {
+ ok = link_function_calls(prog, linked, shader_list, num_shaders);
}
- assert(idx == num_linking_shaders);
- if (!link_function_calls(prog, linked, linking_shaders,
- num_linking_shaders)) {
+ if (!ok) {
ctx->Driver.DeleteShader(ctx, linked);
- free(linking_shaders);
return NULL;
}
- free(linking_shaders);
-
/* At this point linked should contain all of the linked IR, so
* validate it to make sure nothing went wrong.
*/
@@ -1486,7 +1494,7 @@ update_array_sizes(struct gl_shader_program *prog)
foreach_list(node, prog->_LinkedShaders[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_uniform) ||
+ if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
!var->type->is_array())
continue;
@@ -1501,7 +1509,7 @@ update_array_sizes(struct gl_shader_program *prog)
if (var->is_in_uniform_block() || var->type->contains_atomic())
continue;
- unsigned int size = var->max_array_access;
+ unsigned int size = var->data.max_array_access;
for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
if (prog->_LinkedShaders[j] == NULL)
continue;
@@ -1512,8 +1520,8 @@ update_array_sizes(struct gl_shader_program *prog)
continue;
if (strcmp(var->name, other_var->name) == 0 &&
- other_var->max_array_access > size) {
- size = other_var->max_array_access;
+ other_var->data.max_array_access > size) {
+ size = other_var->data.max_array_access;
}
}
}
@@ -1652,16 +1660,17 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
foreach_list(node, sh->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != (unsigned) direction))
+ if ((var == NULL) || (var->data.mode != (unsigned) direction))
continue;
- if (var->explicit_location) {
- if ((var->location >= (int)(max_index + generic_base))
- || (var->location < 0)) {
+ if (var->data.explicit_location) {
+ if ((var->data.location >= (int)(max_index + generic_base))
+ || (var->data.location < 0)) {
linker_error(prog,
"invalid explicit location %d specified for `%s'\n",
- (var->location < 0)
- ? var->location : var->location - generic_base,
+ (var->data.location < 0)
+ ? var->data.location
+ : var->data.location - generic_base,
var->name);
return false;
}
@@ -1670,8 +1679,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
if (prog->AttributeBindings->get(binding, var->name)) {
assert(binding >= VERT_ATTRIB_GENERIC0);
- var->location = binding;
- var->is_unmatched_generic_inout = 0;
+ var->data.location = binding;
+ var->data.is_unmatched_generic_inout = 0;
}
} else if (target_index == MESA_SHADER_FRAGMENT) {
unsigned binding;
@@ -1679,11 +1688,11 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
if (prog->FragDataBindings->get(binding, var->name)) {
assert(binding >= FRAG_RESULT_DATA0);
- var->location = binding;
- var->is_unmatched_generic_inout = 0;
+ var->data.location = binding;
+ var->data.is_unmatched_generic_inout = 0;
if (prog->FragDataIndexBindings->get(index, var->name)) {
- var->index = index;
+ var->data.index = index;
}
}
}
@@ -1694,8 +1703,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
* add it to the list of variables that need linker-assigned locations.
*/
const unsigned slots = var->type->count_attribute_slots();
- if (var->location != -1) {
- if (var->location >= generic_base && var->index < 1) {
+ if (var->data.location != -1) {
+ if (var->data.location >= generic_base && var->data.index < 1) {
/* From page 61 of the OpenGL 4.0 spec:
*
* "LinkProgram will fail if the attribute bindings assigned
@@ -1729,7 +1738,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
/* Mask representing the contiguous slots that will be used by
* this attribute.
*/
- const unsigned attr = var->location - generic_base;
+ const unsigned attr = var->data.location - generic_base;
const unsigned use_mask = (1 << slots) - 1;
/* Generate a link error if the set of bits requested for this
@@ -1795,8 +1804,8 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
return false;
}
- to_assign[i].var->location = generic_base + location;
- to_assign[i].var->is_unmatched_generic_inout = 0;
+ to_assign[i].var->data.location = generic_base + location;
+ to_assign[i].var->data.is_unmatched_generic_inout = 0;
used_locations |= (use_mask << location);
}
@@ -1813,15 +1822,15 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
foreach_list(node, sh->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != int(mode)))
+ if ((var == NULL) || (var->data.mode != int(mode)))
continue;
/* A shader 'in' or 'out' variable is only really an input or output if
* its value is used by other shader stages. This will cause the variable
* to have a location assigned.
*/
- if (var->is_unmatched_generic_inout) {
- var->mode = ir_var_auto;
+ if (var->data.is_unmatched_generic_inout) {
+ var->data.mode = ir_var_auto;
}
}
}
@@ -1849,12 +1858,12 @@ store_fragdepth_layout(struct gl_shader_program *prog)
foreach_list(node, ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (var == NULL || var->mode != ir_var_shader_out) {
+ if (var == NULL || var->data.mode != ir_var_shader_out) {
continue;
}
if (strcmp(var->name, "gl_FragDepth") == 0) {
- switch (var->depth_layout) {
+ switch (var->data.depth_layout) {
case ir_depth_layout_none:
prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE;
return;
diff --git a/mesalib/src/glsl/loop_analysis.cpp b/mesalib/src/glsl/loop_analysis.cpp
index b08241af5..fd2b6c923 100644
--- a/mesalib/src/glsl/loop_analysis.cpp
+++ b/mesalib/src/glsl/loop_analysis.cpp
@@ -33,6 +33,46 @@ static bool all_expression_operands_are_loop_constant(ir_rvalue *,
static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *);
+/**
+ * Record the fact that the given loop variable was referenced inside the loop.
+ *
+ * \arg in_assignee is true if the reference was on the LHS of an assignment.
+ *
+ * \arg in_conditional_code_or_nested_loop is true if the reference occurred
+ * inside an if statement or a nested loop.
+ *
+ * \arg current_assignment is the ir_assignment node that the loop variable is
+ * on the LHS of, if any (ignored if \c in_assignee is false).
+ */
+void
+loop_variable::record_reference(bool in_assignee,
+ bool in_conditional_code_or_nested_loop,
+ ir_assignment *current_assignment)
+{
+ if (in_assignee) {
+ assert(current_assignment != NULL);
+
+ if (in_conditional_code_or_nested_loop ||
+ current_assignment->condition != NULL) {
+ this->conditional_or_nested_assignment = true;
+ }
+
+ if (this->first_assignment == NULL) {
+ assert(this->num_assignments == 0);
+
+ this->first_assignment = current_assignment;
+ }
+
+ this->num_assignments++;
+ } else if (this->first_assignment == current_assignment) {
+ /* This catches the case where the variable is used in the RHS of an
+ * assignment where it is also in the LHS.
+ */
+ this->read_before_write = true;
+ }
+}
+
+
loop_state::loop_state()
{
this->ht = hash_table_ctor(0, hash_table_pointer_hash,
@@ -94,7 +134,7 @@ loop_terminator *
loop_variable_state::insert(ir_if *if_stmt)
{
void *mem_ctx = ralloc_parent(this);
- loop_terminator *t = rzalloc(mem_ctx, loop_terminator);
+ loop_terminator *t = new(mem_ctx) loop_terminator();
t->ir = if_stmt;
this->terminators.push_tail(t);
@@ -102,6 +142,33 @@ loop_variable_state::insert(ir_if *if_stmt)
return t;
}
+
+/**
+ * If the given variable already is recorded in the state for this loop,
+ * return the corresponding loop_variable object that records information
+ * about it.
+ *
+ * Otherwise, create a new loop_variable object to record information about
+ * the variable, and set its \c read_before_write field appropriately based on
+ * \c in_assignee.
+ *
+ * \arg in_assignee is true if this variable was encountered on the LHS of an
+ * assignment.
+ */
+loop_variable *
+loop_variable_state::get_or_insert(ir_variable *var, bool in_assignee)
+{
+ loop_variable *lv = this->get(var);
+
+ if (lv == NULL) {
+ lv = this->insert(var);
+ lv->read_before_write = !in_assignee;
+ }
+
+ return lv;
+}
+
+
namespace {
class loop_analysis : public ir_hierarchical_visitor {
@@ -157,14 +224,14 @@ loop_analysis::visit(ir_loop_jump *ir)
ir_visitor_status
loop_analysis::visit_enter(ir_call *ir)
{
- /* If we're not somewhere inside a loop, there's nothing to do. */
- if (this->state.is_empty())
- return visit_continue;
-
- loop_variable_state *const ls =
- (loop_variable_state *) this->state.get_head();
+ /* Mark every loop that we're currently analyzing as containing an ir_call
+ * (even those at outer nesting levels).
+ */
+ foreach_list(node, &this->state) {
+ loop_variable_state *const ls = (loop_variable_state *) node;
+ ls->contains_calls = true;
+ }
- ls->contains_calls = true;
return visit_continue_with_parent;
}
@@ -177,35 +244,18 @@ loop_analysis::visit(ir_dereference_variable *ir)
if (this->state.is_empty())
return visit_continue;
- loop_variable_state *const ls =
- (loop_variable_state *) this->state.get_head();
-
- ir_variable *var = ir->variable_referenced();
- loop_variable *lv = ls->get(var);
-
- if (lv == NULL) {
- lv = ls->insert(var);
- lv->read_before_write = !this->in_assignee;
- }
-
- if (this->in_assignee) {
- assert(this->current_assignment != NULL);
+ bool nested = false;
- lv->conditional_assignment = (this->if_statement_depth > 0)
- || (this->current_assignment->condition != NULL);
+ foreach_list(node, &this->state) {
+ loop_variable_state *const ls = (loop_variable_state *) node;
- if (lv->first_assignment == NULL) {
- assert(lv->num_assignments == 0);
-
- lv->first_assignment = this->current_assignment;
- }
+ ir_variable *var = ir->variable_referenced();
+ loop_variable *lv = ls->get_or_insert(var, this->in_assignee);
- lv->num_assignments++;
- } else if (lv->first_assignment == this->current_assignment) {
- /* This catches the case where the variable is used in the RHS of an
- * assignment where it is also in the LHS.
- */
- lv->read_before_write = true;
+ lv->record_reference(this->in_assignee,
+ nested || this->if_statement_depth > 0,
+ this->current_assignment);
+ nested = true;
}
return visit_continue;
@@ -286,7 +336,7 @@ loop_analysis::visit_leave(ir_loop *ir)
foreach_list_safe(node, &ls->variables) {
loop_variable *lv = (loop_variable *) node;
- if (lv->conditional_assignment || (lv->num_assignments > 1))
+ if (lv->conditional_or_nested_assignment || (lv->num_assignments > 1))
continue;
/* Process the RHS of the assignment. If all of the variables
@@ -326,9 +376,10 @@ loop_analysis::visit_leave(ir_loop *ir)
assert(lv->num_assignments == 1);
assert(lv->first_assignment != NULL);
- /* The assignmnet to the variable in the loop must be unconditional.
+ /* The assignment to the variable in the loop must be unconditional and
+ * not inside a nested loop.
*/
- if (lv->conditional_assignment)
+ if (lv->conditional_or_nested_assignment)
continue;
/* Basic loop induction variables have a single assignment in the loop
@@ -338,8 +389,6 @@ loop_analysis::visit_leave(ir_loop *ir)
ir_rvalue *const inc =
get_basic_induction_increment(lv->first_assignment, ls->var_hash);
if (inc != NULL) {
- lv->iv_scale = NULL;
- lv->biv = lv->var;
lv->increment = inc;
lv->remove();
@@ -347,6 +396,75 @@ loop_analysis::visit_leave(ir_loop *ir)
}
}
+ /* Search the loop terminating conditions for those of the form 'i < c'
+ * where i is a loop induction variable, c is a constant, and < is any
+ * relative operator. From each of these we can infer an iteration count.
+ * Also figure out which terminator (if any) produces the smallest
+ * iteration count--this is the limiting terminator.
+ */
+ foreach_list(node, &ls->terminators) {
+ loop_terminator *t = (loop_terminator *) node;
+ ir_if *if_stmt = t->ir;
+
+ /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care
+ * about the former here.
+ */
+ ir_expression *cond = if_stmt->condition->as_expression();
+ if (cond == NULL)
+ continue;
+
+ switch (cond->operation) {
+ case ir_binop_less:
+ case ir_binop_greater:
+ case ir_binop_lequal:
+ case ir_binop_gequal: {
+ /* The expressions that we care about will either be of the form
+ * 'counter < limit' or 'limit < counter'. Figure out which is
+ * which.
+ */
+ ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
+ ir_constant *limit = cond->operands[1]->as_constant();
+ enum ir_expression_operation cmp = cond->operation;
+
+ if (limit == NULL) {
+ counter = cond->operands[1]->as_dereference_variable();
+ limit = cond->operands[0]->as_constant();
+
+ switch (cmp) {
+ case ir_binop_less: cmp = ir_binop_greater; break;
+ case ir_binop_greater: cmp = ir_binop_less; break;
+ case ir_binop_lequal: cmp = ir_binop_gequal; break;
+ case ir_binop_gequal: cmp = ir_binop_lequal; break;
+ default: assert(!"Should not get here.");
+ }
+ }
+
+ if ((counter == NULL) || (limit == NULL))
+ break;
+
+ ir_variable *var = counter->variable_referenced();
+
+ ir_rvalue *init = find_initial_value(ir, var);
+
+ loop_variable *lv = ls->get(var);
+ if (lv != NULL && lv->is_induction_var()) {
+ t->iterations = calculate_iterations(init, limit, lv->increment,
+ cmp);
+
+ if (t->iterations >= 0 &&
+ (ls->limiting_terminator == NULL ||
+ t->iterations < ls->limiting_terminator->iterations)) {
+ ls->limiting_terminator = t;
+ }
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
return visit_continue;
}
diff --git a/mesalib/src/glsl/loop_analysis.h b/mesalib/src/glsl/loop_analysis.h
index 769d62661..f841042f0 100644
--- a/mesalib/src/glsl/loop_analysis.h
+++ b/mesalib/src/glsl/loop_analysis.h
@@ -39,16 +39,12 @@ analyze_loop_variables(exec_list *instructions);
/**
* Fill in loop control fields
*
- * Based on analysis of loop variables, this function tries to remove sequences
- * in the loop of the form
+ * Based on analysis of loop variables, this function tries to remove
+ * redundant sequences in the loop of the form
*
* (if (expression bool ...) (break))
*
- * and fill in the \c ir_loop::from, \c ir_loop::to, and \c ir_loop::counter
- * fields of the \c ir_loop.
- *
- * In this process, some conditional break-statements may be eliminated
- * altogether. For example, if it is provable that one loop exit condition will
+ * For example, if it is provable that one loop exit condition will
* always be satisfied before another, the unnecessary exit condition will be
* removed.
*/
@@ -59,6 +55,13 @@ set_loop_controls(exec_list *instructions, loop_state *ls);
extern bool
unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations);
+ir_rvalue *
+find_initial_value(ir_loop *loop, ir_variable *var);
+
+int
+calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
+ enum ir_expression_operation op);
+
/**
* Tracking for all variables used in a loop
@@ -67,15 +70,11 @@ class loop_variable_state : public exec_node {
public:
class loop_variable *get(const ir_variable *);
class loop_variable *insert(ir_variable *);
+ class loop_variable *get_or_insert(ir_variable *, bool in_assignee);
class loop_terminator *insert(ir_if *);
/**
- * Loop whose variable state is being tracked by this structure
- */
- ir_loop *loop;
-
- /**
* Variables that have not yet been classified
*/
exec_list variables;
@@ -104,18 +103,17 @@ public:
exec_list terminators;
/**
- * Hash table containing all variables accessed in this loop
+ * If any of the terminators in \c terminators leads to termination of the
+ * loop after a constant number of iterations, this is the terminator that
+ * leads to termination after the smallest number of iterations. Otherwise
+ * NULL.
*/
- hash_table *var_hash;
+ loop_terminator *limiting_terminator;
/**
- * Maximum number of loop iterations.
- *
- * If this value is negative, then the loop may be infinite. This actually
- * means that analysis was unable to determine an upper bound on the number
- * of loop iterations.
+ * Hash table containing all variables accessed in this loop
*/
- int max_iterations;
+ hash_table *var_hash;
/**
* Number of ir_loop_jump instructions that operate on this loop
@@ -129,11 +127,11 @@ public:
loop_variable_state()
{
- this->max_iterations = -1;
this->num_loop_jumps = 0;
this->contains_calls = false;
this->var_hash = hash_table_ctor(0, hash_table_pointer_hash,
hash_table_pointer_compare);
+ this->limiting_terminator = NULL;
}
~loop_variable_state()
@@ -171,8 +169,11 @@ public:
/** Are all variables in the RHS of the assignment loop constants? */
bool rhs_clean;
- /** Is there an assignment to the variable that is conditional? */
- bool conditional_assignment;
+ /**
+ * Is there an assignment to the variable that is conditional, or inside a
+ * nested loop?
+ */
+ bool conditional_or_nested_assignment;
/** Reference to the first assignment to the variable in the loop body. */
ir_assignment *first_assignment;
@@ -181,27 +182,30 @@ public:
unsigned num_assignments;
/**
- * Increment values for loop induction variables
+ * Increment value for a loop induction variable
*
- * Loop induction variables have a single increment of the form
- * \c b * \c biv + \c c, where \c b and \c c are loop constants and \c i
- * is a basic loop induction variable.
+ * If this is a loop induction variable, the amount by which the variable
+ * is incremented on each iteration through the loop.
*
- * If \c iv_scale is \c NULL, 1 is used. If \c biv is the same as \c var,
- * then \c var is a basic loop induction variable.
+ * If this is not a loop induction variable, NULL.
*/
- /*@{*/
- ir_rvalue *iv_scale;
- ir_variable *biv;
ir_rvalue *increment;
- /*@}*/
+
+
+ inline bool is_induction_var() const
+ {
+ /* Induction variables always have a non-null increment, and vice
+ * versa.
+ */
+ return this->increment != NULL;
+ }
inline bool is_loop_constant() const
{
const bool is_const = (this->num_assignments == 0)
|| ((this->num_assignments == 1)
- && !this->conditional_assignment
+ && !this->conditional_or_nested_assignment
&& !this->read_before_write
&& this->rhs_clean);
@@ -213,16 +217,35 @@ public:
/* Variables that are marked read-only *MUST* be loop constant.
*/
- assert(!this->var->read_only || (this->var->read_only && is_const));
+ assert(!this->var->data.read_only
+ || (this->var->data.read_only && is_const));
return is_const;
}
+
+ void record_reference(bool in_assignee,
+ bool in_conditional_code_or_nested_loop,
+ ir_assignment *current_assignment);
};
class loop_terminator : public exec_node {
public:
+ loop_terminator()
+ : ir(NULL), iterations(-1)
+ {
+ }
+
+ /**
+ * Statement which terminates the loop.
+ */
ir_if *ir;
+
+ /**
+ * The number of iterations after which the terminator is known to
+ * terminate the loop (if that is a fixed value). Otherwise -1.
+ */
+ int iterations;
};
diff --git a/mesalib/src/glsl/loop_controls.cpp b/mesalib/src/glsl/loop_controls.cpp
index 26481930d..3db06ad18 100644
--- a/mesalib/src/glsl/loop_controls.cpp
+++ b/mesalib/src/glsl/loop_controls.cpp
@@ -183,114 +183,41 @@ loop_control_visitor::visit_leave(ir_loop *ir)
return visit_continue;
}
- /* Search the loop terminating conditions for one of the form 'i < c' where
- * i is a loop induction variable, c is a constant, and < is any relative
- * operator.
- */
- int max_iterations = ls->max_iterations;
-
- if(ir->from && ir->to && ir->increment)
- max_iterations = calculate_iterations(ir->from, ir->to, ir->increment, (ir_expression_operation)ir->cmp);
-
- if(max_iterations < 0)
- max_iterations = INT_MAX;
+ if (ls->limiting_terminator != NULL) {
+ /* If the limiting terminator has an iteration count of zero, then we've
+ * proven that the loop cannot run, so delete it.
+ */
+ int iterations = ls->limiting_terminator->iterations;
+ if (iterations == 0) {
+ ir->remove();
+ this->progress = true;
+ return visit_continue;
+ }
+ }
+ /* Remove the conditional break statements associated with all terminators
+ * that are associated with a fixed iteration count, except for the one
+ * associated with the limiting terminator--that one needs to stay, since
+ * it terminates the loop. Exception: if the loop still has a normative
+ * bound, then that terminates the loop, so we don't even need the limiting
+ * terminator.
+ */
foreach_list(node, &ls->terminators) {
loop_terminator *t = (loop_terminator *) node;
- ir_if *if_stmt = t->ir;
- /* If-statements can be either 'if (expr)' or 'if (deref)'. We only care
- * about the former here.
- */
- ir_expression *cond = if_stmt->condition->as_expression();
- if (cond == NULL)
- continue;
-
- switch (cond->operation) {
- case ir_binop_less:
- case ir_binop_greater:
- case ir_binop_lequal:
- case ir_binop_gequal: {
- /* The expressions that we care about will either be of the form
- * 'counter < limit' or 'limit < counter'. Figure out which is
- * which.
- */
- ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
- ir_constant *limit = cond->operands[1]->as_constant();
- enum ir_expression_operation cmp = cond->operation;
-
- if (limit == NULL) {
- counter = cond->operands[1]->as_dereference_variable();
- limit = cond->operands[0]->as_constant();
-
- switch (cmp) {
- case ir_binop_less: cmp = ir_binop_greater; break;
- case ir_binop_greater: cmp = ir_binop_less; break;
- case ir_binop_lequal: cmp = ir_binop_gequal; break;
- case ir_binop_gequal: cmp = ir_binop_lequal; break;
- default: assert(!"Should not get here.");
- }
- }
-
- if ((counter == NULL) || (limit == NULL))
- break;
-
- ir_variable *var = counter->variable_referenced();
-
- ir_rvalue *init = find_initial_value(ir, var);
-
- foreach_list(iv_node, &ls->induction_variables) {
- loop_variable *lv = (loop_variable *) iv_node;
-
- if (lv->var == var) {
- const int iterations = calculate_iterations(init, limit,
- lv->increment,
- cmp);
- if (iterations >= 0) {
- /* If the new iteration count is lower than the previously
- * believed iteration count, update the loop control values.
- */
- if (iterations < max_iterations) {
- ir->from = init->clone(ir, NULL);
- ir->to = limit->clone(ir, NULL);
- ir->increment = lv->increment->clone(ir, NULL);
- ir->counter = lv->var;
- ir->cmp = cmp;
-
- max_iterations = iterations;
- }
-
- /* Remove the conditional break statement. The loop
- * controls are now set such that the exit condition will be
- * satisfied.
- */
- if_stmt->remove();
-
- assert(ls->num_loop_jumps > 0);
- ls->num_loop_jumps--;
-
- this->progress = true;
- }
-
- break;
- }
- }
- break;
- }
+ if (t->iterations < 0)
+ continue;
- default:
- break;
+ if (t != ls->limiting_terminator) {
+ t->ir->remove();
+
+ assert(ls->num_loop_jumps > 0);
+ ls->num_loop_jumps--;
+
+ this->progress = true;
}
}
- /* If we have proven the one of the loop exit conditions is satisifed before
- * running the loop once, remove the loop.
- */
- if (max_iterations == 0)
- ir->remove();
- else
- ls->max_iterations = max_iterations;
-
return visit_continue;
}
diff --git a/mesalib/src/glsl/loop_unroll.cpp b/mesalib/src/glsl/loop_unroll.cpp
index ff97766f1..6eced1736 100644
--- a/mesalib/src/glsl/loop_unroll.cpp
+++ b/mesalib/src/glsl/loop_unroll.cpp
@@ -37,6 +37,10 @@ public:
}
virtual ir_visitor_status visit_leave(ir_loop *ir);
+ void simple_unroll(ir_loop *ir, int iterations);
+ void complex_unroll(ir_loop *ir, int iterations,
+ bool continue_from_then_branch);
+ void splice_post_if_instructions(ir_if *ir_if, exec_list *splice_dest);
loop_state *state;
@@ -86,6 +90,138 @@ public:
};
+/**
+ * Unroll a loop which does not contain any jumps. For example, if the input
+ * is:
+ *
+ * (loop (...) ...instrs...)
+ *
+ * And the iteration count is 3, the output will be:
+ *
+ * ...instrs... ...instrs... ...instrs...
+ */
+void
+loop_unroll_visitor::simple_unroll(ir_loop *ir, int iterations)
+{
+ void *const mem_ctx = ralloc_parent(ir);
+
+ for (int i = 0; i < iterations; i++) {
+ exec_list copy_list;
+
+ copy_list.make_empty();
+ clone_ir_list(mem_ctx, &copy_list, &ir->body_instructions);
+
+ ir->insert_before(&copy_list);
+ }
+
+ /* The loop has been replaced by the unrolled copies. Remove the original
+ * loop from the IR sequence.
+ */
+ ir->remove();
+
+ this->progress = true;
+}
+
+
+/**
+ * Unroll a loop whose last statement is an ir_if. If \c
+ * continue_from_then_branch is true, the loop is repeated only when the
+ * "then" branch of the if is taken; otherwise it is repeated only when the
+ * "else" branch of the if is taken.
+ *
+ * For example, if the input is:
+ *
+ * (loop (...)
+ * ...body...
+ * (if (cond)
+ * (...then_instrs...)
+ * (...else_instrs...)))
+ *
+ * And the iteration count is 3, and \c continue_from_then_branch is true,
+ * then the output will be:
+ *
+ * ...body...
+ * (if (cond)
+ * (...then_instrs...
+ * ...body...
+ * (if (cond)
+ * (...then_instrs...
+ * ...body...
+ * (if (cond)
+ * (...then_instrs...)
+ * (...else_instrs...)))
+ * (...else_instrs...)))
+ * (...else_instrs))
+ */
+void
+loop_unroll_visitor::complex_unroll(ir_loop *ir, int iterations,
+ bool continue_from_then_branch)
+{
+ void *const mem_ctx = ralloc_parent(ir);
+ ir_instruction *ir_to_replace = ir;
+
+ for (int i = 0; i < iterations; i++) {
+ exec_list copy_list;
+
+ copy_list.make_empty();
+ clone_ir_list(mem_ctx, &copy_list, &ir->body_instructions);
+
+ ir_if *ir_if = ((ir_instruction *) copy_list.get_tail())->as_if();
+ assert(ir_if != NULL);
+
+ ir_to_replace->insert_before(&copy_list);
+ ir_to_replace->remove();
+
+ /* placeholder that will be removed in the next iteration */
+ ir_to_replace =
+ new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue);
+
+ exec_list *const list = (continue_from_then_branch)
+ ? &ir_if->then_instructions : &ir_if->else_instructions;
+
+ list->push_tail(ir_to_replace);
+ }
+
+ ir_to_replace->remove();
+
+ this->progress = true;
+}
+
+
+/**
+ * Move all of the instructions which follow \c ir_if to the end of
+ * \c splice_dest.
+ *
+ * For example, in the code snippet:
+ *
+ * (if (cond)
+ * (...then_instructions...
+ * break)
+ * (...else_instructions...))
+ * ...post_if_instructions...
+ *
+ * If \c ir_if points to the "if" instruction, and \c splice_dest points to
+ * (...else_instructions...), the code snippet is transformed into:
+ *
+ * (if (cond)
+ * (...then_instructions...
+ * break)
+ * (...else_instructions...
+ * ...post_if_instructions...))
+ */
+void
+loop_unroll_visitor::splice_post_if_instructions(ir_if *ir_if,
+ exec_list *splice_dest)
+{
+ while (!ir_if->get_next()->is_tail_sentinel()) {
+ ir_instruction *move_ir = (ir_instruction *) ir_if->get_next();
+
+ move_ir->remove();
+ splice_dest->push_tail(move_ir);
+ }
+}
+
+
ir_visitor_status
loop_unroll_visitor::visit_leave(ir_loop *ir)
{
@@ -100,14 +236,14 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
return visit_continue;
}
- iterations = ls->max_iterations;
-
/* Don't try to unroll loops where the number of iterations is not known
* at compile-time.
*/
- if (iterations < 0)
+ if (ls->limiting_terminator == NULL)
return visit_continue;
+ iterations = ls->limiting_terminator->iterations;
+
/* Don't try to unroll loops that have zillions of iterations either.
*/
if (iterations > (int) max_iterations)
@@ -120,127 +256,83 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
if (count.fail || count.nodes * iterations > (int)max_iterations * 5)
return visit_continue;
- if (ls->num_loop_jumps > 1)
- return visit_continue;
- else if (ls->num_loop_jumps) {
- ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail();
- assert(last_ir != NULL);
-
- if (is_break(last_ir)) {
- /* If the only loop-jump is a break at the end of the loop, the loop
- * will execute exactly once. Remove the break, set the iteration
- * count, and fall through to the normal unroller.
- */
- last_ir->remove();
- iterations = 1;
-
- this->progress = true;
- } else {
- ir_if *ir_if = NULL;
- ir_instruction *break_ir = NULL;
- bool continue_from_then_branch = false;
-
- foreach_list(node, &ir->body_instructions) {
- /* recognize loops in the form produced by ir_lower_jumps */
- ir_instruction *cur_ir = (ir_instruction *) node;
-
- ir_if = cur_ir->as_if();
- if (ir_if != NULL) {
- /* Determine which if-statement branch, if any, ends with a
- * break. The branch that did *not* have the break will get a
- * temporary continue inserted in each iteration of the loop
- * unroll.
- *
- * Note that since ls->num_loop_jumps is <= 1, it is impossible
- * for both branches to end with a break.
- */
- ir_instruction *ir_if_last =
- (ir_instruction *) ir_if->then_instructions.get_tail();
-
- if (is_break(ir_if_last)) {
- continue_from_then_branch = false;
- break_ir = ir_if_last;
- break;
- } else {
- ir_if_last =
- (ir_instruction *) ir_if->else_instructions.get_tail();
-
- if (is_break(ir_if_last)) {
- break_ir = ir_if_last;
- continue_from_then_branch = true;
- break;
- }
- }
- }
- }
-
- if (break_ir == NULL)
- return visit_continue;
-
- /* move instructions after then if in the continue branch */
- while (!ir_if->get_next()->is_tail_sentinel()) {
- ir_instruction *move_ir = (ir_instruction *) ir_if->get_next();
-
- move_ir->remove();
- if (continue_from_then_branch)
- ir_if->then_instructions.push_tail(move_ir);
- else
- ir_if->else_instructions.push_tail(move_ir);
- }
-
- /* Remove the break from the if-statement.
- */
- break_ir->remove();
-
- void *const mem_ctx = ralloc_parent(ir);
- ir_instruction *ir_to_replace = ir;
-
- for (int i = 0; i < iterations; i++) {
- exec_list copy_list;
+ /* Note: the limiting terminator contributes 1 to ls->num_loop_jumps.
+ * We'll be removing the limiting terminator before we unroll.
+ */
+ assert(ls->num_loop_jumps > 0);
+ unsigned predicted_num_loop_jumps = ls->num_loop_jumps - 1;
- copy_list.make_empty();
- clone_ir_list(mem_ctx, &copy_list, &ir->body_instructions);
+ if (predicted_num_loop_jumps > 1)
+ return visit_continue;
- ir_if = ((ir_instruction *) copy_list.get_tail())->as_if();
- assert(ir_if != NULL);
+ if (predicted_num_loop_jumps == 0) {
+ ls->limiting_terminator->ir->remove();
+ simple_unroll(ir, iterations);
+ return visit_continue;
+ }
- ir_to_replace->insert_before(&copy_list);
- ir_to_replace->remove();
+ ir_instruction *last_ir = (ir_instruction *) ir->body_instructions.get_tail();
+ assert(last_ir != NULL);
- /* placeholder that will be removed in the next iteration */
- ir_to_replace =
- new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue);
+ if (is_break(last_ir)) {
+ /* If the only loop-jump is a break at the end of the loop, the loop
+ * will execute exactly once. Remove the break and use the simple
+ * unroller with an iteration count of 1.
+ */
+ last_ir->remove();
- exec_list *const list = (continue_from_then_branch)
- ? &ir_if->then_instructions : &ir_if->else_instructions;
+ ls->limiting_terminator->ir->remove();
+ simple_unroll(ir, 1);
+ return visit_continue;
+ }
- list->push_tail(ir_to_replace);
+ foreach_list(node, &ir->body_instructions) {
+ /* recognize loops in the form produced by ir_lower_jumps */
+ ir_instruction *cur_ir = (ir_instruction *) node;
+
+ /* Skip the limiting terminator, since it will go away when we
+ * unroll.
+ */
+ if (cur_ir == ls->limiting_terminator->ir)
+ continue;
+
+ ir_if *ir_if = cur_ir->as_if();
+ if (ir_if != NULL) {
+ /* Determine which if-statement branch, if any, ends with a
+ * break. The branch that did *not* have the break will get a
+ * temporary continue inserted in each iteration of the loop
+ * unroll.
+ *
+ * Note that since ls->num_loop_jumps is <= 1, it is impossible
+ * for both branches to end with a break.
+ */
+ ir_instruction *ir_if_last =
+ (ir_instruction *) ir_if->then_instructions.get_tail();
+
+ if (is_break(ir_if_last)) {
+ ls->limiting_terminator->ir->remove();
+ splice_post_if_instructions(ir_if, &ir_if->else_instructions);
+ ir_if_last->remove();
+ complex_unroll(ir, iterations, false);
+ return visit_continue;
+ } else {
+ ir_if_last =
+ (ir_instruction *) ir_if->else_instructions.get_tail();
+
+ if (is_break(ir_if_last)) {
+ ls->limiting_terminator->ir->remove();
+ splice_post_if_instructions(ir_if, &ir_if->then_instructions);
+ ir_if_last->remove();
+ complex_unroll(ir, iterations, true);
+ return visit_continue;
+ }
}
-
- ir_to_replace->remove();
-
- this->progress = true;
- return visit_continue;
}
}
- void *const mem_ctx = ralloc_parent(ir);
-
- for (int i = 0; i < iterations; i++) {
- exec_list copy_list;
-
- copy_list.make_empty();
- clone_ir_list(mem_ctx, &copy_list, &ir->body_instructions);
-
- ir->insert_before(&copy_list);
- }
-
- /* The loop has been replaced by the unrolled copies. Remove the original
- * loop from the IR sequence.
+ /* Did not find the break statement. It must be in a complex if-nesting,
+ * so don't try to unroll.
*/
- ir->remove();
-
- this->progress = true;
return visit_continue;
}
diff --git a/mesalib/src/glsl/lower_clip_distance.cpp b/mesalib/src/glsl/lower_clip_distance.cpp
index 04fa6d410..bb4f6ab11 100644
--- a/mesalib/src/glsl/lower_clip_distance.cpp
+++ b/mesalib/src/glsl/lower_clip_distance.cpp
@@ -135,13 +135,13 @@ lower_clip_distance_visitor::visit(ir_variable *ir)
"gl_ClipDistanceMESA");
this->new_clip_distance_1d_var->type
= glsl_type::get_array_instance(glsl_type::vec4_type, new_size);
- this->new_clip_distance_1d_var->max_array_access
- = ir->max_array_access / 4;
+ this->new_clip_distance_1d_var->data.max_array_access
+ = ir->data.max_array_access / 4;
ir->replace_with(this->new_clip_distance_1d_var);
} else {
/* 2D gl_ClipDistance (used for geometry input). */
- assert(ir->mode == ir_var_shader_in &&
+ assert(ir->data.mode == ir_var_shader_in &&
this->shader_type == GL_GEOMETRY_SHADER_ARB);
if (this->old_clip_distance_2d_var)
return visit_continue;
@@ -161,8 +161,8 @@ lower_clip_distance_visitor::visit(ir_variable *ir)
glsl_type::get_array_instance(glsl_type::vec4_type,
new_size),
ir->type->array_size());
- this->new_clip_distance_2d_var->max_array_access
- = ir->max_array_access / 4;
+ this->new_clip_distance_2d_var->data.max_array_access
+ = ir->data.max_array_access / 4;
ir->replace_with(this->new_clip_distance_2d_var);
}
@@ -500,8 +500,8 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir)
this->base_ir->insert_before(temp_clip_distance);
actual_param->replace_with(
new(ctx) ir_dereference_variable(temp_clip_distance));
- if (formal_param->mode == ir_var_function_in
- || formal_param->mode == ir_var_function_inout) {
+ if (formal_param->data.mode == ir_var_function_in
+ || formal_param->data.mode == ir_var_function_inout) {
/* Copy from gl_ClipDistance to the temporary before the call.
* Since we are going to insert this copy before the current
* instruction, we need to visit it afterwards to make sure it
@@ -513,8 +513,8 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir)
this->base_ir->insert_before(new_assignment);
this->visit_new_assignment(new_assignment);
}
- if (formal_param->mode == ir_var_function_out
- || formal_param->mode == ir_var_function_inout) {
+ if (formal_param->data.mode == ir_var_function_out
+ || formal_param->data.mode == ir_var_function_inout) {
/* Copy from the temporary to gl_ClipDistance after the call.
* Since visit_list_elements() has already decided which
* instruction it's going to visit next, we need to visit
diff --git a/mesalib/src/glsl/lower_instructions.cpp b/mesalib/src/glsl/lower_instructions.cpp
index d01879cbd..8f8d448ea 100644
--- a/mesalib/src/glsl/lower_instructions.cpp
+++ b/mesalib/src/glsl/lower_instructions.cpp
@@ -383,7 +383,6 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
/* Constants */
ir_constant *zeroi = ir_constant::zero(ir, ivec);
- ir_constant *zerof = ir_constant::zero(ir, ir->type);
ir_constant *sign_mantissa_mask = new(ir) ir_constant(0x807fffffu, vec_elem);
ir_constant *sign_mask = new(ir) ir_constant(0x80000000u, vec_elem);
@@ -429,8 +428,7 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
*/
i.insert_before(zero_sign_x);
i.insert_before(assign(zero_sign_x,
- bitcast_u2f(bit_or(bit_and(bitcast_f2u(x), sign_mask),
- bitcast_f2u(zerof)))));
+ bitcast_u2f(bit_and(bitcast_f2u(x), sign_mask))));
i.insert_before(is_not_zero_or_underflow);
i.insert_before(assign(is_not_zero_or_underflow,
diff --git a/mesalib/src/glsl/lower_named_interface_blocks.cpp b/mesalib/src/glsl/lower_named_interface_blocks.cpp
index d59d11150..09d867ea3 100644
--- a/mesalib/src/glsl/lower_named_interface_blocks.cpp
+++ b/mesalib/src/glsl/lower_named_interface_blocks.cpp
@@ -108,7 +108,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
* but, this will require changes to the other uniform block
* support code.
*/
- if (var->mode == ir_var_uniform)
+ if (var->data.mode == ir_var_uniform)
continue;
const glsl_type * iface_t = var->type;
@@ -139,8 +139,8 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
new_var =
new(mem_ctx) ir_variable(iface_t->fields.structure[i].type,
var_name,
- (ir_variable_mode) var->mode);
- new_var->from_named_ifc_block_nonarray = 1;
+ (ir_variable_mode) var->data.mode);
+ new_var->data.from_named_ifc_block_nonarray = 1;
} else {
const glsl_type *new_array_type =
glsl_type::get_array_instance(
@@ -149,14 +149,15 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
new_var =
new(mem_ctx) ir_variable(new_array_type,
var_name,
- (ir_variable_mode) var->mode);
- new_var->from_named_ifc_block_array = 1;
+ (ir_variable_mode) var->data.mode);
+ new_var->data.from_named_ifc_block_array = 1;
}
- new_var->location = iface_t->fields.structure[i].location;
- new_var->explicit_location = (new_var->location >= 0);
- new_var->interpolation =
+ new_var->data.location = iface_t->fields.structure[i].location;
+ new_var->data.explicit_location = (new_var->data.location >= 0);
+ new_var->data.interpolation =
iface_t->fields.structure[i].interpolation;
- new_var->centroid = iface_t->fields.structure[i].centroid;
+ new_var->data.centroid = iface_t->fields.structure[i].centroid;
+ new_var->data.sample = iface_t->fields.structure[i].sample;
new_var->init_interface_type(iface_t);
hash_table_insert(interface_namespace, new_var,
@@ -211,7 +212,7 @@ flatten_named_interface_blocks_declarations::handle_rvalue(ir_rvalue **rvalue)
* but, this will require changes to the other uniform block
* support code.
*/
- if (var->mode == ir_var_uniform)
+ if (var->data.mode == ir_var_uniform)
return;
if (var->get_interface_type() != NULL) {
diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp
index 128b0b8cd..afe17766b 100644
--- a/mesalib/src/glsl/lower_output_reads.cpp
+++ b/mesalib/src/glsl/lower_output_reads.cpp
@@ -91,7 +91,7 @@ output_read_remover::~output_read_remover()
ir_visitor_status
output_read_remover::visit(ir_dereference_variable *ir)
{
- if (ir->var->mode != ir_var_shader_out)
+ if (ir->var->data.mode != ir_var_shader_out)
return visit_continue;
ir_variable *temp = (ir_variable *) hash_table_find(replacements, ir->var);
diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp
index 61ee692f6..9edef5d04 100644
--- a/mesalib/src/glsl/lower_packed_varyings.cpp
+++ b/mesalib/src/glsl/lower_packed_varyings.cpp
@@ -258,8 +258,8 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
if (var == NULL)
continue;
- if (var->mode != this->mode ||
- var->location < (int) this->location_base ||
+ if (var->data.mode != this->mode ||
+ var->data.location < (int) this->location_base ||
!this->needs_lowering(var))
continue;
@@ -268,18 +268,18 @@ lower_packed_varyings_visitor::run(exec_list *instructions)
* safe, caller should ensure that integral varyings always use flat
* interpolation, even when this is not required by GLSL.
*/
- assert(var->interpolation == INTERP_QUALIFIER_FLAT ||
+ assert(var->data.interpolation == INTERP_QUALIFIER_FLAT ||
!var->type->contains_integer());
/* Change the old varying into an ordinary global. */
- var->mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
/* Create a reference to the old varying. */
ir_dereference_variable *deref
= new(this->mem_ctx) ir_dereference_variable(var);
/* Recursively pack or unpack it. */
- this->lower_rvalue(deref, var->location * 4 + var->location_frac, var,
+ this->lower_rvalue(deref, var->data.location * 4 + var->data.location_frac, var,
var->name, this->gs_input_vertices != 0, 0);
}
}
@@ -547,7 +547,7 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
if (this->packed_varyings[slot] == NULL) {
char *packed_name = ralloc_asprintf(this->mem_ctx, "packed:%s", name);
const glsl_type *packed_type;
- if (unpacked_var->interpolation == INTERP_QUALIFIER_FLAT)
+ if (unpacked_var->data.interpolation == INTERP_QUALIFIER_FLAT)
packed_type = glsl_type::ivec4_type;
else
packed_type = glsl_type::vec4_type;
@@ -562,11 +562,12 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
/* Prevent update_array_sizes() from messing with the size of the
* array.
*/
- packed_var->max_array_access = this->gs_input_vertices - 1;
+ packed_var->data.max_array_access = this->gs_input_vertices - 1;
}
- packed_var->centroid = unpacked_var->centroid;
- packed_var->interpolation = unpacked_var->interpolation;
- packed_var->location = location;
+ packed_var->data.centroid = unpacked_var->data.centroid;
+ packed_var->data.sample = unpacked_var->data.sample;
+ packed_var->data.interpolation = unpacked_var->data.interpolation;
+ packed_var->data.location = location;
unpacked_var->insert_before(packed_var);
this->packed_varyings[slot] = packed_var;
} else {
diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp
index 16b6801b8..c73b148b0 100644
--- a/mesalib/src/glsl/lower_ubo_reference.cpp
+++ b/mesalib/src/glsl/lower_ubo_reference.cpp
@@ -143,7 +143,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
struct gl_uniform_block *block = &shader->UniformBlocks[i];
this->ubo_var = var->is_interface_instance()
- ? &block->Uniforms[0] : &block->Uniforms[var->location];
+ ? &block->Uniforms[0] : &block->Uniforms[var->data.location];
break;
}
diff --git a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp
index 699fb3903..7c5d80f43 100644
--- a/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp
+++ b/mesalib/src/glsl/lower_variable_index_to_cond_assign.cpp
@@ -365,7 +365,7 @@ public:
if (var == NULL)
return this->lower_temps;
- switch (var->mode) {
+ switch (var->data.mode) {
case ir_var_auto:
case ir_var_temporary:
return this->lower_temps;
diff --git a/mesalib/src/glsl/opt_array_splitting.cpp b/mesalib/src/glsl/opt_array_splitting.cpp
index c7c5f6712..e946e0ae5 100644
--- a/mesalib/src/glsl/opt_array_splitting.cpp
+++ b/mesalib/src/glsl/opt_array_splitting.cpp
@@ -122,8 +122,8 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var)
{
assert(var);
- if (var->mode != ir_var_auto &&
- var->mode != ir_var_temporary)
+ if (var->data.mode != ir_var_auto &&
+ var->data.mode != ir_var_temporary)
return NULL;
if (!(var->type->is_array() || var->type->is_matrix()))
diff --git a/mesalib/src/glsl/opt_constant_folding.cpp b/mesalib/src/glsl/opt_constant_folding.cpp
index 072fefe9a..08a47b96b 100644
--- a/mesalib/src/glsl/opt_constant_folding.cpp
+++ b/mesalib/src/glsl/opt_constant_folding.cpp
@@ -127,8 +127,8 @@ 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_function_in
- || sig_param->mode == ir_var_const_in) {
+ if (sig_param->data.mode == ir_var_function_in
+ || sig_param->data.mode == ir_var_const_in) {
ir_rvalue *new_param = param_rval;
handle_rvalue(&new_param);
diff --git a/mesalib/src/glsl/opt_constant_propagation.cpp b/mesalib/src/glsl/opt_constant_propagation.cpp
index 2f65937fe..f1a6fbdaa 100644
--- a/mesalib/src/glsl/opt_constant_propagation.cpp
+++ b/mesalib/src/glsl/opt_constant_propagation.cpp
@@ -285,8 +285,8 @@ ir_constant_propagation_visitor::visit_enter(ir_call *ir)
foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
ir_rvalue *param = (ir_rvalue *)iter.get();
- if (sig_param->mode != ir_var_function_out
- && sig_param->mode != ir_var_function_inout) {
+ if (sig_param->data.mode != ir_var_function_out
+ && sig_param->data.mode != ir_var_function_inout) {
ir_rvalue *new_param = param;
handle_rvalue(&new_param);
if (new_param != param)
diff --git a/mesalib/src/glsl/opt_constant_variable.cpp b/mesalib/src/glsl/opt_constant_variable.cpp
index cbe6450c6..a026c51c3 100644
--- a/mesalib/src/glsl/opt_constant_variable.cpp
+++ b/mesalib/src/glsl/opt_constant_variable.cpp
@@ -137,8 +137,8 @@ ir_constant_variable_visitor::visit_enter(ir_call *ir)
ir_rvalue *param_rval = (ir_rvalue *)iter.get();
ir_variable *param = (ir_variable *)sig_iter.get();
- if (param->mode == ir_var_function_out ||
- param->mode == ir_var_function_inout) {
+ if (param->data.mode == ir_var_function_out ||
+ param->data.mode == ir_var_function_inout) {
ir_variable *var = param_rval->variable_referenced();
struct assignment_entry *entry;
diff --git a/mesalib/src/glsl/opt_copy_propagation.cpp b/mesalib/src/glsl/opt_copy_propagation.cpp
index 7282b611e..db5dfc153 100644
--- a/mesalib/src/glsl/opt_copy_propagation.cpp
+++ b/mesalib/src/glsl/opt_copy_propagation.cpp
@@ -189,8 +189,8 @@ ir_copy_propagation_visitor::visit_enter(ir_call *ir)
foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
ir_instruction *ir = (ir_instruction *)iter.get();
- if (sig_param->mode != ir_var_function_out
- && sig_param->mode != ir_var_function_inout) {
+ if (sig_param->data.mode != ir_var_function_out
+ && sig_param->data.mode != ir_var_function_inout) {
ir->accept(this);
}
sig_param_iter.next();
diff --git a/mesalib/src/glsl/opt_copy_propagation_elements.cpp b/mesalib/src/glsl/opt_copy_propagation_elements.cpp
index 6a19da40d..ba8a0f532 100644
--- a/mesalib/src/glsl/opt_copy_propagation_elements.cpp
+++ b/mesalib/src/glsl/opt_copy_propagation_elements.cpp
@@ -297,8 +297,8 @@ ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir)
foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
ir_instruction *ir = (ir_instruction *)iter.get();
- if (sig_param->mode != ir_var_function_out
- && sig_param->mode != ir_var_function_inout) {
+ if (sig_param->data.mode != ir_var_function_out
+ && sig_param->data.mode != ir_var_function_inout) {
ir->accept(this);
}
sig_param_iter.next();
diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp
index 8f73940d8..a2b63ee99 100644
--- a/mesalib/src/glsl/opt_cse.cpp
+++ b/mesalib/src/glsl/opt_cse.cpp
@@ -193,7 +193,7 @@ is_cse_candidate_visitor::visit(ir_dereference_variable *ir)
/* Currently, since we don't handle kills of the ae based on variables
* getting assigned, we can only handle constant variables.
*/
- if (ir->var->read_only) {
+ if (ir->var->data.read_only) {
return visit_continue;
} else {
ok = false;
diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
index b336bc0a8..a939a2b64 100644
--- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
+++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp
@@ -85,10 +85,10 @@ public:
{
ir_variable *var = ir->variable_referenced();
- if (!var || var->mode != this->mode)
+ if (!var || var->data.mode != this->mode)
return visit_continue;
- if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) {
+ if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) {
this->fragdata_array = var;
ir_constant *index = ir->array_index->as_constant();
@@ -105,7 +105,7 @@ public:
return visit_continue_with_parent;
}
- if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) {
+ if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) {
this->texcoord_array = var;
ir_constant *index = ir->array_index->as_constant();
@@ -130,17 +130,17 @@ public:
{
ir_variable *var = ir->variable_referenced();
- if (var->mode != this->mode || !var->type->is_array())
+ if (var->data.mode != this->mode || !var->type->is_array())
return visit_continue;
- if (this->find_frag_outputs && var->location == FRAG_RESULT_DATA0) {
+ if (this->find_frag_outputs && var->data.location == FRAG_RESULT_DATA0) {
/* This is a whole array dereference. */
this->fragdata_usage |= (1 << var->type->array_size()) - 1;
this->lower_fragdata_array = false;
return visit_continue;
}
- if (!this->find_frag_outputs && var->location == VARYING_SLOT_TEX0) {
+ if (!this->find_frag_outputs && var->data.location == VARYING_SLOT_TEX0) {
/* This is a whole array dereference like "gl_TexCoord = x;",
* there's probably no point in lowering that.
*/
@@ -152,7 +152,7 @@ public:
virtual ir_visitor_status visit(ir_variable *var)
{
- if (var->mode != this->mode)
+ if (var->data.mode != this->mode)
return visit_continue;
/* Nothing to do here for fragment outputs. */
@@ -160,7 +160,7 @@ public:
return visit_continue;
/* Handle colors and fog. */
- switch (var->location) {
+ switch (var->data.location) {
case VARYING_SLOT_COL0:
this->color[0] = var;
this->color_usage |= 1;
@@ -358,9 +358,9 @@ public:
new_var[i] =
new(ctx) ir_variable(glsl_type::vec4_type, name,
this->info->mode);
- new_var[i]->location = start_location + i;
- new_var[i]->explicit_location = true;
- new_var[i]->explicit_index = 0;
+ new_var[i]->data.location = start_location + i;
+ new_var[i]->data.explicit_location = true;
+ new_var[i]->data.explicit_index = 0;
}
ir->head->insert_before(new_var[i]);
diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp
index b65e5c2ce..a8d8b4a39 100644
--- a/mesalib/src/glsl/opt_dead_code.cpp
+++ b/mesalib/src/glsl/opt_dead_code.cpp
@@ -79,9 +79,9 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
/* Remove a single dead assignment to the variable we found.
* Don't do so if it's a shader or function output, though.
*/
- if (entry->var->mode != ir_var_function_out &&
- entry->var->mode != ir_var_function_inout &&
- entry->var->mode != ir_var_shader_out) {
+ if (entry->var->data.mode != ir_var_function_out &&
+ entry->var->data.mode != ir_var_function_inout &&
+ entry->var->data.mode != ir_var_shader_out) {
entry->assign->remove();
progress = true;
@@ -99,7 +99,7 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned)
* stage. Also, once uniform locations have been assigned, the
* declaration cannot be deleted.
*/
- if (entry->var->mode == ir_var_uniform &&
+ if (entry->var->data.mode == ir_var_uniform &&
(uniform_locations_assigned ||
entry->var->constant_value))
continue;
diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp
index 42a30b3d8..43a01662a 100644
--- a/mesalib/src/glsl/opt_dead_code_local.cpp
+++ b/mesalib/src/glsl/opt_dead_code_local.cpp
@@ -121,7 +121,7 @@ public:
*/
foreach_iter(exec_list_iterator, iter, *this->assignments) {
assignment_entry *entry = (assignment_entry *)iter.get();
- if (entry->lhs->mode == ir_var_shader_out) {
+ if (entry->lhs->data.mode == ir_var_shader_out) {
if (debug)
printf("kill %s\n", entry->lhs->name);
entry->remove();
diff --git a/mesalib/src/glsl/opt_flip_matrices.cpp b/mesalib/src/glsl/opt_flip_matrices.cpp
index 2107b1d47..9044fd680 100644
--- a/mesalib/src/glsl/opt_flip_matrices.cpp
+++ b/mesalib/src/glsl/opt_flip_matrices.cpp
@@ -104,8 +104,8 @@ matrix_flipper::visit_enter(ir_expression *ir)
var_ref->var = texmat_transpose;
- texmat_transpose->max_array_access =
- MAX2(texmat_transpose->max_array_access, mat_var->max_array_access);
+ texmat_transpose->data.max_array_access =
+ MAX2(texmat_transpose->data.max_array_access, mat_var->data.max_array_access);
progress = true;
}
diff --git a/mesalib/src/glsl/opt_function_inlining.cpp b/mesalib/src/glsl/opt_function_inlining.cpp
index f8033a095..c8f42a424 100644
--- a/mesalib/src/glsl/opt_function_inlining.cpp
+++ b/mesalib/src/glsl/opt_function_inlining.cpp
@@ -132,21 +132,21 @@ ir_call::generate_inline(ir_instruction *next_ir)
parameters[i] = NULL;
} else {
parameters[i] = sig_param->clone(ctx, ht);
- parameters[i]->mode = ir_var_auto;
+ parameters[i]->data.mode = ir_var_auto;
/* Remove the read-only decoration becuase we're going to write
* directly to this variable. If the cloned variable is left
* read-only and the inlined function is inside a loop, the loop
* analysis code will get confused.
*/
- parameters[i]->read_only = false;
+ parameters[i]->data.read_only = false;
next_ir->insert_before(parameters[i]);
}
/* Move the actual param into our param variable if it's an 'in' type. */
- if (parameters[i] && (sig_param->mode == ir_var_function_in ||
- sig_param->mode == ir_var_const_in ||
- sig_param->mode == ir_var_function_inout)) {
+ if (parameters[i] && (sig_param->data.mode == ir_var_function_in ||
+ sig_param->data.mode == ir_var_const_in ||
+ sig_param->data.mode == ir_var_function_inout)) {
ir_assignment *assign;
assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
@@ -202,8 +202,8 @@ ir_call::generate_inline(ir_instruction *next_ir)
const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();
/* Move our param variable into the actual param if it's an 'out' type. */
- if (parameters[i] && (sig_param->mode == ir_var_function_out ||
- sig_param->mode == ir_var_function_inout)) {
+ if (parameters[i] && (sig_param->data.mode == ir_var_function_out ||
+ sig_param->data.mode == ir_var_function_inout)) {
ir_assignment *assign;
assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(),
diff --git a/mesalib/src/glsl/opt_structure_splitting.cpp b/mesalib/src/glsl/opt_structure_splitting.cpp
index 9f4b3dd8f..414f0000d 100644
--- a/mesalib/src/glsl/opt_structure_splitting.cpp
+++ b/mesalib/src/glsl/opt_structure_splitting.cpp
@@ -103,8 +103,8 @@ ir_structure_reference_visitor::get_variable_entry(ir_variable *var)
{
assert(var);
- if (!var->type->is_record() || var->mode == ir_var_uniform
- || var->mode == ir_var_shader_in || var->mode == ir_var_shader_out)
+ if (!var->type->is_record() || var->data.mode == ir_var_uniform
+ || var->data.mode == ir_var_shader_in || var->data.mode == ir_var_shader_out)
return NULL;
foreach_iter(exec_list_iterator, iter, this->variable_list) {
diff --git a/mesalib/src/glsl/opt_tree_grafting.cpp b/mesalib/src/glsl/opt_tree_grafting.cpp
index 46c06e6c4..6d75a1573 100644
--- a/mesalib/src/glsl/opt_tree_grafting.cpp
+++ b/mesalib/src/glsl/opt_tree_grafting.cpp
@@ -211,8 +211,8 @@ 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_function_in
- && sig_param->mode != ir_var_const_in) {
+ if (sig_param->data.mode != ir_var_function_in
+ && sig_param->data.mode != ir_var_const_in) {
if (check_graft(ir, sig_param) == visit_stop)
return visit_stop;
continue;
@@ -361,9 +361,9 @@ tree_grafting_basic_block(ir_instruction *bb_first,
if (!lhs_var)
continue;
- if (lhs_var->mode == ir_var_function_out ||
- lhs_var->mode == ir_var_function_inout ||
- lhs_var->mode == ir_var_shader_out)
+ if (lhs_var->data.mode == ir_var_function_out ||
+ lhs_var->data.mode == ir_var_function_inout ||
+ lhs_var->data.mode == ir_var_shader_out)
continue;
ir_variable_refcount_entry *entry = info->refs->get_variable_entry(lhs_var);
diff --git a/mesalib/src/glsl/standalone_scaffolding.h b/mesalib/src/glsl/standalone_scaffolding.h
index 7afb1c313..9f4818a8a 100644
--- a/mesalib/src/glsl/standalone_scaffolding.h
+++ b/mesalib/src/glsl/standalone_scaffolding.h
@@ -60,7 +60,7 @@ _mesa_shader_type_to_index(GLenum v)
return MESA_SHADER_GEOMETRY;
default:
assert(!"bad value in _mesa_shader_type_to_index()");
- return MESA_SHADER_TYPES;
+ return MESA_SHADER_VERTEX;
}
}