diff options
author | Ian Romanick <[email protected]> | 2010-08-31 14:44:13 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-08-31 14:44:13 -0700 |
commit | a6c3cd5ca6822da2ec6e869c7bc2b8ac64c177f2 (patch) | |
tree | 6a9eee74ff5b3fc1cd3eaa261ebc9f411430b01e | |
parent | 99f3c9caa39fbe9dfa7561c919202395720e9472 (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.cpp | 83 |
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. |