From a3319339e467beb2f03836842801e9c59eb3f988 Mon Sep 17 00:00:00 2001 From: Francisco Casas Date: Wed, 21 Feb 2024 16:36:43 -0300 Subject: [PATCH] vkd3d-shader/hlsl: Lower casts to int using REINTERPRET instead. I realized that it is better to lower casts to int to FLOOR+REINTERPET instead of appending a FLOOR to all casts to int and assuming that this is the case for all of them in d3dbc.c. This in case we introduce new passes in the future that add casts that we forget to lower, after the lower_casts_to_bool pass. --- libs/vkd3d-shader/d3dbc.c | 11 ++++++++++- libs/vkd3d-shader/hlsl_codegen.c | 15 +++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index a697a2a8..0f5d34ee 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -2002,7 +2002,10 @@ static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b { case HLSL_TYPE_HALF: case HLSL_TYPE_FLOAT: - /* A compilation pass applies a FLOOR operation to casts to int, so no change is necessary. */ + /* A compilation pass turns these into FLOOR+REINTERPRET, so we should not + * reach this case unless we are missing something. */ + hlsl_fixme(ctx, &instr->loc, "Unlowered SM1 cast from float to integer."); + break; case HLSL_TYPE_INT: case HLSL_TYPE_UINT: write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0); @@ -2242,6 +2245,12 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b assert(instr->reg.allocated); + if (expr->op == HLSL_OP1_REINTERPRET) + { + write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, 0); + return; + } + if (expr->op == HLSL_OP1_CAST) { write_sm1_cast(ctx, buffer, instr); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index e7fc02d0..413888d8 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2647,10 +2647,11 @@ static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) return false; } -/* Append a FLOOR before a CAST to int or uint (which is written as a mere MOV). */ +/* Turn CAST to int or uint into FLOOR + REINTERPRET (which is written as a mere MOV). */ static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) { - struct hlsl_ir_node *arg, *floor, *cast2; + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }; + struct hlsl_ir_node *arg, *floor, *res; struct hlsl_ir_expr *expr; if (instr->type != HLSL_IR_EXPR) @@ -2665,17 +2666,15 @@ static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, if (arg->data_type->base_type != HLSL_TYPE_FLOAT && arg->data_type->base_type != HLSL_TYPE_HALF) return false; - /* Check that the argument is not already a FLOOR */ - if (arg->type == HLSL_IR_EXPR && hlsl_ir_expr(arg)->op == HLSL_OP1_FLOOR) - return false; - if (!(floor = hlsl_new_unary_expr(ctx, HLSL_OP1_FLOOR, arg, &instr->loc))) return false; hlsl_block_add_instr(block, floor); - if (!(cast2 = hlsl_new_cast(ctx, floor, instr->data_type, &instr->loc))) + memset(operands, 0, sizeof(operands)); + operands[0] = floor; + if (!(res = hlsl_new_expr(ctx, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc))) return false; - hlsl_block_add_instr(block, cast2); + hlsl_block_add_instr(block, res); return true; }