Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 34 ++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index e43e6378e..7f1829d2c 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -652,7 +652,36 @@ static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins return false; }
-static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +static bool fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct hlsl_ir_constant *value, *res; + struct hlsl_ir_swizzle *swizzle; + unsigned int i, swizzle_bits; + + if (instr->type != HLSL_IR_SWIZZLE) + return false; + swizzle = hlsl_ir_swizzle(instr); + if (swizzle->val.node->type != HLSL_IR_CONSTANT) + return false; + value = hlsl_ir_constant(swizzle->val.node); + + if (!(res = hlsl_alloc(ctx, sizeof(*res)))) + return false; + init_node(&res->node, HLSL_IR_CONSTANT, instr->data_type, instr->loc); + + swizzle_bits = swizzle->swizzle; + for (i = 0; i < swizzle->node.data_type->dimx; ++i) + { + res->value[i] = value->value[swizzle_bits & 3]; + swizzle_bits >>= 2; + } + + list_add_before(&swizzle->node.entry, &res->node.entry); + replace_node(&swizzle->node, &res->node); + return true; +} + +static bool fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { struct hlsl_ir_constant *arg1, *arg2 = NULL, *res; struct hlsl_ir_expr *expr; @@ -1733,7 +1762,8 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun transform_ir(ctx, lower_narrowing_casts, body, NULL); do { - progress = transform_ir(ctx, fold_constants, body, NULL); + progress = transform_ir(ctx, fold_constant_exprs, body, NULL); + progress |= transform_ir(ctx, fold_constant_swizzles, body, NULL); progress |= copy_propagation_execute(ctx, body); } while (progress);