Add support for Vulkan 1.1 & 1.2

This commit is contained in:
Lynix 2020-03-26 20:42:57 +01:00
parent 42d58bd77c
commit d892e8eaff
12 changed files with 143 additions and 45 deletions

View File

@ -44,7 +44,7 @@ namespace Nz
static const std::vector<Vk::PhysicalDevice>& GetPhysicalDevices(); static const std::vector<Vk::PhysicalDevice>& GetPhysicalDevices();
static const Vk::PhysicalDevice& GetPhysicalDeviceInfo(VkPhysicalDevice physDevice); 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(); static bool IsInitialized();

View File

@ -39,7 +39,7 @@ namespace Nz
bool Prepare(const ParameterList& parameters) override; 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: private:
std::list<Vk::Device> m_devices; std::list<Vk::Device> m_devices;

View File

@ -119,6 +119,12 @@ NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUnmapMemory)
NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUpdateDescriptorSets) NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUpdateDescriptorSets)
NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkWaitForFences) 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_EXT_BEGIN(VK_KHR_display_swapchain)
NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSharedSwapchainsKHR) NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSharedSwapchainsKHR)
NAZARA_VULKANRENDERER_DEVICE_EXT_END() NAZARA_VULKANRENDERER_DEVICE_EXT_END()

View File

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

View File

@ -8,10 +8,10 @@
#define NAZARA_VULKANRENDERER_VKINSTANCE_HPP #define NAZARA_VULKANRENDERER_VKINSTANCE_HPP
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/VulkanRenderer/Config.hpp> #include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp> #include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <string>
#include <unordered_set> #include <unordered_set>
namespace Nz namespace Nz
@ -27,13 +27,16 @@ namespace Nz
inline ~Instance(); inline ~Instance();
bool Create(const VkInstanceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); 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<const char*>& layers, const std::vector<const char*>& extensions, const VkAllocationCallbacks* allocator = nullptr); inline bool Create(const std::string& appName, UInt32 appVersion, const std::string& engineName, UInt32 engineVersion, const std::vector<const char*>& layers, const std::vector<const char*>& extensions, const VkAllocationCallbacks* allocator = nullptr);
inline void Destroy(); inline void Destroy();
bool EnumeratePhysicalDevices(std::vector<VkPhysicalDevice>* physicalDevices); bool EnumeratePhysicalDevices(std::vector<VkPhysicalDevice>* physicalDevices);
inline PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name); inline PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name);
inline UInt32 GetApiVersion() const;
inline VkResult GetLastErrorCode() const;
bool GetPhysicalDeviceExtensions(VkPhysicalDevice device, std::vector<VkExtensionProperties>* extensionProperties); bool GetPhysicalDeviceExtensions(VkPhysicalDevice device, std::vector<VkExtensionProperties>* extensionProperties);
inline VkPhysicalDeviceFeatures GetPhysicalDeviceFeatures(VkPhysicalDevice device); inline VkPhysicalDeviceFeatures GetPhysicalDeviceFeatures(VkPhysicalDevice device);
inline VkFormatProperties GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format); inline VkFormatProperties GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format);
@ -42,10 +45,8 @@ namespace Nz
inline VkPhysicalDeviceProperties GetPhysicalDeviceProperties(VkPhysicalDevice device); inline VkPhysicalDeviceProperties GetPhysicalDeviceProperties(VkPhysicalDevice device);
bool GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector<VkQueueFamilyProperties>* queueFamilyProperties); bool GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector<VkQueueFamilyProperties>* queueFamilyProperties);
inline VkResult GetLastErrorCode() const; inline bool IsExtensionLoaded(const std::string& extensionName);
inline bool IsLayerLoaded(const std::string& layerName);
inline bool IsExtensionLoaded(const String& extensionName);
inline bool IsLayerLoaded(const String& layerName);
inline bool IsValid() const; inline bool IsValid() const;
Instance& operator=(const Instance&) = delete; Instance& operator=(const Instance&) = delete;
@ -57,9 +58,11 @@ namespace Nz
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext) #define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext)
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END()
#define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) PFN_##func func; #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) PFN_##func func;
#define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, ...) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func)
#include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp> #include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END
#undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION
@ -73,8 +76,9 @@ namespace Nz
VkAllocationCallbacks m_allocator; VkAllocationCallbacks m_allocator;
VkInstance m_instance; VkInstance m_instance;
VkResult m_lastErrorCode; VkResult m_lastErrorCode;
std::unordered_set<String> m_loadedExtensions; UInt32 m_apiVersion;
std::unordered_set<String> m_loadedLayers; std::unordered_set<std::string> m_loadedExtensions;
std::unordered_set<std::string> m_loadedLayers;
}; };
} }
} }

View File

@ -23,15 +23,15 @@ namespace Nz
DestroyInstance(); DestroyInstance();
} }
inline bool Instance::Create(const String& appName, UInt32 appVersion, const String& engineName, UInt32 engineVersion, const std::vector<const char*>& layers, const std::vector<const char*>& extensions, const VkAllocationCallbacks* allocator) inline bool Instance::Create(const std::string& appName, UInt32 appVersion, const std::string& engineName, UInt32 engineVersion, const std::vector<const char*>& layers, const std::vector<const char*>& extensions, const VkAllocationCallbacks* allocator)
{ {
VkApplicationInfo appInfo = VkApplicationInfo appInfo =
{ {
VK_STRUCTURE_TYPE_APPLICATION_INFO, VK_STRUCTURE_TYPE_APPLICATION_INFO,
nullptr, nullptr,
appName.GetConstBuffer(), appName.data(),
appVersion, appVersion,
engineName.GetConstBuffer(), engineName.data(),
engineVersion engineVersion
}; };
@ -63,22 +63,27 @@ namespace Nz
{ {
PFN_vkVoidFunction func = vkGetDeviceProcAddr(device, name); PFN_vkVoidFunction func = vkGetDeviceProcAddr(device, name);
if (!func) if (!func)
NazaraError("Failed to get " + String(name) + " address"); NazaraError("Failed to get " + std::string(name) + " address");
return func; return func;
} }
inline UInt32 Instance::GetApiVersion() const
{
return m_apiVersion;
}
inline VkResult Instance::GetLastErrorCode() const inline VkResult Instance::GetLastErrorCode() const
{ {
return m_lastErrorCode; return m_lastErrorCode;
} }
inline bool Instance::IsExtensionLoaded(const String& extensionName) inline bool Instance::IsExtensionLoaded(const std::string& extensionName)
{ {
return m_loadedExtensions.count(extensionName) > 0; 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; return m_loadedLayers.count(layerName) > 0;
} }
@ -149,7 +154,7 @@ namespace Nz
{ {
PFN_vkVoidFunction func = Loader::GetInstanceProcAddr(m_instance, name); PFN_vkVoidFunction func = Loader::GetInstanceProcAddr(m_instance, name);
if (!func) if (!func)
NazaraError("Failed to get " + String(name) + " address"); NazaraError("Failed to get " + std::string(name) + " address");
return func; return func;
} }

View File

@ -15,6 +15,14 @@ NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) 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_EXT_BEGIN(VK_KHR_display)
NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayModeKHR) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayModeKHR)
NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayPlaneSurfaceKHR) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayPlaneSurfaceKHR)

View File

@ -31,14 +31,15 @@ namespace Nz
static void Uninitialize(); static void Uninitialize();
// Vulkan functions // Vulkan functions
#define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) static PFN_##func func static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkCreateInstance); #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) static PFN_##func func;
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties); #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT NAZARA_VULKANRENDERER_GLOBAL_FUNCTION
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties);
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkGetInstanceProcAddr);
#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION #include <Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp>
#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT
#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION
private: private:
static DynLib s_vulkanLib; static DynLib s_vulkanLib;

View File

@ -11,6 +11,7 @@
#include <Nazara/VulkanRenderer/Config.hpp> #include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/VulkanDevice.hpp> #include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <array> #include <array>
#include <unordered_set>
#include <Nazara/VulkanRenderer/Debug.hpp> #include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz namespace Nz
@ -40,7 +41,7 @@ namespace Nz
return dummy; return dummy;
} }
bool Vulkan::Initialize(UInt32 apiVersion, const ParameterList& parameters) bool Vulkan::Initialize(UInt32 targetApiVersion, const ParameterList& parameters)
{ {
NazaraAssert(!IsInitialized(), "Vulkan is already initialized"); NazaraAssert(!IsInitialized(), "Vulkan is already initialized");
@ -66,7 +67,7 @@ namespace Nz
long long iParam; long long iParam;
if (parameters.GetIntegerParameter("VkAppInfo_OverrideAPIVersion", &iParam)) if (parameters.GetIntegerParameter("VkAppInfo_OverrideAPIVersion", &iParam))
apiVersion = static_cast<UInt32>(iParam); targetApiVersion = static_cast<UInt32>(iParam);
if (parameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion", &iParam)) if (parameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion", &iParam))
appVersion = static_cast<UInt32>(iParam); appVersion = static_cast<UInt32>(iParam);
@ -74,6 +75,17 @@ namespace Nz
if (parameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion", &iParam)) if (parameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion", &iParam))
engineVersion = static_cast<UInt32>(iParam); engineVersion = static_cast<UInt32>(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 = { VkApplicationInfo appInfo = {
VK_STRUCTURE_TYPE_APPLICATION_INFO, VK_STRUCTURE_TYPE_APPLICATION_INFO,
nullptr, nullptr,
@ -81,7 +93,7 @@ namespace Nz
appVersion, appVersion,
engineName.GetConstBuffer(), engineName.GetConstBuffer(),
engineVersion, engineVersion,
apiVersion targetApiVersion
}; };
VkInstanceCreateFlags createFlags = 0; VkInstanceCreateFlags createFlags = 0;
@ -115,6 +127,15 @@ namespace Nz
} }
} }
// Get extension list
std::unordered_set<std::string> availableExtensions;
std::vector<VkExtensionProperties> extensionList;
if (Vk::Loader::EnumerateInstanceExtensionProperties(&extensionList))
{
for (VkExtensionProperties& extProperty : extensionList)
availableExtensions.insert(extProperty.extensionName);
}
if (!parameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledExtensions", &bParam) || !bParam) if (!parameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledExtensions", &bParam) || !bParam)
{ {
enabledExtensions.push_back("VK_KHR_surface"); enabledExtensions.push_back("VK_KHR_surface");
@ -401,7 +422,7 @@ namespace Nz
if (!s_initializationParameters.GetBooleanParameter("VkDeviceInfo_OverrideEnabledExtensions", &bParam) || !bParam) if (!s_initializationParameters.GetBooleanParameter("VkDeviceInfo_OverrideEnabledExtensions", &bParam) || !bParam)
{ {
// Swapchain extension is required for rendering // Swapchain extension is required for rendering
enabledExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); enabledExtensions.emplace_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
} }

View File

@ -69,12 +69,21 @@ namespace Nz
{ {
ErrorFlags flags(ErrorFlag_ThrowException, true); 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_BEGIN(ext) if (IsExtensionLoaded(#ext)) {
#define NAZARA_VULKANRENDERER_DEVICE_EXT_END() } #define NAZARA_VULKANRENDERER_DEVICE_EXT_END() }
#define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func)); #define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func));
#define NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION(func, coreVersion, suffix, extName) \
if (deviceVersion >= coreVersion) \
func = reinterpret_cast<PFN_##func>(GetProcAddr(#func)); \
else if (IsExtensionLoaded("VK_" #suffix "_" #extName)) \
func = reinterpret_cast<PFN_##func##suffix>(GetProcAddr(#func #suffix));
#include <Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp> #include <Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION
#undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_DEVICE_EXT_END #undef NAZARA_VULKANRENDERER_DEVICE_EXT_END
#undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION #undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION
@ -164,15 +173,17 @@ namespace Nz
m_physicalDevice = nullptr; m_physicalDevice = nullptr;
// Reset functions pointers // 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_BEGIN(ext)
#define NAZARA_VULKANRENDERER_DEVICE_EXT_END() #define NAZARA_VULKANRENDERER_DEVICE_EXT_END()
#define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = nullptr;
#include <Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp> #include <Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_DEVICE_CORE_EXT_FUNCTION
#undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION
#undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_DEVICE_EXT_END #undef NAZARA_VULKANRENDERER_DEVICE_EXT_END
#undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION
} }
void Device::WaitAndDestroyDevice() void Device::WaitAndDestroyDevice()

View File

@ -21,6 +21,8 @@ namespace Nz
return false; return false;
} }
m_apiVersion = createInfo.pApplicationInfo->apiVersion;
// Store the allocator to access them when needed // Store the allocator to access them when needed
if (allocator) if (allocator)
m_allocator = *allocator; m_allocator = *allocator;
@ -43,15 +45,22 @@ namespace Nz
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() } #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() }
#define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func)); #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func));
#define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, coreVersion, suffix, extName) \
if (m_apiVersion >= coreVersion) \
func = reinterpret_cast<PFN_##func>(GetProcAddr(#func)); \
else if (IsExtensionLoaded("VK_" #suffix "_" #extName)) \
func = reinterpret_cast<PFN_##func##suffix>(GetProcAddr(#func #suffix));
#include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp> #include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END
#undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION
} }
catch (const std::exception& e) 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; return false;
} }
@ -87,8 +96,8 @@ namespace Nz
{ {
NazaraAssert(extensionProperties, "Invalid extension properties vector"); NazaraAssert(extensionProperties, "Invalid extension properties vector");
// First, query physical device count // First, query extension count
UInt32 extensionPropertyCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t UInt32 extensionPropertyCount = 0;
m_lastErrorCode = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionPropertyCount, nullptr); m_lastErrorCode = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionPropertyCount, nullptr);
if (m_lastErrorCode != VkResult::VK_SUCCESS) if (m_lastErrorCode != VkResult::VK_SUCCESS)
{ {
@ -99,7 +108,7 @@ namespace Nz
if (extensionPropertyCount == 0) if (extensionPropertyCount == 0)
return true; //< No extension available 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); extensionProperties->resize(extensionPropertyCount);
m_lastErrorCode = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionPropertyCount, extensionProperties->data()); m_lastErrorCode = vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionPropertyCount, extensionProperties->data());
if (m_lastErrorCode != VkResult::VK_SUCCESS) if (m_lastErrorCode != VkResult::VK_SUCCESS)
@ -139,9 +148,11 @@ namespace Nz
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext) #define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext)
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_END() #define NAZARA_VULKANRENDERER_INSTANCE_EXT_END()
#define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = nullptr; #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = nullptr;
#define NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION(func, ...) NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func)
#include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp> #include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_INSTANCE_CORE_EXT_FUNCTION
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END #undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END
#undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION

View File

@ -4,6 +4,7 @@
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp> #include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/VulkanRenderer/Utils.hpp> #include <Nazara/VulkanRenderer/Utils.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp> #include <Nazara/VulkanRenderer/Debug.hpp>
@ -77,7 +78,7 @@ namespace Nz
return false; 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<PFN_vkGetInstanceProcAddr>(s_vulkanLib.GetSymbol("vkGetInstanceProcAddr")); vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(s_vulkanLib.GetSymbol("vkGetInstanceProcAddr"));
if (!vkGetInstanceProcAddr) if (!vkGetInstanceProcAddr)
{ {
@ -85,28 +86,49 @@ namespace Nz
return false; 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 // all other functions should be loaded using vkGetInstanceProcAddr
#define NAZARA_VULKANRENDERER_LOAD_GLOBAL(func) func = reinterpret_cast<PFN_##func>(vkGetInstanceProcAddr(nullptr, #func)) #define NAZARA_VULKANRENDERER_LOAD_GLOBAL(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func))
try
{
ErrorFlags flags(ErrorFlag_ThrowException, true);
NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkCreateInstance); #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func, false));
NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkEnumerateInstanceExtensionProperties); #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT(func) func = reinterpret_cast<PFN_##func>(GetProcAddr(#func, true));
NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkEnumerateInstanceLayerProperties);
#undef NAZARA_VULKANRENDERER_LOAD_GLOBAL #include <Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp>
#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; s_lastErrorCode = VkResult::VK_SUCCESS;
return true; 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); #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) PFN_##func Loader::func = nullptr;
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceExtensionProperties); #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT NAZARA_VULKANRENDERER_GLOBAL_FUNCTION
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceLayerProperties);
NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkGetInstanceProcAddr);
#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL #include <Nazara/VulkanRenderer/Wrapper/GlobalFunctions.hpp>
#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_OPT
#undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION
DynLib Loader::s_vulkanLib; DynLib Loader::s_vulkanLib;
VkResult Loader::s_lastErrorCode; VkResult Loader::s_lastErrorCode;