d3dcompiler: Parse swizzles.
This commit is contained in:
parent
e603ffd19e
commit
7cce71a0c3
|
@ -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);
|
||||
|
|
|
@ -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 ')'
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue