-- v3: vkd3d-shader/spirv: Handle the ORD and UNO instructions. vkd3d-shader/dxil: Support FCMP_ORD and FCMP_UNO for CMP2. tests/shader-runner: Add a test for FCMP_ORD (is ordered).
From: Conor McCarthy cmccarthy@codeweavers.com
--- tests/hlsl/float-comparison.shader_test | 33 +++++++------------------ 1 file changed, 9 insertions(+), 24 deletions(-)
diff --git a/tests/hlsl/float-comparison.shader_test b/tests/hlsl/float-comparison.shader_test index b66543443..0a3e56f80 100644 --- a/tests/hlsl/float-comparison.shader_test +++ b/tests/hlsl/float-comparison.shader_test @@ -32,41 +32,26 @@ float4 main() : sv_target result.z += (n != f.y) ? 100000.0 : 0.0; result.z += !(n == f.y) ? 1000000.0 : 0.0; result.z += !(n != f.y) ? 10000000.0 : 0.0; - /* It doesn't seem possible to generate DXIL instructions for 'is ordered' or 'is unordered'. - * Expressions 'isnan(n)' and '(isnan(n) || isnan(f.x))' compile into intrinsics. */ - result.w = 0; + // These compile to FCMP_ORD, but prepending a ! does not result in FCMP_UNO + result.w = (f.y < f.x || f.y >= f.x) ? 1.0 : 0.0; + result.w += (n < f.x || n >= f.x) ? 10.0 : 0.0; return result; }
-% SM1-3 apparently treats '0/0' as zero. -[require] -shader model < 4.0 - [test] uniform 0 float4 0.0 1.5 1.5 0.0 -todo(sm<4) draw quad -todo probe all rgba (1010101.0, 11001100.0, 1101001.0, 0.0) - +todo(sm<4 | sm>=6) draw quad +% SM1-3 apparently treats '0/0' as zero. +if(sm<4) todo probe all rgba (1010101.0, 11001100.0, 1101001.0, 11.0) % SM4-5 optimises away the 'not' by inverting the condition, even though this is invalid for NaN. -[require] -shader model >= 4.0 -shader model < 6.0 +if(sm>=4 & sm<6) todo probe all rgba (1010101.0, 0.0, 1101001.0, 1.0) +% SM6 emits the correct ordered/unordered instructions, so comparisons are false for NaN, and are made true with 'not'. +if(sm>=6) probe all rgba (1010101.0, 11110000.0, 1101001.0, 1.0)
-[test] -uniform 0 float4 0.0 1.5 1.5 0.0 -draw quad -todo probe all rgba (1010101.0, 0.0, 1101001.0, 0.0)
-% SM6 emits the correct ordered/unordered instructions, so comparisons are false for NaN, and are made true with 'not'. [require] shader model >= 6.0
-[test] -uniform 0 float4 0.0 1.5 1.5 0.0 -draw quad -probe all rgba (1010101.0, 11110000.0, 1101001.0, 0.0) - - [pixel shader] uniform float4 f;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 2 ++ libs/vkd3d-shader/dxil.c | 4 ++-- libs/vkd3d-shader/vkd3d_shader_private.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 3f86bd459..a65311e98 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -250,6 +250,7 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_NOT ] = "not", [VKD3DSIH_NRM ] = "nrm", [VKD3DSIH_OR ] = "or", + [VKD3DSIH_ORD ] = "ord", [VKD3DSIH_PHASE ] = "phase", [VKD3DSIH_PHI ] = "phi", [VKD3DSIH_POW ] = "pow", @@ -321,6 +322,7 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_UMAX ] = "umax", [VKD3DSIH_UMIN ] = "umin", [VKD3DSIH_UMUL ] = "umul", + [VKD3DSIH_UNO ] = "uno", [VKD3DSIH_USHR ] = "ushr", [VKD3DSIH_UTOD ] = "utod", [VKD3DSIH_UTOF ] = "utof", diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 26a8a5c1c..a202d208f 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -5187,8 +5187,8 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) [FCMP_OLT] = {VKD3DSIH_LTO}, [FCMP_OLE] = {VKD3DSIH_GEO, true}, [FCMP_ONE] = {VKD3DSIH_NEO}, - [FCMP_ORD] = {VKD3DSIH_INVALID}, - [FCMP_UNO] = {VKD3DSIH_INVALID}, + [FCMP_ORD] = {VKD3DSIH_ORD}, + [FCMP_UNO] = {VKD3DSIH_UNO}, [FCMP_UEQ] = {VKD3DSIH_EQU}, [FCMP_UGT] = {VKD3DSIH_LTU, true}, [FCMP_UGE] = {VKD3DSIH_GEU}, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 4b322b95b..43e22cba3 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -445,6 +445,7 @@ enum vkd3d_shader_opcode VKD3DSIH_NOT, VKD3DSIH_NRM, VKD3DSIH_OR, + VKD3DSIH_ORD, VKD3DSIH_PHASE, VKD3DSIH_PHI, VKD3DSIH_POW, @@ -516,6 +517,7 @@ enum vkd3d_shader_opcode VKD3DSIH_UMAX, VKD3DSIH_UMIN, VKD3DSIH_UMUL, + VKD3DSIH_UNO, VKD3DSIH_USHR, VKD3DSIH_UTOD, VKD3DSIH_UTOF,
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 37 +++++++++++++++++++++++++ tests/hlsl/float-comparison.shader_test | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index a3baeea75..6a87139d1 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1524,6 +1524,19 @@ static uint32_t vkd3d_spirv_build_op_logical_equal(struct vkd3d_spirv_builder *b SpvOpLogicalEqual, result_type, operand0, operand1); }
+static uint32_t vkd3d_spirv_build_op_logical_or(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t operand0, uint32_t operand1) +{ + return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, + SpvOpLogicalOr, result_type, operand0, operand1); +} + +static uint32_t vkd3d_spirv_build_op_logical_not(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t operand) +{ + return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpLogicalNot, result_type, operand); +} + static uint32_t vkd3d_spirv_build_op_convert_utof(struct vkd3d_spirv_builder *builder, uint32_t result_type, uint32_t unsigned_value) { @@ -7684,6 +7697,26 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id); }
+static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, src0_id, src1_id, val_id; + + type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); + /* OpOrdered and OpUnordered are only available in Kernel mode. */ + src0_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src0_id); + src1_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src1_id); + val_id = vkd3d_spirv_build_op_logical_or(builder, type_id, src0_id, src1_id); + if (instruction->handler_idx == VKD3DSIH_ORD) + val_id = vkd3d_spirv_build_op_logical_not(builder, type_id, val_id); + spirv_compiler_emit_store_dst(compiler, dst, val_id); +} + static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction, uint32_t target_block_id) { @@ -9669,6 +9702,10 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_ULT: spirv_compiler_emit_comparison_instruction(compiler, instruction); break; + case VKD3DSIH_ORD: + case VKD3DSIH_UNO: + spirv_compiler_emit_orderedness_instruction(compiler, instruction); + break; case VKD3DSIH_BFI: case VKD3DSIH_IBFE: case VKD3DSIH_UBFE: diff --git a/tests/hlsl/float-comparison.shader_test b/tests/hlsl/float-comparison.shader_test index 0a3e56f80..619e62f85 100644 --- a/tests/hlsl/float-comparison.shader_test +++ b/tests/hlsl/float-comparison.shader_test @@ -40,7 +40,7 @@ float4 main() : sv_target
[test] uniform 0 float4 0.0 1.5 1.5 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad % SM1-3 apparently treats '0/0' as zero. if(sm<4) todo probe all rgba (1010101.0, 11001100.0, 1101001.0, 11.0) % SM4-5 optimises away the 'not' by inverting the condition, even though this is invalid for NaN.
This merge request was approved by Giovanni Mascellani.
This merge request was approved by Henri Verbeet.