From b39e6f33b60ef9bbaf81f320aaca6a440d8a6a8f Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 22 Sep 2010 11:47:03 -0700 Subject: [PATCH] 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 Reviewed-by: Ian Romanick --- src/glsl/ast_function.cpp | 43 ++++++++-------- src/glsl/builtin_function.cpp | 74 ++++++++++++++-------------- src/glsl/builtins/ir/noise2 | 16 +++--- src/glsl/builtins/ir/noise3 | 24 ++++----- src/glsl/builtins/ir/noise4 | 34 ++++++------- src/glsl/ir.cpp | 29 ++++++++++- src/glsl/ir.h | 8 +++ src/glsl/ir_constant_propagation.cpp | 16 ++++-- src/glsl/ir_mat_op_to_vec.cpp | 5 +- src/glsl/ir_validate.cpp | 16 +++--- src/mesa/program/ir_to_mesa.cpp | 28 ++++++++++- 11 files changed, 181 insertions(+), 112 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); diff --git a/src/glsl/builtin_function.cpp b/src/glsl/builtin_function.cpp index c904f4629f2..5f9bbec2f01 100644 --- a/src/glsl/builtin_function.cpp +++ b/src/glsl/builtin_function.cpp @@ -1889,8 +1889,8 @@ static const char *builtin_noise2 = "\n" " (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p)))\n" " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec4 + (var_ref p) (constant vec4 (601.0 313.0 29.0 277.0)))))\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" " (return (var_ref t))\n" " ))\n" "\n" @@ -1903,8 +1903,8 @@ static const char *builtin_noise2 = "\n" " (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p)))\n" " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec3 + (var_ref p) (constant vec3 (601.0 313.0 29.0)))))\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" " (return (var_ref t))\n" " ))\n" "\n" @@ -1919,8 +1919,8 @@ static const char *builtin_noise2 = "\n" " (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p)))\n" " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec2 + (var_ref p) (constant vec2 (601.0 313.0)))))\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" " (return (var_ref t))\n" " ))\n" "\n" @@ -1935,8 +1935,8 @@ static const char *builtin_noise2 = "\n" " (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p)))\n" " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression float + (var_ref p) (constant float (601.0)))))\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" " (return (var_ref t))\n" " ))\n" "))\n" @@ -1956,9 +1956,9 @@ static const char *builtin_noise3 = " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec4 + (var_ref p) (constant vec4 (601.0 313.0 29.0 277.0)))))\n" " (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression vec4 + (var_ref p) (constant vec4 (1559.0 113.0 1861.0 797.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b)))\n" - " (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" + " (assign (constant bool (1)) (z) (var_ref t) (var_ref c))\n" " (return (var_ref t))\n" " ))\n" "\n" @@ -1974,9 +1974,9 @@ static const char *builtin_noise3 = " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec3 + (var_ref p) (constant vec3 (601.0 313.0 29.0)))))\n" " (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression vec3 + (var_ref p) (constant vec3 (1559.0 113.0 1861.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b)))\n" - " (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" + " (assign (constant bool (1)) (z) (var_ref t) (var_ref c))\n" " (return (var_ref t))\n" " ))\n" "\n" @@ -1992,9 +1992,9 @@ static const char *builtin_noise3 = " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec2 + (var_ref p) (constant vec2 (601.0 313.0)))))\n" " (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression vec2 + (var_ref p) (constant vec2 (1559.0 113.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b)))\n" - " (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" + " (assign (constant bool (1)) (z) (var_ref t) (var_ref c))\n" " (return (var_ref t))\n" " ))\n" "\n" @@ -2010,9 +2010,9 @@ static const char *builtin_noise3 = " (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression float + (var_ref p) (constant float (601.0)))))\n" " (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression float + (var_ref p) (constant float (1559.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a)))\n" - " (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b)))\n" - " (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c)))\n" + " (assign (constant bool (1)) (x) (var_ref t) (var_ref a))\n" + " (assign (constant bool (1)) (y) (var_ref t) (var_ref b))\n" + " (assign (constant bool (1)) (z) (var_ref t) (var_ref c))\n" " (return (var_ref t))\n" " ))\n" "))\n" @@ -2037,10 +2037,10 @@ static const char *builtin_noise4 = " (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p)))\n" " (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression vec4 + (var_ref _p) (constant vec4 (601.0 313.0 29.0 277.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x)))\n" - " (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y)))\n" - " (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z)))\n" - " (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w)))\n" + " (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x))\n" + " (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y))\n" + " (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z))\n" + " (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w))\n" " (return (var_ref _r))\n" " ))\n" "\n" @@ -2061,10 +2061,10 @@ static const char *builtin_noise4 = " (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p)))\n" " (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression vec3 + (var_ref _p) (constant vec3 (601.0 313.0 29.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x)))\n" - " (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y)))\n" - " (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z)))\n" - " (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w)))\n" + " (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x))\n" + " (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y))\n" + " (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z))\n" + " (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w))\n" " (return (var_ref _r))\n" " ))\n" "\n" @@ -2085,10 +2085,10 @@ static const char *builtin_noise4 = " (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p)))\n" " (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression vec2 + (var_ref _p) (constant vec2 (601.0 313.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x)))\n" - " (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y)))\n" - " (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z)))\n" - " (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w)))\n" + " (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x))\n" + " (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y))\n" + " (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z))\n" + " (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w))\n" " (return (var_ref _r))\n" " ))\n" "\n" @@ -2102,17 +2102,17 @@ static const char *builtin_noise4 = " (declare () vec4 _r)\n" "\n" " (declare () float _p)\n" - " (assign (constant bool (1)) (xy) (var_ref _p) (expression float + (var_ref p) (constant float (1559.0))) )\n" + " (assign (constant bool (1)) (x) (var_ref _p) (expression float + (var_ref p) (constant float (1559.0))) )\n" "\n" " (assign (constant bool (1)) (x) (var_ref _x) (expression float noise(var_ref p)))\n" " (assign (constant bool (1)) (x) (var_ref _y) (expression float noise(expression float + (var_ref p) (constant float (601.0 313.0 29.0 277.0)))))\n" " (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p)))\n" " (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression float + (var_ref _p) (constant float (601.0 313.0 29.0 277.0)))))\n" "\n" - " (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x)))\n" - " (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y)))\n" - " (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z)))\n" - " (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w)))\n" + " (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x))\n" + " (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y))\n" + " (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z))\n" + " (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w))\n" " (return (var_ref _r))\n" " ))\n" "))\n" diff --git a/src/glsl/builtins/ir/noise2 b/src/glsl/builtins/ir/noise2 index 008f8b00f1f..383fccfadfb 100644 --- a/src/glsl/builtins/ir/noise2 +++ b/src/glsl/builtins/ir/noise2 @@ -8,8 +8,8 @@ (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p))) (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec4 + (var_ref p) (constant vec4 (601.0 313.0 29.0 277.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) (return (var_ref t)) )) @@ -22,8 +22,8 @@ (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p))) (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec3 + (var_ref p) (constant vec3 (601.0 313.0 29.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) (return (var_ref t)) )) @@ -38,8 +38,8 @@ (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p))) (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec2 + (var_ref p) (constant vec2 (601.0 313.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) (return (var_ref t)) )) @@ -54,8 +54,8 @@ (assign (constant bool (1)) (x) (var_ref a) (expression float noise (var_ref p))) (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression float + (var_ref p) (constant float (601.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xx (var_ref b))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) (return (var_ref t)) )) )) diff --git a/src/glsl/builtins/ir/noise3 b/src/glsl/builtins/ir/noise3 index f191e145f99..ed7ad5190f2 100644 --- a/src/glsl/builtins/ir/noise3 +++ b/src/glsl/builtins/ir/noise3 @@ -11,9 +11,9 @@ (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec4 + (var_ref p) (constant vec4 (601.0 313.0 29.0 277.0))))) (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression vec4 + (var_ref p) (constant vec4 (1559.0 113.0 1861.0 797.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b))) - (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) + (assign (constant bool (1)) (z) (var_ref t) (var_ref c)) (return (var_ref t)) )) @@ -29,9 +29,9 @@ (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec3 + (var_ref p) (constant vec3 (601.0 313.0 29.0))))) (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression vec3 + (var_ref p) (constant vec3 (1559.0 113.0 1861.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b))) - (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) + (assign (constant bool (1)) (z) (var_ref t) (var_ref c)) (return (var_ref t)) )) @@ -47,9 +47,9 @@ (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression vec2 + (var_ref p) (constant vec2 (601.0 313.0))))) (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression vec2 + (var_ref p) (constant vec2 (1559.0 113.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b))) - (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) + (assign (constant bool (1)) (z) (var_ref t) (var_ref c)) (return (var_ref t)) )) @@ -65,9 +65,9 @@ (assign (constant bool (1)) (x) (var_ref b) (expression float noise (expression float + (var_ref p) (constant float (601.0))))) (assign (constant bool (1)) (x) (var_ref c) (expression float noise (expression float + (var_ref p) (constant float (1559.0))))) - (assign (constant bool (1)) (x) (var_ref t) (swiz xxx (var_ref a))) - (assign (constant bool (1)) (y) (var_ref t) (swiz xxx (var_ref b))) - (assign (constant bool (1)) (z) (var_ref t) (swiz xxx (var_ref c))) + (assign (constant bool (1)) (x) (var_ref t) (var_ref a)) + (assign (constant bool (1)) (y) (var_ref t) (var_ref b)) + (assign (constant bool (1)) (z) (var_ref t) (var_ref c)) (return (var_ref t)) )) )) diff --git a/src/glsl/builtins/ir/noise4 b/src/glsl/builtins/ir/noise4 index fb300fd1486..77a2529a180 100644 --- a/src/glsl/builtins/ir/noise4 +++ b/src/glsl/builtins/ir/noise4 @@ -16,10 +16,10 @@ (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p))) (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression vec4 + (var_ref _p) (constant vec4 (601.0 313.0 29.0 277.0))))) - (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x))) - (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y))) - (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z))) - (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w))) + (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x)) + (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y)) + (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z)) + (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w)) (return (var_ref _r)) )) @@ -40,10 +40,10 @@ (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p))) (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression vec3 + (var_ref _p) (constant vec3 (601.0 313.0 29.0))))) - (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x))) - (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y))) - (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z))) - (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w))) + (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x)) + (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y)) + (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z)) + (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w)) (return (var_ref _r)) )) @@ -64,10 +64,10 @@ (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p))) (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression vec2 + (var_ref _p) (constant vec2 (601.0 313.0))))) - (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x))) - (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y))) - (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z))) - (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w))) + (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x)) + (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y)) + (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z)) + (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w)) (return (var_ref _r)) )) @@ -81,17 +81,17 @@ (declare () vec4 _r) (declare () float _p) - (assign (constant bool (1)) (xy) (var_ref _p) (expression float + (var_ref p) (constant float (1559.0))) ) + (assign (constant bool (1)) (x) (var_ref _p) (expression float + (var_ref p) (constant float (1559.0))) ) (assign (constant bool (1)) (x) (var_ref _x) (expression float noise(var_ref p))) (assign (constant bool (1)) (x) (var_ref _y) (expression float noise(expression float + (var_ref p) (constant float (601.0 313.0 29.0 277.0))))) (assign (constant bool (1)) (x) (var_ref _z) (expression float noise(var_ref _p))) (assign (constant bool (1)) (x) (var_ref _w) (expression float noise(expression float + (var_ref _p) (constant float (601.0 313.0 29.0 277.0))))) - (assign (constant bool (1)) (x) (var_ref _r) (swiz xxxx (var_ref _x))) - (assign (constant bool (1)) (y) (var_ref _r) (swiz xxxx (var_ref _y))) - (assign (constant bool (1)) (z) (var_ref _r) (swiz xxxx (var_ref _z))) - (assign (constant bool (1)) (w) (var_ref _r) (swiz xxxx (var_ref _w))) + (assign (constant bool (1)) (x) (var_ref _r) (var_ref _x)) + (assign (constant bool (1)) (y) (var_ref _r) (var_ref _y)) + (assign (constant bool (1)) (z) (var_ref _r) (var_ref _z)) + (assign (constant bool (1)) (w) (var_ref _r) (var_ref _w)) (return (var_ref _r)) )) )) diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 7cc55d40b78..5e2109ecc6e 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -55,6 +55,9 @@ update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to) void ir_assignment::set_lhs(ir_rvalue *lhs) { + void *mem_ctx = this; + bool swizzled = false; + while (lhs != NULL) { ir_swizzle *swiz = lhs->as_swizzle(); @@ -82,7 +85,21 @@ ir_assignment::set_lhs(ir_rvalue *lhs) this->write_mask = write_mask; lhs = swiz->val; - this->rhs = new(this) ir_swizzle(this->rhs, rhs_swiz); + this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz); + swizzled = true; + } + + if (swizzled) { + /* Now, RHS channels line up with the LHS writemask. Collapse it + * to just the channels that will be written. + */ + ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 }; + int rhs_chan = 0; + for (int i = 0; i < 4; i++) { + if (write_mask & (1 << i)) + update_rhs_swizzle(rhs_swiz, i, rhs_chan++); + } + this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz); } assert((lhs == NULL) || lhs->as_dereference()); @@ -122,6 +139,16 @@ ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, this->rhs = rhs; this->lhs = lhs; this->write_mask = write_mask; + + if (lhs->type->is_scalar() || lhs->type->is_vector()) { + int lhs_components = 0; + for (int i = 0; i < 4; i++) { + if (write_mask & (1 << i)) + lhs_components++; + } + + assert(lhs_components == this->rhs->type->vector_elements); + } } ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 240e7cd49af..fa246b5e570 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -646,6 +646,14 @@ public: * For non-vector types in the LHS, this field will be zero. For vector * types, a bit will be set for each component that is written. Note that * for \c vec2 and \c vec3 types only the lower bits will ever be set. + * + * A partially-set write mask means that each enabled channel gets + * the value from a consecutive channel of the rhs. For example, + * to write just .xyw of gl_FrontColor with color: + * + * (assign (constant bool (1)) (xyw) + * (var_ref gl_FragColor) + * (swiz xyw (var_ref color))) */ unsigned write_mask:4; }; diff --git a/src/glsl/ir_constant_propagation.cpp b/src/glsl/ir_constant_propagation.cpp index f7a0599f425..390f295d6e9 100644 --- a/src/glsl/ir_constant_propagation.cpp +++ b/src/glsl/ir_constant_propagation.cpp @@ -168,18 +168,26 @@ ir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue) if (!found) return; + int rhs_channel = 0; + for (int j = 0; j < 4; j++) { + if (j == channel) + break; + if (found->write_mask & (1 << j)) + rhs_channel++; + } + switch (type->base_type) { case GLSL_TYPE_FLOAT: - data.f[i] = found->constant->value.f[channel]; + data.f[i] = found->constant->value.f[rhs_channel]; break; case GLSL_TYPE_INT: - data.i[i] = found->constant->value.i[channel]; + data.i[i] = found->constant->value.i[rhs_channel]; break; case GLSL_TYPE_UINT: - data.u[i] = found->constant->value.u[channel]; + data.u[i] = found->constant->value.u[rhs_channel]; break; case GLSL_TYPE_BOOL: - data.b[i] = found->constant->value.b[channel]; + data.b[i] = found->constant->value.b[rhs_channel]; break; default: assert(!"not reached"); diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp index c32ca88b0fe..244fe489280 100644 --- a/src/glsl/ir_mat_op_to_vec.cpp +++ b/src/glsl/ir_mat_op_to_vec.cpp @@ -310,14 +310,11 @@ ir_mat_op_to_vec_visitor::do_equal_mat_mat(ir_variable *result_var, new(this->mem_ctx) ir_expression(ir_binop_any_nequal, glsl_type::bool_type, op0, op1); - ir_rvalue *const swiz = - new(this->mem_ctx) ir_swizzle(cmp, i, i, i, i, columns); - ir_dereference *const lhs = new(this->mem_ctx) ir_dereference_variable(tmp_bvec); ir_assignment *const assign = - new(this->mem_ctx) ir_assignment(lhs, swiz, NULL, (1U << i)); + new(this->mem_ctx) ir_assignment(lhs, cmp, NULL, (1U << i)); this->base_ir->insert_before(assign); } diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp index 912d1c0d709..e35514aa6f9 100644 --- a/src/glsl/ir_validate.cpp +++ b/src/glsl/ir_validate.cpp @@ -391,14 +391,16 @@ ir_validate::visit_enter(ir_assignment *ir) abort(); } - /* Mask of fields that do not exist in the destination. These should - * not be written by the assignment. - */ - const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1); + int lhs_components = 0; + for (int i = 0; i < 4; i++) { + if (ir->write_mask & (1 << i)) + lhs_components++; + } - if ((invalid_mask & ir->write_mask) != 0) { - printf("Assignment write mask enables invalid components for " - "type %s:\n", lhs->type->name); + if (lhs_components != ir->rhs->type->vector_elements) { + printf("Assignment count of LHS write mask channels enabled not\n" + "matching RHS vector size (%d LHS, %d RHS).\n", + lhs_components, ir->rhs->type->vector_elements); ir->print(); abort(); } diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index f24dce79f65..de0cb1ac5bd 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1577,13 +1577,39 @@ ir_to_mesa_visitor::visit(ir_assignment *ir) assert(!ir->lhs->type->is_scalar() && !ir->lhs->type->is_vector()); l.writemask = WRITEMASK_XYZW; } else if (ir->lhs->type->is_scalar()) { - /* FINISHME: This hack makes writing to gl_FragData, which lives in the + /* FINISHME: This hack makes writing to gl_FragDepth, which lives in the * FINISHME: W component of fragment shader output zero, work correctly. */ l.writemask = WRITEMASK_XYZW; } else { + int swizzles[4]; + int first_enabled_chan = 0; + int rhs_chan = 0; + assert(ir->lhs->type->is_vector()); l.writemask = ir->write_mask; + + for (int i = 0; i < 4; i++) { + if (l.writemask & (1 << i)) { + first_enabled_chan = GET_SWZ(r.swizzle, i); + break; + } + } + + /* Swizzle a small RHS vector into the channels being written. + * + * glsl ir treats write_mask as dictating how many channels are + * present on the RHS while Mesa IR treats write_mask as just + * showing which channels of the vec4 RHS get written. + */ + for (int i = 0; i < 4; i++) { + if (l.writemask & (1 << i)) + swizzles[i] = GET_SWZ(r.swizzle, rhs_chan++); + else + swizzles[i] = first_enabled_chan; + } + r.swizzle = MAKE_SWIZZLE4(swizzles[0], swizzles[1], + swizzles[2], swizzles[3]); } assert(l.file != PROGRAM_UNDEFINED); -- 2.30.2