diff options
author | Eric Anholt <[email protected]> | 2010-09-22 11:47:03 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-09-22 13:09:51 -0700 |
commit | b39e6f33b60ef9bbaf81f320aaca6a440d8a6a8f (patch) | |
tree | c3547819e402b729d84a4847aed95b81ec09fdbf /src/glsl/ast_function.cpp | |
parent | 38da5c9cb636387539daaf5688c2a3badee32447 (diff) |
glsl: Rework assignments with write_masks to have LHS chan count match RHS.
It turns out that most people new to this IR are surprised when an
assignment to (say) 3 components on the LHS takes 4 components on the
RHS. It also makes for quite strange IR output:
(assign (constant bool (1)) (x) (var_ref color) (swiz x (var_ref v) ))
(assign (constant bool (1)) (y) (var_ref color) (swiz yy (var_ref v) ))
(assign (constant bool (1)) (z) (var_ref color) (swiz zzz (var_ref v) ))
But even worse, even we get it wrong, as shown by this line of our
current step(float, vec4):
(assign (constant bool (1)) (w)
(var_ref t)
(expression float b2f (expression bool >=
(swiz w (var_ref x))(var_ref edge))))
where we try to assign a float to the writemasked-out x channel and
don't supply anything for the actual w channel we're writing. Drivers
right now just get lucky since ir_to_mesa spams the float value across
all the source channels of a vec4.
Instead, the RHS will now have a number of components equal to the
number of components actually being written. Hopefully this confuses
everyone less, and it also makes codegen for a scalar target simpler.
Reviewed-by: Kenneth Graunke <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/glsl/ast_function.cpp')
-rw-r--r-- | src/glsl/ast_function.cpp | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 5d9d35b2d9b..20448f5a975 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -504,8 +504,9 @@ emit_inline_vector_constructor(const glsl_type *type, instructions->push_tail(inst); } else { unsigned base_component = 0; + unsigned base_lhs_component = 0; ir_constant_data data; - unsigned constant_mask = 0; + unsigned constant_mask = 0, constant_components = 0; memset(&data, 0, sizeof(data)); @@ -515,8 +516,8 @@ emit_inline_vector_constructor(const glsl_type *type, /* 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; + if ((rhs_components + base_lhs_component) > lhs_components) { + rhs_components = lhs_components - base_lhs_component; } const ir_constant *const c = param->as_constant(); @@ -543,18 +544,23 @@ emit_inline_vector_constructor(const glsl_type *type, /* Mask of fields to be written in the assignment. */ - constant_mask |= ((1U << rhs_components) - 1) << base_component; - } + constant_mask |= ((1U << rhs_components) - 1) << base_lhs_component; + constant_components++; - /* Advance the component index by the number of components that were - * just assigned. + base_component += rhs_components; + } + /* Advance the component index by the number of components + * that were just assigned. */ - base_component += rhs_components; + base_lhs_component += rhs_components; } if (constant_mask != 0) { ir_dereference *lhs = new(ctx) ir_dereference_variable(var); - ir_rvalue *rhs = new(ctx) ir_constant(var->type, &data); + const glsl_type *rhs_type = glsl_type::get_instance(var->type->base_type, + constant_components, + 1); + ir_rvalue *rhs = new(ctx) ir_constant(rhs_type, &data); ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask); @@ -574,12 +580,10 @@ emit_inline_vector_constructor(const glsl_type *type, 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. - */ + /* Generate a swizzle in case rhs_components != rhs->type->vector_elements. */ unsigned swiz[4] = { 0, 0, 0, 0 }; for (unsigned i = 0; i < rhs_components; i++) - swiz[i + base_component] = i; + swiz[i] = i; /* Mask of fields to be written in the assignment. */ @@ -587,7 +591,7 @@ emit_inline_vector_constructor(const glsl_type *type, << base_component; 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_swizzle(param, swiz, rhs_components); ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, write_mask); @@ -632,10 +636,10 @@ assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base, */ unsigned swiz[4] = { src_base, src_base, src_base, src_base }; for (unsigned i = 0; i < count; i++) - swiz[i + row_base] = src_base + i; + swiz[i + row_base] = i; ir_rvalue *const rhs = - new(mem_ctx) ir_swizzle(src, swiz, column_ref->type->components()); + new(mem_ctx) ir_swizzle(src, swiz, count); /* Mask of fields to be written in the assignment. */ @@ -816,7 +820,7 @@ emit_inline_matrix_constructor(const glsl_type *type, var->type->matrix_columns); unsigned swiz[4] = { 0, 0, 0, 0 }; - for (unsigned i = 1; i < src_matrix->type->vector_elements; i++) + for (unsigned i = 1; i < last_row; i++) swiz[i] = i; const unsigned write_mask = (1U << last_row) - 1; @@ -837,14 +841,11 @@ emit_inline_matrix_constructor(const glsl_type *type, */ ir_rvalue *rhs; if (lhs->type->vector_elements != rhs_col->type->vector_elements) { - rhs = new(ctx) ir_swizzle(rhs_col, swiz, - lhs->type->vector_elements); + rhs = new(ctx) ir_swizzle(rhs_col, swiz, last_row); } else { rhs = rhs_col; } - assert(lhs->type == rhs->type); - ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, write_mask); instructions->push_tail(inst); |