X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Flower_variable_index_to_cond_assign.cpp;h=7c5d80f432bcdd42063446611c40993e5989cce2;hb=151a20dcd42c0973275479609470c2b616b3faa9;hp=e08ec13456bf8fdb087c752c9a13561d652a103e;hpb=5f83dfe5b70337bcffe215f7c32d0b862b5e7a3b;p=mesa.git diff --git a/src/glsl/lower_variable_index_to_cond_assign.cpp b/src/glsl/lower_variable_index_to_cond_assign.cpp index e08ec13456b..7c5d80f432b 100644 --- a/src/glsl/lower_variable_index_to_cond_assign.cpp +++ b/src/glsl/lower_variable_index_to_cond_assign.cpp @@ -52,12 +52,77 @@ #include "glsl_types.h" #include "main/macros.h" +/** + * Generate a comparison value for a block of indices + * + * Lowering passes for non-constant indexing of arrays, matrices, or vectors + * can use this to generate blocks of index comparison values. + * + * \param instructions List where new instructions will be appended + * \param index \c ir_variable containing the desired index + * \param base Base value for this block of comparisons + * \param components Number of unique index values to compare. This must + * be on the range [1, 4]. + * \param mem_ctx ralloc memory context to be used for all allocations. + * + * \returns + * An \c ir_rvalue that \b must be cloned for each use in conditional + * assignments, etc. + */ +ir_rvalue * +compare_index_block(exec_list *instructions, ir_variable *index, + unsigned base, unsigned components, void *mem_ctx) +{ + ir_rvalue *broadcast_index = new(mem_ctx) ir_dereference_variable(index); + + assert(index->type->is_scalar()); + assert(index->type->base_type == GLSL_TYPE_INT); + assert(components >= 1 && components <= 4); + + if (components > 1) { + const ir_swizzle_mask m = { 0, 0, 0, 0, components, false }; + broadcast_index = new(mem_ctx) ir_swizzle(broadcast_index, m); + } + + /* Compare the desired index value with the next block of four indices. + */ + ir_constant_data test_indices_data; + memset(&test_indices_data, 0, sizeof(test_indices_data)); + test_indices_data.i[0] = base; + test_indices_data.i[1] = base + 1; + test_indices_data.i[2] = base + 2; + test_indices_data.i[3] = base + 3; + + ir_constant *const test_indices = + new(mem_ctx) ir_constant(broadcast_index->type, + &test_indices_data); + + ir_rvalue *const condition_val = + new(mem_ctx) ir_expression(ir_binop_equal, + glsl_type::bvec(components), + broadcast_index, + test_indices); + + ir_variable *const condition = + new(mem_ctx) ir_variable(condition_val->type, + "dereference_condition", + ir_var_temporary); + instructions->push_tail(condition); + + ir_rvalue *const cond_deref = + new(mem_ctx) ir_dereference_variable(condition); + instructions->push_tail(new(mem_ctx) ir_assignment(cond_deref, condition_val, 0)); + + return cond_deref; +} + static inline bool -is_array_or_matrix(const ir_instruction *ir) +is_array_or_matrix(const ir_rvalue *ir) { return (ir->type->is_array() || ir->type->is_matrix()); } +namespace { /** * Replace a dereference of a variable with a specified r-value * @@ -127,6 +192,12 @@ struct assignment_generator ir_variable* var; assignment_generator() + : base_ir(NULL), + rvalue(NULL), + old_index(NULL), + is_write(false), + write_mask(0), + var(NULL) { } @@ -204,54 +275,17 @@ struct switch_generator for (unsigned i = first; i < end; i += 4) { const unsigned comps = MIN2(condition_components, end - i); - ir_rvalue *broadcast_index = - new(this->mem_ctx) ir_dereference_variable(index); - - if (comps) { - const ir_swizzle_mask m = { 0, 0, 0, 0, comps, false }; - broadcast_index = new(this->mem_ctx) ir_swizzle(broadcast_index, m); - } - - /* Compare the desired index value with the next block of four indices. - */ - ir_constant_data test_indices_data; - memset(&test_indices_data, 0, sizeof(test_indices_data)); - test_indices_data.i[0] = i; - test_indices_data.i[1] = i + 1; - test_indices_data.i[2] = i + 2; - test_indices_data.i[3] = i + 3; - ir_constant *const test_indices = - new(this->mem_ctx) ir_constant(broadcast_index->type, - &test_indices_data); - - ir_rvalue *const condition_val = - new(this->mem_ctx) ir_expression(ir_binop_equal, - &glsl_type::bool_type[comps - 1], - broadcast_index, - test_indices); - - ir_variable *const condition = - new(this->mem_ctx) ir_variable(condition_val->type, - "dereference_array_condition", - ir_var_temporary); - list->push_tail(condition); - ir_rvalue *const cond_deref = - new(this->mem_ctx) ir_dereference_variable(condition); - list->push_tail(new(this->mem_ctx) ir_assignment(cond_deref, - condition_val, 0)); + compare_index_block(list, index, i, comps, this->mem_ctx); if (comps == 1) { - ir_rvalue *const cond_deref = - new(this->mem_ctx) ir_dereference_variable(condition); - - this->generator.generate(i, cond_deref, list); + this->generator.generate(i, cond_deref->clone(this->mem_ctx, NULL), + list); } else { for (unsigned j = 0; j < comps; j++) { - ir_rvalue *const cond_deref = - new(this->mem_ctx) ir_dereference_variable(condition); ir_rvalue *const cond_swiz = - new(this->mem_ctx) ir_swizzle(cond_deref, j, 0, 0, 0, 1); + new(this->mem_ctx) ir_swizzle(cond_deref->clone(this->mem_ctx, NULL), + j, 0, 0, 0, 1); this->generator.generate(i + j, cond_swiz, list); } @@ -321,22 +355,32 @@ public: bool storage_type_needs_lowering(ir_dereference_array *deref) const { - if (deref->array->ir_type == ir_type_constant) + /* If a variable isn't eventually the target of this dereference, then + * it must be a constant or some sort of anonymous temporary storage. + * + * FINISHME: Is this correct? Most drivers treat arrays of constants as + * FINISHME: uniforms. It seems like this should do the same. + */ + const ir_variable *const var = deref->array->variable_referenced(); + if (var == NULL) return this->lower_temps; - const ir_variable *const var = deref->array->variable_referenced(); - switch (var->mode) { + switch (var->data.mode) { case ir_var_auto: case ir_var_temporary: return this->lower_temps; case ir_var_uniform: return this->lower_uniforms; - case ir_var_in: + case ir_var_function_in: case ir_var_const_in: - return (var->location == -1) ? this->lower_temps : this->lower_inputs; - case ir_var_out: - return (var->location == -1) ? this->lower_temps : this->lower_outputs; - case ir_var_inout: + return this->lower_temps; + case ir_var_shader_in: + return this->lower_inputs; + case ir_var_function_out: + return this->lower_temps; + case ir_var_shader_out: + return this->lower_outputs; + case ir_var_function_inout: return this->lower_temps; } @@ -475,6 +519,8 @@ public: } }; +} /* anonymous namespace */ + bool lower_variable_index_to_cond_assign(exec_list *instructions, bool lower_input, @@ -492,10 +538,12 @@ lower_variable_index_to_cond_assign(exec_list *instructions, * matrix columns of an array of matrix), each pass will only lower one * level of indirection. */ + bool progress_ever = false; do { v.progress = false; visit_list_elements(&v, instructions); + progress_ever = v.progress || progress_ever; } while (v.progress); - return v.progress; + return progress_ever; }