vkd3d-shader/hlsl: Invalidate components more precisely in copy propagation.

Signed-off-by: Francisco Casas <fcasas@codeweavers.com>
This commit is contained in:
Francisco Casas 2022-07-20 17:42:13 -04:00 committed by Alexandre Julliard
parent b5b08bd8a0
commit 1bba18aa75
Notes: Alexandre Julliard 2022-10-18 00:13:00 +02:00
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/7
3 changed files with 69 additions and 12 deletions

View File

@ -140,6 +140,23 @@ unsigned int hlsl_type_major_size(const struct hlsl_type *type)
return type->dimx; return type->dimx;
} }
unsigned int hlsl_type_element_count(const struct hlsl_type *type)
{
switch (type->type)
{
case HLSL_CLASS_VECTOR:
return type->dimx;
case HLSL_CLASS_MATRIX:
return hlsl_type_major_size(type);
case HLSL_CLASS_ARRAY:
return type->e.array.elements_count;
case HLSL_CLASS_STRUCT:
return type->e.record.field_count;
default:
return 0;
}
}
static unsigned int get_array_size(const struct hlsl_type *type) static unsigned int get_array_size(const struct hlsl_type *type)
{ {
if (type->type == HLSL_CLASS_ARRAY) if (type->type == HLSL_CLASS_ARRAY)

View File

@ -814,6 +814,7 @@ struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl
bool hlsl_type_is_row_major(const struct hlsl_type *type); bool hlsl_type_is_row_major(const struct hlsl_type *type);
unsigned int hlsl_type_minor_size(const struct hlsl_type *type); unsigned int hlsl_type_minor_size(const struct hlsl_type *type);
unsigned int hlsl_type_major_size(const struct hlsl_type *type); unsigned int hlsl_type_major_size(const struct hlsl_type *type);
unsigned int hlsl_type_element_count(const struct hlsl_type *type);
unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset);
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2); bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);

View File

@ -606,15 +606,58 @@ static void copy_propagation_invalidate_variable(struct copy_propagation_var_def
} }
} }
static void copy_propagation_invalidate_whole_variable(struct copy_propagation_var_def *var_def) static void copy_propagation_invalidate_variable_from_deref_recurse(struct hlsl_ctx *ctx,
struct copy_propagation_var_def *var_def, const struct hlsl_deref *deref,
struct hlsl_type *type, unsigned int depth, unsigned int comp_start, unsigned char writemask)
{ {
unsigned int component_count = hlsl_type_component_count(var_def->var->data_type); unsigned int i, subtype_comp_count;
unsigned i; struct hlsl_ir_node *path_node;
struct hlsl_type *subtype;
TRACE("Invalidate variable %s.\n", var_def->var->name); if (depth == deref->path_len)
{
copy_propagation_invalidate_variable(var_def, comp_start, writemask);
return;
}
for (i = 0; i < component_count; ++i) path_node = deref->path[depth].node;
var_def->values[i].state = VALUE_STATE_DYNAMICALLY_WRITTEN; subtype = hlsl_get_element_type_from_path_index(ctx, type, path_node);
if (type->type == HLSL_CLASS_STRUCT)
{
unsigned int idx = hlsl_ir_constant(path_node)->value[0].u;
for (i = 0; i < idx; ++i)
comp_start += hlsl_type_component_count(type->e.record.fields[i].type);
copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, subtype,
depth + 1, comp_start, writemask);
}
else
{
subtype_comp_count = hlsl_type_component_count(subtype);
if (path_node->type == HLSL_IR_CONSTANT)
{
copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, subtype,
depth + 1, hlsl_ir_constant(path_node)->value[0].u * subtype_comp_count, writemask);
}
else
{
for (i = 0; i < hlsl_type_element_count(type); ++i)
{
copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, subtype,
depth + 1, i * subtype_comp_count, writemask);
}
}
}
}
static void copy_propagation_invalidate_variable_from_deref(struct hlsl_ctx *ctx,
struct copy_propagation_var_def *var_def, const struct hlsl_deref *deref, unsigned char writemask)
{
copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, deref->var->data_type,
0, 0, writemask);
} }
static void copy_propagation_set_value(struct copy_propagation_var_def *var_def, unsigned int comp, static void copy_propagation_set_value(struct copy_propagation_var_def *var_def, unsigned int comp,
@ -765,7 +808,7 @@ static void copy_propagation_record_store(struct hlsl_ctx *ctx, struct hlsl_ir_s
} }
else else
{ {
copy_propagation_invalidate_whole_variable(var_def); copy_propagation_invalidate_variable_from_deref(ctx, var_def, lhs, store->writemask);
} }
} }
@ -796,15 +839,11 @@ static void copy_propagation_invalidate_from_block(struct hlsl_ctx *ctx, struct
struct copy_propagation_var_def *var_def; struct copy_propagation_var_def *var_def;
struct hlsl_deref *lhs = &store->lhs; struct hlsl_deref *lhs = &store->lhs;
struct hlsl_ir_var *var = lhs->var; struct hlsl_ir_var *var = lhs->var;
unsigned int start, count;
if (!(var_def = copy_propagation_create_var_def(ctx, state, var))) if (!(var_def = copy_propagation_create_var_def(ctx, state, var)))
continue; continue;
if (hlsl_component_index_range_from_deref(ctx, lhs, &start, &count)) copy_propagation_invalidate_variable_from_deref(ctx, var_def, lhs, store->writemask);
copy_propagation_invalidate_variable(var_def, start, store->writemask);
else
copy_propagation_invalidate_whole_variable(var_def);
break; break;
} }