mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
vkd3d-shader/hlsl: Add initial support for parsing 'switch' statements.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
parent
ebb5aacabf
commit
ec8dfa467f
Notes:
Alexandre Julliard
2023-10-31 22:37:53 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Zebediah Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/361
@ -1343,6 +1343,40 @@ struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *cond
|
|||||||
return &iff->node;
|
return &iff->node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value,
|
||||||
|
bool is_default, struct hlsl_block *body, const struct vkd3d_shader_location *loc)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
if (!(c = hlsl_alloc(ctx, sizeof(*c))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
c->value = value;
|
||||||
|
c->is_default = is_default;
|
||||||
|
hlsl_block_init(&c->body);
|
||||||
|
if (body)
|
||||||
|
hlsl_block_add_block(&c->body, body);
|
||||||
|
c->loc = *loc;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *selector,
|
||||||
|
struct list *cases, const struct vkd3d_shader_location *loc)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s;
|
||||||
|
|
||||||
|
if (!(s = hlsl_alloc(ctx, sizeof(*s))))
|
||||||
|
return NULL;
|
||||||
|
init_node(&s->node, HLSL_IR_SWITCH, NULL, loc);
|
||||||
|
hlsl_src_from_node(&s->selector, selector);
|
||||||
|
list_init(&s->cases);
|
||||||
|
if (cases)
|
||||||
|
list_move_head(&s->cases, cases);
|
||||||
|
|
||||||
|
return &s->node;
|
||||||
|
}
|
||||||
|
|
||||||
struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
|
struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
|
||||||
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
|
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
|
||||||
{
|
{
|
||||||
@ -1805,6 +1839,58 @@ static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hlsl_free_ir_switch_case(struct hlsl_ir_switch_case *c)
|
||||||
|
{
|
||||||
|
hlsl_block_cleanup(&c->body);
|
||||||
|
list_remove(&c->entry);
|
||||||
|
vkd3d_free(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hlsl_cleanup_ir_switch_cases(struct list *cases)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c, *next;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(c, next, cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
hlsl_free_ir_switch_case(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct hlsl_ir_node *clone_switch(struct hlsl_ctx *ctx,
|
||||||
|
struct clone_instr_map *map, struct hlsl_ir_switch *s)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c, *d;
|
||||||
|
struct hlsl_ir_node *ret;
|
||||||
|
struct hlsl_block body;
|
||||||
|
struct list cases;
|
||||||
|
|
||||||
|
list_init(&cases);
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
if (!(clone_block(ctx, &body, &c->body, map)))
|
||||||
|
{
|
||||||
|
hlsl_cleanup_ir_switch_cases(&cases);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = hlsl_new_switch_case(ctx, c->value, c->is_default, &body, &c->loc);
|
||||||
|
hlsl_block_cleanup(&body);
|
||||||
|
if (!d)
|
||||||
|
{
|
||||||
|
hlsl_cleanup_ir_switch_cases(&cases);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&cases, &d->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hlsl_new_switch(ctx, map_instr(map, s->selector.node), &cases, &s->node.loc);
|
||||||
|
hlsl_cleanup_ir_switch_cases(&cases);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
|
static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
|
||||||
struct clone_instr_map *map, const struct hlsl_ir_node *instr)
|
struct clone_instr_map *map, const struct hlsl_ir_node *instr)
|
||||||
{
|
{
|
||||||
@ -1843,6 +1929,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
|
|||||||
case HLSL_IR_STORE:
|
case HLSL_IR_STORE:
|
||||||
return clone_store(ctx, map, hlsl_ir_store(instr));
|
return clone_store(ctx, map, hlsl_ir_store(instr));
|
||||||
|
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
|
return clone_switch(ctx, map, hlsl_ir_switch(instr));
|
||||||
|
|
||||||
case HLSL_IR_SWIZZLE:
|
case HLSL_IR_SWIZZLE:
|
||||||
return clone_swizzle(ctx, map, hlsl_ir_swizzle(instr));
|
return clone_swizzle(ctx, map, hlsl_ir_swizzle(instr));
|
||||||
}
|
}
|
||||||
@ -2261,6 +2350,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
|
|||||||
[HLSL_IR_RESOURCE_LOAD ] = "HLSL_IR_RESOURCE_LOAD",
|
[HLSL_IR_RESOURCE_LOAD ] = "HLSL_IR_RESOURCE_LOAD",
|
||||||
[HLSL_IR_RESOURCE_STORE] = "HLSL_IR_RESOURCE_STORE",
|
[HLSL_IR_RESOURCE_STORE] = "HLSL_IR_RESOURCE_STORE",
|
||||||
[HLSL_IR_STORE ] = "HLSL_IR_STORE",
|
[HLSL_IR_STORE ] = "HLSL_IR_STORE",
|
||||||
|
[HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH",
|
||||||
[HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE",
|
[HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2685,6 +2775,32 @@ static void dump_ir_index(struct vkd3d_string_buffer *buffer, const struct hlsl_
|
|||||||
vkd3d_string_buffer_printf(buffer, "]");
|
vkd3d_string_buffer_printf(buffer, "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_ir_switch(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_switch *s)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
vkd3d_string_buffer_printf(buffer, "switch (");
|
||||||
|
dump_src(buffer, &s->selector);
|
||||||
|
vkd3d_string_buffer_printf(buffer, ") {\n");
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
if (c->is_default)
|
||||||
|
{
|
||||||
|
vkd3d_string_buffer_printf(buffer, " %10s default: {\n", "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vkd3d_string_buffer_printf(buffer, " %10s case %u : {\n", "", c->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_block(ctx, buffer, &c->body);
|
||||||
|
vkd3d_string_buffer_printf(buffer, " %10s }\n", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
vkd3d_string_buffer_printf(buffer, " %10s }", "");
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_node *instr)
|
static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_node *instr)
|
||||||
{
|
{
|
||||||
if (instr->index)
|
if (instr->index)
|
||||||
@ -2740,6 +2856,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
|
|||||||
dump_ir_store(buffer, hlsl_ir_store(instr));
|
dump_ir_store(buffer, hlsl_ir_store(instr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
|
dump_ir_switch(ctx, buffer, hlsl_ir_switch(instr));
|
||||||
|
break;
|
||||||
|
|
||||||
case HLSL_IR_SWIZZLE:
|
case HLSL_IR_SWIZZLE:
|
||||||
dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr));
|
dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr));
|
||||||
break;
|
break;
|
||||||
@ -2900,6 +3020,14 @@ static void free_ir_swizzle(struct hlsl_ir_swizzle *swizzle)
|
|||||||
vkd3d_free(swizzle);
|
vkd3d_free(swizzle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_ir_switch(struct hlsl_ir_switch *s)
|
||||||
|
{
|
||||||
|
hlsl_src_remove(&s->selector);
|
||||||
|
hlsl_cleanup_ir_switch_cases(&s->cases);
|
||||||
|
|
||||||
|
vkd3d_free(s);
|
||||||
|
}
|
||||||
|
|
||||||
static void free_ir_index(struct hlsl_ir_index *index)
|
static void free_ir_index(struct hlsl_ir_index *index)
|
||||||
{
|
{
|
||||||
hlsl_src_remove(&index->val);
|
hlsl_src_remove(&index->val);
|
||||||
@ -2960,6 +3088,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
|
|||||||
case HLSL_IR_SWIZZLE:
|
case HLSL_IR_SWIZZLE:
|
||||||
free_ir_swizzle(hlsl_ir_swizzle(node));
|
free_ir_swizzle(hlsl_ir_swizzle(node));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
|
free_ir_switch(hlsl_ir_switch(node));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,6 +281,7 @@ enum hlsl_ir_node_type
|
|||||||
HLSL_IR_RESOURCE_STORE,
|
HLSL_IR_RESOURCE_STORE,
|
||||||
HLSL_IR_STORE,
|
HLSL_IR_STORE,
|
||||||
HLSL_IR_SWIZZLE,
|
HLSL_IR_SWIZZLE,
|
||||||
|
HLSL_IR_SWITCH,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Common data for every type of IR instruction node. */
|
/* Common data for every type of IR instruction node. */
|
||||||
@ -499,6 +500,22 @@ struct hlsl_ir_loop
|
|||||||
unsigned int next_index; /* liveness index of the end of the loop */
|
unsigned int next_index; /* liveness index of the end of the loop */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hlsl_ir_switch_case
|
||||||
|
{
|
||||||
|
unsigned int value;
|
||||||
|
bool is_default;
|
||||||
|
struct hlsl_block body;
|
||||||
|
struct list entry;
|
||||||
|
struct vkd3d_shader_location loc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hlsl_ir_switch
|
||||||
|
{
|
||||||
|
struct hlsl_ir_node node;
|
||||||
|
struct hlsl_src selector;
|
||||||
|
struct list cases;
|
||||||
|
};
|
||||||
|
|
||||||
enum hlsl_ir_expr_op
|
enum hlsl_ir_expr_op
|
||||||
{
|
{
|
||||||
HLSL_OP0_VOID,
|
HLSL_OP0_VOID,
|
||||||
@ -947,6 +964,12 @@ static inline struct hlsl_ir_index *hlsl_ir_index(const struct hlsl_ir_node *nod
|
|||||||
return CONTAINING_RECORD(node, struct hlsl_ir_index, node);
|
return CONTAINING_RECORD(node, struct hlsl_ir_index, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct hlsl_ir_switch *hlsl_ir_switch(const struct hlsl_ir_node *node)
|
||||||
|
{
|
||||||
|
assert(node->type == HLSL_IR_SWITCH);
|
||||||
|
return CONTAINING_RECORD(node, struct hlsl_ir_switch, node);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void hlsl_block_init(struct hlsl_block *block)
|
static inline void hlsl_block_init(struct hlsl_block *block)
|
||||||
{
|
{
|
||||||
list_init(&block->instrs);
|
list_init(&block->instrs);
|
||||||
@ -1120,6 +1143,9 @@ bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struc
|
|||||||
void hlsl_cleanup_deref(struct hlsl_deref *deref);
|
void hlsl_cleanup_deref(struct hlsl_deref *deref);
|
||||||
void hlsl_cleanup_semantic(struct hlsl_semantic *semantic);
|
void hlsl_cleanup_semantic(struct hlsl_semantic *semantic);
|
||||||
|
|
||||||
|
void hlsl_cleanup_ir_switch_cases(struct list *cases);
|
||||||
|
void hlsl_free_ir_switch_case(struct hlsl_ir_switch_case *c);
|
||||||
|
|
||||||
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
|
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
|
||||||
|
|
||||||
void hlsl_free_attribute(struct hlsl_attribute *attr);
|
void hlsl_free_attribute(struct hlsl_attribute *attr);
|
||||||
@ -1213,6 +1239,10 @@ struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr
|
|||||||
struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
|
struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
|
||||||
const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers,
|
const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers,
|
||||||
const struct hlsl_reg_reservation *reg_reservation);
|
const struct hlsl_reg_reservation *reg_reservation);
|
||||||
|
struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value, bool is_default,
|
||||||
|
struct hlsl_block *body, const struct vkd3d_shader_location *loc);
|
||||||
|
struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *selector,
|
||||||
|
struct list *cases, const struct vkd3d_shader_location *loc);
|
||||||
|
|
||||||
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
|
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
|
||||||
enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
|
enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
|
||||||
|
@ -46,7 +46,7 @@ static void update_location(struct hlsl_ctx *ctx, YYLTYPE *loc);
|
|||||||
|
|
||||||
%x pp pp_line pp_pragma pp_ignore
|
%x pp pp_line pp_pragma pp_ignore
|
||||||
|
|
||||||
RESERVED1 auto|case|catch|char|class|const_cast|default|delete|dynamic_cast|enum
|
RESERVED1 auto|catch|char|class|const_cast|delete|dynamic_cast|enum
|
||||||
RESERVED2 explicit|friend|goto|long|mutable|new|operator|private|protected|public
|
RESERVED2 explicit|friend|goto|long|mutable|new|operator|private|protected|public
|
||||||
RESERVED3 reinterpret_cast|short|signed|sizeof|static_cast|template|this|throw|try
|
RESERVED3 reinterpret_cast|short|signed|sizeof|static_cast|template|this|throw|try
|
||||||
RESERVED4 typename|union|unsigned|using|virtual
|
RESERVED4 typename|union|unsigned|using|virtual
|
||||||
@ -73,6 +73,7 @@ ANY (.)
|
|||||||
BlendState {return KW_BLENDSTATE; }
|
BlendState {return KW_BLENDSTATE; }
|
||||||
break {return KW_BREAK; }
|
break {return KW_BREAK; }
|
||||||
Buffer {return KW_BUFFER; }
|
Buffer {return KW_BUFFER; }
|
||||||
|
case {return KW_CASE; }
|
||||||
cbuffer {return KW_CBUFFER; }
|
cbuffer {return KW_CBUFFER; }
|
||||||
centroid {return KW_CENTROID; }
|
centroid {return KW_CENTROID; }
|
||||||
compile {return KW_COMPILE; }
|
compile {return KW_COMPILE; }
|
||||||
@ -80,6 +81,7 @@ const {return KW_CONST; }
|
|||||||
continue {return KW_CONTINUE; }
|
continue {return KW_CONTINUE; }
|
||||||
DepthStencilState {return KW_DEPTHSTENCILSTATE; }
|
DepthStencilState {return KW_DEPTHSTENCILSTATE; }
|
||||||
DepthStencilView {return KW_DEPTHSTENCILVIEW; }
|
DepthStencilView {return KW_DEPTHSTENCILVIEW; }
|
||||||
|
default {return KW_DEFAULT; }
|
||||||
discard {return KW_DISCARD; }
|
discard {return KW_DISCARD; }
|
||||||
do {return KW_DO; }
|
do {return KW_DO; }
|
||||||
double {return KW_DOUBLE; }
|
double {return KW_DOUBLE; }
|
||||||
|
@ -162,6 +162,12 @@ static void destroy_block(struct hlsl_block *block)
|
|||||||
vkd3d_free(block);
|
vkd3d_free(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destroy_switch_cases(struct list *cases)
|
||||||
|
{
|
||||||
|
hlsl_cleanup_ir_switch_cases(cases);
|
||||||
|
vkd3d_free(cases);
|
||||||
|
}
|
||||||
|
|
||||||
static bool hlsl_types_are_componentwise_compatible(struct hlsl_ctx *ctx, struct hlsl_type *src,
|
static bool hlsl_types_are_componentwise_compatible(struct hlsl_ctx *ctx, struct hlsl_type *src,
|
||||||
struct hlsl_type *dst)
|
struct hlsl_type *dst)
|
||||||
{
|
{
|
||||||
@ -1180,6 +1186,7 @@ static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, str
|
|||||||
case HLSL_IR_RESOURCE_LOAD:
|
case HLSL_IR_RESOURCE_LOAD:
|
||||||
case HLSL_IR_RESOURCE_STORE:
|
case HLSL_IR_RESOURCE_STORE:
|
||||||
case HLSL_IR_STORE:
|
case HLSL_IR_STORE:
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||||
"Expected literal expression.");
|
"Expected literal expression.");
|
||||||
}
|
}
|
||||||
@ -4679,17 +4686,20 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
|
|||||||
enum hlsl_sampler_dim sampler_dim;
|
enum hlsl_sampler_dim sampler_dim;
|
||||||
struct hlsl_attribute *attr;
|
struct hlsl_attribute *attr;
|
||||||
struct parse_attribute_list attr_list;
|
struct parse_attribute_list attr_list;
|
||||||
|
struct hlsl_ir_switch_case *switch_case;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token KW_BLENDSTATE
|
%token KW_BLENDSTATE
|
||||||
%token KW_BREAK
|
%token KW_BREAK
|
||||||
%token KW_BUFFER
|
%token KW_BUFFER
|
||||||
|
%token KW_CASE
|
||||||
%token KW_CBUFFER
|
%token KW_CBUFFER
|
||||||
%token KW_CENTROID
|
%token KW_CENTROID
|
||||||
%token KW_COLUMN_MAJOR
|
%token KW_COLUMN_MAJOR
|
||||||
%token KW_COMPILE
|
%token KW_COMPILE
|
||||||
%token KW_CONST
|
%token KW_CONST
|
||||||
%token KW_CONTINUE
|
%token KW_CONTINUE
|
||||||
|
%token KW_DEFAULT
|
||||||
%token KW_DEPTHSTENCILSTATE
|
%token KW_DEPTHSTENCILSTATE
|
||||||
%token KW_DEPTHSTENCILVIEW
|
%token KW_DEPTHSTENCILVIEW
|
||||||
%token KW_DISCARD
|
%token KW_DISCARD
|
||||||
@ -4796,6 +4806,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
|
|||||||
%type <list> type_specs
|
%type <list> type_specs
|
||||||
%type <list> variables_def
|
%type <list> variables_def
|
||||||
%type <list> variables_def_typed
|
%type <list> variables_def_typed
|
||||||
|
%type <list> switch_cases
|
||||||
|
|
||||||
%token <name> VAR_IDENTIFIER
|
%token <name> VAR_IDENTIFIER
|
||||||
%token <name> NEW_IDENTIFIER
|
%token <name> NEW_IDENTIFIER
|
||||||
@ -4838,6 +4849,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
|
|||||||
%type <block> statement
|
%type <block> statement
|
||||||
%type <block> statement_list
|
%type <block> statement_list
|
||||||
%type <block> struct_declaration_without_vars
|
%type <block> struct_declaration_without_vars
|
||||||
|
%type <block> switch_statement
|
||||||
%type <block> unary_expr
|
%type <block> unary_expr
|
||||||
|
|
||||||
%type <boolval> boolean
|
%type <boolval> boolean
|
||||||
@ -4876,6 +4888,8 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
|
|||||||
|
|
||||||
%type <semantic> semantic
|
%type <semantic> semantic
|
||||||
|
|
||||||
|
%type <switch_case> switch_case
|
||||||
|
|
||||||
%type <type> field_type
|
%type <type> field_type
|
||||||
%type <type> named_struct_spec
|
%type <type> named_struct_spec
|
||||||
%type <type> unnamed_struct_spec
|
%type <type> unnamed_struct_spec
|
||||||
@ -5357,6 +5371,11 @@ loop_scope_start:
|
|||||||
ctx->cur_scope->loop = true;
|
ctx->cur_scope->loop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch_scope_start:
|
||||||
|
%empty
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
var_identifier:
|
var_identifier:
|
||||||
VAR_IDENTIFIER
|
VAR_IDENTIFIER
|
||||||
| NEW_IDENTIFIER
|
| NEW_IDENTIFIER
|
||||||
@ -6185,6 +6204,7 @@ statement:
|
|||||||
| jump_statement
|
| jump_statement
|
||||||
| selection_statement
|
| selection_statement
|
||||||
| loop_statement
|
| loop_statement
|
||||||
|
| switch_statement
|
||||||
|
|
||||||
jump_statement:
|
jump_statement:
|
||||||
KW_BREAK ';'
|
KW_BREAK ';'
|
||||||
@ -6333,6 +6353,103 @@ loop_statement:
|
|||||||
hlsl_pop_scope(ctx);
|
hlsl_pop_scope(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch_statement:
|
||||||
|
attribute_list_optional switch_scope_start KW_SWITCH '(' expr ')' '{' switch_cases '}'
|
||||||
|
{
|
||||||
|
struct hlsl_ir_node *selector = node_from_block($5);
|
||||||
|
struct hlsl_ir_node *s;
|
||||||
|
|
||||||
|
if (!(selector = add_implicit_conversion(ctx, $5, selector, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &@5)))
|
||||||
|
{
|
||||||
|
destroy_switch_cases($8);
|
||||||
|
destroy_block($5);
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = hlsl_new_switch(ctx, selector, $8, &@3);
|
||||||
|
|
||||||
|
destroy_switch_cases($8);
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
destroy_block($5);
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
$$ = $5;
|
||||||
|
hlsl_block_add_instr($$, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_case:
|
||||||
|
KW_CASE expr ':' statement_list
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
value = evaluate_static_expression_as_uint(ctx, $2, &@2);
|
||||||
|
|
||||||
|
c = hlsl_new_switch_case(ctx, value, false, $4, &@2);
|
||||||
|
|
||||||
|
destroy_block($2);
|
||||||
|
destroy_block($4);
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
YYABORT;
|
||||||
|
$$ = c;
|
||||||
|
}
|
||||||
|
| KW_CASE expr ':'
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
value = evaluate_static_expression_as_uint(ctx, $2, &@2);
|
||||||
|
|
||||||
|
c = hlsl_new_switch_case(ctx, value, false, NULL, &@2);
|
||||||
|
|
||||||
|
destroy_block($2);
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
YYABORT;
|
||||||
|
$$ = c;
|
||||||
|
}
|
||||||
|
| KW_DEFAULT ':' statement_list
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
c = hlsl_new_switch_case(ctx, 0, true, $3, &@1);
|
||||||
|
|
||||||
|
destroy_block($3);
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
YYABORT;
|
||||||
|
$$ = c;
|
||||||
|
}
|
||||||
|
| KW_DEFAULT ':'
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
if (!(c = hlsl_new_switch_case(ctx, 0, true, NULL, &@1)))
|
||||||
|
YYABORT;
|
||||||
|
$$ = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_cases:
|
||||||
|
switch_case
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch_case *c = LIST_ENTRY($1, struct hlsl_ir_switch_case, entry);
|
||||||
|
if (!($$ = make_empty_list(ctx)))
|
||||||
|
{
|
||||||
|
hlsl_free_ir_switch_case(c);
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
list_add_head($$, &$1->entry);
|
||||||
|
}
|
||||||
|
| switch_cases switch_case
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
list_add_tail($$, &$2->entry);
|
||||||
|
}
|
||||||
|
|
||||||
expr_optional:
|
expr_optional:
|
||||||
%empty
|
%empty
|
||||||
{
|
{
|
||||||
|
@ -575,7 +575,19 @@ bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx,
|
|||||||
progress |= hlsl_transform_ir(ctx, func, &iff->else_block, context);
|
progress |= hlsl_transform_ir(ctx, func, &iff->else_block, context);
|
||||||
}
|
}
|
||||||
else if (instr->type == HLSL_IR_LOOP)
|
else if (instr->type == HLSL_IR_LOOP)
|
||||||
|
{
|
||||||
progress |= hlsl_transform_ir(ctx, func, &hlsl_ir_loop(instr)->body, context);
|
progress |= hlsl_transform_ir(ctx, func, &hlsl_ir_loop(instr)->body, context);
|
||||||
|
}
|
||||||
|
else if (instr->type == HLSL_IR_SWITCH)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
progress |= hlsl_transform_ir(ctx, func, &c->body, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progress |= func(ctx, instr, context);
|
progress |= func(ctx, instr, context);
|
||||||
}
|
}
|
||||||
@ -835,6 +847,30 @@ static bool lower_return(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (instr->type == HLSL_IR_SWITCH)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
has_early_return |= lower_return(ctx, func, &c->body, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_early_return)
|
||||||
|
{
|
||||||
|
if (in_loop)
|
||||||
|
{
|
||||||
|
/* For a 'switch' nested in a loop append a break after the 'switch'. */
|
||||||
|
insert_early_return_break(ctx, func, instr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cf_instr = instr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_instr)
|
if (return_instr)
|
||||||
@ -2929,6 +2965,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
|||||||
case HLSL_IR_JUMP:
|
case HLSL_IR_JUMP:
|
||||||
case HLSL_IR_LOOP:
|
case HLSL_IR_LOOP:
|
||||||
case HLSL_IR_RESOURCE_STORE:
|
case HLSL_IR_RESOURCE_STORE:
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2956,6 +2993,16 @@ static unsigned int index_instructions(struct hlsl_block *block, unsigned int in
|
|||||||
index = index_instructions(&hlsl_ir_loop(instr)->body, index);
|
index = index_instructions(&hlsl_ir_loop(instr)->body, index);
|
||||||
hlsl_ir_loop(instr)->next_index = index;
|
hlsl_ir_loop(instr)->next_index = index;
|
||||||
}
|
}
|
||||||
|
else if (instr->type == HLSL_IR_SWITCH)
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
index = index_instructions(&c->body, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
@ -3173,6 +3220,16 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
|
|||||||
jump->condition.node->last_read = last_read;
|
jump->condition.node->last_read = last_read;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
compute_liveness_recurse(&c->body, loop_first, loop_last);
|
||||||
|
s->selector.node->last_read = last_read;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case HLSL_IR_CONSTANT:
|
case HLSL_IR_CONSTANT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3524,6 +3581,18 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
allocate_temp_registers_recurse(ctx, &c->body, allocator);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3633,6 +3702,18 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case HLSL_IR_SWITCH:
|
||||||
|
{
|
||||||
|
struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
|
||||||
|
struct hlsl_ir_switch_case *c;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
|
||||||
|
{
|
||||||
|
allocate_const_registers_recurse(ctx, &c->body, allocator);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ float4 main() : sv_target
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
uint4 v;
|
uint4 v;
|
||||||
|
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
@ -246,7 +246,7 @@ float4 main() : sv_target
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
uint4 v;
|
uint4 v;
|
||||||
|
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
@ -262,7 +262,7 @@ float4 main() : sv_target
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pixel shader fail(sm<6)]
|
[pixel shader fail(sm<6) todo]
|
||||||
uint4 v;
|
uint4 v;
|
||||||
|
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
@ -279,7 +279,7 @@ float4 main() : sv_target
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pixel shader fail(sm<6)]
|
[pixel shader fail(sm<6) todo]
|
||||||
uint4 v;
|
uint4 v;
|
||||||
|
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
@ -296,7 +296,7 @@ float4 main() : sv_target
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pixel shader fail(sm<6)]
|
[pixel shader fail(sm<6) todo]
|
||||||
uint4 v;
|
uint4 v;
|
||||||
|
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
@ -455,7 +455,7 @@ todo draw quad
|
|||||||
probe all rgba (1.0, 2.0, 3.0, 4.0)
|
probe all rgba (1.0, 2.0, 3.0, 4.0)
|
||||||
|
|
||||||
% 'continue' is not supported in switches
|
% 'continue' is not supported in switches
|
||||||
[pixel shader fail(sm<6)]
|
[pixel shader fail(sm<6) todo]
|
||||||
uint4 v;
|
uint4 v;
|
||||||
|
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
|
Loading…
x
Reference in New Issue
Block a user