Zebediah Figura : d3dcompiler: Unwrap swizzles from the left-hand side of an assignment.

Alexandre Julliard julliard at winehq.org
Thu Mar 12 17:09:07 CDT 2020


Module: wine
Branch: master
Commit: bdbf0b43b729b09e7acbdd9b680d34d0cf582ef7
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=bdbf0b43b729b09e7acbdd9b680d34d0cf582ef7

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Fri Mar  6 17:17:33 2020 -0600

d3dcompiler: Unwrap swizzles from the left-hand side of an assignment.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/d3dcompiler_43/tests/hlsl_d3d9.c |   5 +-
 dlls/d3dcompiler_43/utils.c           | 104 ++++++++++++++++++++++++++++------
 2 files changed, 88 insertions(+), 21 deletions(-)

diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
index ce63d3ea5d..7f391833f3 100644
--- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
+++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
@@ -828,10 +828,9 @@ static void test_fail(void)
             compiled = errors = NULL;
             hr = ppD3DCompile(tests[i], strlen(tests[i]), NULL, NULL, NULL, "test", targets[j], 0, 0, &compiled, &errors);
             todo_wine ok(hr == E_FAIL, "Test %u, target %s, got unexpected hr %#x.\n", i, targets[j], hr);
-            todo_wine_if (i == 1) ok(!!errors, "Test %u, target %s, expected non-NULL error blob.\n", i, targets[j]);
+            ok(!!errors, "Test %u, target %s, expected non-NULL error blob.\n", i, targets[j]);
             ok(!compiled, "Test %u, target %s, expected no compiled shader blob.\n", i, targets[j]);
-            if (errors)
-                ID3D10Blob_Release(errors);
+            ID3D10Blob_Release(errors);
         }
     }
 }
diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c
index 1b572aa0ae..9c38800808 100644
--- a/dlls/d3dcompiler_43/utils.c
+++ b/dlls/d3dcompiler_43/utils.c
@@ -1422,13 +1422,46 @@ static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op)
     return ops[op];
 }
 
-struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *left, enum parse_assign_op assign_op,
-        struct hlsl_ir_node *right)
+static unsigned int invert_swizzle(unsigned int *swizzle, unsigned int writemask)
+{
+    unsigned int i, j, bit = 0, inverted = 0, components, new_writemask = 0, new_swizzle = 0;
+
+    /* Apply the writemask to the swizzle to get a new writemask and swizzle. */
+    for (i = 0; i < 4; ++i)
+    {
+        if (writemask & (1 << i))
+        {
+            unsigned int s = (*swizzle >> (i * 2)) & 3;
+            new_swizzle |= s << (bit++ * 2);
+            if (new_writemask & (1 << s))
+                return 0;
+            new_writemask |= 1 << s;
+        }
+    }
+    components = bit;
+
+    /* Invert the swizzle. */
+    bit = 0;
+    for (i = 0; i < 4; ++i)
+    {
+        for (j = 0; j < components; ++j)
+        {
+            unsigned int s = (new_swizzle >> (j * 2)) & 3;
+            if (s == i)
+                inverted |= j << (bit++ * 2);
+        }
+    }
+
+    *swizzle = inverted;
+    return new_writemask;
+}
+
+struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *lhs, enum parse_assign_op assign_op,
+        struct hlsl_ir_node *rhs)
 {
     struct hlsl_ir_assignment *assign = d3dcompiler_alloc(sizeof(*assign));
-    DWORD writemask = BWRITERSP_WRITEMASK_ALL;
+    DWORD writemask = (1 << lhs->data_type->dimx) - 1;
     struct hlsl_type *type;
-    struct hlsl_ir_node *lhs, *rhs;
 
     if (!assign)
     {
@@ -1436,46 +1469,81 @@ struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *left, enum parse_assig
         return NULL;
     }
 
+    while (lhs->type != HLSL_IR_DEREF)
+    {
+        struct hlsl_ir_node *lhs_inner;
+
+        if (lhs->type == HLSL_IR_EXPR && expr_from_node(lhs)->op == HLSL_IR_UNOP_CAST)
+        {
+            FIXME("Cast on the lhs.\n");
+            d3dcompiler_free(assign);
+            return NULL;
+        }
+        else if (lhs->type == HLSL_IR_SWIZZLE)
+        {
+            struct hlsl_ir_swizzle *swizzle = swizzle_from_node(lhs);
+
+            if (lhs->data_type->type == HLSL_CLASS_MATRIX)
+                FIXME("Assignments with writemasks and matrices on lhs are not supported yet.\n");
+
+            lhs_inner = swizzle->val;
+            list_remove(&lhs->entry);
+
+            list_add_after(&rhs->entry, &lhs->entry);
+            swizzle->val = rhs;
+            if (!(writemask = invert_swizzle(&swizzle->swizzle, writemask)))
+            {
+                hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid writemask");
+                d3dcompiler_free(assign);
+                return NULL;
+            }
+            rhs = &swizzle->node;
+        }
+        else
+        {
+            hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR, "invalid lvalue");
+            d3dcompiler_free(assign);
+            return NULL;
+        }
+
+        lhs = lhs_inner;
+    }
+
     TRACE("Creating proper assignment expression.\n");
-    rhs = right;
     if (writemask == BWRITERSP_WRITEMASK_ALL)
-        type = left->data_type;
+        type = lhs->data_type;
     else
     {
         unsigned int dimx = 0;
         DWORD bitmask;
         enum hlsl_type_class type_class;
 
-        if (left->data_type->type > HLSL_CLASS_LAST_NUMERIC)
+        if (lhs->data_type->type > HLSL_CLASS_LAST_NUMERIC)
         {
-            hlsl_report_message(left->loc, HLSL_LEVEL_ERROR,
+            hlsl_report_message(lhs->loc, HLSL_LEVEL_ERROR,
                     "writemask on a non scalar/vector/matrix type");
             d3dcompiler_free(assign);
             return NULL;
         }
-        bitmask = writemask & ((1 << left->data_type->dimx) - 1);
+        bitmask = writemask & ((1 << lhs->data_type->dimx) - 1);
         while (bitmask)
         {
             if (bitmask & 1)
                 dimx++;
             bitmask >>= 1;
         }
-        if (left->data_type->type == HLSL_CLASS_MATRIX)
+        if (lhs->data_type->type == HLSL_CLASS_MATRIX)
             FIXME("Assignments with writemasks and matrices on lhs are not supported yet.\n");
         if (dimx == 1)
             type_class = HLSL_CLASS_SCALAR;
         else
-            type_class = left->data_type->type;
-        type = new_hlsl_type(NULL, type_class, left->data_type->base_type, dimx, 1);
+            type_class = lhs->data_type->type;
+        type = new_hlsl_type(NULL, type_class, lhs->data_type->base_type, dimx, 1);
     }
     assign->node.type = HLSL_IR_ASSIGNMENT;
-    assign->node.loc = left->loc;
+    assign->node.loc = lhs->loc;
     assign->node.data_type = type;
     assign->writemask = writemask;
-    FIXME("Check for casts in the lhs.\n");
-
-    lhs = left;
-    /* FIXME: check for invalid writemasks on the lhs. */
 
     rhs = implicit_conversion(rhs, type, &rhs->loc);
 
@@ -1485,7 +1553,7 @@ struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *left, enum parse_assig
         enum hlsl_ir_expr_op op = op_from_assignment(assign_op);
         struct hlsl_ir_node *expr;
 
-        if (lhs->type != HLSL_IR_DEREF || deref_from_node(lhs)->type != HLSL_IR_DEREF_VAR)
+        if (deref_from_node(lhs)->type != HLSL_IR_DEREF_VAR)
         {
             FIXME("LHS expression not supported in compound assignments yet.\n");
             assign->rhs = rhs;




More information about the wine-cvs mailing list