From 343022cdc174b83b35c214580ae9bf052805c3d7 Mon Sep 17 00:00:00 2001
From: Giovanni Mascellani <gmascellani@codeweavers.com>
Date: Tue, 21 Jan 2025 12:01:13 +0100
Subject: [PATCH] vkd3d-shader/spirv: Interpret the write mask as a destination
 swizzle for double comparison operations.

This fixes a failure on a shader in Wild hearts.
---
 libs/vkd3d-shader/spirv.c                     | 18 +++++++-
 .../hlsl/arithmetic-float-uniform.shader_test | 41 +++++++++++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 7bd59062e..c8dc6de45 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -8193,6 +8193,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co
     const struct vkd3d_shader_dst_param *dst = instruction->dst;
     const struct vkd3d_shader_src_param *src = instruction->src;
     uint32_t src0_id, src1_id, type_id, result_id;
+    uint32_t write_mask = dst->write_mask;
     unsigned int component_count;
     SpvOp op;
 
@@ -8223,8 +8224,21 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co
 
     component_count = vsir_write_mask_component_count(dst->write_mask);
 
-    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);
+    switch (instruction->opcode)
+    {
+        case VKD3DSIH_DEQO:
+        case VKD3DSIH_DGEO:
+        case VKD3DSIH_DLT:
+        case VKD3DSIH_DNE:
+            write_mask = vkd3d_write_mask_from_component_count(component_count);
+            break;
+
+        default:
+            break;
+    }
+
+    src0_id = spirv_compiler_emit_load_src(compiler, &src[0], write_mask);
+    src1_id = spirv_compiler_emit_load_src(compiler, &src[1], write_mask);
 
     type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
     result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
diff --git a/tests/hlsl/arithmetic-float-uniform.shader_test b/tests/hlsl/arithmetic-float-uniform.shader_test
index 4183642ff..fad6323f0 100644
--- a/tests/hlsl/arithmetic-float-uniform.shader_test
+++ b/tests/hlsl/arithmetic-float-uniform.shader_test
@@ -209,3 +209,44 @@ float4 main() : sv_target
 uniform 0 float4 0.2 0.3 9.1 3.2
 draw quad
 probe (0, 0) rgba (0.4, 0.6, 18.2, 6.4)
+
+[rtv 0]
+format r32g32b32a32-uint
+size (2d, 640, 480)
+
+[pixel shader todo]
+uniform double2 a, b, c, d;
+
+% Return bool4 to ensure that non-trivial destination swizzling happens on the
+% DLT instruction, rather than on the instruction to convert the result.
+bool4 main() : SV_TARGET
+{
+    bool2 first = a < b;
+    bool2 second = c < d;
+    return bool4(first.x, second.x, second.y, first.y);
+}
+
+[test]
+uniform 0 double2 1.0 3.0
+uniform 4 double2 2.0 4.0
+uniform 8 double2 5.0 7.0
+uniform 12 double2 6.0 8.0
+todo(sm<6) draw quad
+if(sm<6) probe (0, 0) rgbaui(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
+if(sm>=6) probe (0, 0) rgbaui(1, 1, 1, 1)
+
+uniform 0 double2 1.0 4.0
+uniform 4 double2 2.0 3.0
+uniform 8 double2 5.0 8.0
+uniform 12 double2 6.0 7.0
+todo(sm<6) draw quad
+if(sm<6) probe (0, 0) rgbaui(0xffffffff, 0xffffffff, 0, 0)
+if(sm>=6) probe (0, 0) rgbaui(1, 1, 0, 0)
+
+uniform 0 double2 1.0 4.0
+uniform 4 double2 2.0 3.0
+uniform 8 double2 6.0 7.0
+uniform 12 double2 5.0 8.0
+todo(sm<6) draw quad
+if(sm<6) probe (0, 0) rgbaui(0xffffffff, 0, 0xffffffff, 0)
+if(sm>=6) probe (0, 0) rgbaui(1, 0, 1, 0)
-- 
GitLab