Replace DeviceHandle by references

and keep device alive until Vulkan is freed
This commit is contained in:
Lynix
2020-03-13 18:38:26 +01:00
parent 4cf24cde7d
commit 63547fcd4e
56 changed files with 303 additions and 268 deletions

View File

@@ -7,6 +7,7 @@
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/VulkanRenderer/Vulkan.hpp>
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <array>
#include <stdexcept>
@@ -43,7 +44,7 @@ namespace Nz
return true;
}
bool VkRenderWindow::Create(RendererImpl* renderer, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters)
bool VkRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters)
{
m_physicalDevice = Vulkan::GetPhysicalDevices()[0].device;
@@ -74,8 +75,6 @@ namespace Nz
if (!parameters.depthFormats.empty())
{
const Vk::PhysicalDevice& deviceInfo = Vulkan::GetPhysicalDeviceInfo(m_physicalDevice);
for (PixelFormatType format : parameters.depthFormats)
{
switch (format)
@@ -163,7 +162,7 @@ namespace Nz
1U // uint32_t layers;
};
if (!m_frameBuffers[i].Create(m_device, frameBufferCreate))
if (!m_frameBuffers[i].Create(*m_device, frameBufferCreate))
{
NazaraError("Failed to create framebuffer for image #" + String::Number(i));
return false;
@@ -195,14 +194,14 @@ namespace Nz
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
if (!m_depthBuffer.Create(m_device, imageCreateInfo))
if (!m_depthBuffer.Create(*m_device, imageCreateInfo))
{
NazaraError("Failed to create depth buffer");
return false;
}
VkMemoryRequirements memoryReq = m_depthBuffer.GetMemoryRequirements();
if (!m_depthBufferMemory.Create(m_device, memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
if (!m_depthBufferMemory.Create(*m_device, memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
{
NazaraError("Failed to allocate depth buffer memory");
return false;
@@ -236,7 +235,7 @@ namespace Nz
}
};
if (!m_depthBufferView.Create(m_device, imageViewCreateInfo))
if (!m_depthBufferView.Create(*m_device, imageViewCreateInfo))
{
NazaraError("Failed to create depth buffer view");
return false;
@@ -330,7 +329,7 @@ namespace Nz
dependencies.data() // const VkSubpassDependency* pDependencies;
};
return m_renderPass.Create(m_device, createInfo);
return m_renderPass.Create(*m_device, createInfo);
}
bool VkRenderWindow::SetupSwapchain(Vk::Surface& surface, const Vector2ui& size)
@@ -395,7 +394,7 @@ namespace Nz
0
};
if (!m_swapchain.Create(m_device, swapchainInfo))
if (!m_swapchain.Create(*m_device, swapchainInfo))
{
NazaraError("Failed to create swapchain");
return false;

View File

@@ -444,13 +444,7 @@ namespace Nz
{
for (auto it = s_devices.begin(); it != s_devices.end();)
{
auto devicePtr = it->lock();
if (!devicePtr)
{
it = s_devices.erase(it);
continue;
}
const auto& devicePtr = *it;
if (devicePtr->GetPhysicalDevice() == gpu)
return devicePtr;
}
@@ -463,13 +457,7 @@ namespace Nz
// First, try to find a device compatible with that surface
for (auto it = s_devices.begin(); it != s_devices.end();)
{
auto devicePtr = it->lock();
if (!devicePtr)
{
it = s_devices.erase(it);
continue;
}
const auto& devicePtr = *it;
if (devicePtr->GetPhysicalDevice() == gpu)
{
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = devicePtr->GetEnabledQueues();
@@ -511,7 +499,7 @@ namespace Nz
Vk::Loader::Uninitialize();
}
std::vector<std::weak_ptr<VulkanDevice>> Vulkan::s_devices;
std::vector<std::shared_ptr<VulkanDevice>> Vulkan::s_devices;
std::vector<Vk::PhysicalDevice> Vulkan::s_physDevices;
Vk::Instance Vulkan::s_instance;
ParameterList Vulkan::s_initializationParameters;

View File

@@ -12,20 +12,20 @@ namespace Nz
{
VulkanDevice::~VulkanDevice() = default;
std::unique_ptr<AbstractBuffer> VulkanDevice::InstantiateBuffer(Buffer* parent, BufferType type)
std::unique_ptr<AbstractBuffer> VulkanDevice::InstantiateBuffer(BufferType type)
{
return std::make_unique<VulkanBuffer>(shared_from_this(), parent, type);
return std::make_unique<VulkanBuffer>(*this, type);
}
std::unique_ptr<RenderPipeline> VulkanDevice::InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo)
{
return std::make_unique<VulkanRenderPipeline>(shared_from_this(), std::move(pipelineInfo));
return std::make_unique<VulkanRenderPipeline>(*this, std::move(pipelineInfo));
}
std::shared_ptr<RenderPipelineLayout> VulkanDevice::InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo)
{
auto pipelineLayout = std::make_shared<VulkanRenderPipelineLayout>();
if (!pipelineLayout->Create(shared_from_this(), std::move(pipelineLayoutInfo)))
if (!pipelineLayout->Create(*this, std::move(pipelineLayoutInfo)))
return {};
return pipelineLayout;
@@ -34,7 +34,7 @@ namespace Nz
std::shared_ptr<ShaderStageImpl> VulkanDevice::InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize)
{
auto stage = std::make_shared<VulkanShaderStage>();
if (!stage->Create(shared_from_this(), type, lang, source, sourceSize))
if (!stage->Create(*this, type, lang, source, sourceSize))
return {};
return stage;

View File

@@ -12,8 +12,8 @@
namespace Nz
{
VulkanRenderPipeline::VulkanRenderPipeline(Vk::DeviceHandle device, RenderPipelineInfo pipelineInfo) :
m_device(std::move(device)),
VulkanRenderPipeline::VulkanRenderPipeline(Vk::Device& device, RenderPipelineInfo pipelineInfo) :
m_device(&device),
m_pipelineInfo(std::move(pipelineInfo))
{
m_pipelineCreateInfo = BuildCreateInfo(m_pipelineInfo);
@@ -29,7 +29,7 @@ namespace Nz
pipelineCreateInfo.renderPass = renderPass;
Vk::Pipeline newPipeline;
if (!newPipeline.CreateGraphics(m_device, pipelineCreateInfo))
if (!newPipeline.CreateGraphics(*m_device, pipelineCreateInfo))
return VK_NULL_HANDLE;
auto it = m_pipelines.emplace(renderPass, std::move(newPipeline)).first;

View File

@@ -12,9 +12,9 @@
namespace Nz
{
bool VulkanRenderPipelineLayout::Create(Vk::DeviceHandle device, RenderPipelineLayoutInfo layoutInfo)
bool VulkanRenderPipelineLayout::Create(Vk::Device& device, RenderPipelineLayoutInfo layoutInfo)
{
m_device = std::move(device);
m_device = &device;
m_layoutInfo = std::move(layoutInfo);
StackVector<VkDescriptorSetLayoutBinding> layoutBindings = NazaraStackVector(VkDescriptorSetLayoutBinding, m_layoutInfo.bindings.size());
@@ -28,10 +28,10 @@ namespace Nz
layoutBinding.stageFlags = ToVulkan(bindingInfo.shaderStageFlags);
}
if (!m_descriptorSetLayout.Create(m_device, layoutBindings.size(), layoutBindings.data()))
if (!m_descriptorSetLayout.Create(*m_device, UInt32(layoutBindings.size()), layoutBindings.data()))
return false;
if (!m_pipelineLayout.Create(m_device, m_descriptorSetLayout))
if (!m_pipelineLayout.Create(*m_device, m_descriptorSetLayout))
return false;
return true;

View File

@@ -73,7 +73,7 @@ namespace Nz
for (const Vk::PhysicalDevice& physDevice : m_physDevices)
{
RenderDeviceInfo device;
RenderDeviceInfo& device = devices.emplace_back();
device.name = physDevice.properties.deviceName;
switch (physDevice.properties.deviceType)
@@ -100,8 +100,6 @@ namespace Nz
device.type = RenderDeviceType::Unknown;
break;
}
devices.emplace_back(std::move(device));
}
return devices;

View File

@@ -7,7 +7,7 @@
namespace Nz
{
bool VulkanShaderStage::Create(const Vk::DeviceHandle& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize)
bool VulkanShaderStage::Create(Vk::Device& device, ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize)
{
if (lang != ShaderLanguage::SpirV)
{

View File

@@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/Wrapper/Device.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Queue.hpp>
@@ -12,6 +13,28 @@ namespace Nz
{
namespace Vk
{
Device::Device(Instance& instance) :
m_instance(instance),
m_physicalDevice(nullptr),
m_device(VK_NULL_HANDLE)
{
}
Device::~Device()
{
if (m_device != VK_NULL_HANDLE)
WaitAndDestroyDevice();
}
void Device::Destroy()
{
if (m_device != VK_NULL_HANDLE)
{
WaitAndDestroyDevice();
ResetPointers();
}
}
bool Device::Create(const Vk::PhysicalDevice& deviceInfo, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator)
{
m_lastErrorCode = m_instance.vkCreateDevice(deviceInfo.device, &createInfo, allocator, &m_device);
@@ -21,6 +44,8 @@ namespace Nz
return false;
}
CallOnExit destroyOnFailure([this] { Destroy(); });
m_physicalDevice = &deviceInfo;
// Store the allocator to access them when needed
@@ -53,7 +78,7 @@ namespace Nz
}
catch (const std::exception& e)
{
NazaraError(String("Failed to query device function: ") + e.what());
NazaraError(std::string("Failed to query device function: ") + e.what());
return false;
}
@@ -88,6 +113,8 @@ namespace Nz
for (const QueueFamilyInfo& familyInfo : m_enabledQueuesInfos)
m_queuesByFamily[familyInfo.familyIndex] = &familyInfo.queues;
destroyOnFailure.Reset();
return true;
}
@@ -96,8 +123,37 @@ namespace Nz
VkQueue queue;
vkGetDeviceQueue(m_device, queueFamilyIndex, queueIndex, &queue);
return Queue(shared_from_this(), queue);
return Queue(*this, queue);
}
void Device::WaitAndDestroyDevice()
{
assert(m_device != VK_NULL_HANDLE);
if (vkDeviceWaitIdle)
vkDeviceWaitIdle(m_device);
m_internalData.reset();
if (vkDestroyDevice)
vkDestroyDevice(m_device, (m_allocator.pfnAllocation) ? &m_allocator : nullptr);
}
void Device::ResetPointers()
{
m_device = VK_NULL_HANDLE;
m_physicalDevice = nullptr;
// Reset functions pointers
#define NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN(ext)
#define NAZARA_VULKANRENDERER_DEVICE_EXT_END()
#define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) func = nullptr;
#include <Nazara/VulkanRenderer/Wrapper/DeviceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_DEVICE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_DEVICE_EXT_END
#undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION
}
}
}

View File

@@ -103,5 +103,20 @@ namespace Nz
return true;
}
void Instance::ResetPointers()
{
assert(m_instance != VK_NULL_HANDLE);
m_instance = VK_NULL_HANDLE;
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN(ext)
#define NAZARA_VULKANRENDERER_INSTANCE_EXT_END()
#define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) func = nullptr;
#include <Nazara/VulkanRenderer/Wrapper/InstanceFunctions.hpp>
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_BEGIN
#undef NAZARA_VULKANRENDERER_INSTANCE_EXT_END
#undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION
}
}
}