From: Francisco Casas fcasas@codeweavers.com
Allows to replace load+swizzle instruction pairs with direct references to the value source, requiring only the components that appear in the swizzle to originate from the same source.
For instance, this shader:
uniform float4 f;
float4 main() : sv_target { float4 g = f; g.yz = float2(2, 3); return g.xwxw; }
results in a swizzle that directly references the uniform f:
float4 | f | return float4 | @2.xwxw | = (<output-sv_target0> @4) --- libs/vkd3d-shader/hlsl_codegen.c | 56 +++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 15 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index fdd25c93..7965da7a 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -683,20 +683,28 @@ static void copy_propagation_set_value(struct copy_propagation_var_def *var_def,
static struct hlsl_ir_node *copy_propagation_compute_replacement(struct hlsl_ctx *ctx, const struct copy_propagation_state *state, const struct hlsl_deref *deref, - unsigned int *swizzle) + const struct hlsl_ir_swizzle *swizzle, unsigned int *out_swizzle) { const struct hlsl_ir_var *var = deref->var; + unsigned int start, count, comps, i; struct hlsl_ir_node *instr = NULL; - unsigned int start, count, i;
if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count)) return NULL;
- *swizzle = 0; + *out_swizzle = 0;
- for (i = 0; i < count; ++i) + comps = swizzle ? swizzle->node.data_type->dimx : count; + for (i = 0; i < comps; ++i) { - struct copy_propagation_value *value = copy_propagation_get_value(state, var, start + i); + struct copy_propagation_value *value; + unsigned int k; + + if (swizzle) + k = start + ((swizzle->swizzle >> i * 2) & 3); + else + k = start + i; + value = copy_propagation_get_value(state, var, k);
if (!value) return NULL; @@ -707,14 +715,16 @@ static struct hlsl_ir_node *copy_propagation_compute_replacement(struct hlsl_ctx } else if (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, swizzle ? debug_hlsl_swizzle(swizzle->swizzle, comps) : ""); return NULL; } - *swizzle |= value->component << i * 2; + *out_swizzle |= value->component << i * 2; }
- TRACE("Load from %s[%u-%u] propagated as instruction %p%s.\n", - var->name, start, start + count, instr, debug_hlsl_swizzle(*swizzle, count)); + TRACE("Load from %s[%u-%u]%s propagated as instruction %p%s.\n", + var->name, start, start + count, swizzle ? debug_hlsl_swizzle(swizzle->swizzle, comps) : "", + instr, debug_hlsl_swizzle(*out_swizzle, count)); return instr; }
@@ -787,8 +797,8 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr = &load->node, *new_instr; struct hlsl_type *type = instr->data_type; struct hlsl_ir_swizzle *swizzle_node; + unsigned int out_swizzle; unsigned int dimx = 0; - unsigned int swizzle;
switch (type->type) { @@ -816,12 +826,12 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, return true; }
- if (!(new_instr = copy_propagation_compute_replacement(ctx, state, &load->src, &swizzle))) + if (!(new_instr = copy_propagation_compute_replacement(ctx, state, &load->src, NULL, &out_swizzle))) return false;
if (type->type != HLSL_CLASS_OBJECT) { - if (!(swizzle_node = hlsl_new_swizzle(ctx, swizzle, dimx, new_instr, &instr->loc))) + if (!(swizzle_node = hlsl_new_swizzle(ctx, out_swizzle, dimx, new_instr, &instr->loc))) return false; list_add_before(&instr->entry, &swizzle_node->node.entry); new_instr = &swizzle_node->node; @@ -835,9 +845,9 @@ static bool copy_propagation_transform_object_load(struct hlsl_ctx *ctx, { struct hlsl_ir_load *load; struct hlsl_ir_node *instr; - unsigned int swizzle; + unsigned int out_swizzle;
- if (!(instr = copy_propagation_compute_replacement(ctx, state, deref, &swizzle))) + if (!(instr = copy_propagation_compute_replacement(ctx, state, deref, NULL, &out_swizzle))) return false;
/* Only HLSL_IR_LOAD can produce an object. */ @@ -864,6 +874,9 @@ static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx, struct hlsl_ir_swizzle *swizzle, struct copy_propagation_state *state) { struct hlsl_ir_node *instr = &swizzle->node, *new_instr; + struct hlsl_ir_swizzle *new_swizzle; + struct hlsl_ir_load *load; + unsigned int out_swizzle;
if ((new_instr = copy_propagation_compute_constant_replacement(ctx, state, instr))) { @@ -871,7 +884,20 @@ static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx, hlsl_replace_node(instr, new_instr); return true; } - return false; + + if (swizzle->val.node->type != HLSL_IR_LOAD) + return false; + load = hlsl_ir_load(swizzle->val.node); + + if (!(new_instr = copy_propagation_compute_replacement(ctx, state, &load->src, swizzle, &out_swizzle))) + return false; + if (!(new_swizzle = hlsl_new_swizzle(ctx, out_swizzle, swizzle->node.data_type->dimx, new_instr, &instr->loc))) + return false; + list_add_before(&instr->entry, &new_swizzle->node.entry); + new_instr = &new_swizzle->node; + + hlsl_replace_node(instr, new_instr); + return true; }
static bool copy_propagation_transform_resource_store(struct hlsl_ctx *ctx,