Vulkan: Add renderpass and framebuffers

This commit is contained in:
Lynix 2020-04-10 17:36:05 +02:00
parent 9507c56fc9
commit d9a08640d6
41 changed files with 659 additions and 95 deletions

View File

@ -17,20 +17,27 @@
namespace Nz
{
class Framebuffer;
class RenderPass;
class RenderPipeline;
class ShaderBinding;
class NAZARA_RENDERER_API CommandBufferBuilder
{
public:
struct ClearValues;
CommandBufferBuilder() = default;
CommandBufferBuilder(const CommandBufferBuilder&) = delete;
CommandBufferBuilder(CommandBufferBuilder&&) = default;
virtual ~CommandBufferBuilder();
virtual void BeginDebugRegion(const std::string_view& regionName, const Nz::Color& color) = 0;
virtual void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti renderRect, std::initializer_list<ClearValues> clearValues) = 0;
virtual void BindIndexBuffer(Nz::AbstractBuffer* indexBuffer, UInt64 offset = 0) = 0;
virtual void BindShaderBinding(ShaderBinding& binding) = 0;
virtual void BindPipeline(const RenderPipeline& pipeline) = 0;
virtual void BindShaderBinding(const ShaderBinding& binding) = 0;
virtual void BindVertexBuffer(UInt32 binding, Nz::AbstractBuffer* vertexBuffer, UInt64 offset = 0) = 0;
inline void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target);
@ -42,6 +49,7 @@ namespace Nz
virtual void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) = 0;
virtual void EndDebugRegion() = 0;
virtual void EndRenderPass() = 0;
virtual void PreTransferBarrier() = 0;
virtual void PostTransferBarrier() = 0;
@ -51,6 +59,13 @@ namespace Nz
CommandBufferBuilder& operator=(const CommandBufferBuilder&) = delete;
CommandBufferBuilder& operator=(CommandBufferBuilder&&) = default;
struct ClearValues
{
Nz::Color color;
float depth;
UInt32 stencil;
};
};
}

View File

@ -0,0 +1,30 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_FRAMEBUFFER_HPP
#define NAZARA_FRAMEBUFFER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Config.hpp>
namespace Nz
{
class NAZARA_RENDERER_API Framebuffer
{
public:
Framebuffer() = default;
Framebuffer(const Framebuffer&) = delete;
Framebuffer(Framebuffer&&) noexcept = default;
virtual ~Framebuffer();
Framebuffer& operator=(const Framebuffer&) = delete;
Framebuffer& operator=(Framebuffer&&) noexcept = default;
};
}
#include <Nazara/Renderer/Framebuffer.inl>
#endif // NAZARA_FRAMEBUFFER_HPP

View File

@ -0,0 +1,12 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/Framebuffer.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -0,0 +1,40 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RENDERPASS_HPP
#define NAZARA_RENDERPASS_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/Enums.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
namespace Nz
{
class NAZARA_RENDERER_API RenderPass
{
public:
struct Attachment;
RenderPass() = default;
RenderPass(const RenderPass&) = delete;
RenderPass(RenderPass&&) noexcept = default;
virtual ~RenderPass();
RenderPass& operator=(const RenderPass&) = delete;
RenderPass& operator=(RenderPass&&) noexcept = default;
struct Attachment
{
PixelFormat format;
// TODO
};
};
}
#include <Nazara/Renderer/RenderPass.inl>
#endif // NAZARA_RENDERPASS_HPP

View File

@ -0,0 +1,12 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderPass.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Renderer/DebugOff.hpp>

View File

@ -17,8 +17,10 @@
namespace Nz
{
class CommandPool;
class Framebuffer;
class RendererImpl;
class RenderImage;
class RenderPass;
class RenderSurface;
class NAZARA_RENDERER_API RenderWindowImpl
@ -32,7 +34,9 @@ namespace Nz
virtual bool Create(RendererImpl* renderer, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) = 0;
virtual std::unique_ptr<CommandPool> CreateCommandPool(QueueType queueType) = 0;
virtual const Framebuffer& GetFramebuffer() const = 0;
virtual std::shared_ptr<RenderDevice> GetRenderDevice() = 0;
virtual const RenderPass& GetRenderPass() const = 0;
};
}

View File

@ -26,22 +26,12 @@ namespace Nz
VkRenderTarget(VkRenderTarget&&) = delete; ///TOOD?
virtual ~VkRenderTarget();
virtual const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const = 0;
virtual UInt32 GetFramebufferCount() const = 0;
inline const Vk::RenderPass& GetRenderPass() const;
VkRenderTarget& operator=(const VkRenderTarget&) = delete;
VkRenderTarget& operator=(VkRenderTarget&&) = delete; ///TOOD?
// Signals:
NazaraSignal(OnRenderTargetRelease, const VkRenderTarget* /*renderTarget*/);
NazaraSignal(OnRenderTargetSizeChange, const VkRenderTarget* /*renderTarget*/);
protected:
void Destroy();
Vk::RenderPass m_renderPass;
};
}

View File

@ -7,10 +7,6 @@
namespace Nz
{
inline const Vk::RenderPass& VkRenderTarget::GetRenderPass() const
{
return m_renderPass;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -16,7 +16,9 @@
#include <Nazara/Renderer/RenderWindowImpl.hpp>
#include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/VulkanDevice.hpp>
#include <Nazara/VulkanRenderer/VulkanMultipleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderImage.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/VkRenderTarget.hpp>
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
#include <Nazara/VulkanRenderer/Wrapper/CommandPool.hpp>
@ -27,6 +29,7 @@
#include <Nazara/VulkanRenderer/Wrapper/QueueHandle.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Surface.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Swapchain.hpp>
#include <optional>
#include <vector>
namespace Nz
@ -44,11 +47,11 @@ namespace Nz
bool Create(RendererImpl* renderer, RenderSurface* surface, const Vector2ui& size, const RenderWindowParameters& parameters) override;
std::unique_ptr<CommandPool> CreateCommandPool(QueueType queueType) override;
inline const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const override;
inline UInt32 GetFramebufferCount() const override;
inline const VulkanMultipleFramebuffer& GetFramebuffer() const override;
inline VulkanDevice& GetDevice();
inline const VulkanDevice& GetDevice() const;
inline Vk::QueueHandle& GetGraphicsQueue();
const VulkanRenderPass& GetRenderPass() const override;
inline const Vk::Swapchain& GetSwapchain() const;
std::shared_ptr<RenderDevice> GetRenderDevice() override;
@ -63,19 +66,15 @@ namespace Nz
bool SetupRenderPass();
bool SetupSwapchain(const Vk::PhysicalDevice& deviceInfo, Vk::Surface& surface, const Vector2ui& size);
struct ImageData
{
Vk::Framebuffer framebuffer;
Vk::Fence* inFlightFence = nullptr;
};
std::size_t m_currentFrame;
Clock m_clock;
VkColorSpaceKHR m_colorSpace;
VkFormat m_colorFormat;
VkFormat m_depthStencilFormat;
std::optional<VulkanMultipleFramebuffer> m_framebuffer;
std::optional<VulkanRenderPass> m_renderPass;
std::shared_ptr<VulkanDevice> m_device;
std::vector<ImageData> m_imageData;
std::vector<Vk::Fence*> m_inflightFences;
std::vector<VulkanRenderImage> m_concurrentImageData;
Vk::DeviceMemory m_depthBufferMemory;
Vk::Image m_depthBuffer;

View File

@ -7,6 +7,11 @@
namespace Nz
{
inline const VulkanMultipleFramebuffer& VkRenderWindow::GetFramebuffer() const
{
return *m_framebuffer;
}
inline VulkanDevice& VkRenderWindow::GetDevice()
{
return *m_device;
@ -22,16 +27,6 @@ namespace Nz
return m_graphicsQueue;
}
inline const Vk::Framebuffer& VkRenderWindow::GetFrameBuffer(UInt32 imageIndex) const
{
return m_imageData[imageIndex].framebuffer;
}
inline UInt32 VkRenderWindow::GetFramebufferCount() const
{
return static_cast<UInt32>(m_imageData.size());
}
inline const Vk::Swapchain& VkRenderWindow::GetSwapchain() const
{
return m_swapchain;
@ -44,11 +39,11 @@ namespace Nz
inline void VkRenderWindow::Present(UInt32 imageIndex, VkSemaphore waitSemaphore)
{
NazaraAssert(imageIndex < m_imageData.size(), "Invalid image index");
NazaraAssert(imageIndex < m_inflightFences.size(), "Invalid image index");
m_presentQueue.Present(m_swapchain, imageIndex, waitSemaphore);
m_currentFrame = (m_currentFrame + 1) % m_imageData.size();
m_currentFrame = (m_currentFrame + 1) % m_inflightFences.size();
}
}

View File

@ -11,6 +11,7 @@
#include <Nazara/Renderer/CommandBuffer.hpp>
#include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
#include <vector>
namespace Nz
{
@ -18,17 +19,18 @@ namespace Nz
{
public:
inline VulkanCommandBuffer(Vk::AutoCommandBuffer commandBuffer);
inline VulkanCommandBuffer(std::vector<Vk::AutoCommandBuffer> commandBuffers);
VulkanCommandBuffer(const VulkanCommandBuffer&) = delete;
VulkanCommandBuffer(VulkanCommandBuffer&&) noexcept = default;
~VulkanCommandBuffer() = default;
inline Vk::CommandBuffer& GetCommandBuffer();
inline Vk::CommandBuffer& GetCommandBuffer(std::size_t imageIndex = 0);
VulkanCommandBuffer& operator=(const VulkanCommandBuffer&) = delete;
VulkanCommandBuffer& operator=(VulkanCommandBuffer&&) = delete;
private:
Vk::AutoCommandBuffer m_commandBuffer;
std::vector<Vk::AutoCommandBuffer> m_commandBuffers;
};
}

View File

@ -7,14 +7,19 @@
namespace Nz
{
inline VulkanCommandBuffer::VulkanCommandBuffer(Vk::AutoCommandBuffer commandBuffer) :
m_commandBuffer(std::move(commandBuffer))
inline VulkanCommandBuffer::VulkanCommandBuffer(Vk::AutoCommandBuffer commandBuffer)
{
m_commandBuffers.push_back(std::move(commandBuffer));
}
inline VulkanCommandBuffer::VulkanCommandBuffer(std::vector<Vk::AutoCommandBuffer> commandBuffers) :
m_commandBuffers(std::move(commandBuffers))
{
}
inline Vk::CommandBuffer& VulkanCommandBuffer::GetCommandBuffer()
inline Vk::CommandBuffer& VulkanCommandBuffer::GetCommandBuffer(std::size_t imageIndex)
{
return m_commandBuffer.Get();
return m_commandBuffers[imageIndex].Get();
}
}

View File

@ -14,18 +14,22 @@
namespace Nz
{
class VulkanRenderPass;
class NAZARA_VULKANRENDERER_API VulkanCommandBufferBuilder final : public CommandBufferBuilder
{
public:
inline VulkanCommandBufferBuilder(Vk::CommandBuffer& commandBuffer);
inline VulkanCommandBufferBuilder(Vk::CommandBuffer& commandBuffer, std::size_t imageIndex = 0);
VulkanCommandBufferBuilder(const VulkanCommandBufferBuilder&) = delete;
VulkanCommandBufferBuilder(VulkanCommandBufferBuilder&&) noexcept = default;
~VulkanCommandBufferBuilder() = default;
void BeginDebugRegion(const std::string_view& regionName, const Nz::Color& color) override;
void BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti renderRect, std::initializer_list<ClearValues> clearValues) override;
void BindIndexBuffer(AbstractBuffer* indexBuffer, UInt64 offset = 0) override;
void BindShaderBinding(ShaderBinding& binding) override;
void BindPipeline(const RenderPipeline& pipeline) override;
void BindShaderBinding(const ShaderBinding& binding) override;
void BindVertexBuffer(UInt32 binding, Nz::AbstractBuffer* vertexBuffer, UInt64 offset = 0) override;
void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
@ -35,8 +39,10 @@ namespace Nz
void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0) override;
void EndDebugRegion() override;
void EndRenderPass() override;
inline Vk::CommandBuffer& GetCommandBuffer();
inline std::size_t GetMaxFramebufferCount() const;
void PreTransferBarrier() override;
void PostTransferBarrier() override;
@ -49,6 +55,9 @@ namespace Nz
private:
Vk::CommandBuffer& m_commandBuffer;
const VulkanRenderPass* m_currentRenderPass;
std::size_t m_framebufferCount;
std::size_t m_imageIndex;
};
}

View File

@ -7,8 +7,10 @@
namespace Nz
{
inline VulkanCommandBufferBuilder::VulkanCommandBufferBuilder(Vk::CommandBuffer& commandBuffer) :
m_commandBuffer(commandBuffer)
inline VulkanCommandBufferBuilder::VulkanCommandBufferBuilder(Vk::CommandBuffer& commandBuffer, std::size_t imageIndex) :
m_commandBuffer(commandBuffer),
m_framebufferCount(0),
m_imageIndex(imageIndex)
{
}
@ -16,6 +18,11 @@ namespace Nz
{
return m_commandBuffer;
}
inline std::size_t VulkanCommandBufferBuilder::GetMaxFramebufferCount() const
{
return m_framebufferCount;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -0,0 +1,43 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VULKANRENDERER_VULKANFRAMEBUFFER_HPP
#define NAZARA_VULKANRENDERER_VULKANFRAMEBUFFER_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/Framebuffer.hpp>
#include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/Wrapper/Framebuffer.hpp>
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanFramebuffer : public Framebuffer
{
public:
enum class Type
{
Multiple,
Single
};
inline VulkanFramebuffer(Type type);
VulkanFramebuffer(const VulkanFramebuffer&) = delete;
VulkanFramebuffer(VulkanFramebuffer&&) noexcept = default;
~VulkanFramebuffer() = default;
inline Type GetType() const;
VulkanFramebuffer& operator=(const VulkanFramebuffer&) = delete;
VulkanFramebuffer& operator=(VulkanFramebuffer&&) noexcept = default;
private:
Type m_type;
};
}
#include <Nazara/VulkanRenderer/VulkanFramebuffer.inl>
#endif // NAZARA_VULKANRENDERER_VULKANFRAMEBUFFER_HPP

View File

@ -0,0 +1,21 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline VulkanFramebuffer::VulkanFramebuffer(Type type) :
m_type(type)
{
}
inline auto VulkanFramebuffer::GetType() const -> Type
{
return m_type;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -0,0 +1,36 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VULKANRENDERER_VULKANMULTIPLEFRAMEBUFFER_HPP
#define NAZARA_VULKANRENDERER_VULKANMULTIPLEFRAMEBUFFER_HPP
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
#include <vector>
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanMultipleFramebuffer final : public VulkanFramebuffer
{
public:
inline VulkanMultipleFramebuffer(Vk::Framebuffer* framebuffers, std::size_t count);
VulkanMultipleFramebuffer(const VulkanMultipleFramebuffer&) = delete;
VulkanMultipleFramebuffer(VulkanMultipleFramebuffer&&) noexcept = default;
~VulkanMultipleFramebuffer() = default;
inline const Vk::Framebuffer& GetFramebuffer(std::size_t index) const;
inline std::size_t GetFramebufferCount() const;
VulkanMultipleFramebuffer& operator=(const VulkanMultipleFramebuffer&) = delete;
VulkanMultipleFramebuffer& operator=(VulkanMultipleFramebuffer&&) noexcept = default;
private:
std::vector<Vk::Framebuffer> m_framebuffers;
};
}
#include <Nazara/VulkanRenderer/VulkanMultipleFramebuffer.inl>
#endif // NAZARA_VULKANRENDERER_VULKANMULTIPLEFRAMEBUFFER_HPP

View File

@ -0,0 +1,30 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanMultipleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline VulkanMultipleFramebuffer::VulkanMultipleFramebuffer(Vk::Framebuffer* framebuffers, std::size_t count) :
VulkanFramebuffer(Type::Multiple)
{
m_framebuffers.reserve(count);
for (std::size_t i = 0; i < count; ++i)
m_framebuffers.push_back(std::move(framebuffers[i]));
}
inline const Vk::Framebuffer& Nz::VulkanMultipleFramebuffer::GetFramebuffer(std::size_t index) const
{
assert(index < m_framebuffers.size());
return m_framebuffers[index];
}
inline std::size_t VulkanMultipleFramebuffer::GetFramebufferCount() const
{
return m_framebuffers.size();
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -0,0 +1,41 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VULKANRENDERER_VULKANRENDERPASS_HPP
#define NAZARA_VULKANRENDERER_VULKANRENDERPASS_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Renderer/RenderPass.hpp>
#include <Nazara/VulkanRenderer/Config.hpp>
#include <Nazara/VulkanRenderer/Wrapper/RenderPass.hpp>
#include <vector>
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanRenderPass final : public RenderPass
{
public:
inline VulkanRenderPass(Vk::RenderPass renderPass, std::initializer_list<PixelFormat> formats); //< FIXME
VulkanRenderPass(const VulkanRenderPass&) = delete;
VulkanRenderPass(VulkanRenderPass&&) noexcept = default;
~VulkanRenderPass() = default;
inline PixelFormat GetAttachmentFormat(std::size_t attachmentIndex) const;
inline Vk::RenderPass& GetRenderPass();
inline const Vk::RenderPass& GetRenderPass() const;
VulkanRenderPass& operator=(const VulkanRenderPass&) = delete;
VulkanRenderPass& operator=(VulkanRenderPass&&) noexcept = default;
private:
std::vector<PixelFormat> m_formats;
Vk::RenderPass m_renderPass;
};
}
#include <Nazara/VulkanRenderer/VulkanRenderPass.inl>
#endif // NAZARA_VULKANRENDERER_VULKANRENDERPASS_HPP

View File

@ -0,0 +1,32 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline VulkanRenderPass::VulkanRenderPass(Vk::RenderPass renderPass, std::initializer_list<PixelFormat> formats) :
m_formats(std::begin(formats), std::end(formats)),
m_renderPass(std::move(renderPass))
{
}
inline PixelFormat VulkanRenderPass::GetAttachmentFormat(std::size_t attachmentIndex) const
{
return m_formats[attachmentIndex];
}
inline Vk::RenderPass& VulkanRenderPass::GetRenderPass()
{
return m_renderPass;
}
inline const Vk::RenderPass& VulkanRenderPass::GetRenderPass() const
{
return m_renderPass;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -26,7 +26,7 @@ namespace Nz
VulkanRenderPipeline(Vk::Device& device, RenderPipelineInfo pipelineInfo);
~VulkanRenderPipeline() = default;
VkPipeline Get(const Vk::RenderPass& renderPass);
VkPipeline Get(const Vk::RenderPass& renderPass) const;
static std::vector<VkPipelineColorBlendAttachmentState> BuildColorBlendAttachmentStateList(const RenderPipelineInfo& pipelineInfo);
static VkPipelineColorBlendStateCreateInfo BuildColorBlendInfo(const RenderPipelineInfo& pipelineInfo, const std::vector<VkPipelineColorBlendAttachmentState>& attachmentState);
@ -69,7 +69,7 @@ namespace Nz
};
private:
std::unordered_map<VkRenderPass, Vk::Pipeline> m_pipelines;
mutable std::unordered_map<VkRenderPass, Vk::Pipeline> m_pipelines;
MovablePtr<Vk::Device> m_device;
CreateInfo m_pipelineCreateInfo;
RenderPipelineInfo m_pipelineInfo;

View File

@ -24,9 +24,9 @@ namespace Nz
~VulkanShaderBinding() = default;
inline std::size_t GetBindingIndex() const;
inline Vk::DescriptorSet& GetDescriptorSet();
inline const Vk::DescriptorSet& GetDescriptorSet() const;
inline std::size_t GetPoolIndex() const;
inline VulkanRenderPipelineLayout& GetOwner();
inline const VulkanRenderPipelineLayout& GetOwner() const;
void Update(std::initializer_list<Binding> bindings) override;

View File

@ -25,12 +25,12 @@ namespace Nz
return m_poolIndex;
}
inline Vk::DescriptorSet& VulkanShaderBinding::GetDescriptorSet()
inline const Vk::DescriptorSet& VulkanShaderBinding::GetDescriptorSet() const
{
return m_descriptorSet;
}
inline VulkanRenderPipelineLayout& VulkanShaderBinding::GetOwner()
inline const VulkanRenderPipelineLayout& VulkanShaderBinding::GetOwner() const
{
return m_owner;
}

View File

@ -0,0 +1,35 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_VULKANRENDERER_VULKANSINGLEFRAMEBUFFER_HPP
#define NAZARA_VULKANRENDERER_VULKANSINGLEFRAMEBUFFER_HPP
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
namespace Nz
{
class NAZARA_VULKANRENDERER_API VulkanSingleFramebuffer final : public VulkanFramebuffer
{
public:
inline VulkanSingleFramebuffer(Vk::Framebuffer renderPass);
VulkanSingleFramebuffer(const VulkanSingleFramebuffer&) = delete;
VulkanSingleFramebuffer(VulkanSingleFramebuffer&&) noexcept = default;
~VulkanSingleFramebuffer() = default;
inline Vk::Framebuffer& GetFramebuffer();
inline const Vk::Framebuffer& GetFramebuffer() const;
VulkanSingleFramebuffer& operator=(const VulkanSingleFramebuffer&) = delete;
VulkanSingleFramebuffer& operator=(VulkanSingleFramebuffer&&) noexcept = default;
private:
Vk::Framebuffer m_framebuffer;
};
}
#include <Nazara/VulkanRenderer/VulkanSingleFramebuffer.inl>
#endif // NAZARA_VULKANRENDERER_VULKANSINGLEFRAMEBUFFER_HPP

View File

@ -0,0 +1,27 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
inline VulkanSingleFramebuffer::VulkanSingleFramebuffer(Vk::Framebuffer framebuffer) :
VulkanFramebuffer(Type::Single),
m_framebuffer(std::move(framebuffer))
{
}
inline Vk::Framebuffer& VulkanSingleFramebuffer::GetFramebuffer()
{
return m_framebuffer;
}
inline const Vk::Framebuffer& VulkanSingleFramebuffer::GetFramebuffer() const
{
return m_framebuffer;
}
}
#include <Nazara/VulkanRenderer/DebugOff.hpp>

View File

@ -38,7 +38,7 @@ namespace Nz
void SetDebugName(const std::string& name);
DeviceObject& operator=(const DeviceObject&) = delete;
DeviceObject& operator=(DeviceObject&&) = delete;
DeviceObject& operator=(DeviceObject&& object) noexcept;
operator VkType() const;

View File

@ -103,6 +103,17 @@ namespace Nz
return SetDebugName(name.data());
}
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
auto DeviceObject<C, VkType, CreateInfo, ObjectType>::operator=(DeviceObject&& object) noexcept -> DeviceObject&
{
std::swap(m_allocator, object.m_allocator);
std::swap(m_device, object.m_device);
std::swap(m_handle, object.m_handle);
std::swap(m_lastErrorCode, object.m_lastErrorCode);
return *this;
}
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
DeviceObject<C, VkType, CreateInfo, ObjectType>::operator VkType() const
{

View File

@ -25,7 +25,7 @@ namespace Nz
~RenderPass() = default;
RenderPass& operator=(const RenderPass&) = delete;
RenderPass& operator=(RenderPass&&) = delete;
RenderPass& operator=(RenderPass&&) = default;
private:
static inline VkResult CreateHelper(Device& device, const VkRenderPassCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkRenderPass* handle);

View File

@ -2,8 +2,8 @@
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NazaraSDK/Components/PhysicsComponent3D.hpp>
#include <Nazara/Core/Error.hpp>
#include "PhysicsComponent3D.hpp"
namespace Ndk
{

View File

@ -0,0 +1,11 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/Framebuffer.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
Framebuffer::~Framebuffer() = default;
}

View File

@ -0,0 +1,11 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Renderer module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/RenderPass.hpp>
#include <Nazara/Renderer/Debug.hpp>
namespace Nz
{
RenderPass::~RenderPass() = default;
}

View File

@ -11,9 +11,4 @@ namespace Nz
{
OnRenderTargetRelease(this);
}
void VkRenderTarget::Destroy()
{
m_renderPass.Destroy();
}
}

View File

@ -5,6 +5,8 @@
#include <Nazara/VulkanRenderer/VkRenderWindow.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/VulkanRenderer/Vulkan.hpp>
#include <Nazara/VulkanRenderer/VulkanCommandPool.hpp>
@ -28,11 +30,9 @@ namespace Nz
m_device->WaitForIdle();
m_concurrentImageData.clear();
m_imageData.clear();
m_renderPass.Destroy();
m_renderPass.reset();
m_framebuffer.reset();
m_swapchain.Destroy();
VkRenderTarget::Destroy();
}
VulkanRenderImage& VkRenderWindow::Acquire()
@ -47,11 +47,11 @@ namespace Nz
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();
if (m_inflightFences[imageIndex])
m_inflightFences[imageIndex]->Wait();
m_imageData[imageIndex].inFlightFence = &inFlightFence;
m_imageData[imageIndex].inFlightFence->Reset();
m_inflightFences[imageIndex] = &inFlightFence;
m_inflightFences[imageIndex]->Reset();
currentFrame.Reset(imageIndex);
@ -164,30 +164,34 @@ namespace Nz
UInt32 imageCount = m_swapchain.GetBufferCount();
// Framebuffers
m_imageData.resize(imageCount);
m_inflightFences.resize(imageCount);
Nz::StackArray<Vk::Framebuffer> framebuffers = NazaraStackArray(Vk::Framebuffer, imageCount);
for (UInt32 i = 0; i < imageCount; ++i)
{
std::array<VkImageView, 2> attachments = { m_swapchain.GetBuffer(i).view, m_depthBufferView };
VkFramebufferCreateInfo frameBufferCreate = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0, // VkFramebufferCreateFlags flags;
m_renderPass, // VkRenderPass renderPass;
(attachments[1] != VK_NULL_HANDLE) ? 2U : 1U, // uint32_t attachmentCount;
attachments.data(), // const VkImageView* pAttachments;
size.x, // uint32_t width;
size.y, // uint32_t height;
1U // uint32_t layers;
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
nullptr,
0,
m_renderPass->GetRenderPass(),
(attachments[1] != VK_NULL_HANDLE) ? 2U : 1U,
attachments.data(),
size.x,
size.y,
1U
};
if (!m_imageData[i].framebuffer.Create(*m_device, frameBufferCreate))
if (!framebuffers[i].Create(*m_device, frameBufferCreate))
{
NazaraError("Failed to create framebuffer for image #" + String::Number(i) + ": " + TranslateVulkanError(m_imageData[i].framebuffer.GetLastErrorCode()));
NazaraError("Failed to create framebuffer for image #" + String::Number(i) + ": " + TranslateVulkanError(framebuffers[i].GetLastErrorCode()));
return false;
}
}
m_framebuffer.emplace(framebuffers.data(), framebuffers.size());
const std::size_t MaxConcurrentImage = imageCount;
m_concurrentImageData.reserve(MaxConcurrentImage);
@ -220,6 +224,11 @@ namespace Nz
return std::make_unique<VulkanCommandPool>(*m_device, queueFamilyIndex);
}
const VulkanRenderPass& VkRenderWindow::GetRenderPass() const
{
return *m_renderPass;
}
bool VkRenderWindow::SetupDepthBuffer(const Vector2ui& size)
{
VkImageCreateInfo imageCreateInfo = {
@ -375,7 +384,16 @@ namespace Nz
dependencies.data() // const VkSubpassDependency* pDependencies;
};
return m_renderPass.Create(*m_device, createInfo);
Vk::RenderPass renderPass;
if (!renderPass.Create(*m_device, createInfo))
{
NazaraError("Failed to create render pass: " + TranslateVulkanError(renderPass.GetLastErrorCode()));
return false;
}
std::initializer_list<PixelFormat> fixmeplease = { PixelFormat::PixelFormat_RGB8, PixelFormat::PixelFormat_Depth24Stencil8 };
m_renderPass.emplace(std::move(renderPass), fixmeplease);
return true;
}
bool VkRenderWindow::SetupSwapchain(const Vk::PhysicalDevice& deviceInfo, Vk::Surface& surface, const Vector2ui& size)

View File

@ -5,7 +5,11 @@
#include <Nazara/VulkanRenderer/VulkanCommandBufferBuilder.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanMultipleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipeline.hpp>
#include <Nazara/VulkanRenderer/VulkanRenderPipelineLayout.hpp>
#include <Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/VulkanShaderBinding.hpp>
#include <Nazara/VulkanRenderer/VulkanUploadPool.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
@ -22,6 +26,73 @@ namespace Nz
m_commandBuffer.BeginDebugRegion(regionNameEOS.data(), color);
}
void VulkanCommandBufferBuilder::BeginRenderPass(const Framebuffer& framebuffer, const RenderPass& renderPass, Nz::Recti renderRect, std::initializer_list<ClearValues> clearValues)
{
const VulkanRenderPass& vkRenderPass = static_cast<const VulkanRenderPass&>(renderPass);
const Vk::Framebuffer& vkFramebuffer = [&] () -> const Vk::Framebuffer&
{
const VulkanFramebuffer& vkFramebuffer = static_cast<const VulkanFramebuffer&>(framebuffer);
switch (vkFramebuffer.GetType())
{
case VulkanFramebuffer::Type::Multiple:
{
const VulkanMultipleFramebuffer& vkMultipleFramebuffer = static_cast<const VulkanMultipleFramebuffer&>(vkFramebuffer);
m_framebufferCount = std::max(m_framebufferCount, vkMultipleFramebuffer.GetFramebufferCount());
return vkMultipleFramebuffer.GetFramebuffer(m_imageIndex);
}
case VulkanFramebuffer::Type::Single:
return static_cast<const VulkanSingleFramebuffer&>(vkFramebuffer).GetFramebuffer();
}
throw std::runtime_error("Unhandled framebuffer type " + std::to_string(UnderlyingCast(vkFramebuffer.GetType())));
}();
VkRect2D renderArea;
renderArea.offset.x = renderRect.x;
renderArea.offset.y = renderRect.y;
renderArea.extent.width = renderRect.width;
renderArea.extent.height = renderRect.height;
StackArray<VkClearValue> vkClearValues = NazaraStackArray(VkClearValue, clearValues.size());
std::size_t index = 0;
for (const ClearValues& values : clearValues)
{
auto& vkValues = vkClearValues[index];
if (PixelFormatInfo::GetContent(vkRenderPass.GetAttachmentFormat(index)) == PixelFormatContent_ColorRGBA)
{
vkValues.color.float32[0] = values.color.r / 255.f;
vkValues.color.float32[1] = values.color.g / 255.f;
vkValues.color.float32[2] = values.color.b / 255.f;
vkValues.color.float32[3] = values.color.a / 255.f;
}
else
{
vkValues.depthStencil.depth = values.depth;
vkValues.depthStencil.stencil = values.stencil;
}
index++;
}
VkRenderPassBeginInfo beginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
beginInfo.renderPass = vkRenderPass.GetRenderPass();
beginInfo.framebuffer = vkFramebuffer;
beginInfo.renderArea.offset.x = renderRect.x;
beginInfo.renderArea.offset.y = renderRect.y;
beginInfo.renderArea.extent.width = renderRect.width;
beginInfo.renderArea.extent.height = renderRect.height;
beginInfo.clearValueCount = vkClearValues.size();
beginInfo.pClearValues = vkClearValues.data();
m_commandBuffer.BeginRenderPass(beginInfo);
m_currentRenderPass = &vkRenderPass;
}
void VulkanCommandBufferBuilder::BindIndexBuffer(Nz::AbstractBuffer* indexBuffer, UInt64 offset)
{
VulkanBuffer& vkBuffer = *static_cast<VulkanBuffer*>(indexBuffer);
@ -29,11 +100,21 @@ namespace Nz
m_commandBuffer.BindIndexBuffer(vkBuffer.GetBuffer(), offset, VK_INDEX_TYPE_UINT16); //< Fuck me right?
}
void VulkanCommandBufferBuilder::BindShaderBinding(ShaderBinding& binding)
void VulkanCommandBufferBuilder::BindPipeline(const RenderPipeline& pipeline)
{
VulkanShaderBinding& vkBinding = static_cast<VulkanShaderBinding&>(binding);
if (!m_currentRenderPass)
throw std::runtime_error("BindPipeline must be called in a RenderPass");
VulkanRenderPipelineLayout& pipelineLayout = vkBinding.GetOwner();
const VulkanRenderPipeline& vkBinding = static_cast<const VulkanRenderPipeline&>(pipeline);
m_commandBuffer.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, vkBinding.Get(m_currentRenderPass->GetRenderPass()));
}
void VulkanCommandBufferBuilder::BindShaderBinding(const ShaderBinding& binding)
{
const VulkanShaderBinding& vkBinding = static_cast<const VulkanShaderBinding&>(binding);
const VulkanRenderPipelineLayout& pipelineLayout = vkBinding.GetOwner();
m_commandBuffer.BindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.GetPipelineLayout(), 0U, vkBinding.GetDescriptorSet());
}
@ -76,6 +157,12 @@ namespace Nz
m_commandBuffer.EndDebugRegion();
}
void VulkanCommandBufferBuilder::EndRenderPass()
{
m_commandBuffer.EndRenderPass();
m_currentRenderPass = nullptr;
}
void VulkanCommandBufferBuilder::PreTransferBarrier()
{
m_commandBuffer.MemoryBarrier(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0U, VK_ACCESS_TRANSFER_READ_BIT);

View File

@ -12,17 +12,27 @@ namespace Nz
{
std::unique_ptr<CommandBuffer> VulkanCommandPool::BuildCommandBuffer(const std::function<void(CommandBufferBuilder& builder)>& callback)
{
Vk::AutoCommandBuffer commandBuffer = m_commandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
std::vector<Vk::AutoCommandBuffer> commandBuffers;
auto BuildCommandBuffer = [&](std::size_t imageIndex)
{
Vk::AutoCommandBuffer& commandBuffer = commandBuffers.emplace_back(m_commandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
if (!commandBuffer->Begin())
throw std::runtime_error("failed to begin command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
if (!commandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT))
throw std::runtime_error("failed to begin command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
VulkanCommandBufferBuilder builder(commandBuffer.Get());
callback(builder);
VulkanCommandBufferBuilder builder(commandBuffer.Get(), imageIndex);
callback(builder);
if (!commandBuffer->End())
throw std::runtime_error("failed to build command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
if (!commandBuffer->End())
throw std::runtime_error("failed to build command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
return std::make_unique<VulkanCommandBuffer>(std::move(commandBuffer));
return builder.GetMaxFramebufferCount();
};
std::size_t maxFramebufferCount = BuildCommandBuffer(0);
for (std::size_t i = 1; i < maxFramebufferCount; ++i)
BuildCommandBuffer(i);
return std::make_unique<VulkanCommandBuffer>(std::move(commandBuffers));
}
}

View File

@ -0,0 +1,10 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanFramebuffer.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
}

View File

@ -0,0 +1,10 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanMultipleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
}

View File

@ -49,7 +49,7 @@ namespace Nz
if (!commandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT))
throw std::runtime_error("failed to begin command buffer: " + TranslateVulkanError(commandBuffer->GetLastErrorCode()));
VulkanCommandBufferBuilder builder(*commandBuffer);
VulkanCommandBufferBuilder builder(*commandBuffer, m_imageIndex);
callback(builder);
if (!commandBuffer->End())
@ -67,7 +67,7 @@ namespace Nz
{
VulkanCommandBuffer& vkCommandBuffer = *static_cast<VulkanCommandBuffer*>(commandBuffer);
return SubmitCommandBuffer(vkCommandBuffer.GetCommandBuffer(), queueTypeFlags);
return SubmitCommandBuffer(vkCommandBuffer.GetCommandBuffer(m_imageIndex), queueTypeFlags);
}
void VulkanRenderImage::SubmitCommandBuffer(VkCommandBuffer commandBuffer, QueueTypeFlags queueTypeFlags)

View File

@ -0,0 +1,10 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
}

View File

@ -19,7 +19,7 @@ namespace Nz
m_pipelineCreateInfo = BuildCreateInfo(m_pipelineInfo);
}
VkPipeline VulkanRenderPipeline::Get(const Vk::RenderPass& renderPass)
VkPipeline VulkanRenderPipeline::Get(const Vk::RenderPass& renderPass) const
{
if (auto it = m_pipelines.find(renderPass); it != m_pipelines.end())
return it->second;

View File

@ -0,0 +1,10 @@
// Copyright (C) 2020 Jérôme Leclercq
// This file is part of the "Nazara Engine - Vulkan Renderer"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/VulkanRenderer/VulkanSingleFramebuffer.hpp>
#include <Nazara/VulkanRenderer/Debug.hpp>
namespace Nz
{
}