aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-07-19 15:00:38 +0200
committermarha <marha@users.sourceforge.net>2014-07-19 15:00:38 +0200
commitd0c30e7945e76ac119f6d867e27137c8a76f7e15 (patch)
tree1bfb3148a6f43bdd32746c5b882f9f083076cf91 /mesalib/src/glsl
parente708bebcc029873004ade4241f347ce8c58896af (diff)
downloadvcxsrv-d0c30e7945e76ac119f6d867e27137c8a76f7e15.tar.gz
vcxsrv-d0c30e7945e76ac119f6d867e27137c8a76f7e15.tar.bz2
vcxsrv-d0c30e7945e76ac119f6d867e27137c8a76f7e15.zip
fontconfig plink libX11 libxcb mesa git update 19 July 2014
plink revision 10207 xserver commit cfa302d6224d10860e60491333950544c4fb9b04 libxcb commit 49a61c8b459ab19c7f39e653bbb0d0339ea8f00f libX11 commit 5525e8433f93bce464412f27cffa203ea628f368 fontconfig commit 6781c6baef062eeea5b5b68e4a9c31ea6cd7539b mesa commit f6fc80734533140a69b30361fe0d4773a03515db
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r--mesalib/src/glsl/ast_function.cpp35
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp87
-rw-r--r--mesalib/src/glsl/builtin_functions.cpp67
-rw-r--r--mesalib/src/glsl/glsl_parser.yy8
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp2
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h5
-rw-r--r--mesalib/src/glsl/ir.cpp6
-rw-r--r--mesalib/src/glsl/ir.h33
-rw-r--r--mesalib/src/glsl/ir_builder.cpp18
-rw-r--r--mesalib/src/glsl/ir_builder.h4
-rw-r--r--mesalib/src/glsl/ir_constant_expression.cpp2
-rw-r--r--mesalib/src/glsl/ir_hierarchical_visitor.cpp158
-rw-r--r--mesalib/src/glsl/ir_hierarchical_visitor.h29
-rw-r--r--mesalib/src/glsl/ir_reader.cpp7
-rw-r--r--mesalib/src/glsl/ir_validate.cpp30
-rw-r--r--mesalib/src/glsl/list.h40
-rw-r--r--mesalib/src/glsl/opt_function_inlining.cpp7
-rw-r--r--mesalib/src/glsl/opt_rebalance_tree.cpp23
18 files changed, 466 insertions, 95 deletions
diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp
index cdb34cc69..4981fe174 100644
--- a/mesalib/src/glsl/ast_function.cpp
+++ b/mesalib/src/glsl/ast_function.cpp
@@ -178,6 +178,24 @@ verify_parameter_modes(_mesa_glsl_parse_state *state,
return false;
}
+ /* Verify that shader_in parameters are shader inputs */
+ if (formal->data.must_be_shader_input) {
+ ir_variable *var = actual->variable_referenced();
+ if (var && var->data.mode != ir_var_shader_in) {
+ _mesa_glsl_error(&loc, state,
+ "parameter `%s` must be a shader input",
+ formal->name);
+ return false;
+ }
+
+ if (actual->ir_type == ir_type_swizzle) {
+ _mesa_glsl_error(&loc, state,
+ "parameter `%s` must not be swizzled",
+ formal->name);
+ return false;
+ }
+ }
+
/* Verify that 'out' and 'inout' actual parameters are lvalues. */
if (formal->data.mode == ir_var_function_out
|| formal->data.mode == ir_var_function_inout) {
@@ -742,11 +760,22 @@ process_vec_mat_constructor(exec_list *instructions,
instructions->push_tail(var);
int i = 0;
+
foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
- ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
- new(ctx) ir_constant(i));
+ ir_instruction *assignment = NULL;
+
+ if (var->type->is_matrix()) {
+ ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
+ new(ctx) ir_constant(i));
+ assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
+ } else {
+ /* use writemask rather than index for vector */
+ assert(var->type->is_vector());
+ assert(i < 4);
+ ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+ assignment = new(ctx) ir_assignment(lhs, rhs, NULL, (unsigned)(1 << i));
+ }
- ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs, NULL);
instructions->push_tail(assignment);
i++;
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 885bee547..328cd1b1b 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -4513,6 +4513,12 @@ ast_switch_statement::hir(exec_list *instructions,
instructions->push_tail(new(ctx) ir_assignment(deref_is_break_var,
is_break_val));
+ state->switch_state.run_default =
+ new(ctx) ir_variable(glsl_type::bool_type,
+ "run_default_tmp",
+ ir_var_temporary);
+ instructions->push_tail(state->switch_state.run_default);
+
/* Cache test expression.
*/
test_to_hir(instructions, state);
@@ -4567,8 +4573,71 @@ ir_rvalue *
ast_case_statement_list::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
{
- foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases)
- case_stmt->hir(instructions, state);
+ exec_list default_case, after_default, tmp;
+
+ foreach_list_typed (ast_case_statement, case_stmt, link, & this->cases) {
+ case_stmt->hir(&tmp, state);
+
+ /* Default case. */
+ if (state->switch_state.previous_default && default_case.is_empty()) {
+ default_case.append_list(&tmp);
+ continue;
+ }
+
+ /* If default case found, append 'after_default' list. */
+ if (!default_case.is_empty())
+ after_default.append_list(&tmp);
+ else
+ instructions->append_list(&tmp);
+ }
+
+ /* Handle the default case. This is done here because default might not be
+ * the last case. We need to add checks against following cases first to see
+ * if default should be chosen or not.
+ */
+ if (!default_case.is_empty()) {
+
+ /* Default case was the last one, no checks required. */
+ if (after_default.is_empty()) {
+ instructions->append_list(&default_case);
+ return NULL;
+ }
+
+ ir_rvalue *const true_val = new (state) ir_constant(true);
+ ir_dereference_variable *deref_run_default_var =
+ new(state) ir_dereference_variable(state->switch_state.run_default);
+
+ /* Choose to run default case initially, following conditional
+ * assignments might change this.
+ */
+ ir_assignment *const init_var =
+ new(state) ir_assignment(deref_run_default_var, true_val);
+ instructions->push_tail(init_var);
+
+ foreach_in_list(ir_instruction, ir, &after_default) {
+ ir_assignment *assign = ir->as_assignment();
+
+ if (!assign)
+ continue;
+
+ /* Clone the check between case label and init expression. */
+ ir_expression *exp = (ir_expression*) assign->condition;
+ ir_expression *clone = exp->clone(state, NULL);
+
+ ir_dereference_variable *deref_var =
+ new(state) ir_dereference_variable(state->switch_state.run_default);
+ ir_rvalue *const false_val = new (state) ir_constant(false);
+
+ ir_assignment *const set_false =
+ new(state) ir_assignment(deref_var, false_val, clone);
+
+ instructions->push_tail(set_false);
+ }
+
+ /* Append default case and all cases after it. */
+ instructions->append_list(&default_case);
+ instructions->append_list(&after_default);
+ }
/* Case statements do not have r-values. */
return NULL;
@@ -4728,9 +4797,17 @@ ast_case_label::hir(exec_list *instructions,
}
state->switch_state.previous_default = this;
+ /* Set fallthru condition on 'run_default' bool. */
+ ir_dereference_variable *deref_run_default =
+ new(ctx) ir_dereference_variable(state->switch_state.run_default);
+ ir_rvalue *const cond_true = new(ctx) ir_constant(true);
+ ir_expression *test_cond = new(ctx) ir_expression(ir_binop_all_equal,
+ cond_true,
+ deref_run_default);
+
/* Set falltrhu state. */
ir_assignment *set_fallthru =
- new(ctx) ir_assignment(deref_fallthru_var, true_val);
+ new(ctx) ir_assignment(deref_fallthru_var, true_val, test_cond);
instructions->push_tail(set_fallthru);
}
@@ -5007,9 +5084,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
* 'declarations' list in each of the elements.
*/
foreach_list_typed (ast_declarator_list, decl_list, link, declarations) {
- foreach_list_typed (ast_declaration, decl, link, &decl_list->declarations) {
- decl_count++;
- }
+ decl_count += decl_list->declarations.length();
}
/* Allocate storage for the fields and process the field
diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp
index 258b83142..e01742c4d 100644
--- a/mesalib/src/glsl/builtin_functions.cpp
+++ b/mesalib/src/glsl/builtin_functions.cpp
@@ -226,6 +226,14 @@ shader_packing_or_gpu_shader5(const _mesa_glsl_parse_state *state)
}
static bool
+fs_gpu_shader5(const _mesa_glsl_parse_state *state)
+{
+ return state->stage == MESA_SHADER_FRAGMENT &&
+ (state->is_version(400, 0) || state->ARB_gpu_shader5_enable);
+}
+
+
+static bool
texture_array_lod(const _mesa_glsl_parse_state *state)
{
return lod_exists_in_stage(state) &&
@@ -627,6 +635,9 @@ private:
B1(uaddCarry)
B1(usubBorrow)
B1(mulExtended)
+ B1(interpolateAtCentroid)
+ B1(interpolateAtOffset)
+ B1(interpolateAtSample)
ir_function_signature *_atomic_intrinsic(builtin_available_predicate avail);
ir_function_signature *_atomic_op(const char *intrinsic,
@@ -2186,6 +2197,24 @@ builtin_builder::create_builtins()
_mulExtended(glsl_type::uvec3_type),
_mulExtended(glsl_type::uvec4_type),
NULL);
+ add_function("interpolateAtCentroid",
+ _interpolateAtCentroid(glsl_type::float_type),
+ _interpolateAtCentroid(glsl_type::vec2_type),
+ _interpolateAtCentroid(glsl_type::vec3_type),
+ _interpolateAtCentroid(glsl_type::vec4_type),
+ NULL);
+ add_function("interpolateAtOffset",
+ _interpolateAtOffset(glsl_type::float_type),
+ _interpolateAtOffset(glsl_type::vec2_type),
+ _interpolateAtOffset(glsl_type::vec3_type),
+ _interpolateAtOffset(glsl_type::vec4_type),
+ NULL);
+ add_function("interpolateAtSample",
+ _interpolateAtSample(glsl_type::float_type),
+ _interpolateAtSample(glsl_type::vec2_type),
+ _interpolateAtSample(glsl_type::vec3_type),
+ _interpolateAtSample(glsl_type::vec4_type),
+ NULL);
add_function("atomicCounter",
_atomic_op("__intrinsic_atomic_read",
@@ -4260,6 +4289,44 @@ builtin_builder::_mulExtended(const glsl_type *type)
}
ir_function_signature *
+builtin_builder::_interpolateAtCentroid(const glsl_type *type)
+{
+ ir_variable *interpolant = in_var(type, "interpolant");
+ interpolant->data.must_be_shader_input = 1;
+ MAKE_SIG(type, fs_gpu_shader5, 1, interpolant);
+
+ body.emit(ret(interpolate_at_centroid(interpolant)));
+
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_interpolateAtOffset(const glsl_type *type)
+{
+ ir_variable *interpolant = in_var(type, "interpolant");
+ interpolant->data.must_be_shader_input = 1;
+ ir_variable *offset = in_var(glsl_type::vec2_type, "offset");
+ MAKE_SIG(type, fs_gpu_shader5, 2, interpolant, offset);
+
+ body.emit(ret(interpolate_at_offset(interpolant, offset)));
+
+ return sig;
+}
+
+ir_function_signature *
+builtin_builder::_interpolateAtSample(const glsl_type *type)
+{
+ ir_variable *interpolant = in_var(type, "interpolant");
+ interpolant->data.must_be_shader_input = 1;
+ ir_variable *sample_num = in_var(glsl_type::int_type, "sample_num");
+ MAKE_SIG(type, fs_gpu_shader5, 2, interpolant, sample_num);
+
+ body.emit(ret(interpolate_at_sample(interpolant, sample_num)));
+
+ return sig;
+}
+
+ir_function_signature *
builtin_builder::_atomic_intrinsic(builtin_available_predicate avail)
{
ir_variable *counter = in_var(glsl_type::atomic_uint_type, "counter");
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index b9897498f..4c871633f 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -376,6 +376,14 @@ external_declaration_list:
if ($2 != NULL)
state->translation_unit.push_tail(& $2->link);
}
+ | external_declaration_list extension_statement {
+ if (!state->allow_extension_directive_midshader) {
+ _mesa_glsl_error(& @2, state,
+ "#extension directive is not allowed "
+ "in the middle of a shader");
+ YYERROR;
+ }
+ }
;
variable_identifier:
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index b327c2b43..890123ad1 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -210,6 +210,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->early_fragment_tests = false;
memset(this->atomic_counter_offsets, 0,
sizeof(this->atomic_counter_offsets));
+ this->allow_extension_directive_midshader =
+ ctx->Const.AllowGLSLExtensionDirectiveMidShader;
}
/**
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index 17918163e..ce66e2fa4 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -43,6 +43,9 @@ struct glsl_switch_state {
ir_variable *is_break_var;
class ast_switch_statement *switch_nesting_ast;
+ /** Used to set condition if 'default' label should be chosen. */
+ ir_variable *run_default;
+
/** Table of constant values already used in case labels */
struct hash_table *labels_ht;
class ast_case_label *previous_default;
@@ -490,6 +493,8 @@ struct _mesa_glsl_parse_state {
/** Atomic counter offsets by binding */
unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS];
+
+ bool allow_extension_directive_midshader;
};
# define YYLLOC_DEFAULT(Current, Rhs, N) \
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 1d8bb6e7b..28fd94b95 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -250,6 +250,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
case ir_unop_dFdx:
case ir_unop_dFdy:
case ir_unop_bitfield_reverse:
+ case ir_unop_interpolate_at_centroid:
this->type = op0->type;
break;
@@ -403,6 +404,8 @@ ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1)
case ir_binop_rshift:
case ir_binop_bfm:
case ir_binop_ldexp:
+ case ir_binop_interpolate_at_offset:
+ case ir_binop_interpolate_at_sample:
this->type = op0->type;
break;
@@ -524,6 +527,7 @@ static const char *const operator_strs[] = {
"find_msb",
"find_lsb",
"noise",
+ "interpolate_at_centroid",
"+",
"-",
"*",
@@ -557,6 +561,8 @@ static const char *const operator_strs[] = {
"ubo_load",
"ldexp",
"vector_extract",
+ "interpolate_at_offset",
+ "interpolate_at_sample",
"fma",
"lrp",
"csel",
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index d5239d4de..ea19924ab 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -678,6 +678,12 @@ public:
unsigned from_named_ifc_block_array:1;
/**
+ * Non-zero if the variable must be a shader input. This is useful for
+ * constraints on function parameters.
+ */
+ unsigned must_be_shader_input:1;
+
+ /**
* \brief Layout qualifier for gl_FragDepth.
*
* This is not equal to \c ir_depth_layout_none if and only if this
@@ -1234,9 +1240,16 @@ enum ir_expression_operation {
ir_unop_noise,
/**
+ * Interpolate fs input at centroid
+ *
+ * operand0 is the fs input.
+ */
+ ir_unop_interpolate_at_centroid,
+
+ /**
* A sentinel marking the last of the unary operations.
*/
- ir_last_unop = ir_unop_noise,
+ ir_last_unop = ir_unop_interpolate_at_centroid,
ir_binop_add,
ir_binop_sub,
@@ -1355,9 +1368,25 @@ enum ir_expression_operation {
ir_binop_vector_extract,
/**
+ * Interpolate fs input at offset
+ *
+ * operand0 is the fs input
+ * operand1 is the offset from the pixel center
+ */
+ ir_binop_interpolate_at_offset,
+
+ /**
+ * Interpolate fs input at sample position
+ *
+ * operand0 is the fs input
+ * operand1 is the sample ID
+ */
+ ir_binop_interpolate_at_sample,
+
+ /**
* A sentinel marking the last of the binary operations.
*/
- ir_last_binop = ir_binop_vector_extract,
+ ir_last_binop = ir_binop_interpolate_at_sample,
/**
* \name Fused floating-point multiply-add, part of ARB_gpu_shader5.
diff --git a/mesalib/src/glsl/ir_builder.cpp b/mesalib/src/glsl/ir_builder.cpp
index f4a1c6efa..f03941443 100644
--- a/mesalib/src/glsl/ir_builder.cpp
+++ b/mesalib/src/glsl/ir_builder.cpp
@@ -501,6 +501,24 @@ b2f(operand a)
}
ir_expression *
+interpolate_at_centroid(operand a)
+{
+ return expr(ir_unop_interpolate_at_centroid, a);
+}
+
+ir_expression *
+interpolate_at_offset(operand a, operand b)
+{
+ return expr(ir_binop_interpolate_at_offset, a, b);
+}
+
+ir_expression *
+interpolate_at_sample(operand a, operand b)
+{
+ return expr(ir_binop_interpolate_at_sample, a, b);
+}
+
+ir_expression *
fma(operand a, operand b, operand c)
{
return expr(ir_triop_fma, a, b, c);
diff --git a/mesalib/src/glsl/ir_builder.h b/mesalib/src/glsl/ir_builder.h
index 108b53a5e..573596cf1 100644
--- a/mesalib/src/glsl/ir_builder.h
+++ b/mesalib/src/glsl/ir_builder.h
@@ -186,6 +186,10 @@ ir_expression *b2f(operand a);
ir_expression *min2(operand a, operand b);
ir_expression *max2(operand a, operand b);
+ir_expression *interpolate_at_centroid(operand a);
+ir_expression *interpolate_at_offset(operand a, operand b);
+ir_expression *interpolate_at_sample(operand a, operand b);
+
ir_expression *fma(operand a, operand b, operand c);
ir_expression *lrp(operand x, operand y, operand a);
ir_expression *csel(operand a, operand b, operand c);
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index 7f83eb134..5570ed46f 100644
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -510,6 +510,8 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
case ir_binop_lshift:
case ir_binop_rshift:
case ir_binop_ldexp:
+ case ir_binop_interpolate_at_offset:
+ case ir_binop_interpolate_at_sample:
case ir_binop_vector_extract:
case ir_triop_csel:
case ir_triop_bitfield_extract:
diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.cpp b/mesalib/src/glsl/ir_hierarchical_visitor.cpp
index d3c00ecdb..adb629414 100644
--- a/mesalib/src/glsl/ir_hierarchical_visitor.cpp
+++ b/mesalib/src/glsl/ir_hierarchical_visitor.cpp
@@ -27,16 +27,18 @@
ir_hierarchical_visitor::ir_hierarchical_visitor()
{
this->base_ir = NULL;
- this->callback = NULL;
- this->data = NULL;
+ this->callback_enter = NULL;
+ this->callback_leave = NULL;
+ this->data_enter = NULL;
+ this->data_leave = NULL;
this->in_assignee = false;
}
ir_visitor_status
ir_hierarchical_visitor::visit(ir_rvalue *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -44,8 +46,8 @@ ir_hierarchical_visitor::visit(ir_rvalue *ir)
ir_visitor_status
ir_hierarchical_visitor::visit(ir_variable *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -53,8 +55,8 @@ ir_hierarchical_visitor::visit(ir_variable *ir)
ir_visitor_status
ir_hierarchical_visitor::visit(ir_constant *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -62,8 +64,8 @@ ir_hierarchical_visitor::visit(ir_constant *ir)
ir_visitor_status
ir_hierarchical_visitor::visit(ir_loop_jump *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -71,8 +73,8 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir)
ir_visitor_status
ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -80,8 +82,8 @@ ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_loop *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -89,15 +91,17 @@ ir_hierarchical_visitor::visit_enter(ir_loop *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_loop *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -105,15 +109,17 @@ ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_function *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -121,15 +127,17 @@ ir_hierarchical_visitor::visit_enter(ir_function *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_function *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_expression *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -137,15 +145,17 @@ ir_hierarchical_visitor::visit_enter(ir_expression *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_expression *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_texture *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -153,15 +163,17 @@ ir_hierarchical_visitor::visit_enter(ir_texture *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_texture *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -169,15 +181,17 @@ ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -185,15 +199,17 @@ ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -201,15 +217,17 @@ ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -217,15 +235,17 @@ ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_call *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -233,15 +253,17 @@ ir_hierarchical_visitor::visit_enter(ir_call *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_call *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_return *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -249,15 +271,17 @@ ir_hierarchical_visitor::visit_enter(ir_return *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_return *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_discard *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -265,15 +289,17 @@ ir_hierarchical_visitor::visit_enter(ir_discard *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_discard *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_if *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -281,15 +307,17 @@ ir_hierarchical_visitor::visit_enter(ir_if *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_if *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_emit_vertex *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -297,15 +325,17 @@ ir_hierarchical_visitor::visit_enter(ir_emit_vertex *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_emit_vertex *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_end_primitive *ir)
{
- if (this->callback != NULL)
- this->callback(ir, this->data);
+ if (this->callback_enter != NULL)
+ this->callback_enter(ir, this->data_enter);
return visit_continue;
}
@@ -313,7 +343,9 @@ ir_hierarchical_visitor::visit_enter(ir_end_primitive *ir)
ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_end_primitive *ir)
{
- (void) ir;
+ if (this->callback_leave != NULL)
+ this->callback_leave(ir, this->data_leave);
+
return visit_continue;
}
@@ -326,13 +358,17 @@ ir_hierarchical_visitor::run(exec_list *instructions)
void
visit_tree(ir_instruction *ir,
- void (*callback)(class ir_instruction *ir, void *data),
- void *data)
+ void (*callback_enter)(class ir_instruction *ir, void *data),
+ void *data_enter,
+ void (*callback_leave)(class ir_instruction *ir, void *data),
+ void *data_leave)
{
ir_hierarchical_visitor v;
- v.callback = callback;
- v.data = data;
+ v.callback_enter = callback_enter;
+ v.callback_leave = callback_leave;
+ v.data_enter = data_enter;
+ v.data_leave = data_leave;
ir->accept(&v);
}
diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.h b/mesalib/src/glsl/ir_hierarchical_visitor.h
index bc89a04d8..faa52fd79 100644
--- a/mesalib/src/glsl/ir_hierarchical_visitor.h
+++ b/mesalib/src/glsl/ir_hierarchical_visitor.h
@@ -163,14 +163,29 @@ public:
* \warning
* Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
* invoke this function. This can be used, for example, to cause the
- * callback to be invoked on every node type execpt one.
+ * callback to be invoked on every node type except one.
*/
- void (*callback)(class ir_instruction *ir, void *data);
+ void (*callback_enter)(class ir_instruction *ir, void *data);
/**
- * Extra data parameter passed to the per-node callback function
+ * Callback function that is invoked on exit of each node visited.
+ *
+ * \warning
+ * Visitor classes derived from \c ir_hierarchical_visitor \b may \b not
+ * invoke this function. This can be used, for example, to cause the
+ * callback to be invoked on every node type except one.
+ */
+ void (*callback_leave)(class ir_instruction *ir, void *data);
+
+ /**
+ * Extra data parameter passed to the per-node callback_enter function
+ */
+ void *data_enter;
+
+ /**
+ * Extra data parameter passed to the per-node callback_leave function
*/
- void *data;
+ void *data_leave;
/**
* Currently in the LHS of an assignment?
@@ -181,8 +196,10 @@ public:
};
void visit_tree(ir_instruction *ir,
- void (*callback)(class ir_instruction *ir, void *data),
- void *data);
+ void (*callback_enter)(class ir_instruction *ir, void *data),
+ void *data_enter,
+ void (*callback_leave)(class ir_instruction *ir, void *data) = NULL,
+ void *data_leave = NULL);
ir_visitor_status visit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
bool statement_list = true);
diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp
index 4017bdd73..e3566e1d6 100644
--- a/mesalib/src/glsl/ir_reader.cpp
+++ b/mesalib/src/glsl/ir_reader.cpp
@@ -723,10 +723,9 @@ ir_reader::read_expression(s_expression *expr)
ir_read_error(expr, "invalid operator: %s", s_op->value());
return NULL;
}
-
- int num_operands = -3; /* skip "expression" <type> <operation> */
- foreach_in_list(s_expression, e, &((s_list *) expr)->subexpressions)
- ++num_operands;
+
+ /* Skip "expression" <type> <operation> by subtracting 3. */
+ int num_operands = (int) ((s_list *) expr)->subexpressions.length() - 3;
int expected_operands = ir_expression::get_num_operands(op);
if (num_operands != expected_operands) {
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index 271dbe096..37e1ce33e 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -49,8 +49,8 @@ public:
this->current_function = NULL;
- this->callback = ir_validate::validate_ir;
- this->data = ht;
+ this->callback_enter = ir_validate::validate_ir;
+ this->data_enter = ht;
}
~ir_validate()
@@ -100,7 +100,7 @@ ir_validate::visit(ir_dereference_variable *ir)
abort();
}
- this->validate_ir(ir, this->data);
+ this->validate_ir(ir, this->data_enter);
return visit_continue;
}
@@ -167,7 +167,7 @@ ir_validate::visit_enter(ir_function *ir)
*/
this->current_function = ir;
- this->validate_ir(ir, this->data);
+ this->validate_ir(ir, this->data_enter);
/* Verify that all of the things stored in the list of signatures are,
* in fact, function signatures.
@@ -211,7 +211,7 @@ ir_validate::visit_enter(ir_function_signature *ir)
abort();
}
- this->validate_ir(ir, this->data);
+ this->validate_ir(ir, this->data_enter);
return visit_continue;
}
@@ -371,6 +371,11 @@ ir_validate::visit_leave(ir_expression *ir)
/* XXX what can we assert here? */
break;
+ case ir_unop_interpolate_at_centroid:
+ assert(ir->operands[0]->type == ir->type);
+ assert(ir->operands[0]->type->is_float());
+ break;
+
case ir_binop_add:
case ir_binop_sub:
case ir_binop_mul:
@@ -510,6 +515,19 @@ ir_validate::visit_leave(ir_expression *ir)
&& ir->operands[1]->type->is_integer());
break;
+ case ir_binop_interpolate_at_offset:
+ assert(ir->operands[0]->type == ir->type);
+ assert(ir->operands[0]->type->is_float());
+ assert(ir->operands[1]->type->components() == 2);
+ assert(ir->operands[1]->type->is_float());
+ break;
+
+ case ir_binop_interpolate_at_sample:
+ assert(ir->operands[0]->type == ir->type);
+ assert(ir->operands[0]->type->is_float());
+ assert(ir->operands[1]->type == glsl_type::int_type);
+ break;
+
case ir_triop_fma:
assert(ir->type->base_type == GLSL_TYPE_FLOAT);
assert(ir->type == ir->operands[0]->type);
@@ -708,7 +726,7 @@ ir_validate::visit_enter(ir_assignment *ir)
}
}
- this->validate_ir(ir, this->data);
+ this->validate_ir(ir, this->data_enter);
return visit_continue;
}
diff --git a/mesalib/src/glsl/list.h b/mesalib/src/glsl/list.h
index a4444bda9..3ee6cdaa9 100644
--- a/mesalib/src/glsl/list.h
+++ b/mesalib/src/glsl/list.h
@@ -325,6 +325,8 @@ struct exec_list {
const exec_node *get_tail() const;
exec_node *get_tail();
+ unsigned length() const;
+
void push_head(exec_node *n);
void push_tail(exec_node *n);
void push_degenerate_list_at_head(exec_node *n);
@@ -345,9 +347,15 @@ struct exec_list {
void move_nodes_to(exec_list *target);
/**
- * Append all nodes from the source list to the target list
+ * Append all nodes from the source list to the end of the target list
*/
void append_list(exec_list *source);
+
+ /**
+ * Prepend all nodes from the source list to the beginning of the target
+ * list
+ */
+ void prepend_list(exec_list *source);
#endif
};
@@ -399,6 +407,19 @@ exec_list_get_tail(struct exec_list *list)
return !exec_list_is_empty(list) ? list->tail_pred : NULL;
}
+static inline unsigned
+exec_list_length(const struct exec_list *list)
+{
+ unsigned size = 0;
+ struct exec_node *node;
+
+ for (node = list->head; node->next != NULL; node = node->next) {
+ size++;
+ }
+
+ return size;
+}
+
static inline void
exec_list_push_head(struct exec_list *list, struct exec_node *n)
{
@@ -479,6 +500,13 @@ exec_list_append(struct exec_list *list, struct exec_list *source)
}
static inline void
+exec_list_prepend(struct exec_list *list, struct exec_list *source)
+{
+ exec_list_append(source, list);
+ exec_list_move_nodes_to(source, list);
+}
+
+static inline void
exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
{
if (exec_list_is_empty(before))
@@ -524,6 +552,11 @@ inline exec_node *exec_list::get_tail()
return exec_list_get_tail(this);
}
+inline unsigned exec_list::length() const
+{
+ return exec_list_length(this);
+}
+
inline void exec_list::push_head(exec_node *n)
{
exec_list_push_head(this, n);
@@ -554,6 +587,11 @@ inline void exec_list::append_list(exec_list *source)
exec_list_append(this, source);
}
+inline void exec_list::prepend_list(exec_list *source)
+{
+ exec_list_prepend(this, source);
+}
+
inline void exec_node::insert_before(exec_list *before)
{
exec_node_insert_list_before(this, before);
diff --git a/mesalib/src/glsl/opt_function_inlining.cpp b/mesalib/src/glsl/opt_function_inlining.cpp
index b84bb8e11..64b4907ba 100644
--- a/mesalib/src/glsl/opt_function_inlining.cpp
+++ b/mesalib/src/glsl/opt_function_inlining.cpp
@@ -100,16 +100,13 @@ ir_call::generate_inline(ir_instruction *next_ir)
{
void *ctx = ralloc_parent(this);
ir_variable **parameters;
- int num_parameters;
+ unsigned num_parameters;
int i;
struct hash_table *ht;
ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
- num_parameters = 0;
- foreach_in_list(ir_rvalue, param, &this->callee->parameters)
- num_parameters++;
-
+ num_parameters = this->callee->parameters.length();
parameters = new ir_variable *[num_parameters];
/* Generate the declarations for the parameters to our inlined code,
diff --git a/mesalib/src/glsl/opt_rebalance_tree.cpp b/mesalib/src/glsl/opt_rebalance_tree.cpp
index 773aab3f6..095f2d7d2 100644
--- a/mesalib/src/glsl/opt_rebalance_tree.cpp
+++ b/mesalib/src/glsl/opt_rebalance_tree.cpp
@@ -60,6 +60,7 @@
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h"
+#include "main/macros.h" /* for MAX2 */
/* The DSW algorithm generates a degenerate tree (really, a linked list) in
* tree_to_vine(). We'd rather not leave a binary expression with only one
@@ -216,7 +217,9 @@ is_reduction(ir_instruction *ir, void *data)
* constant fold once split up. Handling matrices will need some more
* work.
*/
- if (expr->type->is_matrix()) {
+ if (expr->type->is_matrix() ||
+ expr->operands[0]->type->is_matrix() ||
+ (expr->operands[1] && expr->operands[1]->type->is_matrix())) {
ird->is_reduction = false;
return;
}
@@ -261,6 +264,22 @@ handle_expression(ir_expression *expr)
return expr;
}
+static void
+update_types(ir_instruction *ir, void *)
+{
+ ir_expression *expr = ir->as_expression();
+ if (!expr)
+ return;
+
+ const glsl_type *const new_type =
+ glsl_type::get_instance(expr->type->base_type,
+ MAX2(expr->operands[0]->type->vector_elements,
+ expr->operands[1]->type->vector_elements),
+ 1);
+ assert(new_type != glsl_type::error_type);
+ expr->type = new_type;
+}
+
void
ir_rebalance_visitor::handle_rvalue(ir_rvalue **rvalue)
{
@@ -285,6 +304,8 @@ ir_rebalance_visitor::handle_rvalue(ir_rvalue **rvalue)
if (new_rvalue == *rvalue)
return;
+ visit_tree(new_rvalue, NULL, NULL, update_types);
+
*rvalue = new_rvalue;
this->progress = true;
}