From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 92da9c49..6763558a 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -753,6 +753,56 @@ static struct hlsl_ir_node *copy_propagation_compute_load_constant_replacement(s return &cons->node; }
+static struct hlsl_ir_node *copy_propagation_compute_swizzle_constant_replacement(struct hlsl_ctx *ctx, + const struct copy_propagation_state *state, const struct hlsl_ir_swizzle *swizzle) +{ + unsigned int start, count, i, c, swizzle_bits, n_comps; + union hlsl_constant_value values[4] = {0}; + const struct hlsl_ir_load *load; + struct hlsl_ir_constant *cons; + const struct hlsl_ir_var *var; + + if (swizzle->val.node->type != HLSL_IR_LOAD) + return NULL; + load = hlsl_ir_load(swizzle->val.node); + var = load->src.var; + + if (load->node.data_type->type != HLSL_CLASS_SCALAR && load->node.data_type->type != HLSL_CLASS_VECTOR) + return NULL; + + if (!hlsl_component_index_range_from_deref(ctx, &load->src, &start, &count)) + return NULL; + + swizzle_bits = swizzle->swizzle; + n_comps = swizzle->node.data_type->dimx; + for (i = 0; i < n_comps; ++i) + { + struct copy_propagation_value *value; + + c = swizzle_bits & 3; + assert(c < count); + value = copy_propagation_get_value(state, var, start + c); + + if (!value || value->node->type != HLSL_IR_CONSTANT) + return NULL; + + values[i] = hlsl_ir_constant(value->node)->value[value->component]; + + swizzle_bits >>= 2; + } + + if (!(cons = hlsl_new_constant(ctx, swizzle->node.data_type, &swizzle->node.loc))) + return NULL; + cons->value[0] = values[0]; + cons->value[1] = values[1]; + cons->value[2] = values[2]; + cons->value[3] = values[3]; + + TRACE("Swizzle from %s[%u-%u]%s turned into a constant %p.\n", var->name, start, start + count, + debug_hlsl_swizzle(swizzle->swizzle, n_comps), cons); + return &cons->node; +} + static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, struct hlsl_ir_load *load, struct copy_propagation_state *state) { @@ -832,6 +882,20 @@ static bool copy_propagation_transform_resource_load(struct hlsl_ctx *ctx, return progress; }
+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; + + if ((new_instr = copy_propagation_compute_swizzle_constant_replacement(ctx, state, swizzle))) + { + list_add_before(&instr->entry, &new_instr->entry); + hlsl_replace_node(instr, new_instr); + return true; + } + return false; +} + static bool copy_propagation_transform_resource_store(struct hlsl_ctx *ctx, struct hlsl_ir_resource_store *store, struct copy_propagation_state *state) { @@ -995,6 +1059,10 @@ static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_b copy_propagation_record_store(ctx, hlsl_ir_store(instr), state); break;
+ case HLSL_IR_SWIZZLE: + copy_propagation_transform_swizzle(ctx, hlsl_ir_swizzle(instr), state); + break; + case HLSL_IR_IF: progress |= copy_propagation_process_if(ctx, hlsl_ir_if(instr), state); break;