Matteo Bruni : d3dcompiler: Parse swizzles.

Alexandre Julliard julliard at winehq.org
Mon Sep 17 14:06:35 CDT 2012


Module: wine
Branch: master
Commit: 7cce71a0c3e35ee50cf0f05d6d30e8acb42cd34c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7cce71a0c3e35ee50cf0f05d6d30e8acb42cd34c

Author: Matteo Bruni <mbruni at codeweavers.com>
Date:   Mon Sep 17 15:32:04 2012 +0200

d3dcompiler: Parse swizzles.

---

 dlls/d3dcompiler_43/d3dcompiler_private.h |   14 ++++
 dlls/d3dcompiler_43/hlsl.y                |  122 +++++++++++++++++++++++++++++
 dlls/d3dcompiler_43/utils.c               |   33 ++++++++
 3 files changed, 169 insertions(+), 0 deletions(-)

diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h
index 05454f1..01c31ef 100644
--- a/dlls/d3dcompiler_43/d3dcompiler_private.h
+++ b/dlls/d3dcompiler_43/d3dcompiler_private.h
@@ -706,6 +706,7 @@ enum hlsl_ir_node_type
     HLSL_IR_DEREF,
     HLSL_IR_EXPR,
     HLSL_IR_FUNCTION_DECL,
+    HLSL_IR_SWIZZLE,
 };
 
 struct hlsl_ir_node
@@ -834,6 +835,13 @@ struct hlsl_ir_expr
     struct list *subexpressions;
 };
 
+struct hlsl_ir_swizzle
+{
+    struct hlsl_ir_node node;
+    struct hlsl_ir_node *val;
+    DWORD swizzle;
+};
+
 enum hlsl_ir_deref_type
 {
     HLSL_IR_DEREF_VAR,
@@ -999,6 +1007,12 @@ static inline struct hlsl_ir_assignment *assignment_from_node(const struct hlsl_
     return CONTAINING_RECORD(node, struct hlsl_ir_assignment, node);
 }
 
+static inline struct hlsl_ir_swizzle *swizzle_from_node(const struct hlsl_ir_node *node)
+{
+    assert(node->type == HLSL_IR_SWIZZLE);
+    return CONTAINING_RECORD(node, struct hlsl_ir_swizzle, node);
+}
+
 static inline struct hlsl_ir_constructor *constructor_from_node(const struct hlsl_ir_node *node)
 {
     assert(node->type == HLSL_IR_CONSTRUCTOR);
diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y
index c67ab54..c003754 100644
--- a/dlls/d3dcompiler_43/hlsl.y
+++ b/dlls/d3dcompiler_43/hlsl.y
@@ -187,6 +187,103 @@ static unsigned int components_count_expr_list(struct list *list)
     return count;
 }
 
+static struct hlsl_ir_swizzle *new_swizzle(DWORD s, unsigned int components,
+        struct hlsl_ir_node *val, struct source_location *loc)
+{
+    struct hlsl_ir_swizzle *swizzle = d3dcompiler_alloc(sizeof(*swizzle));
+
+    if (!swizzle)
+        return NULL;
+    swizzle->node.type = HLSL_IR_SWIZZLE;
+    swizzle->node.loc = *loc;
+    swizzle->node.data_type = new_hlsl_type(NULL, HLSL_CLASS_VECTOR, val->data_type->base_type, components, 1);
+    swizzle->val = val;
+    swizzle->swizzle = s;
+    return swizzle;
+}
+
+static struct hlsl_ir_swizzle *get_swizzle(struct hlsl_ir_node *value, const char *swizzle,
+        struct source_location *loc)
+{
+    unsigned int len = strlen(swizzle), component = 0;
+    unsigned int i, set, swiz = 0;
+    BOOL valid;
+
+    if (value->data_type->type == HLSL_CLASS_MATRIX)
+    {
+        /* Matrix swizzle */
+        BOOL m_swizzle;
+        unsigned int inc, x, y;
+
+        if (len < 3 || swizzle[0] != '_')
+            return NULL;
+        m_swizzle = swizzle[1] == 'm';
+        inc = m_swizzle ? 4 : 3;
+
+        if (len % inc || len > inc * 4)
+            return NULL;
+
+        for (i = 0; i < len; i += inc)
+        {
+            if (swizzle[i] != '_')
+                return NULL;
+            if (m_swizzle)
+            {
+                if (swizzle[i + 1] != 'm')
+                    return NULL;
+                x = swizzle[i + 2] - '0';
+                y = swizzle[i + 3] - '0';
+            }
+            else
+            {
+                x = swizzle[i + 1] - '1';
+                y = swizzle[i + 2] - '1';
+            }
+
+            if (x >= value->data_type->dimx || y >= value->data_type->dimy)
+                return NULL;
+            swiz |= (y << 4 | x) << component * 8;
+            component++;
+        }
+        return new_swizzle(swiz, component, value, loc);
+    }
+
+    /* Vector swizzle */
+    if (len > 4)
+        return NULL;
+
+    for (set = 0; set < 2; ++set)
+    {
+        valid = TRUE;
+        component = 0;
+        for (i = 0; i < len; ++i)
+        {
+            char c[2][4] = {{'x', 'y', 'z', 'w'}, {'r', 'g', 'b', 'a'}};
+            unsigned int s = 0;
+
+            for (s = 0; s < 4; ++s)
+            {
+                if (swizzle[i] == c[set][s])
+                    break;
+            }
+            if (s == 4)
+            {
+                valid = FALSE;
+                break;
+            }
+
+            if (s >= value->data_type->dimx)
+                return NULL;
+            swiz |= s << component * 2;
+            component++;
+        }
+        if (valid)
+            return new_swizzle(swiz, component, value, loc);
+    }
+
+    return NULL;
+}
+
 %}
 
 %locations
@@ -944,6 +1041,31 @@ postfix_expr:             primary_expr
                                 set_location(&loc, &@2);
                                 $$ = &new_expr(HLSL_IR_BINOP_POSTDEC, operands, &loc)->node;
                             }
+                        | postfix_expr '.' any_identifier
+                            {
+                                struct source_location loc;
+
+                                set_location(&loc, &@2);
+                                if ($1->data_type->type <= HLSL_CLASS_LAST_NUMERIC)
+                                {
+                                    struct hlsl_ir_swizzle *swizzle;
+
+                                    swizzle = get_swizzle($1, $3, &loc);
+                                    if (!swizzle)
+                                    {
+                                        hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
+                                                "invalid swizzle %s", debugstr_a($3));
+                                        return 1;
+                                    }
+                                    $$ = &swizzle->node;
+                                }
+                                else
+                                {
+                                    hlsl_report_message(loc.file, loc.line, loc.col, HLSL_LEVEL_ERROR,
+                                            "invalid subscript %s", debugstr_a($3));
+                                    return 1;
+                                }
+                            }
                           /* "var_modifiers" doesn't make sense in this case, but it's needed
                              in the grammar to avoid shift/reduce conflicts. */
                         | var_modifiers type '(' initializer_expr_list ')'
diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c
index 242f5fb..c416060 100644
--- a/dlls/d3dcompiler_43/utils.c
+++ b/dlls/d3dcompiler_43/utils.c
@@ -1457,6 +1457,7 @@ struct hlsl_ir_node *make_assignment(struct hlsl_ir_node *left, enum parse_assig
         struct hlsl_ir_deref *lhs_deref = new_var_deref(var_from_node(lhs));
         lhs = &lhs_deref->node;
     }
+    /* FIXME: check for invalid writemasks on the lhs. */
 
     if (!compare_hlsl_types(type, rhs->data_type))
     {
@@ -1870,6 +1871,26 @@ static void debug_dump_ir_assignment(const struct hlsl_ir_assignment *assign)
     TRACE(")");
 }
 
+static void debug_dump_ir_swizzle(const struct hlsl_ir_swizzle *swizzle)
+{
+    unsigned int i;
+
+    debug_dump_instr(swizzle->val);
+    TRACE(".");
+    if (swizzle->val->data_type->dimy > 1)
+    {
+        for (i = 0; i < swizzle->node.data_type->dimx; ++i)
+            TRACE("_m%u%u", (swizzle->swizzle >> i * 8) & 0xf, (swizzle->swizzle >> (i * 8 + 4)) & 0xf);
+    }
+    else
+    {
+        char c[] = {'x', 'y', 'z', 'w'};
+
+        for (i = 0; i < swizzle->node.data_type->dimx; ++i)
+            TRACE("%c", c[(swizzle->swizzle >> i * 2) & 0x3]);
+    }
+}
+
 static void debug_dump_instr(const struct hlsl_ir_node *instr)
 {
     switch (instr->type)
@@ -1886,6 +1907,9 @@ static void debug_dump_instr(const struct hlsl_ir_node *instr)
         case HLSL_IR_ASSIGNMENT:
             debug_dump_ir_assignment(assignment_from_node(instr));
             break;
+        case HLSL_IR_SWIZZLE:
+            debug_dump_ir_swizzle(swizzle_from_node(instr));
+            break;
         case HLSL_IR_CONSTRUCTOR:
             debug_dump_ir_constructor(constructor_from_node(instr));
             break;
@@ -1993,6 +2017,12 @@ static void free_ir_deref(struct hlsl_ir_deref *deref)
     d3dcompiler_free(deref);
 }
 
+static void free_ir_swizzle(struct hlsl_ir_swizzle *swizzle)
+{
+    free_instr(swizzle->val);
+    d3dcompiler_free(swizzle);
+}
+
 static void free_ir_constructor(struct hlsl_ir_constructor *constructor)
 {
     free_instr_list(constructor->arguments);
@@ -2033,6 +2063,9 @@ void free_instr(struct hlsl_ir_node *node)
         case HLSL_IR_DEREF:
             free_ir_deref(deref_from_node(node));
             break;
+        case HLSL_IR_SWIZZLE:
+            free_ir_swizzle(swizzle_from_node(node));
+            break;
         case HLSL_IR_CONSTRUCTOR:
             free_ir_constructor(constructor_from_node(node));
             break;




More information about the wine-cvs mailing list