Module: Mesa Branch: shader-work Commit: 277312e184ebb54f4c5f119d199bf906fed0b8dc URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=277312e184ebb54f4c5f119d199bf906fed0b8dc
Author: Luca Barbieri <[email protected]> Date: Wed Sep 8 03:47:58 2010 +0200 glsl: teach structure splitting to split arrays, and never split in/outs Currently structure splitting cannot split arrays, which makes do_array_index_to_cond_assign useless. This commit adds that capability. Also, it prevents it from splitting in/out/inout variables, which were incorrectly split. It may be possible to split them if user-defined, but that will need further changes and some way to make sure we link stages correctly. --- src/glsl/ir_array_index_to_cond_assign.cpp | 2 +- src/glsl/ir_structure_splitting.cpp | 149 ++++++++++++++++++++++------ src/glsl/ir_validate.cpp | 23 +++-- src/glsl/main.cpp | 3 + 4 files changed, 137 insertions(+), 40 deletions(-) diff --git a/src/glsl/ir_array_index_to_cond_assign.cpp b/src/glsl/ir_array_index_to_cond_assign.cpp index 641168a..517c4c0 100644 --- a/src/glsl/ir_array_index_to_cond_assign.cpp +++ b/src/glsl/ir_array_index_to_cond_assign.cpp @@ -80,7 +80,7 @@ struct switch_generator test_indices = new(index) ir_constant(broadcast_index->type, &test_indices_data); ir_rvalue* condition_val = new(index) ir_expression(ir_binop_equal, - &glsl_type::bool_type[comps], + &glsl_type::bool_type[comps - 1], broadcast_index, test_indices); ir_variable* condition = new(index) ir_variable(&glsl_type::bool_type[comps], "dereference_array_condition", ir_var_temporary); diff --git a/src/glsl/ir_structure_splitting.cpp b/src/glsl/ir_structure_splitting.cpp index ff3ec93..1925067 100644 --- a/src/glsl/ir_structure_splitting.cpp +++ b/src/glsl/ir_structure_splitting.cpp @@ -86,6 +86,7 @@ public: virtual ir_visitor_status visit(ir_variable *); virtual ir_visitor_status visit(ir_dereference_variable *); virtual ir_visitor_status visit_enter(ir_dereference_record *); + virtual ir_visitor_status visit_enter(ir_dereference_array *); virtual ir_visitor_status visit_enter(ir_assignment *); virtual ir_visitor_status visit_enter(ir_function_signature *); @@ -102,7 +103,9 @@ ir_structure_reference_visitor::get_variable_entry2(ir_variable *var) { assert(var); - if (!var->type->is_record() || var->mode == ir_var_uniform) + printf("stru %s\n", var->name); + if ((!var->type->is_record() && !var->type->is_array()) + || (var->mode != ir_var_auto && var->mode != ir_var_temporary)) return NULL; foreach_iter(exec_list_iterator, iter, this->variable_list) { @@ -149,6 +152,25 @@ ir_structure_reference_visitor::visit_enter(ir_dereference_record *ir) } ir_visitor_status +ir_structure_reference_visitor::visit_enter(ir_dereference_array *ir) +{ + ir->array_index->accept(this); + if(!ir->array_index->as_constant()) + { + /* FINISHME: could produce and make use of information + * about possible values of the index + */ + ir_variable *const var = ir->array->variable_referenced(); + variable_entry2 *entry = this->get_variable_entry2(var); + + if (entry) + entry->whole_structure_access++; + } + + /* Don't descend into the ir_dereference_variable below. */ + return visit_continue_with_parent; +} +ir_visitor_status ir_structure_reference_visitor::visit_enter(ir_assignment *ir) { if (ir->lhs->as_dereference_variable() && @@ -198,7 +220,7 @@ ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var) { assert(var); - if (!var->type->is_record()) + if (!var->type->is_record() && !var->type->is_array()) return NULL; foreach_iter(exec_list_iterator, iter, *this->variable_list) { @@ -214,27 +236,62 @@ ir_structure_splitting_visitor::get_splitting_entry(ir_variable *var) void ir_structure_splitting_visitor::split_deref(ir_dereference **deref) { - if ((*deref)->ir_type != ir_type_dereference_record) - return; - - ir_dereference_record *deref_record = (ir_dereference_record *)*deref; - ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable(); - if (!deref_var) - return; - - variable_entry2 *entry = get_splitting_entry(deref_var->var); - if (!entry) - return; + if ((*deref)->ir_type == ir_type_dereference_record) + { + ir_dereference_record *deref_record = (ir_dereference_record *)*deref; + ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable(); + if (!deref_var) + return; + + variable_entry2 *entry = get_splitting_entry(deref_var->var); + if (!entry) + return; + + unsigned int i; + for (i = 0; i < entry->var->type->length; i++) { + if (strcmp(deref_record->field, + entry->var->type->fields.structure[i].name) == 0) + break; + } + assert(i != entry->var->type->length); - unsigned int i; - for (i = 0; i < entry->var->type->length; i++) { - if (strcmp(deref_record->field, - entry->var->type->fields.structure[i].name) == 0) - break; + *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]); + } + else if ((*deref)->ir_type == ir_type_dereference_array) + { + ir_dereference_array *deref_array = (ir_dereference_array*)*deref; + ir_dereference_variable *deref_var = deref_array->array->as_dereference_variable(); + if (!deref_var) + return; + + variable_entry2 *entry = get_splitting_entry(deref_var->var); + if (!entry) + return; + + ir_constant* index = deref_array->array_index->as_constant(); + assert(index); + assert(index->type->is_scalar()); + assert(index->type->base_type == GLSL_TYPE_INT || index->type->base_type == GLSL_TYPE_UINT); + + unsigned i = index->value.u[0]; + if(i < (unsigned)deref_var->var->type->length) + { + *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]); + } + else + { + ir_variable* undef = new(entry->mem_ctx) ir_variable((*deref)->type, "undef", ir_var_temporary); + base_ir->insert_before(undef); + *deref = new(entry->mem_ctx) ir_dereference_variable(undef); +#if 0 + /* FINISHME: add an "undef" value to the ir and use it, or perhaps just kill base_ir directly */ + if(type->is_numeric() || type->is_boolean()) + *deref = ir_constant::zero(entry->mem_ctx, (*deref)->type); + else + *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[0]); +#endif + } } - assert(i != entry->var->type->length); - - *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]); } void @@ -268,19 +325,30 @@ ir_structure_splitting_visitor::visit_leave(ir_assignment *ir) if (lhs_entry) { new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]); - } else { + } else if(type->is_record()) { new_lhs = new(mem_ctx) ir_dereference_record(ir->lhs->clone(mem_ctx, NULL), type->fields.structure[i].name); - } + } else if(type->is_array()) { + new_lhs = new(mem_ctx) + ir_dereference_array(ir->lhs->clone(mem_ctx, NULL), + new(mem_ctx) ir_constant((int)i)); + } else + assert(0); if (rhs_entry) { new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]); - } else { + } else if(type->is_record()){ new_rhs = new(mem_ctx) ir_dereference_record(ir->rhs->clone(mem_ctx, NULL), type->fields.structure[i].name); - } + } else if(type->is_array()) { + new_rhs = new(mem_ctx) + ir_dereference_array(ir->rhs->clone(mem_ctx, NULL), + new(mem_ctx) ir_constant((int)i)); + } else + assert(0); + ir->insert_before(new(mem_ctx) ir_assignment(new_lhs, new_rhs, @@ -337,18 +405,39 @@ do_structure_splitting(exec_list *instructions) ir_variable *, type->length); + /* FINISHME: create these on demand */ for (unsigned int i = 0; i < entry->var->type->length; i++) { - const char *name = talloc_asprintf(mem_ctx, "%s_%s", + const char *name; + + if(type->is_record()) + { + name = talloc_asprintf(mem_ctx, "%s_%s", entry->var->name, type->fields.structure[i].name); - entry->components[i] = - new(entry->mem_ctx) ir_variable(type->fields.structure[i].type, - name, - ir_var_temporary); + entry->components[i] = + new(entry->mem_ctx) ir_variable(type->fields.structure[i].type, + name, + ir_var_temporary); + } + else if(type->is_array()) + { + name = talloc_asprintf(mem_ctx, "%s_%i", + entry->var->name, + i); + + entry->components[i] = + new(entry->mem_ctx) ir_variable(type->fields.array, + name, + ir_var_temporary); + } + else + assert(0); + entry->var->insert_before(entry->components[i]); } + printf("SPLIT %s\n", entry->var->name); entry->var->remove(); } diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index b3ea566..de31ad7 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -283,6 +283,17 @@ ir_validate::visit_leave(ir_expression *ir) case ir_binop_min: case ir_binop_max: case ir_binop_pow: + if (ir->operands[0]->type->is_scalar()) + assert(ir->operands[1]->type == ir->type); + else if (ir->operands[1]->type->is_scalar()) + assert(ir->operands[0]->type == ir->type); + else if (ir->operands[0]->type->is_vector() && + ir->operands[1]->type->is_vector()) { + assert(ir->operands[0]->type == ir->operands[1]->type); + assert(ir->operands[0]->type == ir->type); + } + break; + case ir_binop_less: case ir_binop_greater: case ir_binop_lequal: @@ -293,15 +304,9 @@ ir_validate::visit_leave(ir_expression *ir) * IR we want to do them for vectors instead to support the * lessEqual() and friends builtins, and Mesa IR constructs */ - if (ir->operands[0]->type->is_scalar()) - assert(ir->operands[1]->type == ir->type); - else if (ir->operands[1]->type->is_scalar()) - assert(ir->operands[0]->type == ir->type); - else if (ir->operands[0]->type->is_vector() && - ir->operands[1]->type->is_vector()) { - assert(ir->operands[0]->type == ir->operands[1]->type); - assert(ir->operands[0]->type == ir->type); - } + assert(ir->type->base_type == GLSL_TYPE_BOOL); + assert(ir->operands[0]->type == ir->operands[1]->type); + assert(ir->type->components() == ir->operands[0]->type->components()); break; case ir_binop_all_equal: diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index 8e73eb8..40c9781 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -180,6 +180,9 @@ compile_shader(struct gl_shader *shader) progress = set_loop_controls(shader->ir, ls) || progress; progress = unroll_loops(shader->ir, ls, 32) || progress; delete ls; + + progress = do_array_index_to_cond_assign(shader->ir) || progress; + progress = do_structure_splitting(shader->ir) || progress; } while (progress); validate_ir_tree(shader->ir); _______________________________________________ mesa-commit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-commit
