diff options
author | Matt Turner <mattst88@gmail.com> | 2014-02-28 17:49:20 -0800 |
---|---|---|
committer | Matt Turner <mattst88@gmail.com> | 2014-07-06 18:44:36 -0700 |
commit | 88c8db6f32f9332432ab02e9c8c61d25a42ebb04 (patch) | |
tree | 4fc225cfb187b75f77d44bfe5f212bb9c37739fc | |
parent | 56be00b7a16c3b26357825927101d380a6996a78 (diff) |
Optimize 1 - vec4 into a swizzle of the vec4.experiment/opt-1-minus-x-into-swiz
-rw-r--r-- | src/glsl/opt_algebraic.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp index ac7514acfd9e..3eb971662b60 100644 --- a/src/glsl/opt_algebraic.cpp +++ b/src/glsl/opt_algebraic.cpp @@ -34,6 +34,7 @@ #include "ir_optimization.h" #include "ir_builder.h" #include "glsl_types.h" +#include "main/core.h" /* for MAX2 */ using namespace ir_builder; @@ -432,6 +433,62 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) } } + /* Recognize if the result of an addition is a swizzle of one of the + * operands. E.g., in + * + * vec4 foo = vec4(0.6, 0.4, 0.1, 0.9); + * vec4 bar = 1.0 - foo; + * + * bar could be rewritten as + * + * vec4 bar = foo.yxwz; + * + * We should only perform this operation if the backend operates on + * arrays of structs. + */ + break; + if (options->OptimizeForAOS) { + if (op_const[0] && op_const[1] && ir->type->is_float()) { +#if 0 + assert(op_const[0]->type->components() == op_const[1]->type->components() || + op_const[0]->type->is_scalar() || + op_const[1]->type->is_scalar()); +#endif + const unsigned components = MAX2(op_const[0]->type->components(), + op_const[1]->type->components()); + const unsigned c0_inc = op_const[0]->type->is_scalar() ? 0 : 1; + const unsigned c1_inc = op_const[1]->type->is_scalar() ? 0 : 1; + + float *result = ralloc_array(mem_ctx, float, components); + + for (unsigned c = 0, c0 = 0, c1 = 0; c < components; + c++, c0 += c0_inc, c1 += c1_inc) { + result[c] = -(op_const[0]->value.f[c0] + op_const[1]->value.f[c1]); + } + + int *swiz = ralloc_array(mem_ctx, int, components); + bool can_swiz = true; + for (unsigned c = 0, c1 = 0; c < components; c++, c1 += c1_inc) { + swiz[c] = -1; + + for (unsigned i = 0; i < components; i += c1_inc) { + if (fabsf(result[c] - op_const[1]->value.f[i]) < FLT_EPSILON) { + swiz[c] = i; + break; + } + } + + if (swiz[c] == -1) { + can_swiz = false; + break; + } + } + + if (can_swiz) { + return new(mem_ctx) ir_swizzle(ir->operands[1], (const unsigned *)swiz, components); + } + } + } break; case ir_binop_sub: |