Cleanup device creation/selection

This commit is contained in:
Lynix 2020-03-18 13:48:53 +01:00
parent 4ede9f1cfe
commit 07fa581525
8 changed files with 51 additions and 54 deletions

View File

@ -58,13 +58,12 @@ namespace Nz
private:
bool SetupDepthBuffer(const Vector2ui& size);
bool SetupRenderPass();
bool SetupSwapchain(Vk::Surface& surface, const Vector2ui& size);
bool SetupSwapchain(const Vk::PhysicalDevice& deviceInfo, Vk::Surface& surface, const Vector2ui& size);
Clock m_clock;
VkColorSpaceKHR m_colorSpace;
VkFormat m_colorFormat;
VkFormat m_depthStencilFormat;
VkPhysicalDevice m_physicalDevice;
std::shared_ptr<VulkanDevice> m_device;
std::vector<Vk::Framebuffer> m_frameBuffers;
Vk::DeviceMemory m_depthBufferMemory;

View File

@ -35,9 +35,9 @@ namespace Nz
Vulkan() = delete;
~Vulkan() = delete;
static std::shared_ptr<VulkanDevice> CreateDevice(VkPhysicalDevice gpu);
static std::shared_ptr<VulkanDevice> CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
static std::shared_ptr<VulkanDevice> CreateDevice(VkPhysicalDevice gpu, const QueueFamily* queueFamilies, std::size_t queueFamilyCount);
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo);
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const QueueFamily* queueFamilies, std::size_t queueFamilyCount);
static Vk::Instance& GetInstance();
@ -48,8 +48,8 @@ namespace Nz
static bool IsInitialized();
static std::shared_ptr<VulkanDevice> SelectDevice(VkPhysicalDevice gpu);
static std::shared_ptr<VulkanDevice> SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
static std::shared_ptr<VulkanDevice> SelectDevice(const Vk::PhysicalDevice& deviceInfo);
static std::shared_ptr<VulkanDevice> SelectDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* presentableFamilyQueue);
static void Uninitialize();

View File

@ -41,7 +41,7 @@ namespace Nz
inline VkPhysicalDevice Device::GetPhysicalDevice() const
{
return m_physicalDevice->device;
return m_physicalDevice->physDevice;
}
inline const Vk::PhysicalDevice& Device::GetPhysicalDeviceInfo() const

View File

@ -8,6 +8,7 @@
#define NAZARA_VULKANRENDERER_VKPHYSICALDEVICE_HPP
#include <vulkan/vulkan.h>
#include <unordered_set>
#include <vector>
namespace Nz
@ -16,11 +17,11 @@ namespace Nz
{
struct PhysicalDevice
{
VkPhysicalDevice device;
VkPhysicalDevice physDevice;
VkPhysicalDeviceFeatures features;
VkPhysicalDeviceMemoryProperties memoryProperties;
VkPhysicalDeviceProperties properties;
std::vector<VkQueueFamilyProperties> queues;
std::vector<VkQueueFamilyProperties> queueFamilies;
};
}
}

View File

@ -16,7 +16,6 @@
namespace Nz
{
VkRenderWindow::VkRenderWindow() :
m_physicalDevice(nullptr),
m_depthStencilFormat(VK_FORMAT_MAX_ENUM)
{
}
@ -46,11 +45,11 @@ namespace Nz
bool VkRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters)
{
m_physicalDevice = Vulkan::GetPhysicalDevices()[0].device;
const auto& deviceInfo = Vulkan::GetPhysicalDevices()[0];
Vk::Surface& vulkanSurface = static_cast<VulkanSurface*>(surface)->GetSurface();
m_device = Vulkan::SelectDevice(m_physicalDevice, vulkanSurface, &m_presentableFamilyQueue);
m_device = Vulkan::SelectDevice(deviceInfo, vulkanSurface, &m_presentableFamilyQueue);
if (!m_device)
{
NazaraError("Failed to get compatible Vulkan device");
@ -60,7 +59,7 @@ namespace Nz
m_presentQueue = m_device->GetQueue(m_presentableFamilyQueue, 0);
std::vector<VkSurfaceFormatKHR> surfaceFormats;
if (!vulkanSurface.GetFormats(m_physicalDevice, &surfaceFormats))
if (!vulkanSurface.GetFormats(deviceInfo.physDevice, &surfaceFormats))
{
NazaraError("Failed to query supported surface formats");
return false;
@ -115,7 +114,7 @@ namespace Nz
if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM)
{
VkFormatProperties formatProperties = m_device->GetInstance().GetPhysicalDeviceFormatProperties(m_physicalDevice, m_depthStencilFormat);
VkFormatProperties formatProperties = m_device->GetInstance().GetPhysicalDeviceFormatProperties(deviceInfo.physDevice, m_depthStencilFormat);
if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
break; //< Found it
@ -124,7 +123,7 @@ namespace Nz
}
}
if (!SetupSwapchain(vulkanSurface, size))
if (!SetupSwapchain(deviceInfo, vulkanSurface, size))
{
NazaraError("Failed to create swapchain");
return false;
@ -332,10 +331,10 @@ namespace Nz
return m_renderPass.Create(*m_device, createInfo);
}
bool VkRenderWindow::SetupSwapchain(Vk::Surface& surface, const Vector2ui& size)
bool VkRenderWindow::SetupSwapchain(const Vk::PhysicalDevice& deviceInfo, Vk::Surface& surface, const Vector2ui& size)
{
VkSurfaceCapabilitiesKHR surfaceCapabilities;
if (!surface.GetCapabilities(m_physicalDevice, &surfaceCapabilities))
if (!surface.GetCapabilities(deviceInfo.physDevice, &surfaceCapabilities))
{
NazaraError("Failed to query surface capabilities");
return false;
@ -355,7 +354,7 @@ namespace Nz
extent = surfaceCapabilities.currentExtent;
std::vector<VkPresentModeKHR> presentModes;
if (!surface.GetPresentModes(m_physicalDevice, &presentModes))
if (!surface.GetPresentModes(deviceInfo.physDevice, &presentModes))
{
NazaraError("Failed to query supported present modes");
return false;
@ -391,7 +390,7 @@ namespace Nz
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
swapchainPresentMode,
VK_TRUE,
0
VK_NULL_HANDLE
};
if (!m_swapchain.Create(*m_device, swapchainInfo))

View File

@ -29,7 +29,7 @@ namespace Nz
{
for (const Vk::PhysicalDevice& info : s_physDevices)
{
if (info.device == physDevice)
if (info.physDevice == physDevice)
return info;
}
@ -190,13 +190,13 @@ namespace Nz
for (VkPhysicalDevice physDevice : physDevices)
{
Vk::PhysicalDevice deviceInfo;
if (!s_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queues))
if (!s_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queueFamilies))
{
NazaraWarning("Failed to query physical device queue family properties for " + String(deviceInfo.properties.deviceName) + " (0x" + String::Number(deviceInfo.properties.deviceID, 16) + ')');
continue;
}
deviceInfo.device = physDevice;
deviceInfo.physDevice = physDevice;
deviceInfo.features = s_instance.GetPhysicalDeviceFeatures(physDevice);
deviceInfo.memoryProperties = s_instance.GetPhysicalDeviceMemoryProperties(physDevice);
@ -224,29 +224,26 @@ namespace Nz
return s_instance.IsValid();
}
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(VkPhysicalDevice gpu)
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo)
{
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 transfertQueueNodeFamily = UINT32_MAX;
for (UInt32 i = 0; i < queueFamilies.size(); i++)
for (UInt32 i = 0; i < deviceInfo.queueFamilies.size(); i++)
{
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
if (deviceInfo.queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
graphicsQueueNodeIndex = i;
break;
}
}
for (UInt32 i = 0; i < queueFamilies.size(); i++)
for (UInt32 i = 0; i < deviceInfo.queueFamilies.size(); i++)
{
if (queueFamilies[i].queueFlags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT)) //< Compute and graphics queue implicitly support transfer operations
if (deviceInfo.queueFamilies[i].queueFlags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT)) //< Compute and graphics queue implicitly support transfer operations
{
transfertQueueNodeFamily = i;
if (transfertQueueNodeFamily != graphicsQueueNodeIndex)
@ -261,27 +258,24 @@ namespace Nz
}
};
return CreateDevice(gpu, queuesFamilies.data(), queuesFamilies.size());
return CreateDevice(deviceInfo, queuesFamilies.data(), queuesFamilies.size());
}
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, 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 transferQueueNodeFamily = UINT32_MAX;
for (UInt32 i = 0; i < queueFamilies.size(); i++)
for (UInt32 i = 0; i < deviceInfo.queueFamilies.size(); i++)
{
bool supportPresentation = false;
if (!surface.GetSupportPresentation(gpu, i, &supportPresentation))
if (!surface.GetSupportPresentation(deviceInfo.physDevice, i, &supportPresentation))
NazaraWarning("Failed to get presentation support of queue family #" + String::Number(i));
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
if (deviceInfo.queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
if (supportPresentation)
{
@ -312,10 +306,10 @@ namespace Nz
}
// Search for a transfer queue (first one being different to the graphics one)
for (UInt32 i = 0; i < queueFamilies.size(); i++)
for (UInt32 i = 0; i < deviceInfo.queueFamilies.size(); i++)
{
// Transfer bit is not mandatory if compute and graphics bits are set (as they implicitly support transfer)
if (queueFamilies[i].queueFlags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
if (deviceInfo.queueFamilies[i].queueFlags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
{
transferQueueNodeFamily = i;
if (transferQueueNodeFamily != graphicsQueueNodeIndex)
@ -334,10 +328,10 @@ namespace Nz
*presentableFamilyQueue = presentQueueNodeIndex;
return CreateDevice(gpu, queuesFamilies.data(), queuesFamilies.size());
return CreateDevice(deviceInfo, queuesFamilies.data(), queuesFamilies.size());
}
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(VkPhysicalDevice gpu, const QueueFamily* queueFamilies, std::size_t queueFamilyCount)
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const QueueFamily* queueFamilies, std::size_t queueFamilyCount)
{
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
queueCreateInfos.reserve(queueFamilyCount);
@ -396,8 +390,12 @@ namespace Nz
}
if (!s_initializationParameters.GetBooleanParameter("VkDeviceInfo_OverrideEnabledExtensions", &bParam) || !bParam)
{
// Swapchain extension is required for rendering
enabledExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
}
std::vector<String> additionalExtensions; // Just to keep the String alive
if (s_initializationParameters.GetIntegerParameter("VkDeviceInfo_EnabledExtensionCount", &iParam))
{
@ -429,7 +427,7 @@ namespace Nz
};
std::shared_ptr<VulkanDevice> device = std::make_shared<VulkanDevice>(s_instance);
if (!device->Create(GetPhysicalDeviceInfo(gpu), createInfo))
if (!device->Create(deviceInfo, createInfo))
{
NazaraError("Failed to create Vulkan Device: " + TranslateVulkanError(device->GetLastErrorCode()));
return {};
@ -440,32 +438,32 @@ namespace Nz
return device;
}
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(VkPhysicalDevice gpu)
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(const Vk::PhysicalDevice& deviceInfo)
{
for (auto it = s_devices.begin(); it != s_devices.end();)
{
const auto& devicePtr = *it;
if (devicePtr->GetPhysicalDevice() == gpu)
if (devicePtr->GetPhysicalDevice() == deviceInfo.physDevice)
return devicePtr;
}
return CreateDevice(gpu);
return CreateDevice(deviceInfo);
}
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* presentableFamilyQueue)
{
// First, try to find a device compatible with that surface
for (auto it = s_devices.begin(); it != s_devices.end();)
{
const auto& devicePtr = *it;
if (devicePtr->GetPhysicalDevice() == gpu)
if (devicePtr->GetPhysicalDevice() == deviceInfo.physDevice)
{
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = devicePtr->GetEnabledQueues();
UInt32 presentableQueueFamilyIndex = UINT32_MAX;
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
{
bool supported = false;
if (surface.GetSupportPresentation(gpu, queueInfo.familyIndex, &supported) && supported)
if (surface.GetSupportPresentation(deviceInfo.physDevice, queueInfo.familyIndex, &supported) && supported)
{
if (presentableQueueFamilyIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
{
@ -487,7 +485,7 @@ namespace Nz
}
// No device had support for that surface, create one
return CreateDevice(gpu, surface, presentableFamilyQueue);
return CreateDevice(deviceInfo, surface, presentableFamilyQueue);
}
void Vulkan::Uninitialize()

View File

@ -32,7 +32,7 @@ namespace Nz
std::shared_ptr<RenderDevice> VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex)
{
assert(deviceIndex < m_physDevices.size());
return Vulkan::SelectDevice(m_physDevices[deviceIndex].device);
return Vulkan::SelectDevice(m_physDevices[deviceIndex]);
}
bool VulkanRenderer::IsBetterThan(const RendererImpl* other) const

View File

@ -40,7 +40,7 @@ namespace Nz
bool Device::Create(const Vk::PhysicalDevice& deviceInfo, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateDevice(deviceInfo.device, &createInfo, allocator, &m_device);
m_lastErrorCode = m_instance.vkCreateDevice(deviceInfo.physDevice, &createInfo, allocator, &m_device);
if (m_lastErrorCode != VkResult::VK_SUCCESS)
{
NazaraError("Failed to create Vulkan device");
@ -99,7 +99,7 @@ namespace Nz
if (info.familyIndex > maxFamilyIndex)
maxFamilyIndex = info.familyIndex;
const VkQueueFamilyProperties& queueProperties = deviceInfo.queues[info.familyIndex];
const VkQueueFamilyProperties& queueProperties = deviceInfo.queueFamilies[info.familyIndex];
info.flags = queueProperties.queueFlags;
info.minImageTransferGranularity = queueProperties.minImageTransferGranularity;
info.timestampValidBits = queueProperties.timestampValidBits;