end2end: VertexFormatTest: fold bit representation of -0.0 to 0

This is necessary because of how we compute ULP in a cheap way
by looking only at the u32 bits.

Remove the test suppressions for Arm GPUs.
I suspect this also fixes the tests for other GPUs.

Bug: dawn:1566
Change-Id: I36018209cf3254acfa64771b1e40bf498bd3375a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/147243
Reviewed-by: Brandon Jones <bajones@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/dawn/tests/end2end/VertexFormatTests.cpp b/src/dawn/tests/end2end/VertexFormatTests.cpp
index a62c38f..f9a419d 100644
--- a/src/dawn/tests/end2end/VertexFormatTests.cpp
+++ b/src/dawn/tests/end2end/VertexFormatTests.cpp
@@ -242,6 +242,22 @@
         vs << "    @builtin(vertex_index) VertexIndex : u32,\n";
         vs << "}\n";
 
+        // These functions map a 32-bit scalar value to its bits in u32, except
+        // that the negative zero floating point value is remapped to u32(0),
+        // which is also the bit representation for +0.0.
+        // This is necessary because of the simple way we compute ULP.
+        // Negative zero *equals* zero, so treat it as having the same bit
+        // representation.
+        vs << R"(
+            fn rectify_u32(a: u32) -> u32 { return a; }
+            fn rectify_i32(a: i32) -> u32 { return bitcast<u32>(a); }
+            fn rectify_f32(a: f32) -> u32 {
+              const negative_zero_bits = 1u << 31u;
+              let b = bitcast<u32>(a);
+              return select(b, 0u, b == negative_zero_bits);
+            }
+        )";
+
         // Because x86 CPU using "extended
         // precision"(https://en.wikipedia.org/wiki/Extended_precision) during float
         // math(https://developer.nvidia.com/sites/default/files/akamai/cuda/files/NVIDIA-CUDA-Floating-Point.pdf),
@@ -310,6 +326,8 @@
                     // Because Vulkan and D3D12 handle -0.0f through bitcast have different
                     // result (Vulkan take -0.0f as -0.0 but D3D12 take -0.0f as 0), add workaround
                     // for -0.0f.
+                    // TODO(dawn:1566) Since rectify_32 will be used, we might
+                    // not need this.
                     if (static_cast<uint16_t>(expectedData[i * componentCount + j]) ==
                         kNegativeZeroInHalf) {
                         vs << "-0.0);\n";
@@ -342,15 +360,13 @@
                 vs << "    success = success && (isNaNCustom(" << expectedVal << ") == isNaNCustom("
                    << testVal << "));\n";
                 vs << "    if (!isNaNCustom(" << expectedVal << ")) {\n";
-                // Fold -0.0 into 0.0.
-                vs << "        if (" << testVal << " == 0) { " << testVal << " = 0; }\n";
-                vs << "        if (" << expectedVal << " == 0) { " << expectedVal << " = 0; }\n";
                 // TODO(shaobo.yan@intel.com) : a difference of 8 ULPs is allowed in this test
                 // because it is required on MacbookPro 11.5,AMD Radeon HD 8870M(on macOS 10.13.6),
                 // but that it might be possible to tighten.
-                vs << "        let testValFloatToUint : u32 = bitcast<u32>(" << testVal << ");\n";
-                vs << "        let expectedValFloatToUint : u32 = bitcast<u32>(" << expectedVal
-                   << ");\n";
+                vs << "        let testValFloatToUint : u32 = rectify_" << expectedDataType << "("
+                   << testVal << ");\n";
+                vs << "        let expectedValFloatToUint : u32 = rectify_" << expectedDataType
+                   << "(" << expectedVal << ");\n";
                 vs << "        success = success && max(testValFloatToUint, "
                       "expectedValFloatToUint)";
                 vs << "        - min(testValFloatToUint, expectedValFloatToUint) < 8u;\n";
@@ -705,9 +721,8 @@
 
 TEST_P(VertexFormatTest, Float16x2) {
     // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
+    // TODO(dawn:1566) Might pass when using rectify_f32?
     DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
-    // TODO(dawn:1566) Fails on Arm-based Android devices, when using -0.0.
-    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
 
     std::vector<uint16_t> vertexData =
         Float32ToFloat16(std::vector<float>({14.8f, -0.0f, 22.5f, 1.3f, +0.0f, -24.8f}));
@@ -717,9 +732,8 @@
 
 TEST_P(VertexFormatTest, Float16x4) {
     // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
+    // TODO(dawn:1566) Might pass when using rectify_f32?
     DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
-    // TODO(dawn:1566) Fails on Arm-based Android devices, when using -0.0.
-    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
 
     std::vector<uint16_t> vertexData = Float32ToFloat16(std::vector<float>(
         {+0.0f, -16.8f, 18.2f, -0.0f, 12.5f, 1.3f, 14.8f, -12.4f, 22.5f, -48.8f, 47.4f, -24.8f}));
@@ -727,9 +741,9 @@
     DoVertexFormatTest(wgpu::VertexFormat::Float16x4, vertexData, vertexData);
 }
 TEST_P(VertexFormatTest, Float32_Zeros) {
-    // TODO(dawn:1566) Fails on Qualcomm-based and Arm-base Android devices. When using -0.0.
+    // TODO(dawn:1566) Fails on Qualcomm-based Android devices. When using -0.0.
+    // This might pass now that we use rectify_f32?
     DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsQualcomm());
-    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
 
     std::vector<float> vertexData = {1.3f, +0.0f, -0.0f};
 
@@ -746,12 +760,11 @@
 
 TEST_P(VertexFormatTest, Float32x2) {
     // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
+    // TODO(dawn:1566) This might pass now that we use rectify_f32?
     DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
 
     // TODO(dawn:1566) Fails on Qualcomm-based Android devices.
     DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsQualcomm());
-    // TODO(dawn:1566) Fails on Arm-based Android devices, when using -0.0.
-    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
 
     std::vector<float> vertexData = {18.23f, -0.0f, +0.0f, +1.0f, 1.3f, -1.0f};
 
@@ -760,9 +773,8 @@
 
 TEST_P(VertexFormatTest, Float32x3) {
     // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
+    // TODO(dawn:1566) This might pass now that we use rectify_f32?
     DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
-    // TODO(dawn:1566) Fails on Arm-based Android devices, when using -0.0.
-    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
 
     std::vector<float> vertexData = {
         +0.0f, -1.0f, -0.0f, 1.0f, 1.3f, 99.45f, 23.6f, -81.2f, 55.0f,
@@ -772,8 +784,6 @@
 }
 
 TEST_P(VertexFormatTest, Float32x4) {
-    // TODO(dawn:1566) Fails on Arm-based Android devices, when using -0.0.
-    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsARM());
     std::vector<float> vertexData = {
         19.2f, -19.3f, +0.0f, 1.0f, -0.0f, 1.0f, 1.3f, -1.0f, 13.078f, 21.1965f, -1.1f, -1.2f,
     };