vkd3d-shader/hlsl: Apply copy propagation to swizzled loads.

This commit is contained in:
Zebediah Figura 2023-01-12 17:26:03 -06:00 committed by Alexandre Julliard
parent 18adf0d726
commit b7d34e8307
Notes: Alexandre Julliard 2023-01-24 22:27:58 +01: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/51
2 changed files with 52 additions and 22 deletions

View File

@ -556,6 +556,9 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, v
* store instructions, as long as the rhs is the same in every case. This basic * store instructions, as long as the rhs is the same in every case. This basic
* detection is implemented by copy_propagation_replace_with_single_instr(). * detection is implemented by copy_propagation_replace_with_single_instr().
* *
* In some cases, the load itself might not have a single source, but a
* subsequent swizzle might; hence we also try to replace swizzles of loads.
*
* We use the same infrastructure to implement a more specialized * We use the same infrastructure to implement a more specialized
* transformation. We recognize sequences of the form: * transformation. We recognize sequences of the form:
* *
@ -770,11 +773,11 @@ static void copy_propagation_set_value(struct copy_propagation_var_def *var_def,
} }
static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
const struct copy_propagation_state *state, struct hlsl_ir_load *load) const struct copy_propagation_state *state, const struct hlsl_deref *deref,
unsigned int swizzle, struct hlsl_ir_node *instr)
{ {
const struct hlsl_deref *deref = &load->src; const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type);
const struct hlsl_ir_var *var = deref->var; const struct hlsl_ir_var *var = deref->var;
struct hlsl_ir_node *instr = &load->node;
struct hlsl_ir_node *new_instr = NULL; struct hlsl_ir_node *new_instr = NULL;
unsigned int start, count, i; unsigned int start, count, i;
unsigned int ret_swizzle = 0; unsigned int ret_swizzle = 0;
@ -782,11 +785,11 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count)) if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count))
return false; return false;
for (i = 0; i < count; ++i) for (i = 0; i < instr_component_count; ++i)
{ {
struct copy_propagation_value *value = copy_propagation_get_value(state, var, start + i); struct copy_propagation_value *value;
if (!value) if (!(value = copy_propagation_get_value(state, var, start + hlsl_swizzle_get_component(swizzle, i))))
return false; return false;
if (!new_instr) if (!new_instr)
@ -795,14 +798,16 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
} }
else if (new_instr != value->node) else if (new_instr != value->node)
{ {
TRACE("No single source for propagating load from %s[%u-%u].\n", var->name, start, start + count); TRACE("No single source for propagating load from %s[%u-%u]%s\n",
var->name, start, start + count, debug_hlsl_swizzle(swizzle, instr_component_count));
return false; return false;
} }
ret_swizzle |= value->component << HLSL_SWIZZLE_SHIFT(i); ret_swizzle |= value->component << HLSL_SWIZZLE_SHIFT(i);
} }
TRACE("Load from %s[%u-%u] propagated as instruction %p%s.\n", TRACE("Load from %s[%u-%u]%s propagated as instruction %p%s.\n",
var->name, start, start + count, new_instr, debug_hlsl_swizzle(ret_swizzle, count)); var->name, start, start + count, debug_hlsl_swizzle(swizzle, instr_component_count),
new_instr, debug_hlsl_swizzle(ret_swizzle, instr_component_count));
if (instr->data_type->type != HLSL_CLASS_OBJECT) if (instr->data_type->type != HLSL_CLASS_OBJECT)
{ {
@ -819,22 +824,24 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
} }
static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx, static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx,
const struct copy_propagation_state *state, struct hlsl_ir_load *load) const struct copy_propagation_state *state, const struct hlsl_deref *deref,
unsigned int swizzle, struct hlsl_ir_node *instr)
{ {
const struct hlsl_ir_var *var = load->src.var; const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type);
const struct hlsl_ir_var *var = deref->var;
union hlsl_constant_value values[4] = {0}; union hlsl_constant_value values[4] = {0};
struct hlsl_ir_node *instr = &load->node;
struct hlsl_ir_constant *cons; struct hlsl_ir_constant *cons;
unsigned int start, count, i; unsigned int start, count, i;
if (!hlsl_component_index_range_from_deref(ctx, &load->src, &start, &count)) if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count))
return false; return false;
for (i = 0; i < count; ++i) for (i = 0; i < instr_component_count; ++i)
{ {
struct copy_propagation_value *value = copy_propagation_get_value(state, var, start + i); struct copy_propagation_value *value;
if (!value || value->node->type != HLSL_IR_CONSTANT) if (!(value = copy_propagation_get_value(state, var, start + hlsl_swizzle_get_component(swizzle, i)))
|| value->node->type != HLSL_IR_CONSTANT)
return false; return false;
values[i] = hlsl_ir_constant(value->node)->value[value->component]; values[i] = hlsl_ir_constant(value->node)->value[value->component];
@ -848,7 +855,8 @@ static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx,
cons->value[3] = values[3]; cons->value[3] = values[3];
list_add_before(&instr->entry, &cons->node.entry); list_add_before(&instr->entry, &cons->node.entry);
TRACE("Load from %s[%u-%u] turned into a constant %p.\n", var->name, start, start + count, cons); TRACE("Load from %s[%u-%u]%s turned into a constant %p.\n",
var->name, start, start + count, debug_hlsl_swizzle(swizzle, instr_component_count), cons);
hlsl_replace_node(instr, &cons->node); hlsl_replace_node(instr, &cons->node);
return true; return true;
@ -874,10 +882,28 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx,
return false; return false;
} }
if (copy_propagation_replace_with_constant_vector(ctx, state, load)) if (copy_propagation_replace_with_constant_vector(ctx, state, &load->src, HLSL_SWIZZLE(X, Y, Z, W), &load->node))
return true; return true;
if (copy_propagation_replace_with_single_instr(ctx, state, load)) if (copy_propagation_replace_with_single_instr(ctx, state, &load->src, HLSL_SWIZZLE(X, Y, Z, W), &load->node))
return true;
return false;
}
static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx,
struct hlsl_ir_swizzle *swizzle, struct copy_propagation_state *state)
{
struct hlsl_ir_load *load;
if (swizzle->val.node->type != HLSL_IR_LOAD)
return false;
load = hlsl_ir_load(swizzle->val.node);
if (copy_propagation_replace_with_constant_vector(ctx, state, &load->src, swizzle->swizzle, &swizzle->node))
return true;
if (copy_propagation_replace_with_single_instr(ctx, state, &load->src, swizzle->swizzle, &swizzle->node))
return true; return true;
return false; return false;
@ -1081,6 +1107,10 @@ static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_b
copy_propagation_record_store(ctx, hlsl_ir_store(instr), state); copy_propagation_record_store(ctx, hlsl_ir_store(instr), state);
break; break;
case HLSL_IR_SWIZZLE:
progress |= copy_propagation_transform_swizzle(ctx, hlsl_ir_swizzle(instr), state);
break;
case HLSL_IR_IF: case HLSL_IR_IF:
progress |= copy_propagation_process_if(ctx, hlsl_ir_if(instr), state); progress |= copy_propagation_process_if(ctx, hlsl_ir_if(instr), state);
break; break;

View File

@ -13,7 +13,7 @@ size (4, 4)
13 13 13 13 14 14 14 14 14 15 15 15 16 16 16 16 13 13 13 13 14 14 14 14 14 15 15 15 16 16 16 16
[pixel shader todo] [pixel shader]
Texture2D tex; Texture2D tex;
uniform int i; uniform int i;
@ -25,8 +25,8 @@ float4 main() : sv_target
[test] [test]
uniform 0 int 4 uniform 0 int 4
todo draw quad draw quad
todo probe all rgba (110, 210, 410, 410) probe all rgba (110, 210, 410, 410)
[pixel shader todo] [pixel shader todo]