From: Francisco Casas fcasas@codeweavers.com
--- 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 730eecba7..757c52085 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); }
@@ -3726,11 +3726,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 b79c754c9..e8acc7552 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -423,9 +423,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 1dc7d5d34..d0f74ceea 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); }
@@ -2367,10 +2368,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) @@ -5581,6 +5596,7 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %type <type> type_no_void %type <type> typedef_type
+%type <variable_def> state_block_list %type <variable_def> type_spec %type <variable_def> variable_decl %type <variable_def> variable_def @@ -6764,6 +6780,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 @@ -6774,8 +6811,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 7521516b9..5c2d6f9b7 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 { {