diff options
author | Ian Romanick <[email protected]> | 2013-03-15 14:36:46 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2013-05-13 12:05:18 -0700 |
commit | 943de9cdeacb93d48ad5cb17666e7448990d3dbb (patch) | |
tree | 99a01c20a36089701f357c8a94b8706e511a30ee /src | |
parent | 63e1147ea12a393c0750698ea5909f41e1953e75 (diff) |
glsl: Lower ir_binop_vector_extract to swizzle
Lower ir_binop_vector_extract with a constant index to a swizzle. This
is exactly like ir_dereference_array of a vector with a constant index.
v2: Convert tabs to spaces. Suggested by Eric.
v3: Correctly call convert_vector_extract_to_swizzle in
ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir). Suggested by
Ken.
v4: Use CLAMP instead of MIN2(MAX2()). Suggested by Ken.
Signed-off-by: Ian Romanick <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/lower_vec_index_to_swizzle.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/glsl/lower_vec_index_to_swizzle.cpp b/src/glsl/lower_vec_index_to_swizzle.cpp index 264d6dc07cc..5349e58bb5e 100644 --- a/src/glsl/lower_vec_index_to_swizzle.cpp +++ b/src/glsl/lower_vec_index_to_swizzle.cpp @@ -47,6 +47,7 @@ public: } ir_rvalue *convert_vec_index_to_swizzle(ir_rvalue *val); + ir_rvalue *convert_vector_extract_to_swizzle(ir_rvalue *val); virtual ir_visitor_status visit_enter(ir_expression *); virtual ir_visitor_status visit_enter(ir_swizzle *); @@ -98,6 +99,40 @@ ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir) return new(ctx) ir_swizzle(deref->array, i, 0, 0, 0, 1); } +ir_rvalue * +ir_vec_index_to_swizzle_visitor::convert_vector_extract_to_swizzle(ir_rvalue *ir) +{ + ir_expression *const expr = ir->as_expression(); + if (expr == NULL || expr->operation != ir_binop_vector_extract) + return ir; + + ir_constant *const idx = expr->operands[1]->constant_expression_value(); + if (idx == NULL) + return ir; + + void *ctx = ralloc_parent(ir); + this->progress = true; + + /* Page 40 of the GLSL 1.20 spec says: + * + * "When indexing with non-constant expressions, behavior is undefined + * if the index is negative, or greater than or equal to the size of + * the vector." + * + * The quoted spec text mentions non-constant expressions, but this code + * operates on constants. These constants are the result of non-constant + * expressions that have been optimized to constants. The common case here + * is a loop counter from an unrolled loop that is used to index a vector. + * + * The ir_swizzle constructor gets angry if the index is negative or too + * large. For simplicity sake, just clamp the index to [0, size-1]. + */ + const int i = CLAMP(idx->value.i[0], 0, + (int) expr->operands[0]->type->vector_elements - 1); + + return new(ctx) ir_swizzle(expr->operands[0], i, 0, 0, 0, 1); +} + ir_visitor_status ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir) { @@ -105,6 +140,7 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir) for (i = 0; i < ir->get_num_operands(); i++) { ir->operands[i] = convert_vec_index_to_swizzle(ir->operands[i]); + ir->operands[i] = convert_vector_extract_to_swizzle(ir->operands[i]); } return visit_continue; @@ -127,6 +163,7 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir) { ir->set_lhs(convert_vec_index_to_swizzle(ir->lhs)); ir->rhs = convert_vec_index_to_swizzle(ir->rhs); + ir->rhs = convert_vector_extract_to_swizzle(ir->rhs); return visit_continue; } @@ -140,6 +177,12 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir) if (new_param != param) { param->replace_with(new_param); + } else { + new_param = convert_vector_extract_to_swizzle(param); + + if (new_param != param) { + param->replace_with(new_param); + } } } @@ -151,6 +194,7 @@ ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir) { if (ir->value) { ir->value = convert_vec_index_to_swizzle(ir->value); + ir->value = convert_vector_extract_to_swizzle(ir->value); } return visit_continue; @@ -160,6 +204,7 @@ ir_visitor_status ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir) { ir->condition = convert_vec_index_to_swizzle(ir->condition); + ir->condition = convert_vector_extract_to_swizzle(ir->condition); return visit_continue; } |