From 22a31c72ed84b685cd25e20c942682fe6f92233c Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Apr 2016 02:28:26 +0200 Subject: [PATCH] Vulkan: Add loading of Instance/Device Former-commit-id: 0184f78824900bd46cff94dbfe829b126b8c984d --- build/scripts/modules/vulkan.lua | 4 ++ include/Nazara/Vulkan.hpp | 38 ++++++++++ include/Nazara/Vulkan/Config.hpp | 4 +- include/Nazara/Vulkan/Debug.hpp | 2 +- include/Nazara/Vulkan/VkDevice.hpp | 62 ++++++++++++++++ include/Nazara/Vulkan/VkDevice.inl | 67 +++++++++++++++++ include/Nazara/Vulkan/VkInstance.hpp | 74 +++++++++++++++++++ include/Nazara/Vulkan/VkInstance.inl | 86 ++++++++++++++++++++++ include/Nazara/Vulkan/VkLoader.hpp | 44 ++++++++---- include/Nazara/Vulkan/VkLoader.inl | 19 +++++ include/Nazara/Vulkan/Vulkan.hpp | 2 +- src/Nazara/Vulkan/VkDevice.cpp | 50 +++++++++++++ src/Nazara/Vulkan/VkInstance.cpp | 103 +++++++++++++++++++++++++++ src/Nazara/Vulkan/VkLoader.cpp | 60 ++++++++++++++-- src/Nazara/Vulkan/Vulkan.cpp | 2 +- 15 files changed, 592 insertions(+), 25 deletions(-) create mode 100644 include/Nazara/Vulkan.hpp create mode 100644 include/Nazara/Vulkan/VkDevice.hpp create mode 100644 include/Nazara/Vulkan/VkDevice.inl create mode 100644 include/Nazara/Vulkan/VkInstance.hpp create mode 100644 include/Nazara/Vulkan/VkInstance.inl create mode 100644 include/Nazara/Vulkan/VkLoader.inl create mode 100644 src/Nazara/Vulkan/VkDevice.cpp create mode 100644 src/Nazara/Vulkan/VkInstance.cpp diff --git a/build/scripts/modules/vulkan.lua b/build/scripts/modules/vulkan.lua index 687a542c5..876e5e75e 100644 --- a/build/scripts/modules/vulkan.lua +++ b/build/scripts/modules/vulkan.lua @@ -1,5 +1,9 @@ MODULE.Name = "Vulkan" +MODULE.Defines = { + "VK_NO_PROTOTYPES" +} + MODULE.Libraries = { "NazaraCore", "NazaraUtility" diff --git a/include/Nazara/Vulkan.hpp b/include/Nazara/Vulkan.hpp new file mode 100644 index 000000000..a935674e9 --- /dev/null +++ b/include/Nazara/Vulkan.hpp @@ -0,0 +1,38 @@ +// This file was automatically generated on 24 Apr 2016 at 02:26:55 + +/* + Nazara Engine - Vulkan + + Copyright (C) 2015 J茅r么me "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_VULKAN_HPP +#define NAZARA_GLOBAL_VULKAN_HPP + +#include +#include +#include +#include +#include + +#endif // NAZARA_GLOBAL_VULKAN_HPP diff --git a/include/Nazara/Vulkan/Config.hpp b/include/Nazara/Vulkan/Config.hpp index 28a98edfd..d5f616214 100644 --- a/include/Nazara/Vulkan/Config.hpp +++ b/include/Nazara/Vulkan/Config.hpp @@ -1,7 +1,7 @@ /* - Nazara Engine - Module name + Nazara Engine - Vulkan - Copyright (C) YEAR AUTHORS (EMAIL) + Copyright (C) 2015 J茅r么me "Lynix" Leclercq (Lynix680@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/include/Nazara/Vulkan/Debug.hpp b/include/Nazara/Vulkan/Debug.hpp index a744946ef..b5e44efae 100644 --- a/include/Nazara/Vulkan/Debug.hpp +++ b/include/Nazara/Vulkan/Debug.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 J閞鬽e Leclercq +// Copyright (C) 2016 J茅r么me Leclercq // This file is part of the "Nazara Engine - Vulkan" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/include/Nazara/Vulkan/VkDevice.hpp b/include/Nazara/Vulkan/VkDevice.hpp new file mode 100644 index 000000000..0779cdcd8 --- /dev/null +++ b/include/Nazara/Vulkan/VkDevice.hpp @@ -0,0 +1,62 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKAN_VKDEVICE_HPP +#define NAZARA_VULKAN_VKDEVICE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class Instance; + + class NAZARA_VULKAN_API Device + { + public: + inline Device(Instance& instance); + Device(const Device&) = delete; + Device(Device&&) = delete; + inline ~Device(); + + bool Create(VkPhysicalDevice device, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline void Destroy(); + + inline void GetDeviceQueue(UInt32 queueFamilyIndex, UInt32 queueIndex, VkQueue* queue); + inline VkResult GetLastErrorCode() const; + + inline bool WaitForIdle(); + + Device& operator=(const Device&) = delete; + Device& operator=(Device&&) = delete; + + // Vulkan functions + #define NAZARA_VULKAN_DEVICE_FUNCTION(func) PFN_##func func + + NAZARA_VULKAN_DEVICE_FUNCTION(vkDestroyDevice); + NAZARA_VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle); + NAZARA_VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue); + + #undef NAZARA_VULKAN_DEVICE_FUNCTION + + private: + inline PFN_vkVoidFunction GetProcAddr(const char* name); + + Instance& m_instance; + VkAllocationCallbacks m_allocator; + VkDevice m_device; + VkResult m_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKAN_VKDEVICE_HPP diff --git a/include/Nazara/Vulkan/VkDevice.inl b/include/Nazara/Vulkan/VkDevice.inl new file mode 100644 index 000000000..75a3a6e8b --- /dev/null +++ b/include/Nazara/Vulkan/VkDevice.inl @@ -0,0 +1,67 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Device::Device(Instance& instance) : + m_instance(instance), + m_device(nullptr) + { + } + + inline Device::~Device() + { + Destroy(); + } + + inline void Device::Destroy() + { + if (m_device) + { + vkDeviceWaitIdle(m_device); + vkDestroyDevice(m_device, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + } + } + + inline void Device::GetDeviceQueue(UInt32 queueFamilyIndex, UInt32 queueIndex, VkQueue* queue) + { + return vkGetDeviceQueue(m_device, queueFamilyIndex, queueIndex, queue); + } + + inline VkResult Device::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline bool Device::WaitForIdle() + { + m_lastErrorCode = vkDeviceWaitIdle(m_device); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to wait for device idle"); + return false; + } + + return true; + } + + inline PFN_vkVoidFunction Device::GetProcAddr(const char* name) + { + PFN_vkVoidFunction func = m_instance.GetDeviceProcAddr(m_device, name); + if (!func) + NazaraError("Failed to get " + String(name) + " address"); + + return func; + } + } +} + +#include diff --git a/include/Nazara/Vulkan/VkInstance.hpp b/include/Nazara/Vulkan/VkInstance.hpp new file mode 100644 index 000000000..b3b0b62eb --- /dev/null +++ b/include/Nazara/Vulkan/VkInstance.hpp @@ -0,0 +1,74 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKAN_VKINSTANCE_HPP +#define NAZARA_VULKAN_VKINSTANCE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class NAZARA_VULKAN_API Instance + { + public: + inline Instance(); + Instance(const Instance&) = delete; + Instance(Instance&&) = delete; + inline ~Instance(); + + bool Create(const VkInstanceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline void Destroy(); + + bool EnumeratePhysicalDevices(std::vector* physicalDevices); + + inline PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name); + + inline void GetPhysicalDeviceFeatures(VkPhysicalDevice device, VkPhysicalDeviceFeatures* features); + inline void GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format, VkFormatProperties* formatProperties); + inline bool GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* imageFormatProperties); + inline void GetPhysicalDeviceMemoryProperties(VkPhysicalDevice device, VkPhysicalDeviceMemoryProperties* properties); + inline void GetPhysicalDeviceProperties(VkPhysicalDevice device, VkPhysicalDeviceProperties* properties); + bool GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector* queueFamilyProperties); + + inline VkResult GetLastErrorCode() const; + + Instance& operator=(const Instance&) = delete; + Instance& operator=(Instance&&) = delete; + + // Vulkan functions + #define NAZARA_VULKAN_INSTANCE_FUNCTION(func) PFN_##func func + + NAZARA_VULKAN_INSTANCE_FUNCTION(vkCreateDevice); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkDestroyInstance); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties); + NAZARA_VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties); + + #undef NAZARA_VULKAN_INSTANCE_FUNCTION + + private: + inline PFN_vkVoidFunction GetProcAddr(const char* name); + + VkAllocationCallbacks m_allocator; + VkInstance m_instance; + VkResult m_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKAN_VKINSTANCE_HPP diff --git a/include/Nazara/Vulkan/VkInstance.inl b/include/Nazara/Vulkan/VkInstance.inl new file mode 100644 index 000000000..1aaa508ef --- /dev/null +++ b/include/Nazara/Vulkan/VkInstance.inl @@ -0,0 +1,86 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Instance::Instance() : + m_instance(nullptr) + { + } + + inline Instance::~Instance() + { + Destroy(); + } + + inline void Instance::Destroy() + { + if (m_instance) + vkDestroyInstance(m_instance, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + } + + inline PFN_vkVoidFunction Instance::GetDeviceProcAddr(VkDevice device, const char* name) + { + PFN_vkVoidFunction func = vkGetDeviceProcAddr(device, name); + if (!func) + NazaraError("Failed to get " + String(name) + " address"); + + return func; + } + + inline VkResult Instance::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline void Instance::GetPhysicalDeviceFeatures(VkPhysicalDevice device, VkPhysicalDeviceFeatures* features) + { + return vkGetPhysicalDeviceFeatures(device, features); + } + + inline void Instance::GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format, VkFormatProperties* formatProperties) + { + return vkGetPhysicalDeviceFormatProperties(device, format, formatProperties); + } + + inline bool Instance::GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* imageFormatProperties) + { + m_lastErrorCode = vkGetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, imageFormatProperties); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to get physical device image format properties"); + return false; + } + + return true; + } + + inline void Instance::GetPhysicalDeviceMemoryProperties(VkPhysicalDevice device, VkPhysicalDeviceMemoryProperties* memoryProperties) + { + return vkGetPhysicalDeviceMemoryProperties(device, memoryProperties); + } + + inline void Instance::GetPhysicalDeviceProperties(VkPhysicalDevice device, VkPhysicalDeviceProperties* properties) + { + return vkGetPhysicalDeviceProperties(device, properties); + } + + inline PFN_vkVoidFunction Instance::GetProcAddr(const char* name) + { + PFN_vkVoidFunction func = Loader::GetInstanceProcAddr(m_instance, name); + if (!func) + NazaraError("Failed to get " + String(name) + " address"); + + return func; + } + } +} + +#include diff --git a/include/Nazara/Vulkan/VkLoader.hpp b/include/Nazara/Vulkan/VkLoader.hpp index 8e973b0bb..c700451c5 100644 --- a/include/Nazara/Vulkan/VkLoader.hpp +++ b/include/Nazara/Vulkan/VkLoader.hpp @@ -1,11 +1,11 @@ -// Copyright (C) 2016 J閞鬽e Leclercq +// Copyright (C) 2016 J茅r么me Leclercq // This file is part of the "Nazara Engine - Vulkan" // For conditions of distribution and use, see copyright notice in Config.hpp #pragma once -#ifndef NAZARA_VULKAN_LOADER_HPP -#define NAZARA_VULKAN_LOADER_HPP +#ifndef NAZARA_VULKAN_VKLOADER_HPP +#define NAZARA_VULKAN_VKLOADER_HPP #include #include @@ -14,21 +14,35 @@ namespace Nz { - class NAZARA_VULKAN_API VkLoader + namespace Vk { - public: - VkLoader() = delete; - ~VkLoader() = delete; + class NAZARA_VULKAN_API Loader + { + public: + Loader() = delete; + ~Loader() = delete; + + static inline PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name); - static bool Initialize(); + static bool Initialize(); + static void Uninitialize(); - private: - static DynLib s_vulkanLib; - }; + // Vulkan functions + #define NAZARA_VULKAN_GLOBAL_FUNCTION(func) static PFN_##func func + + NAZARA_VULKAN_GLOBAL_FUNCTION(vkCreateInstance); + NAZARA_VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties); + NAZARA_VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties); + NAZARA_VULKAN_GLOBAL_FUNCTION(vkGetInstanceProcAddr); + + #undef NAZARA_VULKAN_GLOBAL_FUNCTION + + private: + static DynLib s_vulkanLib; + }; + } } -#define NAZARA_VULKAN_EXPORTED_FUNCTION(func) extern PFN_##func func; +#include -NAZARA_VULKAN_EXPORTED_FUNCTION(vkGetInstanceProcAddr); - -#endif // NAZARA_VULKAN_LOADER_HPP +#endif // NAZARA_VULKAN_VKLOADER_HPP diff --git a/include/Nazara/Vulkan/VkLoader.inl b/include/Nazara/Vulkan/VkLoader.inl new file mode 100644 index 000000000..49467366d --- /dev/null +++ b/include/Nazara/Vulkan/VkLoader.inl @@ -0,0 +1,19 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline PFN_vkVoidFunction Loader::GetInstanceProcAddr(VkInstance instance, const char* name) + { + return vkGetInstanceProcAddr(instance, name); + } + } +} + +#include diff --git a/include/Nazara/Vulkan/Vulkan.hpp b/include/Nazara/Vulkan/Vulkan.hpp index aabb87aea..9d90202c2 100644 --- a/include/Nazara/Vulkan/Vulkan.hpp +++ b/include/Nazara/Vulkan/Vulkan.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 J閞鬽e Leclercq +// Copyright (C) 2016 J茅r么me Leclercq // This file is part of the "Nazara Engine - Vulkan" // For conditions of distribution and use, see copyright notice in Config.hpp diff --git a/src/Nazara/Vulkan/VkDevice.cpp b/src/Nazara/Vulkan/VkDevice.cpp new file mode 100644 index 000000000..ef28af223 --- /dev/null +++ b/src/Nazara/Vulkan/VkDevice.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + bool Device::Create(VkPhysicalDevice device, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateDevice(device, &createInfo, allocator, &m_device); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan device"); + return false; + } + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + #define NAZARA_VULKAN_LOAD_DEVICE(func) func = reinterpret_cast(GetProcAddr(#func)) + + try + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + + NAZARA_VULKAN_LOAD_DEVICE(vkDestroyDevice); + NAZARA_VULKAN_LOAD_DEVICE(vkDeviceWaitIdle); + NAZARA_VULKAN_LOAD_DEVICE(vkGetDeviceQueue); + } + catch (const std::exception& e) + { + NazaraError(String("Failed to query device function: ") + e.what()); + return false; + } + + #undef NAZARA_VULKAN_LOAD_DEVICE + + return true; + } + } +} diff --git a/src/Nazara/Vulkan/VkInstance.cpp b/src/Nazara/Vulkan/VkInstance.cpp new file mode 100644 index 000000000..304bbc277 --- /dev/null +++ b/src/Nazara/Vulkan/VkInstance.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2016 J茅r么me Leclercq +// This file is part of the "Nazara Engine - Vulkan" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + bool Instance::Create(const VkInstanceCreateInfo& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = Loader::vkCreateInstance(&createInfo, allocator, &m_instance); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan instance"); + return false; + } + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + #define NAZARA_VULKAN_LOAD_INSTANCE(func) func = reinterpret_cast(GetProcAddr(#func)) + + try + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + + NAZARA_VULKAN_LOAD_INSTANCE(vkCreateDevice); + NAZARA_VULKAN_LOAD_INSTANCE(vkDestroyInstance); + NAZARA_VULKAN_LOAD_INSTANCE(vkEnumeratePhysicalDevices); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetDeviceProcAddr); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetPhysicalDeviceFeatures); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetPhysicalDeviceFormatProperties); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetPhysicalDeviceImageFormatProperties); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetPhysicalDeviceMemoryProperties); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetPhysicalDeviceProperties); + NAZARA_VULKAN_LOAD_INSTANCE(vkGetPhysicalDeviceQueueFamilyProperties); + } + catch (const std::exception& e) + { + NazaraError(String("Failed to query instance function: ") + e.what()); + return false; + } + + #undef NAZARA_VULKAN_LOAD_INSTANCE + + return true; + } + + bool Instance::EnumeratePhysicalDevices(std::vector* devices) + { + NazaraAssert(devices, "Invalid device vector"); + + // First, query physical device count + UInt32 deviceCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + m_lastErrorCode = vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr); + if (m_lastErrorCode != VkResult::VK_SUCCESS || deviceCount == 0) + { + NazaraError("Failed to query physical device count"); + return false; + } + + // Now we can get the list of the available physical device + devices->resize(deviceCount); + m_lastErrorCode = vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices->data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query physical devices"); + return false; + } + + return true; + } + + bool Instance::GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector* queueFamilyProperties) + { + NazaraAssert(queueFamilyProperties, "Invalid device vector"); + + // First, query physical device count + UInt32 queueFamiliesCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamiliesCount, nullptr); + if (queueFamiliesCount == 0) + { + NazaraError("Failed to query physical device count"); + return false; + } + + // Now we can get the list of the available physical device + queueFamilyProperties->resize(queueFamiliesCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamiliesCount, queueFamilyProperties->data()); + + return true; + } + + } +} diff --git a/src/Nazara/Vulkan/VkLoader.cpp b/src/Nazara/Vulkan/VkLoader.cpp index b261778df..c4a6f08b5 100644 --- a/src/Nazara/Vulkan/VkLoader.cpp +++ b/src/Nazara/Vulkan/VkLoader.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 J閞鬽e Leclercq +// Copyright (C) 2016 J茅r么me Leclercq // This file is part of the "Nazara Engine - Vulkan" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -7,8 +7,58 @@ namespace Nz { + namespace Vk + { + bool Loader::Initialize() + { + #ifdef NAZARA_PLATFORM_WINDOWS + s_vulkanLib.Load("vulkan-1.dll"); + #elif defined(NAZARA_PLATFORM_LINUX) + s_vulkanLib.Load("libvulkan.so"); + #else + #error Unhandled platform + #endif + + if (!s_vulkanLib.IsLoaded()) + { + NazaraError("Failed to open vulkan library: " + s_vulkanLib.GetLastError()); + return false; + } + + // vkGetInstanceProcAddr is the only function that's garantee to be exported + vkGetInstanceProcAddr = reinterpret_cast(s_vulkanLib.GetSymbol("vkGetInstanceProcAddr")); + if (!vkGetInstanceProcAddr) + { + NazaraError("Failed to get symbol \"vkGetInstanceProcAddr\": " + s_vulkanLib.GetLastError()); + return false; + } + + // all other functions should be loaded using vkGetInstanceProcAddr + #define NAZARA_VULKAN_LOAD_GLOBAL(func) func = reinterpret_cast(vkGetInstanceProcAddr(nullptr, #func)) + + NAZARA_VULKAN_LOAD_GLOBAL(vkCreateInstance); + NAZARA_VULKAN_LOAD_GLOBAL(vkEnumerateInstanceExtensionProperties); + NAZARA_VULKAN_LOAD_GLOBAL(vkEnumerateInstanceLayerProperties); + + #undef NAZARA_VULKAN_LOAD_GLOBAL + + return true; + } + + #define NAZARA_VULKAN_GLOBAL_FUNCTION_IMPL(func) PFN_##func Loader::func = nullptr + + NAZARA_VULKAN_GLOBAL_FUNCTION_IMPL(vkCreateInstance); + NAZARA_VULKAN_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceExtensionProperties); + NAZARA_VULKAN_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceLayerProperties); + NAZARA_VULKAN_GLOBAL_FUNCTION_IMPL(vkGetInstanceProcAddr); + + #undef NAZARA_VULKAN_GLOBAL_FUNCTION_IMPL + + DynLib Loader::s_vulkanLib; + + void Loader::Uninitialize() + { + s_vulkanLib.Unload(); + } + } } - -#define NAZARA_VULKAN_EXPORTED_FUNCTION_IMPL(func) PFN_##func func = nullptr; - -NAZARA_VULKAN_EXPORTED_FUNCTION_IMPL(vkGetInstanceProcAddr) \ No newline at end of file diff --git a/src/Nazara/Vulkan/Vulkan.cpp b/src/Nazara/Vulkan/Vulkan.cpp index 5c41e0034..00bb55337 100644 --- a/src/Nazara/Vulkan/Vulkan.cpp +++ b/src/Nazara/Vulkan/Vulkan.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 J閞鬽e Leclercq +// Copyright (C) 2016 J茅r么me Leclercq // This file is part of the "Nazara Engine - Vulkan" // For conditions of distribution and use, see copyright notice in Config.hpp