summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2014-02-28 17:49:20 -0800
committerMatt Turner <mattst88@gmail.com>2014-07-06 18:44:36 -0700
commit88c8db6f32f9332432ab02e9c8c61d25a42ebb04 (patch)
tree4fc225cfb187b75f77d44bfe5f212bb9c37739fc
parent56be00b7a16c3b26357825927101d380a6996a78 (diff)
Optimize 1 - vec4 into a swizzle of the vec4.experiment/opt-1-minus-x-into-swiz
-rw-r--r--src/glsl/opt_algebraic.cpp57
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: