From 9123b05c1ff23e534fac01d0a98daa9b4627b981 Mon Sep 17 00:00:00 2001 From: Ben Ashbaugh Date: Tue, 11 Feb 2025 10:40:19 -0800 Subject: [PATCH] add a unified SVM consistency check test (#2174) Adds a unified SVM consistency check test, as per the description in #2150. Note that the target branch for this PR is the cl_khr_unified_svm branch, not the main branch. --- test_conformance/SVM/CMakeLists.txt | 1 + .../SVM/test_unified_svm_consistency.cpp | 159 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 test_conformance/SVM/test_unified_svm_consistency.cpp diff --git a/test_conformance/SVM/CMakeLists.txt b/test_conformance/SVM/CMakeLists.txt index 57cbcac7..d16310ec 100644 --- a/test_conformance/SVM/CMakeLists.txt +++ b/test_conformance/SVM/CMakeLists.txt @@ -16,6 +16,7 @@ set(${MODULE_NAME}_SOURCES test_shared_address_space_fine_grain_buffers.cpp test_shared_sub_buffers.cpp test_migrate.cpp + test_unified_svm_consistency.cpp ) set_gnulike_module_compile_flags("-Wno-sometimes-uninitialized -Wno-sign-compare") diff --git a/test_conformance/SVM/test_unified_svm_consistency.cpp b/test_conformance/SVM/test_unified_svm_consistency.cpp new file mode 100644 index 00000000..40bde914 --- /dev/null +++ b/test_conformance/SVM/test_unified_svm_consistency.cpp @@ -0,0 +1,159 @@ +// +// Copyright (c) 2024 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "common.h" +#include + +REGISTER_TEST(unified_svm_consistency) +{ + if (!is_extension_available(deviceID, "cl_khr_unified_svm")) + { + log_info("cl_khr_unified_svm is not supported, skipping test.\n"); + return TEST_SKIPPED_ITSELF; + } + + cl_int err; + + cl_platform_id platformID; + err = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(cl_platform_id), + (void *)(&platformID), nullptr); + test_error(err, "clGetDeviceInfo failed for CL_DEVICE_PLATFORM"); + + cl_uint numDevices = 0; + err = + clGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 0, nullptr, &numDevices); + test_error(err, "clGetDeviceIDs failed to get number of devices"); + + std::vector devices(numDevices); + err = clGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, numDevices, + devices.data(), nullptr); + test_error(err, "clGetDeviceIDs failed to get device IDs"); + + // For each device in the platform, check that the platform and device + // report the same number of SVM capability combinations. + + size_t platformSize{}; + err = clGetPlatformInfo(platformID, CL_PLATFORM_SVM_TYPE_CAPABILITIES_KHR, + 0, nullptr, &platformSize); + test_error(err, + "clGetPlatformInfo failed for " + "CL_PLATFORM_SVM_TYPE_CAPABILITIES_KHR"); + + if (platformSize % sizeof(cl_svm_capabilities_khr) != 0) + { + test_fail( + "Unexpected platform SVM type capabilities size: %zu bytes.\n", + platformSize); + } + + for (auto device : devices) + { + size_t deviceSize{}; + err = clGetDeviceInfo(device, CL_DEVICE_SVM_TYPE_CAPABILITIES_KHR, 0, + nullptr, &deviceSize); + test_error( + err, + "clGetDeviceInfo failed for CL_DEVICE_SVM_TYPE_CAPABILITIES_KHR"); + + if (deviceSize % sizeof(cl_svm_capabilities_khr) != 0) + { + test_fail("Unexpected device SVM type capabilities size: " + "%zu bytes.\n", + deviceSize); + } + if (platformSize != deviceSize) + { + test_fail("Platform and device report different number of " + "SVM type capability combinations.\n"); + } + } + + // For each SVM capability combination reported by the platform, check that + // the reported platform capabilities at an index are the intersection of + // all non-zero device capabilities at the same index. + + size_t capabilityCount = platformSize / sizeof(cl_svm_capabilities_khr); + + std::vector platformCapabilities(capabilityCount); + err = clGetPlatformInfo(platformID, CL_PLATFORM_SVM_TYPE_CAPABILITIES_KHR, + platformSize, platformCapabilities.data(), nullptr); + test_error(err, + "clGetPlatformInfo failed for " + "CL_PLATFORM_SVM_TYPE_CAPABILITIES_KHR"); + + for (int i = 0; i < capabilityCount; i++) + { + cl_svm_capabilities_khr check = 0; + for (auto device : devices) + { + std::vector deviceCapabilities( + capabilityCount); + err = clGetDeviceInfo(device, CL_DEVICE_SVM_TYPE_CAPABILITIES_KHR, + platformSize, deviceCapabilities.data(), + nullptr); + test_error( + err, + "clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES_KHR"); + + if (deviceCapabilities[i] != 0) + { + if (check == 0) + { + check = deviceCapabilities[i]; + } + else + { + check &= deviceCapabilities[i]; + } + } + } + if (platformCapabilities[i] != check) + { + test_fail("Platform SVM type capabilities at index %zu: 0x%" PRIx64 + " do not match the intersection of device capabilities " + "0x%" PRIx64 ".\n", + i, platformCapabilities[i], check); + } + } + + // For each SVM capability combination reported by the test device, check + // that the device SVM capabilities are either a super-set of the platform + // SVM capabilities or are zero, indicating that this SVM type is not + // supported. + + std::vector deviceCapabilities(capabilityCount); + err = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_TYPE_CAPABILITIES_KHR, + platformSize, deviceCapabilities.data(), nullptr); + test_error(err, + "clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES_KHR"); + + for (int i = 0; i < capabilityCount; i++) + { + bool consistent = (deviceCapabilities[i] & platformCapabilities[i]) + == platformCapabilities[i] + || deviceCapabilities[i] == 0; + if (!consistent) + { + test_fail( + "Device SVM type capabilities at index %zu: 0x%" PRIx64 + " are not consistent with platform SVM type capabilities: " + "0x%" PRIx64 ".\n", + i, deviceCapabilities[i], platformCapabilities[i]); + } + } + + return TEST_PASS; +}