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:
``` 2: float4 | f 3: | return 4: float4 | @2.xwxw 5: | = (<output-sv_target0> @4) ``` --- libs/vkd3d-shader/hlsl_codegen.c | 43 +++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 1ca35d34..00be55ad 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -683,20 +683,19 @@ 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) + unsigned int *swizzle, unsigned int comp_count) { + unsigned int start, count, i, out_swizzle = 0; const struct hlsl_ir_var *var = deref->var; 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; - - for (i = 0; i < count; ++i) + for (i = 0; i < comp_count; ++i) { - struct copy_propagation_value *value = copy_propagation_get_value(state, var, start + i); + unsigned int k = start + (((*swizzle) >> i * 2) & 3); + struct copy_propagation_value *value = copy_propagation_get_value(state, var, k);
if (!value) return NULL; @@ -707,14 +706,17 @@ 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, debug_hlsl_swizzle(*swizzle, comp_count)); 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, debug_hlsl_swizzle(*swizzle, comp_count), instr, + debug_hlsl_swizzle(out_swizzle, comp_count)); + *swizzle = out_swizzle; return instr; }
@@ -792,7 +794,7 @@ 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, &swizzle, dimx))) return false;
if (type->type != HLSL_CLASS_OBJECT) @@ -809,11 +811,11 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, static bool copy_propagation_transform_object_load(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct copy_propagation_state *state) { + unsigned int swizzle = HLSL_SWIZZLE(X, Y, Z, W); struct hlsl_ir_load *load; struct hlsl_ir_node *instr; - unsigned int swizzle;
- if (!(instr = copy_propagation_compute_replacement(ctx, state, deref, &swizzle))) + if (!(instr = copy_propagation_compute_replacement(ctx, state, deref, &swizzle, 1))) return false;
/* Only HLSL_IR_LOAD can produce an object. */ @@ -842,19 +844,30 @@ static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx, { struct hlsl_ir_node *instr = &swizzle->node, *new_instr; struct hlsl_type *type = swizzle->node.data_type; + unsigned int swizzle_bits = swizzle->swizzle; + struct hlsl_ir_swizzle *new_swizzle; struct hlsl_ir_load *load;
if (swizzle->val.node->type != HLSL_IR_LOAD) return false; load = hlsl_ir_load(swizzle->val.node);
- if ((new_instr = copy_propagation_compute_load_constant_replacement(ctx, state, load, swizzle->swizzle, type->dimx))) + if ((new_instr = copy_propagation_compute_load_constant_replacement(ctx, state, load, swizzle_bits, type->dimx))) { list_add_before(&instr->entry, &new_instr->entry); hlsl_replace_node(instr, new_instr); return true; } - return false; + + if (!(new_instr = copy_propagation_compute_replacement(ctx, state, &load->src, &swizzle_bits, type->dimx))) + return false; + if (!(new_swizzle = hlsl_new_swizzle(ctx, swizzle_bits, type->dimx, new_instr, &instr->loc))) + return false; + new_instr = &new_swizzle->node; + list_add_before(&instr->entry, &new_instr->entry); + + hlsl_replace_node(instr, new_instr); + return true; }
static bool copy_propagation_transform_resource_store(struct hlsl_ctx *ctx,