Vulkan: Add CreateDevice/SelectDevice functions

Former-commit-id: bb15b0f93fbc5a21c83178f13738976159044d9a [formerly 98145969e963560d9677ad24683189847511b5e6]
Former-commit-id: 90348ef452c507387377c609bbb238d735342973
This commit is contained in:
Lynix 2016-06-13 19:56:38 +02:00
parent 26e2f57c35
commit a91085550d
2 changed files with 131 additions and 0 deletions

View File

@ -11,7 +11,9 @@
#include <Nazara/Core/Initializer.hpp> #include <Nazara/Core/Initializer.hpp>
#include <Nazara/Core/ParameterList.hpp> #include <Nazara/Core/ParameterList.hpp>
#include <Nazara/Vulkan/Config.hpp> #include <Nazara/Vulkan/Config.hpp>
#include <Nazara/Vulkan/VkDevice.hpp>
#include <Nazara/Vulkan/VkInstance.hpp> #include <Nazara/Vulkan/VkInstance.hpp>
#include <Nazara/Vulkan/VkSurface.hpp>
namespace Nz namespace Nz
{ {
@ -21,17 +23,22 @@ namespace Nz
Vulkan() = delete; Vulkan() = delete;
~Vulkan() = delete; ~Vulkan() = delete;
static Vk::Device& CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
static Vk::Instance& GetInstance(); static Vk::Instance& GetInstance();
static bool Initialize(); static bool Initialize();
static bool IsInitialized(); static bool IsInitialized();
static Vk::Device& SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
static void SetParameters(const ParameterList& parameters); static void SetParameters(const ParameterList& parameters);
static void Uninitialize(); static void Uninitialize();
private: private:
static std::list<Vk::Device> s_devices;
static Vk::Instance s_instance; static Vk::Instance s_instance;
static ParameterList s_initializationParameters; static ParameterList s_initializationParameters;
static unsigned int s_moduleReferenceCounter; static unsigned int s_moduleReferenceCounter;

View File

@ -5,9 +5,11 @@
#include <Nazara/Vulkan/Vulkan.hpp> #include <Nazara/Vulkan/Vulkan.hpp>
#include <Nazara/Core/CallOnExit.hpp> #include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/Log.hpp> #include <Nazara/Core/Log.hpp>
#include <Nazara/Utility/Utility.hpp> #include <Nazara/Utility/Utility.hpp>
#include <Nazara/Vulkan/Config.hpp> #include <Nazara/Vulkan/Config.hpp>
#include <array>
#include <Nazara/Vulkan/Debug.hpp> #include <Nazara/Vulkan/Debug.hpp>
namespace Nz namespace Nz
@ -156,6 +158,127 @@ namespace Nz
return s_moduleReferenceCounter != 0; return s_moduleReferenceCounter != 0;
} }
Vk::Device& Vulkan::CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
{
Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true);
std::vector<VkQueueFamilyProperties> queueFamilies;
s_instance.GetPhysicalDeviceQueueFamilyProperties(gpu, &queueFamilies);
// Find a queue that supports graphics operations
UInt32 graphicsQueueNodeIndex = UINT32_MAX;
UInt32 presentQueueNodeIndex = UINT32_MAX;
UInt32 transfertQueueNodeFamily = UINT32_MAX;
for (UInt32 i = 0; i < queueFamilies.size(); i++)
{
bool supportPresentation = false;
if (!surface.GetSupportPresentation(gpu, i, &supportPresentation))
NazaraWarning("Failed to get presentation support of queue family #" + String::Number(i));
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
if (graphicsQueueNodeIndex == UINT32_MAX)
graphicsQueueNodeIndex = i;
if (supportPresentation)
{
graphicsQueueNodeIndex = i;
presentQueueNodeIndex = i;
break;
}
}
else if (supportPresentation)
presentQueueNodeIndex = i;
}
for (UInt32 i = 0; i < queueFamilies.size(); i++)
{
if (queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT)
{
transfertQueueNodeFamily = i;
if (transfertQueueNodeFamily != graphicsQueueNodeIndex)
break;
}
}
std::array<UInt32, 3> usedQueueFamilies = {graphicsQueueNodeIndex, presentQueueNodeIndex, transfertQueueNodeFamily};
float priority = 1.f;
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
for (UInt32 queueFamily : usedQueueFamilies)
{
VkDeviceQueueCreateInfo createInfo = {
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
nullptr,
0,
queueFamily,
1,
&priority
};
queueCreateInfos.emplace_back(createInfo);
}
std::array<const char*, 1> enabledExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
std::array<const char*, 0> enabledLayers;
VkDeviceCreateInfo createInfo = {
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
nullptr,
0,
UInt32(queueCreateInfos.size()),
queueCreateInfos.data(),
UInt32(enabledLayers.size()),
enabledLayers.data(),
UInt32(enabledLayers.size()),
enabledLayers.data(),
nullptr
};
///TODO: First create then move
s_devices.emplace_back(s_instance);
Vk::Device& device = s_devices.back();
device.Create(gpu, createInfo);
*presentableFamilyQueue = presentQueueNodeIndex;
return device;
}
Vk::Device& Vulkan::SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
{
// First, try to find a device compatible with that surface
for (Vk::Device& device : s_devices)
{
if (device.GetPhysicalDevice() == gpu)
{
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = device.GetEnabledQueues();
UInt32 presentableQueueFamilyIndex = UINT32_MAX;
for (Vk::Device::QueueFamilyInfo queueInfo : queueFamilyInfo)
{
bool supported = false;
if (surface.GetSupportPresentation(gpu, queueInfo.familyIndex, &supported) && supported)
{
if (presentableQueueFamilyIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
presentableQueueFamilyIndex = queueInfo.familyIndex;
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
break;
}
}
}
if (presentableQueueFamilyIndex != UINT32_MAX)
*presentableFamilyQueue = presentableQueueFamilyIndex;
}
}
// No device had support for that surface, create one
return CreateDevice(gpu, surface, presentableFamilyQueue);
}
void Vulkan::SetParameters(const ParameterList& parameters) void Vulkan::SetParameters(const ParameterList& parameters)
{ {
s_initializationParameters = parameters; s_initializationParameters = parameters;
@ -185,6 +308,7 @@ namespace Nz
Utility::Uninitialize(); Utility::Uninitialize();
} }
std::list<Vk::Device> Vulkan::s_devices;
Vk::Instance Vulkan::s_instance; Vk::Instance Vulkan::s_instance;
ParameterList Vulkan::s_initializationParameters; ParameterList Vulkan::s_initializationParameters;
unsigned int Vulkan::s_moduleReferenceCounter = 0; unsigned int Vulkan::s_moduleReferenceCounter = 0;