Add command buffers (WIP)

This commit is contained in:
Lynix
2020-04-02 21:07:01 +02:00
parent cf396b0792
commit f443bec6bc
50 changed files with 1076 additions and 215 deletions

View File

@@ -7,6 +7,8 @@
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/VulkanRenderer/Vulkan.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandBuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanSurface.hpp>
#include <array>
@@ -16,6 +18,7 @@
namespace Nz
{
VkRenderWindow::VkRenderWindow() :
m_currentFrame(0),
m_depthStencilFormat(VK_FORMAT_MAX_ENUM)
{
}
@@ -25,22 +28,52 @@ namespace Nz
if (m_device)
m_device->WaitForIdle();
m_frameBuffers.clear();
m_concurrentImageData.clear();
m_graphicsCommandPool.Destroy();
m_imageData.clear();
m_renderPass.Destroy();
m_swapchain.Destroy();
VkRenderTarget::Destroy();
}
bool VkRenderWindow::Acquire(UInt32* imageIndex, VkSemaphore signalSemaphore, VkFence signalFence) const
VulkanRenderImage& VkRenderWindow::Acquire()
{
if (!m_swapchain.AcquireNextImage(std::numeric_limits<UInt64>::max(), signalSemaphore, signalFence, imageIndex))
{
NazaraError("Failed to acquire next image");
return false;
}
VulkanRenderImage& currentFrame = m_concurrentImageData[m_currentFrame];
Vk::Fence& inFlightFence = currentFrame.GetInFlightFence();
return true;
// Wait until previous rendering to this image has been done
inFlightFence.Wait();
UInt32 imageIndex;
if (!m_swapchain.AcquireNextImage(std::numeric_limits<UInt64>::max(), currentFrame.GetImageAvailableSemaphore(), VK_NULL_HANDLE, &imageIndex))
throw std::runtime_error("Failed to acquire next image: " + TranslateVulkanError(m_swapchain.GetLastErrorCode()));
if (m_imageData[imageIndex].inFlightFence)
m_imageData[imageIndex].inFlightFence->Wait();
m_imageData[imageIndex].inFlightFence = &inFlightFence;
m_imageData[imageIndex].inFlightFence->Reset();
currentFrame.Reset(imageIndex);
return currentFrame;
}
std::unique_ptr<CommandBuffer> VkRenderWindow::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
{
Vk::AutoCommandBuffer commandBuffer = m_graphicsCommandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
if (!commandBuffer->Begin())
throw std::runtime_error("failed to begin command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
VulkanCommandBufferBuilder builder(commandBuffer.Get());
callback(builder);
if (!commandBuffer->End())
throw std::runtime_error("failed to build command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
return std::make_unique<VulkanCommandBuffer>(std::move(commandBuffer));
}
bool VkRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters)
@@ -49,14 +82,17 @@ namespace Nz
Vk::Surface& vulkanSurface = static_cast<VulkanSurface*>(surface)->GetSurface();
m_device = Vulkan::SelectDevice(deviceInfo, vulkanSurface, &m_presentableFamilyQueue);
UInt32 graphicsFamilyQueueIndex;
UInt32 presentableFamilyQueueIndex;
m_device = Vulkan::SelectDevice(deviceInfo, vulkanSurface, &graphicsFamilyQueueIndex, &presentableFamilyQueueIndex);
if (!m_device)
{
NazaraError("Failed to get compatible Vulkan device");
return false;
}
m_presentQueue = m_device->GetQueue(m_presentableFamilyQueue, 0);
m_graphicsQueue = m_device->GetQueue(graphicsFamilyQueueIndex, 0);
m_presentQueue = m_device->GetQueue(presentableFamilyQueueIndex, 0);
std::vector<VkSurfaceFormatKHR> surfaceFormats;
if (!vulkanSurface.GetFormats(deviceInfo.physDevice, &surfaceFormats))
@@ -144,10 +180,10 @@ namespace Nz
UInt32 imageCount = m_swapchain.GetBufferCount();
// Framebuffers
m_frameBuffers.resize(imageCount);
m_imageData.resize(imageCount);
for (UInt32 i = 0; i < imageCount; ++i)
{
std::array<VkImageView, 2> attachments = {m_swapchain.GetBuffer(i).view, m_depthBufferView};
std::array<VkImageView, 2> attachments = { m_swapchain.GetBuffer(i).view, m_depthBufferView };
VkFramebufferCreateInfo frameBufferCreate = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
@@ -161,13 +197,25 @@ namespace Nz
1U // uint32_t layers;
};
if (!m_frameBuffers[i].Create(*m_device, frameBufferCreate))
if (!m_imageData[i].framebuffer.Create(*m_device, frameBufferCreate))
{
NazaraError("Failed to create framebuffer for image #" + String::Number(i));
NazaraError("Failed to create framebuffer for image #" + String::Number(i) + ": " + TranslateVulkanError(m_imageData[i].framebuffer.GetLastErrorCode()));
return false;
}
}
if (!m_graphicsCommandPool.Create(*m_device, m_graphicsQueue.GetQueueFamilyIndex()))
{
NazaraError("Failed to create graphics command pool: " + TranslateVulkanError(m_graphicsCommandPool.GetLastErrorCode()));
return false;
}
const std::size_t MaxConcurrentImage = imageCount;
m_concurrentImageData.reserve(MaxConcurrentImage);
for (std::size_t i = 0; i < MaxConcurrentImage; ++i)
m_concurrentImageData.emplace_back(*this);
m_clock.Restart();
return true;
@@ -181,7 +229,7 @@ namespace Nz
0U, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
m_depthStencilFormat, // VkFormat format;
{size.x, size.y, 1U}, // VkExtent3D extent;
{size.x, size.y, 1U}, // VkExtent3D extent;
1U, // uint32_t mipLevels;
1U, // uint32_t arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;