[PATCH 1/3] d3dcompiler: Parse swizzles.
Matteo Bruni
mbruni at codeweavers.com
Mon Sep 17 08:32:04 CDT 2012
---
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;
--
1.7.8.6
More information about the wine-patches
mailing list