From 835044dd8e14d64e7c8797ed83563f4d8707f523 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani Date: Mon, 13 Oct 2025 21:45:48 +0200 Subject: [PATCH] vkd3d-shader/ir: Introduce VSIR_OP_SATURATE to represent floating-point clamping to [0, 1]. --- libs/vkd3d-shader/dxil.c | 5 ++--- libs/vkd3d-shader/ir.c | 4 ++++ libs/vkd3d-shader/msl.c | 3 +++ libs/vkd3d-shader/spirv.c | 15 +++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 5ba33276e..7861efc16 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -6252,13 +6252,12 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; - vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SATURATE); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; src_param_init_from_value(src_param, operands[0], 0, sm6); - if (instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) - ins->dst->modifiers = VKD3DSPDM_SATURATE; + instruction_dst_param_init_ssa_scalar(ins, 0, sm6); } static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b604808e4..ec1af7db1 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -338,6 +338,7 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) [VSIR_OP_SAMPLE_LOD ] = "sample_l", [VSIR_OP_SAMPLE_LOD_S ] = "sample_l_s", [VSIR_OP_SAMPLE_POS ] = "sample_pos", + [VSIR_OP_SATURATE ] = "saturate", [VSIR_OP_SETP ] = "setp", [VSIR_OP_SGE ] = "sge", [VSIR_OP_SGN ] = "sgn", @@ -8795,6 +8796,7 @@ static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src case VSIR_OP_ROUND_PI: case VSIR_OP_ROUND_Z: case VSIR_OP_RSQ: + case VSIR_OP_SATURATE: case VSIR_OP_SETP: case VSIR_OP_SGE: case VSIR_OP_SGN: @@ -12876,6 +12878,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ [VSIR_OP_ROUND_NE] = {1, 1, vsir_validate_float_elementwise_operation}, [VSIR_OP_ROUND_NI] = {1, 1, vsir_validate_float_elementwise_operation}, [VSIR_OP_SAMPLE_INFO] = {1, 1, vsir_validate_sample_info}, + [VSIR_OP_SATURATE] = {1, 1, vsir_validate_float_or_double_elementwise_operation}, [VSIR_OP_SWITCH] = {0, 1, vsir_validate_switch}, [VSIR_OP_SWITCH_MONOLITHIC] = {0, ~0u, vsir_validate_switch_monolithic}, [VSIR_OP_USHR] = {1, 2, vsir_validate_ushr}, @@ -13316,6 +13319,7 @@ static bool vsir_instruction_has_side_effects(const struct vkd3d_shader_instruct case VSIR_OP_SAMPLE_LOD: case VSIR_OP_SAMPLE_LOD_S: case VSIR_OP_SAMPLE_POS: + case VSIR_OP_SATURATE: case VSIR_OP_SETP: case VSIR_OP_SGE: case VSIR_OP_SGN: diff --git a/libs/vkd3d-shader/msl.c b/libs/vkd3d-shader/msl.c index 6c64627e7..f2d28acbe 100644 --- a/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d-shader/msl.c @@ -1671,6 +1671,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VSIR_OP_RSQ: msl_intrinsic(gen, ins, "rsqrt"); break; + case VSIR_OP_SATURATE: + msl_intrinsic(gen, ins, "saturate"); + break; case VSIR_OP_SIN: msl_intrinsic(gen, ins, "sin"); break; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index e75725cbd..1ceb72c65 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7628,6 +7628,18 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil return VKD3D_OK; } +static void spirv_compiler_emit_saturate(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t val_id; + + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + val_id = spirv_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id); + spirv_compiler_emit_store_dst(compiler, dst, val_id); +} + static void spirv_compiler_emit_isfinite(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -10521,6 +10533,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VSIR_OP_ISFINITE: spirv_compiler_emit_isfinite(compiler, instruction); break; + case VSIR_OP_SATURATE: + spirv_compiler_emit_saturate(compiler, instruction); + break; case VSIR_OP_ABS: case VSIR_OP_ACOS: case VSIR_OP_ASIN: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index b2c98fc17..e06ca00c1 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -542,6 +542,7 @@ enum vkd3d_shader_opcode VSIR_OP_SAMPLE_LOD, VSIR_OP_SAMPLE_LOD_S, VSIR_OP_SAMPLE_POS, + VSIR_OP_SATURATE, VSIR_OP_SETP, VSIR_OP_SGE, VSIR_OP_SGN,