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.
This commit is contained in:
Karol Herbst
2025-08-19 19:06:22 +02:00
committed by GitHub
parent cef3ef6b59
commit e51fadbbb1
3 changed files with 42 additions and 5 deletions

View File

@@ -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();

View File

@@ -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 {

View File

@@ -17,6 +17,7 @@
#include <vulkan_interop_common.hpp>
#include <string>
#include "harness/errorHelpers.h"
#include "harness/imageHelpers.h"
#include "harness/os_helpers.h"
#include <algorithm>
@@ -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<const float *>(a);
const float *b_float = static_cast<const float *>(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<const cl_half *>(a);
const cl_half *b_half = static_cast<const cl_half *>(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");