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_DEREF,
|
||||||
HLSL_IR_EXPR,
|
HLSL_IR_EXPR,
|
||||||
HLSL_IR_FUNCTION_DECL,
|
HLSL_IR_FUNCTION_DECL,
|
||||||
|
HLSL_IR_SWIZZLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hlsl_ir_node
|
struct hlsl_ir_node
|
||||||
|
@ -834,6 +835,13 @@ struct hlsl_ir_expr
|
||||||
struct list *subexpressions;
|
struct list *subexpressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hlsl_ir_swizzle
|
||||||
|
{
|
||||||
|
struct hlsl_ir_node node;
|
||||||
|
struct hlsl_ir_node *val;
|
||||||
|
DWORD swizzle;
|
||||||
|
};
|
||||||
|
|
||||||
enum hlsl_ir_deref_type
|
enum hlsl_ir_deref_type
|
||||||
{
|
{
|
||||||
HLSL_IR_DEREF_VAR,
|
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);
|
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)
|
static inline struct hlsl_ir_constructor *constructor_from_node(const struct hlsl_ir_node *node)
|
||||||
{
|
{
|
||||||
assert(node->type == HLSL_IR_CONSTRUCTOR);
|
assert(node->type == HLSL_IR_CONSTRUCTOR);
|
||||||
|
|
|
@ -187,6 +187,103 @@ static unsigned int components_count_expr_list(struct list *list)
|
||||||
return count;
|
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
|
%locations
|
||||||
|
@ -944,6 +1041,31 @@ postfix_expr: primary_expr
|
||||||
set_location(&loc, &@2);
|
set_location(&loc, &@2);
|
||||||
$$ = &new_expr(HLSL_IR_BINOP_POSTDEC, operands, &loc)->node;
|
$$ = &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
|
/* "var_modifiers" doesn't make sense in this case, but it's needed
|
||||||
in the grammar to avoid shift/reduce conflicts. */
|
in the grammar to avoid shift/reduce conflicts. */
|
||||||
| var_modifiers type '(' initializer_expr_list ')'
|
| 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));
|
struct hlsl_ir_deref *lhs_deref = new_var_deref(var_from_node(lhs));
|
||||||
lhs = &lhs_deref->node;
|
lhs = &lhs_deref->node;
|
||||||
}
|
}
|
||||||
|
/* FIXME: check for invalid writemasks on the lhs. */
|
||||||
|
|
||||||
if (!compare_hlsl_types(type, rhs->data_type))
|
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(")");
|
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)
|
static void debug_dump_instr(const struct hlsl_ir_node *instr)
|
||||||
{
|
{
|
||||||
switch (instr->type)
|
switch (instr->type)
|
||||||
|
@ -1886,6 +1907,9 @@ static void debug_dump_instr(const struct hlsl_ir_node *instr)
|
||||||
case HLSL_IR_ASSIGNMENT:
|
case HLSL_IR_ASSIGNMENT:
|
||||||
debug_dump_ir_assignment(assignment_from_node(instr));
|
debug_dump_ir_assignment(assignment_from_node(instr));
|
||||||
break;
|
break;
|
||||||
|
case HLSL_IR_SWIZZLE:
|
||||||
|
debug_dump_ir_swizzle(swizzle_from_node(instr));
|
||||||
|
break;
|
||||||
case HLSL_IR_CONSTRUCTOR:
|
case HLSL_IR_CONSTRUCTOR:
|
||||||
debug_dump_ir_constructor(constructor_from_node(instr));
|
debug_dump_ir_constructor(constructor_from_node(instr));
|
||||||
break;
|
break;
|
||||||
|
@ -1993,6 +2017,12 @@ static void free_ir_deref(struct hlsl_ir_deref *deref)
|
||||||
d3dcompiler_free(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)
|
static void free_ir_constructor(struct hlsl_ir_constructor *constructor)
|
||||||
{
|
{
|
||||||
free_instr_list(constructor->arguments);
|
free_instr_list(constructor->arguments);
|
||||||
|
@ -2033,6 +2063,9 @@ void free_instr(struct hlsl_ir_node *node)
|
||||||
case HLSL_IR_DEREF:
|
case HLSL_IR_DEREF:
|
||||||
free_ir_deref(deref_from_node(node));
|
free_ir_deref(deref_from_node(node));
|
||||||
break;
|
break;
|
||||||
|
case HLSL_IR_SWIZZLE:
|
||||||
|
free_ir_swizzle(swizzle_from_node(node));
|
||||||
|
break;
|
||||||
case HLSL_IR_CONSTRUCTOR:
|
case HLSL_IR_CONSTRUCTOR:
|
||||||
free_ir_constructor(constructor_from_node(node));
|
free_ir_constructor(constructor_from_node(node));
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue