From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 18 ++++++++++++------ libs/vkd3d-shader/hlsl.h | 7 +++++-- libs/vkd3d-shader/hlsl.y | 32 ++++++++++++++++++++++++++------ tests/hlsl/fx-syntax.shader_test | 4 ++-- 4 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index ebeeedafd..84bb09aa0 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -156,17 +156,20 @@ void hlsl_free_state_block(struct hlsl_state_block *state_block)
void hlsl_free_var(struct hlsl_ir_var *decl) { + struct hlsl_state_block *state_block, *next_state_block; unsigned int k;
vkd3d_free((void *)decl->name); hlsl_cleanup_semantic(&decl->semantic); for (k = 0; k <= HLSL_REGSET_LAST_OBJECT; ++k) vkd3d_free((void *)decl->objects_usage[k]); - if (decl->state_block) + + LIST_FOR_EACH_ENTRY_SAFE(state_block, next_state_block, &decl->state_blocks, struct hlsl_state_block, entry) { - hlsl_free_state_block(decl->state_block); - decl->state_block = NULL; + hlsl_free_state_block(state_block); } + list_init(&decl->state_blocks); + vkd3d_free(decl); }
@@ -1122,6 +1125,8 @@ struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct } }
+ list_init(&var->state_blocks); + return var; }
@@ -3699,6 +3704,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil
static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) { + struct hlsl_state_block *state_block, *next_state_block; struct hlsl_buffer *buffer, *next_buffer; struct hlsl_scope *scope, *next_scope; struct hlsl_ir_var *var, *next_var; @@ -3720,11 +3726,11 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) { LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry) { - if (var->state_block) + LIST_FOR_EACH_ENTRY_SAFE(state_block, next_state_block, &var->state_blocks, struct hlsl_state_block, entry) { - hlsl_free_state_block(var->state_block); - var->state_block = NULL; + hlsl_free_state_block(state_block); } + list_init(&var->state_blocks); } }
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 97deb7440..5c5bf6531 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -424,9 +424,10 @@ struct hlsl_ir_var /* Scope that contains annotations for this variable. */ struct hlsl_scope *annotations;
- /* The state block on the variable's declaration, if any. + /* A list containing the state block on the variable's declaration, if any. + * An array variable may contain multiple state blocks. * These are only really used for effect profiles. */ - struct hlsl_state_block *state_block; + struct list state_blocks;
/* Indexes of the IR instructions where the variable is first written and last read (liveness * range). The IR instructions are numerated starting from 2, because 0 means unused, and 1 @@ -501,6 +502,8 @@ struct hlsl_state_block_entry
struct hlsl_state_block { + struct list entry; + struct hlsl_state_block_entry **entries; size_t count, capacity; }; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 015974fe1..5193440b2 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -78,7 +78,7 @@ struct parse_variable_def uint32_t modifiers; struct vkd3d_shader_location modifiers_loc;
- struct hlsl_state_block *state_block; + struct list state_blocks; };
struct parse_function @@ -927,8 +927,7 @@ static void free_parse_variable_def(struct parse_variable_def *v) vkd3d_free(v->arrays.sizes); vkd3d_free(v->name); hlsl_cleanup_semantic(&v->semantic); - if (v->state_block) - hlsl_free_state_block(v->state_block); + assert(list_empty(&v->state_blocks)); vkd3d_free(v); }
@@ -2355,8 +2354,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var continue; }
- var->state_block = v->state_block; - v->state_block = NULL; + list_move_tail(&var->state_blocks, &v->state_blocks); type = var->data_type;
if (v->initializer.args_count) @@ -5469,6 +5467,7 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %type <list> variables_def %type <list> variables_def_typed %type <list> switch_cases +%type <list> state_block_list
%token <name> VAR_IDENTIFIER %token <name> NEW_IDENTIFIER @@ -6639,6 +6638,7 @@ type_spec: $$->loc = @1; $$->name = $1; $$->arrays = $2; + list_init(&$$->state_blocks); }
declaration: @@ -6697,6 +6697,7 @@ variable_decl: $$->arrays = $2; $$->semantic = $3.semantic; $$->reg_reservation = $3.reg_reservation; + list_init(&$$->state_blocks); }
state_block_start: @@ -6754,6 +6755,19 @@ state_block: state_block_add_entry($$, entry); }
+state_block_list: + '{' state_block '}' + { + if (!($$ = make_empty_list(ctx))) + YYABORT; + list_add_tail($$, &$2->entry); + } + | state_block_list ',' '{' state_block '}' + { + $$ = $1; + list_add_tail($$, &$4->entry); + } + variable_def: variable_decl | variable_decl '=' complex_initializer @@ -6764,8 +6778,14 @@ variable_def: | variable_decl '{' state_block_start state_block '}' { $$ = $1; - $$->state_block = $4; ctx->in_state_block = 0; + list_add_tail(&$$->state_blocks, &$4->entry); + } + | variable_decl '{' state_block_start state_block_list '}' + { + $$ = $1; + ctx->in_state_block = 0; + list_move_tail(&$$->state_blocks, $4); }
variable_def_typed: diff --git a/tests/hlsl/fx-syntax.shader_test b/tests/hlsl/fx-syntax.shader_test index 821735f2a..5422d6133 100644 --- a/tests/hlsl/fx-syntax.shader_test +++ b/tests/hlsl/fx-syntax.shader_test @@ -23,7 +23,7 @@ float4 main() : sv_target { return 0; }
% Multiple state blocks for array variables are a thing. -[pixel shader todo] +[pixel shader] sampler sams[2] { { @@ -52,7 +52,7 @@ float4 main() : sv_target { return 0; }
% Multiple state blocks for multi-dimensional array variables are a thing. -[pixel shader todo] +[pixel shader] sampler sams[2][2] { {