Added support to run the CTS with Vulkan validation layers (#2246)
Fixes #2116 according to task description.
As approved 25Mar25
diff --git a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp
index ded1e70..36b94d9 100644
--- a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp
+++ b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp
@@ -1191,6 +1191,10 @@
{
switch (vkExternalMemoryHandleType)
{
+ default:
+ case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE:
+ log_error("Unexpected external memory handle type\n");
+ return 0;
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_FD_KHR;
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT:
@@ -1198,7 +1202,6 @@
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT:
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_KMT:
return CL_EXTERNAL_MEMORY_HANDLE_OPAQUE_WIN32_KMT_KHR;
- case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE: return 0;
}
return 0;
}
diff --git a/test_conformance/common/vulkan_wrapper/vulkan_api_list.hpp b/test_conformance/common/vulkan_wrapper/vulkan_api_list.hpp
index f5e7437..a474102 100644
--- a/test_conformance/common/vulkan_wrapper/vulkan_api_list.hpp
+++ b/test_conformance/common/vulkan_wrapper/vulkan_api_list.hpp
@@ -102,6 +102,8 @@
VK_FUNC_DECL(vkImportSemaphoreFdKHR) \
VK_FUNC_DECL(vkGetPhysicalDeviceExternalSemaphorePropertiesKHR) \
VK_FUNC_DECL(vkGetImageSubresourceLayout) \
+ VK_FUNC_DECL(vkCreateDebugUtilsMessengerEXT) \
+ VK_FUNC_DECL(vkDestroyDebugUtilsMessengerEXT) \
VK_FUNC_DECL(vkGetPhysicalDeviceExternalBufferProperties)
#define VK_WINDOWS_FUNC_LIST \
VK_FUNC_DECL(vkGetMemoryWin32HandleKHR) \
@@ -203,6 +205,8 @@
#define vkGetSemaphoreWin32HandleKHR _vkGetSemaphoreWin32HandleKHR
#define vkImportSemaphoreWin32HandleKHR _vkImportSemaphoreWin32HandleKHR
#define vkGetImageSubresourceLayout _vkGetImageSubresourceLayout
+#define vkCreateDebugUtilsMessengerEXT _vkCreateDebugUtilsMessengerEXT
+#define vkDestroyDebugUtilsMessengerEXT _vkDestroyDebugUtilsMessengerEXT
#define vkGetPhysicalDeviceExternalBufferProperties \
_vkGetPhysicalDeviceExternalBufferProperties
diff --git a/test_conformance/common/vulkan_wrapper/vulkan_utility.cpp b/test_conformance/common/vulkan_wrapper/vulkan_utility.cpp
index 6391d36..75aa536 100644
--- a/test_conformance/common/vulkan_wrapper/vulkan_utility.cpp
+++ b/test_conformance/common/vulkan_wrapper/vulkan_utility.cpp
@@ -32,13 +32,13 @@
#define BUFFERSIZE 3000
-const VulkanInstance &getVulkanInstance()
+const VulkanInstance &getVulkanInstance(bool useValidationLayers)
{
- static VulkanInstance instance;
+ static VulkanInstance instance(useValidationLayers);
return instance;
}
-const VulkanPhysicalDevice &getVulkanPhysicalDevice()
+const VulkanPhysicalDevice &getVulkanPhysicalDevice(bool useValidationLayers)
{
size_t pdIdx = 0;
cl_int errNum = 0;
@@ -47,7 +47,7 @@
cl_uint num_devices = 0;
cl_uint device_no = 0;
const size_t bufsize = BUFFERSIZE;
- const VulkanInstance &instance = getVulkanInstance();
+ const VulkanInstance &instance = getVulkanInstance(useValidationLayers);
const VulkanPhysicalDeviceList &physicalDeviceList =
instance.getPhysicalDeviceList();
@@ -112,12 +112,13 @@
}
const VulkanPhysicalDevice &
-getAssociatedVulkanPhysicalDevice(cl_device_id deviceId)
+getAssociatedVulkanPhysicalDevice(cl_device_id deviceId,
+ bool useValidationLayers)
{
size_t pdIdx;
cl_int errNum = 0;
cl_uchar uuid[CL_UUID_SIZE_KHR];
- const VulkanInstance &instance = getVulkanInstance();
+ const VulkanInstance &instance = getVulkanInstance(useValidationLayers);
const VulkanPhysicalDeviceList &physicalDeviceList =
instance.getPhysicalDeviceList();
@@ -188,10 +189,10 @@
return memoryTypeList[mtIdx];
}
-bool checkVkSupport()
+bool checkVkSupport(bool useValidationLayers)
{
bool result = true;
- const VulkanInstance &instance = getVulkanInstance();
+ const VulkanInstance &instance = getVulkanInstance(useValidationLayers);
const VulkanPhysicalDeviceList &physicalDeviceList =
instance.getPhysicalDeviceList();
if (physicalDeviceList() == NULL)
@@ -711,6 +712,7 @@
{
switch (externalMemoryHandleType)
{
+ default:
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE: return os << "None";
case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD:
return os << "Opaque file descriptor";
@@ -731,6 +733,7 @@
{
switch (externalSemaphoreHandleType)
{
+ default:
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE: return os << "None";
case VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD:
return os << "Opaque file descriptor";
diff --git a/test_conformance/common/vulkan_wrapper/vulkan_utility.hpp b/test_conformance/common/vulkan_wrapper/vulkan_utility.hpp
index 8502866..cd9bf4e 100644
--- a/test_conformance/common/vulkan_wrapper/vulkan_utility.hpp
+++ b/test_conformance/common/vulkan_wrapper/vulkan_utility.hpp
@@ -30,10 +30,12 @@
#define ROUND_UP(n, multiple) \
(((n) + (multiple)-1) - ((((n) + (multiple)-1)) % (multiple)))
-const VulkanInstance& getVulkanInstance();
-const VulkanPhysicalDevice& getVulkanPhysicalDevice();
+const VulkanInstance& getVulkanInstance(bool useValidationLayers = false);
const VulkanPhysicalDevice&
-getAssociatedVulkanPhysicalDevice(cl_device_id deviceId);
+getVulkanPhysicalDevice(bool useValidationLayers = false);
+const VulkanPhysicalDevice&
+getAssociatedVulkanPhysicalDevice(cl_device_id deviceId,
+ bool useValidationLayers = false);
const VulkanQueueFamily& getVulkanQueueFamily(
const VulkanPhysicalDevice& physicalDevice = getVulkanPhysicalDevice(),
uint32_t queueFlags = VULKAN_QUEUE_FLAG_GRAPHICS
@@ -41,7 +43,7 @@
const VulkanMemoryType&
getVulkanMemoryType(const VulkanDevice& device,
VulkanMemoryTypeProperty memoryTypeProperty);
-bool checkVkSupport();
+bool checkVkSupport(bool useValidationLayers = false);
const VulkanQueueFamilyList& getEmptyVulkanQueueFamilyList();
const VulkanDescriptorSetLayoutList& getEmptyVulkanDescriptorSetLayoutList();
const VulkanQueueFamilyToQueueCountMap&
diff --git a/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp b/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp
index 6c31a35..f41e196 100644
--- a/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp
+++ b/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp
@@ -48,16 +48,38 @@
#define CHECK_VK(call) \
if (call != VK_SUCCESS) return call;
+
+static VKAPI_ATTR VkBool32 VKAPI_CALL logCallback(
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageType,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData)
+{
+ switch (messageSeverity)
+ {
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ log_error("Vulkan validation layer: %s\n", pCallbackData->pMessage);
+ break;
+ default:
+ log_info("Vulkan validation layer: %s\n", pCallbackData->pMessage);
+ break;
+ }
+
+ return VK_FALSE;
+}
+
///////////////////////////////////
// VulkanInstance implementation //
///////////////////////////////////
VulkanInstance::VulkanInstance(const VulkanInstance &instance)
: m_vkInstance(instance.m_vkInstance),
- m_physicalDeviceList(instance.m_physicalDeviceList)
+ m_physicalDeviceList(instance.m_physicalDeviceList),
+ m_useValidationLayers(instance.m_useValidationLayers),
+ m_validationLayers(instance.m_validationLayers)
{}
-VulkanInstance::VulkanInstance(): m_vkInstance(VK_NULL_HANDLE)
+VulkanInstance::VulkanInstance(bool useValidationLayers)
+ : m_vkInstance(VK_NULL_HANDLE), m_useValidationLayers(useValidationLayers)
{
#if defined(__linux__) && !defined(__ANDROID__)
char *glibcVersion = strdup(gnu_get_libc_version());
@@ -130,6 +152,35 @@
VK_GET_NULL_INSTANCE_PROC_ADDR(vkCreateInstance);
#undef VK_GET_NULL_INSTANCE_PROC_ADDR
+ if (m_useValidationLayers)
+ {
+ uint32_t layerCount = 0;
+ vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
+
+ std::vector<VkLayerProperties> layers(layerCount);
+ vkEnumerateInstanceLayerProperties(&layerCount, layers.data());
+
+ for (auto it = m_validationLayers.begin();
+ it != m_validationLayers.end();)
+ {
+ bool found = false;
+ for (const auto &layerProps : layers)
+ if (strcmp(*it, layerProps.layerName) == 0)
+ {
+ found = true;
+ break;
+ }
+ if (!found)
+ {
+ log_info("Vulkan layer not found: %s\n", *it);
+ it = m_validationLayers.erase(it);
+ }
+ else
+ ++it;
+ }
+ m_useValidationLayers = !m_validationLayers.empty();
+ }
+
VkApplicationInfo vkApplicationInfo = {};
vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
vkApplicationInfo.pNext = NULL;
@@ -147,6 +198,9 @@
enabledExtensionNameList.push_back(
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
+ if (m_useValidationLayers)
+ enabledExtensionNameList.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+
std::vector<VkExtensionProperties> vkExtensionPropertiesList(
instanceExtensionPropertiesCount);
vkEnumerateInstanceExtensionProperties(NULL,
@@ -174,18 +228,51 @@
VkInstanceCreateInfo vkInstanceCreateInfo = {};
vkInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- vkInstanceCreateInfo.pNext = NULL;
vkInstanceCreateInfo.flags = 0;
vkInstanceCreateInfo.pApplicationInfo = &vkApplicationInfo;
- vkInstanceCreateInfo.enabledLayerCount = 0;
vkInstanceCreateInfo.ppEnabledLayerNames = NULL;
vkInstanceCreateInfo.enabledExtensionCount =
(uint32_t)enabledExtensionNameList.size();
vkInstanceCreateInfo.ppEnabledExtensionNames =
enabledExtensionNameList.data();
+ vkInstanceCreateInfo.enabledLayerCount = 0;
+ vkInstanceCreateInfo.pNext = NULL;
+
+ VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
+ if (m_useValidationLayers)
+ {
+ vkInstanceCreateInfo.enabledLayerCount =
+ static_cast<uint32_t>(m_validationLayers.size());
+ vkInstanceCreateInfo.ppEnabledLayerNames = m_validationLayers.data();
+
+ debugCreateInfo.messageType =
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+
+ debugCreateInfo.sType =
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ debugCreateInfo.messageSeverity =
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ debugCreateInfo.pfnUserCallback = logCallback;
+
+ vkInstanceCreateInfo.pNext =
+ (VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo;
+ }
vkCreateInstance(&vkInstanceCreateInfo, NULL, &m_vkInstance);
+ if (m_useValidationLayers)
+ {
+ _vkCreateDebugUtilsMessengerEXT =
+ (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
+ m_vkInstance, "vkCreateDebugUtilsMessengerEXT");
+ if (_vkCreateDebugUtilsMessengerEXT != nullptr)
+ vkCreateDebugUtilsMessengerEXT(m_vkInstance, &debugCreateInfo,
+ nullptr, &m_debugMessenger);
+ }
+
#define VK_FUNC_DECL(name) \
_##name = (PFN_##name)vkGetInstanceProcAddr(m_vkInstance, #name); \
// ASSERT_NEQ((unsigned long long)name, 0ULL) << "Couldn't obtain address
@@ -228,6 +315,17 @@
m_physicalDeviceList[pdIdx];
delete &physicalDevice;
}
+
+ _vkDestroyDebugUtilsMessengerEXT =
+ (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
+ m_vkInstance, "vkDestroyDebugUtilsMessengerEXT");
+
+ if (_vkDestroyDebugUtilsMessengerEXT != nullptr)
+ {
+ vkDestroyDebugUtilsMessengerEXT(m_vkInstance, m_debugMessenger,
+ nullptr);
+ }
+
if (m_vkInstance)
{
vkDestroyInstance(m_vkInstance, NULL);
diff --git a/test_conformance/common/vulkan_wrapper/vulkan_wrapper.hpp b/test_conformance/common/vulkan_wrapper/vulkan_wrapper.hpp
index a536d14..04d74c5 100644
--- a/test_conformance/common/vulkan_wrapper/vulkan_wrapper.hpp
+++ b/test_conformance/common/vulkan_wrapper/vulkan_wrapper.hpp
@@ -25,14 +25,21 @@
#include <cassert>
class VulkanInstance {
- friend const VulkanInstance &getVulkanInstance();
+ friend const VulkanInstance &getVulkanInstance(bool useValidationLayers);
protected:
VkInstance m_vkInstance;
VulkanPhysicalDeviceList m_physicalDeviceList;
+ VkDebugUtilsMessengerEXT m_debugMessenger;
+ bool m_useValidationLayers;
+ std::vector<const char *> m_validationLayers = {
+ "VK_LAYER_KHRONOS_validation",
+ };
- VulkanInstance();
VulkanInstance(const VulkanInstance &);
+
+public:
+ VulkanInstance(bool useValidationLayers = false);
virtual ~VulkanInstance();
public:
diff --git a/test_conformance/vulkan/main.cpp b/test_conformance/vulkan/main.cpp
index d2d278d..fdc1e8f 100644
--- a/test_conformance/vulkan/main.cpp
+++ b/test_conformance/vulkan/main.cpp
@@ -31,6 +31,7 @@
#endif
#include "harness/testHarness.h"
+#include "harness/parseParameters.h"
unsigned int numCQ;
bool multiImport;
@@ -38,6 +39,7 @@
bool debug_trace = false;
bool useSingleImageKernel = false;
bool useDeviceLocal = false;
+bool useValidationLayers = false;
bool disableNTHandleType = false;
bool enableOffset = false;
@@ -55,7 +57,15 @@
log_info("\n");
log_info("Options:\n");
log_info("\t--debug_trace - Enables additional debug info logging\n");
- log_info("\t--non_dedicated - Choose dedicated Vs. non_dedicated \n");
+ log_info("\t--useSingleImageKernel - Use the same image "
+ "(image_single_queue and image_multiple_queue tests)\n");
+ log_info("\t--useDeviceLocal - Skip tests that use images with local "
+ "memory type\n");
+ log_info("\t--disableNTHandleType - Skip tests that use win32 external "
+ "memory handle\n");
+ log_info("\t--useValidationLayers - Enables Vulkan validation layer "
+ "diagnostic output\n");
+ log_info("\t-h - Print test usage\n");
}
bool isDeviceSelection(const char *arg)
@@ -70,35 +80,47 @@
|| strcmp(arg, "CL_DEVICE_TYPE_DEFAULT") == 0;
}
-size_t parseParams(int argc, const char *argv[], const char **argList)
+void parseParams(int &argc, const char *argv[])
{
- size_t argCount = 1;
- for (int i = 1; i < argc; i++)
+ argc = parseCustomParam(argc, argv);
+
+ for (int i = 0; i < argc; ++i)
{
+ int argsRemoveNum = 0;
+
if (argv[i] == NULL) break;
if (argv[i][0] == '-')
{
if (!strcmp(argv[i], "--debug_trace"))
{
debug_trace = true;
+ argsRemoveNum = 1;
}
if (!strcmp(argv[i], "--useSingleImageKernel"))
{
useSingleImageKernel = true;
+ argsRemoveNum = 1;
}
if (!strcmp(argv[i], "--useDeviceLocal"))
{
useDeviceLocal = true;
+ argsRemoveNum = 1;
+ }
+ if (!strcmp(argv[i], "--useValidationLayers"))
+ {
+ useValidationLayers = true;
+ argsRemoveNum = 1;
}
if (!strcmp(argv[i], "--disableNTHandleType"))
{
disableNTHandleType = true;
+ argsRemoveNum = 1;
}
if (strcmp(argv[i], "-h") == 0)
{
printUsage(argv[0]);
- argCount = 0; // Returning argCount=0 to assert error in main()
- break;
+ argc = 0; // Returning argCount=0 to assert error in main()
+ return;
}
}
else if (isDeviceSelection(argv[i]))
@@ -108,16 +130,20 @@
&& strcmp(argv[i], "CL_DEVICE_TYPE_DEFAULT") != 0)
{
log_info("Vulkan tests can only run on a GPU device.\n");
- return 0;
+ argc = 0;
+ return;
}
}
- else
+
+ if (argsRemoveNum > 0)
{
- argList[argCount] = argv[i];
- argCount++;
+ for (int j = i; j < (argc - argsRemoveNum); ++j)
+ argv[j] = argv[j + argsRemoveNum];
+
+ argc -= argsRemoveNum;
+ --i;
}
}
- return argCount;
}
int main(int argc, const char *argv[])
@@ -147,9 +173,9 @@
return 0;
}
- const char **argList = (const char **)calloc(argc, sizeof(char *));
- size_t argCount = parseParams(argc, argv, argList);
- if (argCount == 0) return 0;
+ parseParams(argc, argv);
+
+ if (argc == 0) return 0;
return runTestHarness(argc, argv, test_registry::getInstance().num_tests(),
test_registry::getInstance().definitions(), false, 0);
diff --git a/test_conformance/vulkan/vulkan_interop_common.hpp b/test_conformance/vulkan/vulkan_interop_common.hpp
index 6f4d915..4e28533 100644
--- a/test_conformance/vulkan/vulkan_interop_common.hpp
+++ b/test_conformance/vulkan/vulkan_interop_common.hpp
@@ -42,6 +42,7 @@
extern bool useSingleImageKernel;
extern bool useDeviceLocal;
+extern bool useValidationLayers;
extern bool disableNTHandleType;
#endif // _vulkan_interop_common_hpp_
diff --git a/test_conformance/vulkan/vulkan_test_base.h b/test_conformance/vulkan/vulkan_test_base.h
index 82b8e63..8c7b07c 100644
--- a/test_conformance/vulkan/vulkan_test_base.h
+++ b/test_conformance/vulkan/vulkan_test_base.h
@@ -40,8 +40,8 @@
cl_command_queue queue, cl_int nelems)
: device(device), context(context), num_elems(nelems)
{
- vkDevice.reset(
- new VulkanDevice(getAssociatedVulkanPhysicalDevice(device)));
+ vkDevice.reset(new VulkanDevice(
+ getAssociatedVulkanPhysicalDevice(device, useValidationLayers)));
cl_platform_id platform;
cl_int error = clGetDeviceInfo(device, CL_DEVICE_PLATFORM,
@@ -101,7 +101,7 @@
return TEST_SKIPPED_ITSELF;
}
- if (!checkVkSupport())
+ if (!checkVkSupport(useValidationLayers))
{
log_info("Vulkan supported GPU not found \n");
log_info("TEST SKIPPED \n");