Cleanup device creation/selection
This commit is contained in:
parent
4ede9f1cfe
commit
07fa581525
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue