summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ast_function.cpp82
1 files changed, 46 insertions, 36 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index c22dfa81eb8..1b8b3195e5b 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -572,16 +572,17 @@ emit_inline_vector_constructor(const glsl_type *type,
ir_rvalue *rhs = new(ctx) ir_swizzle(first_param, 0, 0, 0, 0,
lhs_components);
ir_dereference_variable *lhs = new(ctx) ir_dereference_variable(var);
+ const unsigned mask = (1U << lhs_components) - 1;
assert(rhs->type == lhs->type);
- ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL, mask);
instructions->push_tail(inst);
} else {
unsigned base_component = 0;
foreach_list(node, parameters) {
- ir_rvalue *rhs = (ir_rvalue *) node;
- unsigned rhs_components = rhs->type->components();
+ 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!
*/
@@ -589,19 +590,23 @@ emit_inline_vector_constructor(const glsl_type *type,
rhs_components = lhs_components - base_component;
}
- /* Emit an assignment of the constructor parameter to the next set of
- * components in the temporary variable.
+ /* Generate a swizzle that puts the first element of the source at
+ * the location of the first element of the destination.
*/
- unsigned mask[4] = { 0, 0, 0, 0 };
- for (unsigned i = 0; i < rhs_components; i++) {
- mask[i] = i + base_component;
- }
+ 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_rvalue *lhs_ref = new(ctx) ir_dereference_variable(var);
- ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, mask, rhs_components);
+ 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);
+ 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
@@ -631,18 +636,27 @@ assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base,
ir_rvalue *src, unsigned src_base, unsigned count,
void *mem_ctx)
{
- const unsigned mask[8] = { 0, 1, 2, 3, 0, 0, 0, 0 };
-
ir_constant *col_idx = new(mem_ctx) ir_constant(column);
- ir_rvalue *column_ref = new(mem_ctx) ir_dereference_array(var, col_idx);
+ ir_dereference *column_ref = new(mem_ctx) ir_dereference_array(var, col_idx);
assert(column_ref->type->components() >= (row_base + count));
- ir_rvalue *lhs = new(mem_ctx) ir_swizzle(column_ref, &mask[row_base], count);
-
assert(src->type->components() >= (src_base + count));
- ir_rvalue *rhs = new(mem_ctx) ir_swizzle(src, &mask[src_base], count);
- return new(mem_ctx) ir_assignment(lhs, rhs, 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] = { src_base, src_base, src_base, src_base };
+ for (unsigned i = 0; i < count; i++)
+ swiz[i + row_base] = src_base + i;
+
+ ir_rvalue *const rhs =
+ new(mem_ctx) ir_swizzle(src, swiz, column_ref->type->components());
+
+ /* Mask of fields to be written in the assignment.
+ */
+ const unsigned write_mask = ((1U << count) - 1) << row_base;
+
+ return new(mem_ctx) ir_assignment(column_ref, rhs, NULL, write_mask);
}
@@ -704,10 +718,9 @@ emit_inline_matrix_constructor(const glsl_type *type,
NULL);
instructions->push_tail(inst);
- ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
- ir_rvalue *const x_of_rhs = new(ctx) ir_swizzle(rhs_ref, 0, 0, 0, 0, 1);
+ ir_dereference *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
- inst = new(ctx) ir_assignment(x_of_rhs, first_param, NULL);
+ inst = new(ctx) ir_assignment(rhs_ref, first_param, NULL, 0x01);
instructions->push_tail(inst);
/* Assign the temporary vector to each column of the destination matrix
@@ -813,11 +826,16 @@ emit_inline_matrix_constructor(const glsl_type *type,
instructions->push_tail(inst);
- const unsigned swiz[4] = { 0, 1, 2, 3 };
+ unsigned swiz[4] = { 0, 0, 0, 0 };
+ for (unsigned i = 1; i < src_matrix->type->vector_elements; i++)
+ swiz[i] = i;
+
const unsigned last_col = min(src_matrix->type->matrix_columns,
var->type->matrix_columns);
+ const unsigned write_mask = (1U << var->type->vector_elements) - 1;
+
for (unsigned i = 0; i < last_col; i++) {
- ir_rvalue *const lhs_col =
+ ir_dereference *const lhs =
new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i));
ir_rvalue *const rhs_col =
new(ctx) ir_dereference_array(rhs_var, new(ctx) ir_constant(i));
@@ -830,26 +848,18 @@ emit_inline_matrix_constructor(const glsl_type *type,
* It would be perfectly valid to unconditionally generate the
* swizzles, this this will typically result in a more compact IR tree.
*/
- ir_rvalue *lhs;
ir_rvalue *rhs;
- if (lhs_col->type->vector_elements < rhs_col->type->vector_elements) {
- lhs = lhs_col;
-
+ if (lhs->type->vector_elements != rhs_col->type->vector_elements) {
rhs = new(ctx) ir_swizzle(rhs_col, swiz,
- lhs_col->type->vector_elements);
- } else if (lhs_col->type->vector_elements
- > rhs_col->type->vector_elements) {
- lhs = new(ctx) ir_swizzle(lhs_col, swiz,
- rhs_col->type->vector_elements);
- rhs = rhs_col;
+ lhs->type->vector_elements);
} else {
- lhs = lhs_col;
rhs = rhs_col;
}
assert(lhs->type == rhs->type);
- ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+ ir_instruction *inst =
+ new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
instructions->push_tail(inst);
}
} else {