From 5cb0036376a36d36a16d997b11b7451f90d00d97 Mon Sep 17 00:00:00 2001 From: Marcin Hajder Date: Fri, 24 Jan 2025 15:29:29 +0100 Subject: [PATCH] Added support for vulkan validation layers --- .../vulkan_wrapper/opencl_vulkan_wrapper.cpp | 3 +- .../common/vulkan_wrapper/vulkan_api_list.hpp | 6 +- .../common/vulkan_wrapper/vulkan_utility.cpp | 19 ++-- .../common/vulkan_wrapper/vulkan_utility.hpp | 10 +- .../common/vulkan_wrapper/vulkan_wrapper.cpp | 102 +++++++++++++++++- .../common/vulkan_wrapper/vulkan_wrapper.hpp | 9 +- test_conformance/vulkan/main.cpp | 44 +++++--- .../vulkan/vulkan_interop_common.hpp | 1 + test_conformance/vulkan/vulkan_test_base.h | 6 +- 9 files changed, 165 insertions(+), 35 deletions(-) diff --git a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp index ded1e7092b..560d3678a7 100644 --- a/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp +++ b/test_conformance/common/vulkan_wrapper/opencl_vulkan_wrapper.cpp @@ -1191,6 +1191,8 @@ cl_external_memory_handle_type_khr vkToOpenCLExternalMemoryHandleType( { switch (vkExternalMemoryHandleType) { + default: + case VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE: 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 +1200,6 @@ cl_external_memory_handle_type_khr vkToOpenCLExternalMemoryHandleType( 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 ab4acb431a..46965ef961 100644 --- a/test_conformance/common/vulkan_wrapper/vulkan_api_list.hpp +++ b/test_conformance/common/vulkan_wrapper/vulkan_api_list.hpp @@ -101,7 +101,9 @@ VK_FUNC_DECL(vkGetPhysicalDeviceSurfaceSupportKHR) \ VK_FUNC_DECL(vkImportSemaphoreFdKHR) \ VK_FUNC_DECL(vkGetPhysicalDeviceExternalSemaphorePropertiesKHR) \ - VK_FUNC_DECL(vkGetImageSubresourceLayout) + VK_FUNC_DECL(vkGetImageSubresourceLayout) \ + VK_FUNC_DECL(vkCreateDebugUtilsMessengerEXT) \ + VK_FUNC_DECL(vkDestroyDebugUtilsMessengerEXT) #define VK_WINDOWS_FUNC_LIST \ VK_FUNC_DECL(vkGetMemoryWin32HandleKHR) \ VK_FUNC_DECL(vkGetSemaphoreWin32HandleKHR) \ @@ -202,5 +204,7 @@ #define vkGetSemaphoreWin32HandleKHR _vkGetSemaphoreWin32HandleKHR #define vkImportSemaphoreWin32HandleKHR _vkImportSemaphoreWin32HandleKHR #define vkGetImageSubresourceLayout _vkGetImageSubresourceLayout +#define vkCreateDebugUtilsMessengerEXT _vkCreateDebugUtilsMessengerEXT +#define vkDestroyDebugUtilsMessengerEXT _vkDestroyDebugUtilsMessengerEXT #endif //_vulkan_api_list_hpp_ diff --git a/test_conformance/common/vulkan_wrapper/vulkan_utility.cpp b/test_conformance/common/vulkan_wrapper/vulkan_utility.cpp index e4796bc9d0..e528efc430 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 @@ const VulkanPhysicalDevice &getVulkanPhysicalDevice() 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 &getVulkanPhysicalDevice() } 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 @@ getVulkanMemoryType(const VulkanDevice &device, 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) @@ -695,6 +696,7 @@ operator<<(std::ostream &os, { 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"; @@ -715,6 +717,7 @@ operator<<(std::ostream &os, { 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 486ad97c80..c6f154e5ea 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 VulkanQueueFamily& getVulkanQueueFamily( 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 6c31a35d48..cec9c9d691 100644 --- a/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp +++ b/test_conformance/common/vulkan_wrapper/vulkan_wrapper.cpp @@ -48,16 +48,38 @@ VK_WINDOWS_FUNC_LIST #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,25 @@ VulkanInstance::VulkanInstance(): m_vkInstance(VK_NULL_HANDLE) 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 layers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, layers.data()); + + bool found = false; + for (const char *layerName : m_validationLayers) + for (const auto &layerProps : layers) + if (strcmp(layerName, layerProps.layerName) == 0) + { + found = true; + break; + } + m_useValidationLayers = found; + } + VkApplicationInfo vkApplicationInfo = {}; vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; vkApplicationInfo.pNext = NULL; @@ -147,6 +188,9 @@ VulkanInstance::VulkanInstance(): m_vkInstance(VK_NULL_HANDLE) enabledExtensionNameList.push_back( VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); + if (m_useValidationLayers) + enabledExtensionNameList.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + std::vector vkExtensionPropertiesList( instanceExtensionPropertiesCount); vkEnumerateInstanceExtensionProperties(NULL, @@ -174,18 +218,57 @@ VulkanInstance::VulkanInstance(): m_vkInstance(VK_NULL_HANDLE) 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(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; + + // VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT + // VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT + // VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT + // VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT + debugCreateInfo.messageSeverity |= + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_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 +311,17 @@ VulkanInstance::~VulkanInstance() 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 a536d140a8..e28c259843 100644 --- a/test_conformance/common/vulkan_wrapper/vulkan_wrapper.hpp +++ b/test_conformance/common/vulkan_wrapper/vulkan_wrapper.hpp @@ -30,9 +30,16 @@ class VulkanInstance { protected: VkInstance m_vkInstance; VulkanPhysicalDeviceList m_physicalDeviceList; + VkDebugUtilsMessengerEXT m_debugMessenger; + bool m_useValidationLayers; + const std::vector 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 7be31b231a..0564af4131 100644 --- a/test_conformance/vulkan/main.cpp +++ b/test_conformance/vulkan/main.cpp @@ -32,6 +32,7 @@ #include "procs.h" #include "harness/testHarness.h" +#include "harness/parseParameters.h" #if !defined(_WIN32) #include @@ -65,6 +66,7 @@ bool multiCtx; bool debug_trace = false; bool useSingleImageKernel = false; bool useDeviceLocal = false; +bool useValidationLayers = false; bool disableNTHandleType = false; bool enableOffset = false; @@ -97,35 +99,47 @@ bool isDeviceSelection(const char *arg) || 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])) @@ -135,16 +149,20 @@ size_t parseParams(int argc, const char *argv[], const char **argList) && 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[]) @@ -174,9 +192,9 @@ int main(int argc, const char *argv[]) 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_num, test_list, false, 0); } diff --git a/test_conformance/vulkan/vulkan_interop_common.hpp b/test_conformance/vulkan/vulkan_interop_common.hpp index 6f4d91555f..4e2853357f 100644 --- a/test_conformance/vulkan/vulkan_interop_common.hpp +++ b/test_conformance/vulkan/vulkan_interop_common.hpp @@ -42,6 +42,7 @@ extern bool debug_trace; 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 d4cfa68446..f109198de4 100644 --- a/test_conformance/vulkan/vulkan_test_base.h +++ b/test_conformance/vulkan/vulkan_test_base.h @@ -40,8 +40,8 @@ struct VulkanTestBase 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))); if (!(is_extension_available(device, "cl_khr_external_memory") && is_extension_available(device, "cl_khr_external_semaphore"))) @@ -101,7 +101,7 @@ template int MakeAndRunTest(cl_device_id device, cl_context context, cl_command_queue queue, cl_int nelems) { - if (!checkVkSupport()) + if (!checkVkSupport(useValidationLayers)) { log_info("Vulkan supported GPU not found \n"); log_info("TEST SKIPPED \n");