diff options
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r-- | mesalib/src/glsl/ast_function.cpp | 35 | ||||
-rw-r--r-- | mesalib/src/glsl/ast_to_hir.cpp | 87 | ||||
-rwxr-xr-x | mesalib/src/glsl/builtin_functions.cpp | 67 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser.yy | 8 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.cpp | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | mesalib/src/glsl/ir.cpp | 6 | ||||
-rw-r--r-- | mesalib/src/glsl/ir.h | 33 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_builder.cpp | 18 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_builder.h | 4 | ||||
-rwxr-xr-x | mesalib/src/glsl/ir_constant_expression.cpp | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_hierarchical_visitor.cpp | 158 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_hierarchical_visitor.h | 29 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_reader.cpp | 7 | ||||
-rw-r--r-- | mesalib/src/glsl/ir_validate.cpp | 30 | ||||
-rw-r--r-- | mesalib/src/glsl/list.h | 40 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_function_inlining.cpp | 7 | ||||
-rw-r--r-- | mesalib/src/glsl/opt_rebalance_tree.cpp | 23 |
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 a987ab2c2..8fc9051bb 100755 --- 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 980acc8ae..beabb5ffd 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -377,6 +377,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 0ea3ce34a..ab5c006f5 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; @@ -494,6 +497,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 4b14668ea..578548b23 100644..100755 --- 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_mesa", "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 fa59cc16a..13aa2b5bd 100755 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -503,6 +503,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 9f08d45f7..500a85717 100644 --- a/mesalib/src/glsl/list.h +++ b/mesalib/src/glsl/list.h @@ -333,6 +333,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); @@ -353,9 +355,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 }; @@ -407,6 +415,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) { @@ -487,6 +508,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)) @@ -532,6 +560,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); @@ -562,6 +595,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; } |