From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 32 +++++++++++++++++++++++++++ libs/vkd3d-shader/hlsl.h | 16 ++++++++++++++ libs/vkd3d-shader/hlsl.y | 47 ++++++++++++++++++++++++++++++++++------ 3 files changed, 88 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 3d068ac6d..8a4b9a4ef 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -134,6 +134,19 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) return hlsl_get_var(scope->upper, name); }
+void hlsl_free_state_block(struct hlsl_state_block *sblock) +{ + unsigned int k; + + assert(sblock); + for (k = 0; k < sblock->count; ++k) + { + hlsl_block_cleanup(sblock->entries[k].rhs_instrs); + vkd3d_free(sblock->entries[k].rhs_instrs); + } + vkd3d_free(sblock); +} + void hlsl_free_var(struct hlsl_ir_var *decl) { unsigned int k; @@ -142,6 +155,11 @@ void hlsl_free_var(struct hlsl_ir_var *decl) 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; + } vkd3d_free(decl); }
@@ -3591,6 +3609,20 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx)
rb_destroy(&ctx->functions, free_function_rb, NULL);
+ /* State blocks must be free before the variables, because they contain instructions that may + * refer to them. */ + LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &ctx->scopes, struct hlsl_scope, entry) + { + 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; + } + } + } + LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &ctx->scopes, struct hlsl_scope, entry) { LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry) diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 43bc079db..d46675e70 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -413,6 +413,9 @@ struct hlsl_ir_var /* Scope that contains annotations for this variable. */ struct hlsl_scope *annotations;
+ /* The state_block on the variable's declaration, if it has one. */ + struct hlsl_state_block *state_block; + /* 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 * means function entry. */ @@ -448,6 +451,18 @@ struct hlsl_ir_var uint32_t is_separated_resource : 1; };
+struct hlsl_state_block_entry +{ + char *lhs_name; + struct hlsl_block *rhs_instrs; +}; + +struct hlsl_state_block +{ + struct hlsl_state_block_entry *entries; + size_t count, capacity; +}; + /* Sized array of variables representing a function's parameters. */ struct hlsl_func_parameters { @@ -1188,6 +1203,7 @@ 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_instr(struct hlsl_ir_node *node); void hlsl_free_instr_list(struct list *list); +void hlsl_free_state_block(struct hlsl_state_block *sblock); void hlsl_free_type(struct hlsl_type *type); void hlsl_free_var(struct hlsl_ir_var *decl);
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 37a372893..d88de8a6a 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -77,6 +77,8 @@ struct parse_variable_def struct hlsl_type *basic_type; uint32_t modifiers; struct vkd3d_shader_location modifiers_loc; + + struct hlsl_state_block *state_block; };
struct parse_function @@ -925,6 +927,8 @@ 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); vkd3d_free(v); }
@@ -2343,6 +2347,9 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var free_parse_variable_def(v); continue; } + + var->state_block = v->state_block; + v->state_block = NULL; type = var->data_type;
if (v->initializer.args_count) @@ -5047,6 +5054,16 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, hlsl_release_string_buffer(ctx, string); }
+static bool state_block_add_entry(struct hlsl_state_block *stateb, struct hlsl_state_block_entry entry) +{ + if (!vkd3d_array_reserve((void **)&stateb->entries, &stateb->capacity, stateb->count + 1, + sizeof(*stateb->entries))) + return false; + + stateb->entries[stateb->count++] = entry; + return true; +} + }
%locations @@ -5087,6 +5104,8 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct parse_attribute_list attr_list; struct hlsl_ir_switch_case *switch_case; struct hlsl_scope *scope; + struct hlsl_state_block *state_block; + struct hlsl_state_block_entry state_block_entry; }
%token KW_BLENDSTATE @@ -5312,6 +5331,9 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %type <variable_def> variable_def %type <variable_def> variable_def_typed
+%type <state_block_entry> state +%type <state_block> state_block + %%
hlsl_prog: @@ -6427,20 +6449,29 @@ variable_decl:
state: any_identifier '=' expr ';' - { - vkd3d_free($1); - destroy_block($3); - } + { + $$.lhs_name = $1; + $$.rhs_instrs = $3; + }
state_block_start: %empty - { - ctx->in_state_block = 1; - } + { + ctx->in_state_block = 1; + hlsl_push_scope(ctx); + }
state_block: %empty + { + if (!($$ = hlsl_alloc(ctx, sizeof(*$$)))) + YYABORT; + } | state_block state + { + $$ = $1; + state_block_add_entry($$, $2); + }
variable_def: variable_decl @@ -6452,7 +6483,9 @@ variable_def: | variable_decl '{' state_block_start state_block '}' { $$ = $1; + $$->state_block = $4; ctx->in_state_block = 0; + hlsl_pop_scope(ctx); }
variable_def_typed: