From e51fadbbb1136d13f0e52bc4848519c4d986e472 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 19 Aug 2025 19:06:22 +0200 Subject: [PATCH] Properly handle NaN when comparing images in Vulkan interop testing (#2484) I was considering reusing other code where NaN gets taken into account, but all the other places are a mess. The kernel read write tests are just doing it within loops. Other places only compare raw values as outside of kernel functions it seems to be fine to expect NaN to not mess up results. However the vulkan interop testing does run kernels and does operate on NaN float values, so we need to special case this there. --- .../vulkan_wrapper/opencl_vulkan_wrapper.cpp | 2 +- .../vulkan_wrapper/opencl_vulkan_wrapper.hpp | 2 + .../vulkan/test_vulkan_interop_image.cpp | 43 +++++++++++++++++-- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp index f4245703..ba1b7445 100644 --- a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp +++ b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp @@ -863,7 +863,7 @@ clExternalMemoryImage::clExternalMemoryImage( size_t clImageFormatSize; cl_image_desc image_desc; memset(&image_desc, 0x0, sizeof(cl_image_desc)); - cl_image_format img_format = { 0 }; + img_format = { 0 }; const VkImageCreateInfo VulkanImageCreateInfo = image2D.getVkImageCreateInfo(); diff --git a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.hpp b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.hpp index f9a305e1..0bf89322 100644 --- a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.hpp +++ b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.hpp @@ -106,6 +106,7 @@ protected: cl_mem m_externalMemory; int fd; void *handle; + cl_image_format img_format; clExternalMemoryImage(); public: @@ -117,6 +118,7 @@ public: cl_device_id deviceId); virtual ~clExternalMemoryImage(); cl_mem getExternalMemoryImage(); + cl_image_format getImageFormat() { return img_format; }; }; class clExternalSemaphore { diff --git a/test_conformance/vulkan/test_vulkan_interop_image.cpp b/test_conformance/vulkan/test_vulkan_interop_image.cpp index 0c1887aa..0dc2fa8a 100644 --- a/test_conformance/vulkan/test_vulkan_interop_image.cpp +++ b/test_conformance/vulkan/test_vulkan_interop_image.cpp @@ -17,6 +17,7 @@ #include #include #include "harness/errorHelpers.h" +#include "harness/imageHelpers.h" #include "harness/os_helpers.h" #include @@ -136,6 +137,38 @@ const uint32_t num2DImagesList[] = { 1, 2, 4 }; const uint32_t widthList[] = { 4, 64, 183, 1024 }; const uint32_t heightList[] = { 4, 64, 365 }; +bool memcmp_images(const void *a, const void *b, size_t size, + cl_image_format format) +{ + if (format.image_channel_data_type == CL_FLOAT) + { + const float *a_float = static_cast(a); + const float *b_float = static_cast(b); + return !std::equal(a_float, a_float + size / sizeof(*a_float), b_float, + b_float + size / sizeof(*b_float), + [](float a, float b) { + if (isnan(a) && isnan(b)) return true; + return a == b; + }); + } + else if (format.image_channel_data_type == CL_HALF_FLOAT) + { + const cl_half *a_half = static_cast(a); + const cl_half *b_half = static_cast(b); + return !std::equal(a_half, a_half + size / sizeof(*a_half), b_half, + b_half + size / sizeof(*b_half), + [](cl_half a, cl_half b) { + if (is_half_nan(a) && is_half_nan(b)) + return true; + return a == b; + }); + } + else + { + return memcmp(a, b, size) != 0; + } +} + const cl_kernel getKernelType(VulkanFormat format, cl_kernel kernel_float, cl_kernel kernel_signed, cl_kernel kernel_unsigned) @@ -744,8 +777,9 @@ int run_test_with_two_queue( "clEnqueueReadImage failed with" "error\n"); - if (memcmp(srcBufferPtr, dstBufferPtr, - srcBufSize)) + if (memcmp_images( + srcBufferPtr, dstBufferPtr, srcBufSize, + externalMemory2[i]->getImageFormat())) { log_info("Source and destination buffers " "don't match\n"); @@ -1296,8 +1330,9 @@ int run_test_with_one_queue( "clEnqueueReadImage failed with" "error\n"); - if (memcmp(srcBufferPtr, dstBufferPtr, - srcBufSize)) + if (memcmp_images( + srcBufferPtr, dstBufferPtr, srcBufSize, + externalMemory2[i]->getImageFormat())) { log_info("Source and destination buffers " "don't match\n");