glsl: Factor out code that generates block of index comparisons

Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Ian Romanick
2011-07-18 18:48:39 -07:00
parent 156f85336f
commit 90cc372400
2 changed files with 73 additions and 42 deletions

View File

@@ -69,3 +69,7 @@ bool lower_variable_index_to_cond_assign(exec_list *instructions,
bool lower_input, bool lower_output, bool lower_temp, bool lower_uniform);
bool lower_quadop_vector(exec_list *instructions, bool dont_lower_swz);
bool optimize_redundant_jumps(exec_list *instructions);
ir_rvalue *
compare_index_block(exec_list *instructions, ir_variable *index,
unsigned base, unsigned components, void *mem_ctx);

View File

@@ -52,6 +52,70 @@
#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::bool_type[components - 1],
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)
{
@@ -204,54 +268,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);
}