glsl: Rework assignments with write_masks to have LHS chan count match RHS.
authorEric Anholt <eric@anholt.net>
Wed, 22 Sep 2010 18:47:03 +0000 (11:47 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 22 Sep 2010 20:09:51 +0000 (13:09 -0700)
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 <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/ast_function.cpp
src/glsl/builtin_function.cpp
src/glsl/builtins/ir/noise2
src/glsl/builtins/ir/noise3
src/glsl/builtins/ir/noise4
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_constant_propagation.cpp
src/glsl/ir_mat_op_to_vec.cpp
src/glsl/ir_validate.cpp
src/mesa/program/ir_to_mesa.cpp

index 5d9d35b2d9b0058a4406537927aad98b2bc454c9..20448f5a975c5b00e98d1830ab7ddebd875530e4 100644 (file)
@@ -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);
index c904f4629f2ff7391db53cea3ee379edd7bc5329..5f9bbec2f012b44750d10a08b2de94dabc2cbef9 100644 (file)
@@ -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"
index 008f8b00f1f5488ea45e86ed9b31b8360a8625d0..383fccfadfbe9e694ffca845adddd14cf9868c1b 100644 (file)
@@ -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))
     ))
 ))
index f191e145f9921c577a525dfe100cff6c8098d9b3..ed7ad5190f2518d6badd37bae55473f7fb0631d6 100644 (file)
@@ -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))
     ))
 ))
index fb300fd1486e86065d3291e67825f7d0ed362a47..77a2529a180d39f813614c06bd20bfb62c1099b5 100644 (file)
       (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))
     ))
 
       (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))
     ))
 
       (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))
     ))
 
       (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))
     ))
 ))
index 7cc55d40b78846c388154f4e790b59da58c15296..5e2109ecc6e1f0d944563ce256d156185ee0245d 100644 (file)
@@ -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,
index 240e7cd49affd0515060de0b2fa5b43b9a1d00ba..fa246b5e57073308fa7fd15c19ac5c6f5e75bc09 100644 (file)
@@ -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;
 };
index f7a0599f425e4f2dc5fe262925d8b4b603c591f0..390f295d6e9423b68b8b45466a4679209ee721cd 100644 (file)
@@ -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");
index c32ca88b0fe8ac70f890bbe8eed1a25208ce9d8b..244fe489280e7f416e428818bce19d0689d6dd84 100644 (file)
@@ -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);
    }
index 912d1c0d7091c38ef495857d266ca71af1d96a26..e35514aa6f956a06af7e1244385cd6b9dec4b62e 100644 (file)
@@ -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();
       }
index f24dce79f654ef991ca28f377f5c17c36f350e91..de0cb1ac5bd1d362bb352ea8324141cec2c92c28 100644 (file)
@@ -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);