From d892e8eaff79b7e6a2d4c7fc3ffbed49b649a845 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 26 Mar 2020 20:42:57 +0100 Subject: [PATCH] Add support for Vulkan 1.1 & 1.2 --- include/Nazara/VulkanRenderer/Vulkan.hpp | 2 +- .../Nazara/VulkanRenderer/VulkanRenderer.hpp | 2 +- .../Wrapper/DeviceFunctions.hpp | 6 +++ .../Wrapper/GlobalFunctions.hpp | 9 ++++ .../VulkanRenderer/Wrapper/Instance.hpp | 20 ++++---- .../VulkanRenderer/Wrapper/Instance.inl | 19 +++++--- .../Wrapper/InstanceFunctions.hpp | 8 ++++ .../Nazara/VulkanRenderer/Wrapper/Loader.hpp | 13 +++--- src/Nazara/VulkanRenderer/Vulkan.cpp | 29 ++++++++++-- src/Nazara/VulkanRenderer/Wrapper/Device.cpp | 15 +++++- .../VulkanRenderer/Wrapper/Instance.cpp | 19 ++++++-- src/Nazara/VulkanRenderer/Wrapper/Loader.cpp | 46 ++++++++++++++----- 12 files changed, 143 insertions(+), 45 deletions(-) create mode 100644 include/Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp diff --git a/include/Nazara/VulkanRenderer/Vulkan.hpp b/include/Nazara/VulkanRenderer/Vulkan.hpp index bffff2e1a..f3c40959c 100644 --- a/include/Nazara/VulkanRenderer/Vulkan.hpp +++ b/include/Nazara/VulkanRenderer/Vulkan.hpp @@ -44,7 +44,7 @@ namespace Nz static const std::vector& GetPhysicalDevices(); static const Vk::PhysicalDevice& GetPhysicalDeviceInfo(VkPhysicalDevice physDevice); - static bool Initialize(UInt32 apiVersion, const ParameterList& parameters); + static bool Initialize(UInt32 targetApiVersion, const ParameterList& parameters); static bool IsInitialized(); diff --git a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp index 62bd426ca..2d7b2f779 100644 --- a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp @@ -39,7 +39,7 @@ namespace Nz bool Prepare(const ParameterList& parameters) override; - static constexpr UInt32 APIVersion = VK_API_VERSION_1_0; + static constexpr UInt32 APIVersion = VK_API_VERSION_1_2; private: std::list m_devices; diff --git a/include/Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp b/include/Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp index 2b3b03564..6c76c4e7e 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp @@ -119,6 +119,12 @@ NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUnmapMemory) NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUpdateDescriptorSets) NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkWaitForFences) +NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(vkBindBufferMemory2, VK_API_VERSION_1_1, KHR, bind_memory2) +NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(vkBindImageMemory2, VK_API_VERSION_1_1, KHR, bind_memory2) + +NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(vkGetBufferMemoryRequirements2, VK_API_VERSION_1_1, KHR, get_memory_requirements2) +NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(vkGetImageMemoryRequirements2, VK_API_VERSION_1_1, KHR, get_memory_requirements2) + NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN(VK_KHR_display_swapchain) NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSharedSwapchainsKHR) NAZARA_VULKANRENDERER_DEVICE_EXT_END() diff --git a/include/Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp b/include/Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp new file mode 100644 index 000000000..a1ee8a8dc --- /dev/null +++ b/include/Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp @@ -0,0 +1,9 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Vulkan core +NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkCreateInstance) +NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties) +NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties) +NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT(vkEnumerateInstanceVersion) diff --git a/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp b/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp index 5ec96ec0d..3d3e86df8 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/Instance.hpp @@ -8,10 +8,10 @@ #define NAZARA_VULKANRENDERER_VKINSTANCE_HPP #include -#include #include #include #include +#include #include namespace Nz @@ -27,13 +27,16 @@ namespace Nz inline ~Instance(); bool Create(const VkInstanceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); - inline bool Create(const String& appName, UInt32 appVersion, const String& engineName, UInt32 engineVersion, const std::vector& layers, const std::vector& extensions, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(const std::string& appName, UInt32 appVersion, const std::string& engineName, UInt32 engineVersion, const std::vector& layers, const std::vector& extensions, const VkAllocationCallbacks* allocator = nullptr); inline void Destroy(); bool EnumeratePhysicalDevices(std::vector* physicalDevices); inline PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name); + inline UInt32 GetApiVersion() const; + inline VkResult GetLastErrorCode() const; + bool GetPhysicalDeviceExtensions(VkPhysicalDevice device, std::vector* extensionProperties); inline VkPhysicalDeviceFeatures GetPhysicalDeviceFeatures(VkPhysicalDevice device); inline VkFormatProperties GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format); @@ -42,10 +45,8 @@ namespace Nz inline VkPhysicalDeviceProperties GetPhysicalDeviceProperties(VkPhysicalDevice device); bool GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector* queueFamilyProperties); - inline VkResult GetLastErrorCode() const; - - inline bool IsExtensionLoaded(const String& extensionName); - inline bool IsLayerLoaded(const String& layerName); + inline bool IsExtensionLoaded(const std::string& extensionName); + inline bool IsLayerLoaded(const std::string& layerName); inline bool IsValid() const; Instance& operator=(const Instance&) = delete; @@ -57,9 +58,11 @@ namespace Nz #define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext) #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) PFN_##func func; +#define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, ...) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) #include +#undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION @@ -73,8 +76,9 @@ namespace Nz VkAllocationCallbacks m_allocator; VkInstance m_instance; VkResult m_lastErrorCode; - std::unordered_set m_loadedExtensions; - std::unordered_set m_loadedLayers; + UInt32 m_apiVersion; + std::unordered_set m_loadedExtensions; + std::unordered_set m_loadedLayers; }; } } diff --git a/include/Nazara/VulkanRenderer/Wrapper/Instance.inl b/include/Nazara/VulkanRenderer/Wrapper/Instance.inl index 50feca010..64224d746 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Instance.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/Instance.inl @@ -23,15 +23,15 @@ namespace Nz DestroyInstance(); } - inline bool Instance::Create(const String& appName, UInt32 appVersion, const String& engineName, UInt32 engineVersion, const std::vector& layers, const std::vector& extensions, const VkAllocationCallbacks* allocator) + inline bool Instance::Create(const std::string& appName, UInt32 appVersion, const std::string& engineName, UInt32 engineVersion, const std::vector& layers, const std::vector& extensions, const VkAllocationCallbacks* allocator) { VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, - appName.GetConstBuffer(), + appName.data(), appVersion, - engineName.GetConstBuffer(), + engineName.data(), engineVersion }; @@ -63,22 +63,27 @@ namespace Nz { PFN_vkVoidFunction func = vkGetDeviceProcAddr(device, name); if (!func) - NazaraError("Failed to get " + String(name) + " address"); + NazaraError("Failed to get " + std::string(name) + " address"); return func; } + inline UInt32 Instance::GetApiVersion() const + { + return m_apiVersion; + } + inline VkResult Instance::GetLastErrorCode() const { return m_lastErrorCode; } - inline bool Instance::IsExtensionLoaded(const String& extensionName) + inline bool Instance::IsExtensionLoaded(const std::string& extensionName) { return m_loadedExtensions.count(extensionName) > 0; } - inline bool Instance::IsLayerLoaded(const String& layerName) + inline bool Instance::IsLayerLoaded(const std::string& layerName) { return m_loadedLayers.count(layerName) > 0; } @@ -149,7 +154,7 @@ namespace Nz { PFN_vkVoidFunction func = Loader::GetInstanceProcAddr(m_instance, name); if (!func) - NazaraError("Failed to get " + String(name) + " address"); + NazaraError("Failed to get " + std::string(name) + " address"); return func; } diff --git a/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp b/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp index a08459ba5..25e9235c0 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp @@ -15,6 +15,14 @@ NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceFeatures2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceProperties2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceFormatProperties2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceImageFormatProperties2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceMemoryProperties2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) +NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(vkGetPhysicalDeviceSparseImageFormatProperties2, VK_API_VERSION_1_1, KHR, get_physical_device_properties2) + NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(VK_KHR_display) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayModeKHR) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayPlaneSurfaceKHR) diff --git a/include/Nazara/VulkanRenderer/Wrapper/Loader.hpp b/include/Nazara/VulkanRenderer/Wrapper/Loader.hpp index c4d584132..5a0e77e45 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/Loader.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/Loader.hpp @@ -31,14 +31,15 @@ namespace Nz static void Uninitialize(); // Vulkan functions - #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) static PFN_##func func + static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkCreateInstance); - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties); - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties); - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkGetInstanceProcAddr); +#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) static PFN_##func func; +#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT NAZARA_VULKANRENDERER_GLOBAL_FUNCTION - #undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION +#include + +#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT +#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION private: static DynLib s_vulkanLib; diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index a3bab8bbf..49dffd8b6 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Nz @@ -40,7 +41,7 @@ namespace Nz return dummy; } - bool Vulkan::Initialize(UInt32 apiVersion, const ParameterList& parameters) + bool Vulkan::Initialize(UInt32 targetApiVersion, const ParameterList& parameters) { NazaraAssert(!IsInitialized(), "Vulkan is already initialized"); @@ -66,7 +67,7 @@ namespace Nz long long iParam; if (parameters.GetIntegerParameter("VkAppInfo_OverrideAPIVersion", &iParam)) - apiVersion = static_cast(iParam); + targetApiVersion = static_cast(iParam); if (parameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion", &iParam)) appVersion = static_cast(iParam); @@ -74,6 +75,17 @@ namespace Nz if (parameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion", &iParam)) engineVersion = static_cast(iParam); + if (Vk::Loader::vkEnumerateInstanceVersion) + { + UInt32 supportedApiVersion; + Vk::Loader::vkEnumerateInstanceVersion(&supportedApiVersion); + + targetApiVersion = std::min(targetApiVersion, supportedApiVersion); + } + else + // vkEnumerateInstanceVersion is available from Vulkan 1.1, fallback to 1.0 if not supported + targetApiVersion = VK_API_VERSION_1_0; + VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, @@ -81,7 +93,7 @@ namespace Nz appVersion, engineName.GetConstBuffer(), engineVersion, - apiVersion + targetApiVersion }; VkInstanceCreateFlags createFlags = 0; @@ -115,6 +127,15 @@ namespace Nz } } + // Get extension list + std::unordered_set availableExtensions; + std::vector extensionList; + if (Vk::Loader::EnumerateInstanceExtensionProperties(&extensionList)) + { + for (VkExtensionProperties& extProperty : extensionList) + availableExtensions.insert(extProperty.extensionName); + } + if (!parameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledExtensions", &bParam) || !bParam) { enabledExtensions.push_back("VK_KHR_surface"); @@ -401,7 +422,7 @@ namespace Nz if (!s_initializationParameters.GetBooleanParameter("VkDeviceInfo_OverrideEnabledExtensions", &bParam) || !bParam) { // Swapchain extension is required for rendering - enabledExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + enabledExtensions.emplace_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); } diff --git a/src/Nazara/VulkanRenderer/Wrapper/Device.cpp b/src/Nazara/VulkanRenderer/Wrapper/Device.cpp index 4c566fb30..29bd02b86 100644 --- a/src/Nazara/VulkanRenderer/Wrapper/Device.cpp +++ b/src/Nazara/VulkanRenderer/Wrapper/Device.cpp @@ -69,12 +69,21 @@ namespace Nz { ErrorFlags flags(ErrorFlag_ThrowException, true); + UInt32 deviceVersion = deviceInfo.properties.apiVersion; + #define NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN(ext) if (IsExtensionLoaded(#ext)) { #define NAZARA_VULKANRENDERER_DEVICE_EXT_END() } #define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = reinterpret_cast(GetProcAddr(#func)); +#define NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(func, coreVersion, suffix, extName) \ + if (deviceVersion >= coreVersion) \ + func = reinterpret_cast(GetProcAddr(#func)); \ + else if (IsExtensionLoaded("VK_" #suffix "_" #extName)) \ + func = reinterpret_cast(GetProcAddr(#func #suffix)); + #include +#undef NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION #undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_DEVICE_EXT_END #undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION @@ -164,15 +173,17 @@ namespace Nz m_physicalDevice = nullptr; // Reset functions pointers +#define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = nullptr; +#define NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(func, ...) NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) #define NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN(ext) #define NAZARA_VULKANRENDERER_DEVICE_EXT_END() -#define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = nullptr; #include +#undef NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION +#undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION #undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_DEVICE_EXT_END -#undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION } void Device::WaitAndDestroyDevice() diff --git a/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp b/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp index e70f2ef9d..8d88817a4 100644 --- a/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp +++ b/src/Nazara/VulkanRenderer/Wrapper/Instance.cpp @@ -21,6 +21,8 @@ namespace Nz return false; } + m_apiVersion = createInfo.pApplicationInfo->apiVersion; + // Store the allocator to access them when needed if (allocator) m_allocator = *allocator; @@ -43,15 +45,22 @@ namespace Nz #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() } #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = reinterpret_cast(GetProcAddr(#func)); +#define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, coreVersion, suffix, extName) \ + if (m_apiVersion >= coreVersion) \ + func = reinterpret_cast(GetProcAddr(#func)); \ + else if (IsExtensionLoaded("VK_" #suffix "_" #extName)) \ + func = reinterpret_cast(GetProcAddr(#func #suffix)); + #include +#undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION } catch (const std::exception& e) { - NazaraError(String("Failed to query instance function: ") + e.what()); + NazaraError(std::string("Failed to query instance function: ") + e.what()); return false; } @@ -87,8 +96,8 @@ namespace Nz { NazaraAssert(extensionProperties, "Invalid extension properties vector"); - // First, query physical device count - UInt32 extensionPropertyCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + // First, query extension count + UInt32 extensionPropertyCount = 0; m_lastErrorCode = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionPropertyCount, nullptr); if (m_lastErrorCode != VkResult::VK_SUCCESS) { @@ -99,7 +108,7 @@ namespace Nz if (extensionPropertyCount == 0) return true; //< No extension available - // Now we can get the list of the available physical device + // Now we can get the list of the available extensions extensionProperties->resize(extensionPropertyCount); m_lastErrorCode = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionPropertyCount, extensionProperties->data()); if (m_lastErrorCode != VkResult::VK_SUCCESS) @@ -139,9 +148,11 @@ namespace Nz #define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext) #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = nullptr; +#define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, ...) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) #include +#undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION diff --git a/src/Nazara/VulkanRenderer/Wrapper/Loader.cpp b/src/Nazara/VulkanRenderer/Wrapper/Loader.cpp index fd7aed2ac..89a6843de 100644 --- a/src/Nazara/VulkanRenderer/Wrapper/Loader.cpp +++ b/src/Nazara/VulkanRenderer/Wrapper/Loader.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -77,7 +78,7 @@ namespace Nz return false; } - // vkGetInstanceProcAddr is the only function that's garantee to be exported + // vkGetInstanceProcAddr is the only function that's guarantee to be exported vkGetInstanceProcAddr = reinterpret_cast(s_vulkanLib.GetSymbol("vkGetInstanceProcAddr")); if (!vkGetInstanceProcAddr) { @@ -85,28 +86,49 @@ namespace Nz return false; } + auto GetProcAddr = [&](const char* name, bool opt) + { + PFN_vkVoidFunction func = vkGetInstanceProcAddr(nullptr, name); + if (!func && !opt) + NazaraError("Failed to get " + std::string(name) + " address"); + + return func; + }; + // all other functions should be loaded using vkGetInstanceProcAddr - #define NAZARA_VULKANRENDERER_LOAD_GLOBAL(func) func = reinterpret_cast(vkGetInstanceProcAddr(nullptr, #func)) + #define NAZARA_VULKANRENDERER_LOAD_GLOBAL(func) func = reinterpret_cast(GetProcAddr(#func)) + try + { + ErrorFlags flags(ErrorFlag_ThrowException, true); - NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkCreateInstance); - NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkEnumerateInstanceExtensionProperties); - NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkEnumerateInstanceLayerProperties); +#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) func = reinterpret_cast(GetProcAddr(#func, false)); +#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT(func) func = reinterpret_cast(GetProcAddr(#func, true)); - #undef NAZARA_VULKANRENDERER_LOAD_GLOBAL +#include + +#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT +#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION + } + catch (const std::exception& e) + { + NazaraError(std::string("Failed to query device function: ") + e.what()); + return false; + } s_lastErrorCode = VkResult::VK_SUCCESS; return true; } - #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(func) PFN_##func Loader::func = nullptr + PFN_vkGetInstanceProcAddr Loader::vkGetInstanceProcAddr = nullptr; - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkCreateInstance); - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceExtensionProperties); - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceLayerProperties); - NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkGetInstanceProcAddr); +#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) PFN_##func Loader::func = nullptr; +#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT NAZARA_VULKANRENDERER_GLOBAL_FUNCTION - #undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL +#include + +#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT +#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION DynLib Loader::s_vulkanLib; VkResult Loader::s_lastErrorCode;