summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2010-08-31 14:44:13 -0700
committerIan Romanick <[email protected]>2010-08-31 14:44:13 -0700
commita6c3cd5ca6822da2ec6e869c7bc2b8ac64c177f2 (patch)
tree6a9eee74ff5b3fc1cd3eaa261ebc9f411430b01e
parent99f3c9caa39fbe9dfa7561c919202395720e9472 (diff)
glsl2: Write vector constructor constants in a single assignment
Make two passes over the constructor parameters. Write all of the constants in a single write, then write the non-constants one at a time. This causes the fragment shader varying float g; void main() { gl_FragColor = vec4(0.0, g, 0.0, 1.0); } to generate (function main (signature void (parameters ) ( (declare (temporary ) vec4 vec_ctor@0x8580058) (assign (constant bool (1)) (xzw) (var_ref vec_ctor@0x8580058) (constant vec4 (0.000000 0.000000 0.000000 1.000000)) ) (assign (constant bool (1)) (y) (var_ref vec_ctor@0x8580058) (swiz xxxx (var_ref g@0x8580218) )) (assign (constant bool (1)) (xyzw) (var_ref gl_FragColor@0x84d32a0) (var_ref vec_ctor@0x8580058) ) )) ) instead of (function main (signature void (parameters ) ( (declare (temporary ) vec4 vec_ctor@0x8580058) (assign (constant bool (1)) (x) (var_ref vec_ctor@0x8580058) (constant vec4 (0.000000 0.000000 0.000000 1.000000)) ) (assign (constant bool (1)) (y) (var_ref vec_ctor@0x8580058) (swiz xxxx (var_ref g@0x8580218) )) (assign (constant bool (1)) (z) (var_ref vec_ctor@0x8580058) (constant vec4 (0.000000 0.000000 0.000000 1.000000)) ) (assign (constant bool (1)) (w) (var_ref vec_ctor@0x8580058) (constant vec4 (0.000000 0.000000 0.000000 1.000000)) ) (assign (constant bool (1)) (xyzw) (var_ref gl_FragColor@0x84d32a0) (var_ref vec_ctor@0x8580058) ) )) ) A similar optimization could be done for matrix constructors, but it is a little more complicate there.
-rw-r--r--src/glsl/ast_function.cpp83
1 files changed, 72 insertions, 11 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index c2e526cf896..d39c4b195cd 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -621,6 +621,11 @@ emit_inline_vector_constructor(const glsl_type *type,
instructions->push_tail(inst);
} else {
unsigned base_component = 0;
+ ir_constant_data data;
+ unsigned constant_mask = 0;
+
+ memset(&data, 0, sizeof(data));
+
foreach_list(node, parameters) {
ir_rvalue *param = (ir_rvalue *) node;
unsigned rhs_components = param->type->components();
@@ -631,24 +636,80 @@ emit_inline_vector_constructor(const glsl_type *type,
rhs_components = lhs_components - base_component;
}
- /* Generate a swizzle that puts the first element of the source at
- * the location of the first element of the destination.
- */
- unsigned swiz[4] = { 0, 0, 0, 0 };
- for (unsigned i = 0; i < rhs_components; i++)
- swiz[i + base_component] = i;
+ const ir_constant *const c = param->as_constant();
+ if (c != NULL) {
+ for (unsigned i = 0; i < rhs_components; i++) {
+ switch (c->type->base_type) {
+ case GLSL_TYPE_UINT:
+ data.u[i + base_component] = c->get_uint_component(i);
+ break;
+ case GLSL_TYPE_INT:
+ data.i[i + base_component] = c->get_int_component(i);
+ break;
+ case GLSL_TYPE_FLOAT:
+ data.f[i + base_component] = c->get_float_component(i);
+ break;
+ case GLSL_TYPE_BOOL:
+ data.b[i + base_component] = c->get_bool_component(i);
+ break;
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ }
- /* Mask of fields to be written in the assignment.
+ /* Mask of fields to be written in the assignment.
+ */
+ constant_mask |= ((1U << rhs_components) - 1) << base_component;
+ }
+
+ /* Advance the component index by the number of components that were
+ * just assigned.
*/
- const unsigned write_mask = ((1U << rhs_components) - 1)
- << base_component;
+ base_component += rhs_components;
+ }
+ if (constant_mask != 0) {
ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
- ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+ ir_rvalue *rhs = new(ctx) ir_constant(var->type, &data);
ir_instruction *inst =
- new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+ new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask);
instructions->push_tail(inst);
+ }
+
+ base_component = 0;
+ foreach_list(node, parameters) {
+ ir_rvalue *param = (ir_rvalue *) node;
+ unsigned rhs_components = param->type->components();
+
+ /* Do not try to assign more components to the vector than it has!
+ */
+ if ((rhs_components + base_component) > lhs_components) {
+ rhs_components = lhs_components - base_component;
+ }
+
+ const ir_constant *const c = param->as_constant();
+ if (c == NULL) {
+ /* Generate a swizzle that puts the first element of the source at
+ * the location of the first element of the destination.
+ */
+ unsigned swiz[4] = { 0, 0, 0, 0 };
+ for (unsigned i = 0; i < rhs_components; i++)
+ swiz[i + base_component] = i;
+
+ /* Mask of fields to be written in the assignment.
+ */
+ const unsigned write_mask = ((1U << rhs_components) - 1)
+ << base_component;
+
+ ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+ ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+
+ ir_instruction *inst =
+ new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+ instructions->push_tail(inst);
+ }
/* Advance the component index by the number of components that were
* just assigned.