mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader/hlsl: Parse and store state blocks on variables.
This commit is contained in:
parent
73ef6907bc
commit
ee0d439a1b
Notes:
Alexandre Julliard
2024-04-11 17:02:42 -05: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/739
@ -134,6 +134,26 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name)
|
|||||||
return hlsl_get_var(scope->upper, name);
|
return hlsl_get_var(scope->upper, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_state_block_entry(struct hlsl_state_block_entry *entry)
|
||||||
|
{
|
||||||
|
vkd3d_free(entry->name);
|
||||||
|
vkd3d_free(entry->args);
|
||||||
|
hlsl_block_cleanup(entry->instrs);
|
||||||
|
vkd3d_free(entry->instrs);
|
||||||
|
vkd3d_free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hlsl_free_state_block(struct hlsl_state_block *state_block)
|
||||||
|
{
|
||||||
|
unsigned int k;
|
||||||
|
|
||||||
|
assert(state_block);
|
||||||
|
for (k = 0; k < state_block->count; ++k)
|
||||||
|
free_state_block_entry(state_block->entries[k]);
|
||||||
|
vkd3d_free(state_block->entries);
|
||||||
|
vkd3d_free(state_block);
|
||||||
|
}
|
||||||
|
|
||||||
void hlsl_free_var(struct hlsl_ir_var *decl)
|
void hlsl_free_var(struct hlsl_ir_var *decl)
|
||||||
{
|
{
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
@ -142,6 +162,11 @@ void hlsl_free_var(struct hlsl_ir_var *decl)
|
|||||||
hlsl_cleanup_semantic(&decl->semantic);
|
hlsl_cleanup_semantic(&decl->semantic);
|
||||||
for (k = 0; k <= HLSL_REGSET_LAST_OBJECT; ++k)
|
for (k = 0; k <= HLSL_REGSET_LAST_OBJECT; ++k)
|
||||||
vkd3d_free((void *)decl->objects_usage[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);
|
vkd3d_free(decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3659,6 +3684,20 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx)
|
|||||||
|
|
||||||
rb_destroy(&ctx->functions, free_function_rb, NULL);
|
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(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)
|
LIST_FOR_EACH_ENTRY_SAFE(var, next_var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||||||
|
@ -423,6 +423,10 @@ struct hlsl_ir_var
|
|||||||
/* Scope that contains annotations for this variable. */
|
/* Scope that contains annotations for this variable. */
|
||||||
struct hlsl_scope *annotations;
|
struct hlsl_scope *annotations;
|
||||||
|
|
||||||
|
/* The state block on the variable's declaration, if any.
|
||||||
|
* These are only really used for effect profiles. */
|
||||||
|
struct hlsl_state_block *state_block;
|
||||||
|
|
||||||
/* Indexes of the IR instructions where the variable is first written and last read (liveness
|
/* 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
|
* range). The IR instructions are numerated starting from 2, because 0 means unused, and 1
|
||||||
* means function entry. */
|
* means function entry. */
|
||||||
@ -458,6 +462,38 @@ struct hlsl_ir_var
|
|||||||
uint32_t is_separated_resource : 1;
|
uint32_t is_separated_resource : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This struct is used to represent assignments in state block entries:
|
||||||
|
* name = {args[0], args[1], ...};
|
||||||
|
* - or -
|
||||||
|
* name = args[0]
|
||||||
|
* - or -
|
||||||
|
* name[lhs_index] = args[0]
|
||||||
|
* - or -
|
||||||
|
* name[lhs_index] = {args[0], args[1], ...};
|
||||||
|
*/
|
||||||
|
struct hlsl_state_block_entry
|
||||||
|
{
|
||||||
|
/* For assignments, the name in the lhs. */
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* Whether the lhs in the assignment is indexed and, in that case, its index. */
|
||||||
|
bool lhs_has_index;
|
||||||
|
unsigned int lhs_index;
|
||||||
|
|
||||||
|
/* Instructions present in the rhs. */
|
||||||
|
struct hlsl_block *instrs;
|
||||||
|
|
||||||
|
/* For assignments, arguments of the rhs initializer. */
|
||||||
|
struct hlsl_ir_node **args;
|
||||||
|
unsigned int args_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hlsl_state_block
|
||||||
|
{
|
||||||
|
struct hlsl_state_block_entry **entries;
|
||||||
|
size_t count, capacity;
|
||||||
|
};
|
||||||
|
|
||||||
/* Sized array of variables representing a function's parameters. */
|
/* Sized array of variables representing a function's parameters. */
|
||||||
struct hlsl_func_parameters
|
struct hlsl_func_parameters
|
||||||
{
|
{
|
||||||
@ -1216,6 +1252,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_attribute(struct hlsl_attribute *attr);
|
||||||
void hlsl_free_instr(struct hlsl_ir_node *node);
|
void hlsl_free_instr(struct hlsl_ir_node *node);
|
||||||
void hlsl_free_instr_list(struct list *list);
|
void hlsl_free_instr_list(struct list *list);
|
||||||
|
void hlsl_free_state_block(struct hlsl_state_block *state_block);
|
||||||
void hlsl_free_type(struct hlsl_type *type);
|
void hlsl_free_type(struct hlsl_type *type);
|
||||||
void hlsl_free_var(struct hlsl_ir_var *decl);
|
void hlsl_free_var(struct hlsl_ir_var *decl);
|
||||||
|
|
||||||
|
@ -77,6 +77,8 @@ struct parse_variable_def
|
|||||||
struct hlsl_type *basic_type;
|
struct hlsl_type *basic_type;
|
||||||
uint32_t modifiers;
|
uint32_t modifiers;
|
||||||
struct vkd3d_shader_location modifiers_loc;
|
struct vkd3d_shader_location modifiers_loc;
|
||||||
|
|
||||||
|
struct hlsl_state_block *state_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct parse_function
|
struct parse_function
|
||||||
@ -114,6 +116,12 @@ struct parse_attribute_list
|
|||||||
const struct hlsl_attribute **attrs;
|
const struct hlsl_attribute **attrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct state_block_index
|
||||||
|
{
|
||||||
|
bool has_index;
|
||||||
|
unsigned int index;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
%code provides
|
%code provides
|
||||||
@ -931,6 +939,8 @@ static void free_parse_variable_def(struct parse_variable_def *v)
|
|||||||
vkd3d_free(v->arrays.sizes);
|
vkd3d_free(v->arrays.sizes);
|
||||||
vkd3d_free(v->name);
|
vkd3d_free(v->name);
|
||||||
hlsl_cleanup_semantic(&v->semantic);
|
hlsl_cleanup_semantic(&v->semantic);
|
||||||
|
if (v->state_block)
|
||||||
|
hlsl_free_state_block(v->state_block);
|
||||||
vkd3d_free(v);
|
vkd3d_free(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2347,6 +2357,9 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
|
|||||||
free_parse_variable_def(v);
|
free_parse_variable_def(v);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var->state_block = v->state_block;
|
||||||
|
v->state_block = NULL;
|
||||||
type = var->data_type;
|
type = var->data_type;
|
||||||
|
|
||||||
if (v->initializer.args_count)
|
if (v->initializer.args_count)
|
||||||
@ -5252,6 +5265,16 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|||||||
hlsl_release_string_buffer(ctx, string);
|
hlsl_release_string_buffer(ctx, string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool state_block_add_entry(struct hlsl_state_block *state_block, struct hlsl_state_block_entry *entry)
|
||||||
|
{
|
||||||
|
if (!vkd3d_array_reserve((void **)&state_block->entries, &state_block->capacity, state_block->count + 1,
|
||||||
|
sizeof(*state_block->entries)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
state_block->entries[state_block->count++] = entry;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
%locations
|
%locations
|
||||||
@ -5292,6 +5315,8 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|||||||
struct parse_attribute_list attr_list;
|
struct parse_attribute_list attr_list;
|
||||||
struct hlsl_ir_switch_case *switch_case;
|
struct hlsl_ir_switch_case *switch_case;
|
||||||
struct hlsl_scope *scope;
|
struct hlsl_scope *scope;
|
||||||
|
struct hlsl_state_block *state_block;
|
||||||
|
struct state_block_index state_block_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
%token KW_BLENDSTATE
|
%token KW_BLENDSTATE
|
||||||
@ -5493,6 +5518,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|||||||
%type <name> var_identifier
|
%type <name> var_identifier
|
||||||
%type <name> name_opt
|
%type <name> name_opt
|
||||||
|
|
||||||
|
|
||||||
%type <parameter> parameter
|
%type <parameter> parameter
|
||||||
|
|
||||||
%type <parameters> param_list
|
%type <parameters> param_list
|
||||||
@ -5505,6 +5531,10 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim,
|
|||||||
|
|
||||||
%type <semantic> semantic
|
%type <semantic> semantic
|
||||||
|
|
||||||
|
%type <state_block> state_block
|
||||||
|
|
||||||
|
%type <state_block_index> state_block_index_opt
|
||||||
|
|
||||||
%type <switch_case> switch_case
|
%type <switch_case> switch_case
|
||||||
|
|
||||||
%type <type> field_type
|
%type <type> field_type
|
||||||
@ -6649,22 +6679,54 @@ variable_decl:
|
|||||||
$$->reg_reservation = $3.reg_reservation;
|
$$->reg_reservation = $3.reg_reservation;
|
||||||
}
|
}
|
||||||
|
|
||||||
state:
|
|
||||||
any_identifier '=' expr ';'
|
|
||||||
{
|
|
||||||
vkd3d_free($1);
|
|
||||||
destroy_block($3);
|
|
||||||
}
|
|
||||||
|
|
||||||
state_block_start:
|
state_block_start:
|
||||||
%empty
|
%empty
|
||||||
{
|
{
|
||||||
ctx->in_state_block = 1;
|
ctx->in_state_block = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state_block_index_opt:
|
||||||
|
%empty
|
||||||
|
{
|
||||||
|
$$.has_index = false;
|
||||||
|
$$.index = 0;
|
||||||
|
}
|
||||||
|
| '[' C_INTEGER ']'
|
||||||
|
{
|
||||||
|
if ($2 < 0)
|
||||||
|
{
|
||||||
|
hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX,
|
||||||
|
"State block array index is not a positive integer constant.");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
$$.has_index = true;
|
||||||
|
$$.index = $2;
|
||||||
|
}
|
||||||
|
|
||||||
state_block:
|
state_block:
|
||||||
%empty
|
%empty
|
||||||
| state_block state
|
{
|
||||||
|
if (!($$ = hlsl_alloc(ctx, sizeof(*$$))))
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
| state_block any_identifier state_block_index_opt '=' complex_initializer ';'
|
||||||
|
{
|
||||||
|
struct hlsl_state_block_entry *entry;
|
||||||
|
|
||||||
|
if (!(entry = hlsl_alloc(ctx, sizeof(*entry))))
|
||||||
|
YYABORT;
|
||||||
|
|
||||||
|
entry->name = $2;
|
||||||
|
entry->lhs_has_index = $3.has_index;
|
||||||
|
entry->lhs_index = $3.index;
|
||||||
|
|
||||||
|
entry->instrs = $5.instrs;
|
||||||
|
entry->args = $5.args;
|
||||||
|
entry->args_count = $5.args_count;
|
||||||
|
|
||||||
|
$$ = $1;
|
||||||
|
state_block_add_entry($$, entry);
|
||||||
|
}
|
||||||
|
|
||||||
variable_def:
|
variable_def:
|
||||||
variable_decl
|
variable_decl
|
||||||
@ -6676,6 +6738,7 @@ variable_def:
|
|||||||
| variable_decl '{' state_block_start state_block '}'
|
| variable_decl '{' state_block_start state_block '}'
|
||||||
{
|
{
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
$$->state_block = $4;
|
||||||
ctx->in_state_block = 0;
|
ctx->in_state_block = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +380,7 @@ float4 main() : sv_target { return 0; }
|
|||||||
|
|
||||||
|
|
||||||
% State block entries may have indexes.
|
% State block entries may have indexes.
|
||||||
[pixel shader todo]
|
[pixel shader]
|
||||||
sampler sam
|
sampler sam
|
||||||
{
|
{
|
||||||
dogs[3] = 5;
|
dogs[3] = 5;
|
||||||
|
Loading…
Reference in New Issue
Block a user