From a99bcb1196355da500bfa6beaaad6b8a8706e718 Mon Sep 17 00:00:00 2001 From: Francisco Casas Date: Mon, 18 Mar 2024 21:57:36 -0300 Subject: [PATCH] vkd3d-shader/hlsl: Parse list of state blocks. --- libs/vkd3d-shader/hlsl.c | 23 ++++---- libs/vkd3d-shader/hlsl.h | 7 ++- libs/vkd3d-shader/hlsl.y | 66 ++++++++++++++++++++--- tests/hlsl/state-block-syntax.shader_test | 12 ++--- 4 files changed, 83 insertions(+), 25 deletions(-) diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 1ecb14d2..ed80e2b7 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -156,17 +156,17 @@ void hlsl_free_state_block(struct hlsl_state_block *state_block) void hlsl_free_var(struct hlsl_ir_var *decl) { - unsigned int k; + unsigned int k, i; 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) - { - hlsl_free_state_block(decl->state_block); - decl->state_block = NULL; - } + + for (i = 0; i < decl->state_block_count; ++i) + hlsl_free_state_block(decl->state_blocks[i]); + vkd3d_free(decl->state_blocks); + vkd3d_free(decl); } @@ -3740,11 +3740,12 @@ 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) - { - hlsl_free_state_block(var->state_block); - var->state_block = NULL; - } + for (i = 0; i < var->state_block_count; ++i) + hlsl_free_state_block(var->state_blocks[i]); + vkd3d_free(var->state_blocks); + var->state_blocks = NULL; + var->state_block_count = 0; + var->state_block_capacity = 0; } } diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index b6309ac4..4fa7fe1c 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -424,9 +424,12 @@ 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 dynamic array 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 hlsl_state_block **state_blocks; + unsigned int state_block_count; + size_t state_block_capacity; /* 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 diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 5acbc3a3..c52bd49e 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -78,7 +78,9 @@ struct parse_variable_def uint32_t modifiers; struct vkd3d_shader_location modifiers_loc; - struct hlsl_state_block *state_block; + struct hlsl_state_block **state_blocks; + unsigned int state_block_count; + size_t state_block_capacity; }; struct parse_function @@ -939,8 +941,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(!v->state_blocks); vkd3d_free(v); } @@ -2359,10 +2360,24 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var continue; } - var->state_block = v->state_block; - v->state_block = NULL; type = var->data_type; + var->state_blocks = v->state_blocks; + var->state_block_count = v->state_block_count; + var->state_block_capacity = v->state_block_capacity; + v->state_block_count = 0; + v->state_block_capacity = 0; + v->state_blocks = NULL; + + if (var->state_blocks && hlsl_type_component_count(type) != var->state_block_count) + { + hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Expected %u state blocks, but got %u.", + hlsl_type_component_count(type), var->state_block_count); + free_parse_variable_def(v); + continue; + } + if (v->initializer.args_count) { if (v->initializer.braces) @@ -5546,6 +5561,7 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %type type_no_void %type typedef_type +%type state_block_list %type type_spec %type variable_decl %type variable_def @@ -6729,6 +6745,27 @@ state_block: state_block_add_entry($$, entry); } +state_block_list: + '{' state_block '}' + { + if (!($$ = hlsl_alloc(ctx, sizeof(*$$)))) + YYABORT; + + if(!(vkd3d_array_reserve((void **)&$$->state_blocks, &$$->state_block_capacity, + $$->state_block_count + 1, sizeof(*$$->state_blocks)))) + YYABORT; + $$->state_blocks[$$->state_block_count++] = $2; + } + | state_block_list ',' '{' state_block '}' + { + $$ = $1; + + if(!(vkd3d_array_reserve((void **)&$$->state_blocks, &$$->state_block_capacity, + $$->state_block_count + 1, sizeof(*$$->state_blocks)))) + YYABORT; + $$->state_blocks[$$->state_block_count++] = $4; + } + variable_def: variable_decl | variable_decl '=' complex_initializer @@ -6739,8 +6776,25 @@ variable_def: | variable_decl '{' state_block_start state_block '}' { $$ = $1; - $$->state_block = $4; ctx->in_state_block = 0; + + if(!(vkd3d_array_reserve((void **)&$$->state_blocks, &$$->state_block_capacity, + $$->state_block_count + 1, sizeof(*$$->state_blocks)))) + YYABORT; + $$->state_blocks[$$->state_block_count++] = $4; + } + | variable_decl '{' state_block_start state_block_list '}' + { + $$ = $1; + ctx->in_state_block = 0; + + $$->state_blocks = $4->state_blocks; + $$->state_block_count = $4->state_block_count; + $$->state_block_capacity = $4->state_block_capacity; + $4->state_blocks = NULL; + $4->state_block_count = 0; + $4->state_block_capacity = 0; + free_parse_variable_def($4); } variable_def_typed: diff --git a/tests/hlsl/state-block-syntax.shader_test b/tests/hlsl/state-block-syntax.shader_test index 7521516b..5c2d6f9b 100644 --- a/tests/hlsl/state-block-syntax.shader_test +++ b/tests/hlsl/state-block-syntax.shader_test @@ -194,7 +194,7 @@ float4 main() : sv_target { return 0; } % State blocks can be empty -[pixel shader todo] +[pixel shader] sampler sams[2] { { @@ -207,7 +207,7 @@ float4 main() : sv_target { return 0; } % Multiple state blocks for array variables, as a list, are a thing. -[pixel shader todo] +[pixel shader] sampler sams[2] { { @@ -222,7 +222,7 @@ float4 main() : sv_target { return 0; } % Multiple state blocks for multi-component variables, as a list, are a thing. -[pixel shader todo] +[pixel shader] float2 val { { @@ -270,7 +270,7 @@ float2 arr[2] float4 main() : sv_target { return 0; } -[pixel shader todo] +[pixel shader] float3 arr[2] { { @@ -305,7 +305,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] { { @@ -359,7 +359,7 @@ sampler sams[1] float4 main() : sv_target { return 0; } -[pixel shader todo] +[pixel shader] sampler sam { {