Renderer/RenderPass: Implement RenderPass correctly
This commit is contained in:
parent
3d84479d0e
commit
d058a127e1
|
|
@ -17,7 +17,7 @@ namespace Nz
|
||||||
class NAZARA_OPENGLRENDERER_API OpenGLRenderPass final : public RenderPass
|
class NAZARA_OPENGLRENDERER_API OpenGLRenderPass final : public RenderPass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenGLRenderPass() = default;
|
using RenderPass::RenderPass;
|
||||||
OpenGLRenderPass(const OpenGLRenderPass&) = delete;
|
OpenGLRenderPass(const OpenGLRenderPass&) = delete;
|
||||||
OpenGLRenderPass(OpenGLRenderPass&&) noexcept = default;
|
OpenGLRenderPass(OpenGLRenderPass&&) noexcept = default;
|
||||||
~OpenGLRenderPass() = default;
|
~OpenGLRenderPass() = default;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,96 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
enum class AttachmentLoadOp
|
||||||
|
{
|
||||||
|
Clear,
|
||||||
|
Discard,
|
||||||
|
Load
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AttachmentStoreOp
|
||||||
|
{
|
||||||
|
Discard,
|
||||||
|
Store
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MemoryAccess
|
||||||
|
{
|
||||||
|
ColorRead,
|
||||||
|
ColorWrite,
|
||||||
|
DepthStencilRead,
|
||||||
|
DepthStencilWrite,
|
||||||
|
IndexBufferRead,
|
||||||
|
IndirectCommandRead,
|
||||||
|
HostRead,
|
||||||
|
HostWrite,
|
||||||
|
MemoryRead,
|
||||||
|
MemoryWrite,
|
||||||
|
ShaderRead,
|
||||||
|
ShaderWrite,
|
||||||
|
TransferRead,
|
||||||
|
TransferWrite,
|
||||||
|
UniformBufferRead,
|
||||||
|
VertexBufferRead,
|
||||||
|
|
||||||
|
Max = VertexBufferRead
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EnumAsFlags<MemoryAccess>
|
||||||
|
{
|
||||||
|
static constexpr MemoryAccess max = MemoryAccess::Max;
|
||||||
|
};
|
||||||
|
|
||||||
|
using MemoryAccessFlags = Flags<MemoryAccess>;
|
||||||
|
|
||||||
|
enum class PipelineStage
|
||||||
|
{
|
||||||
|
TopOfPipe,
|
||||||
|
|
||||||
|
ColorOutput,
|
||||||
|
DrawIndirect,
|
||||||
|
FragmentShader,
|
||||||
|
FragmentTestsEarly,
|
||||||
|
FragmentTestsLate,
|
||||||
|
GeometryShader,
|
||||||
|
TessellationControlShader,
|
||||||
|
TessellationEvaluationShader,
|
||||||
|
Transfer,
|
||||||
|
TransformFeedback,
|
||||||
|
VertexInput,
|
||||||
|
VertexShader,
|
||||||
|
|
||||||
|
BottomOfPipe,
|
||||||
|
|
||||||
|
Max = BottomOfPipe
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EnumAsFlags<PipelineStage>
|
||||||
|
{
|
||||||
|
static constexpr PipelineStage max = PipelineStage::Max;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PipelineStageFlags = Flags<PipelineStage>;
|
||||||
|
|
||||||
|
enum class QueueType
|
||||||
|
{
|
||||||
|
Compute,
|
||||||
|
Graphics,
|
||||||
|
Transfer,
|
||||||
|
|
||||||
|
Max = Transfer
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EnumAsFlags<QueueType>
|
||||||
|
{
|
||||||
|
static constexpr QueueType max = QueueType::Max;
|
||||||
|
};
|
||||||
|
|
||||||
|
using QueueTypeFlags = Flags<QueueType>;
|
||||||
|
|
||||||
enum class RenderAPI
|
enum class RenderAPI
|
||||||
{
|
{
|
||||||
Direct3D, ///< Microsoft Render API, only works on MS platforms
|
Direct3D, ///< Microsoft Render API, only works on MS platforms
|
||||||
|
|
@ -53,22 +143,17 @@ namespace Nz
|
||||||
SpirV
|
SpirV
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class QueueType
|
enum class TextureLayout
|
||||||
{
|
{
|
||||||
Compute,
|
ColorInput,
|
||||||
Graphics,
|
ColorOutput,
|
||||||
Transfer,
|
DepthStencilInput,
|
||||||
|
DepthStencilOutput,
|
||||||
Max = Transfer
|
Present,
|
||||||
|
TransferSource,
|
||||||
|
TransferDestination,
|
||||||
|
Undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
struct EnumAsFlags<QueueType>
|
|
||||||
{
|
|
||||||
static constexpr QueueType max = QueueType::Max;
|
|
||||||
};
|
|
||||||
|
|
||||||
using QueueTypeFlags = Flags<QueueType>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_ENUMS_RENDERER_HPP
|
#endif // NAZARA_ENUMS_RENDERER_HPP
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@
|
||||||
#include <Nazara/Renderer/Config.hpp>
|
#include <Nazara/Renderer/Config.hpp>
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <Nazara/Utility/PixelFormat.hpp>
|
#include <Nazara/Utility/PixelFormat.hpp>
|
||||||
|
#include <limits>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
|
@ -18,20 +21,64 @@ namespace Nz
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Attachment;
|
struct Attachment;
|
||||||
|
struct SubpassDependency;
|
||||||
|
struct SubpassDescription;
|
||||||
|
|
||||||
RenderPass() = default;
|
inline RenderPass(std::vector<Attachment> attachments, std::vector<SubpassDescription> subpassDescriptions, std::vector<SubpassDependency> subpassDependencies);
|
||||||
RenderPass(const RenderPass&) = delete;
|
RenderPass(const RenderPass&) = delete;
|
||||||
RenderPass(RenderPass&&) noexcept = default;
|
RenderPass(RenderPass&&) noexcept = default;
|
||||||
virtual ~RenderPass();
|
virtual ~RenderPass();
|
||||||
|
|
||||||
|
inline const Attachment& GetAttachment(std::size_t attachmentIndex) const;
|
||||||
|
inline std::size_t GetAttachmentCount() const;
|
||||||
|
inline const std::vector<Attachment>& GetAttachments() const;
|
||||||
|
inline const std::vector<SubpassDescription>& GetSubpassDescriptions() const;
|
||||||
|
inline const std::vector<SubpassDependency>& GetsubpassDependencies() const;
|
||||||
|
|
||||||
RenderPass& operator=(const RenderPass&) = delete;
|
RenderPass& operator=(const RenderPass&) = delete;
|
||||||
RenderPass& operator=(RenderPass&&) noexcept = default;
|
RenderPass& operator=(RenderPass&&) noexcept = default;
|
||||||
|
|
||||||
struct Attachment
|
struct Attachment
|
||||||
{
|
{
|
||||||
PixelFormat format;
|
PixelFormat format;
|
||||||
// TODO
|
AttachmentLoadOp loadOp = AttachmentLoadOp::Load;
|
||||||
|
AttachmentLoadOp stencilLoadOp = AttachmentLoadOp::Load;
|
||||||
|
AttachmentStoreOp storeOp = AttachmentStoreOp::Store;
|
||||||
|
AttachmentStoreOp stencilStoreOp = AttachmentStoreOp::Store;
|
||||||
|
TextureLayout initialLayout = TextureLayout::Undefined;
|
||||||
|
TextureLayout finalLayout = TextureLayout::Present;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AttachmentReference
|
||||||
|
{
|
||||||
|
std::size_t attachmentIndex;
|
||||||
|
TextureLayout attachmentLayout = TextureLayout::ColorInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubpassDependency
|
||||||
|
{
|
||||||
|
std::size_t fromSubpassIndex;
|
||||||
|
PipelineStageFlags fromStages;
|
||||||
|
MemoryAccessFlags fromAccessFlags;
|
||||||
|
std::size_t toSubpassIndex;
|
||||||
|
PipelineStageFlags toStages;
|
||||||
|
MemoryAccessFlags toAccessFlags;
|
||||||
|
bool tilable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubpassDescription
|
||||||
|
{
|
||||||
|
std::vector<AttachmentReference> colorAttachment;
|
||||||
|
std::vector<AttachmentReference> inputAttachments;
|
||||||
|
std::optional<AttachmentReference> depthStencilAttachment;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::size_t ExternalSubpassIndex = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<Attachment> m_attachments;
|
||||||
|
std::vector<SubpassDependency> m_subpassDependencies;
|
||||||
|
std::vector<SubpassDescription> m_subpassDescriptions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,43 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderPass.hpp>
|
#include <Nazara/Renderer/RenderPass.hpp>
|
||||||
|
#include <cassert>
|
||||||
#include <Nazara/Renderer/Debug.hpp>
|
#include <Nazara/Renderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline RenderPass::RenderPass(std::vector<Attachment> attachments, std::vector<SubpassDescription> subpassDescriptions, std::vector<SubpassDependency> subpassDependencies) :
|
||||||
|
m_attachments(std::move(attachments)),
|
||||||
|
m_subpassDescriptions(std::move(subpassDescriptions)),
|
||||||
|
m_subpassDependencies(std::move(subpassDependencies))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto Nz::RenderPass::GetAttachment(std::size_t attachmentIndex) const -> const Attachment&
|
||||||
|
{
|
||||||
|
assert(attachmentIndex < m_attachments.size());
|
||||||
|
return m_attachments[attachmentIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t RenderPass::GetAttachmentCount() const
|
||||||
|
{
|
||||||
|
return m_attachments.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto RenderPass::GetAttachments() const -> const std::vector<Attachment>&
|
||||||
|
{
|
||||||
|
return m_attachments;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto RenderPass::GetSubpassDescriptions() const -> const std::vector<SubpassDescription>&
|
||||||
|
{
|
||||||
|
return m_subpassDescriptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto RenderPass::GetsubpassDependencies() const -> const std::vector<SubpassDependency>&
|
||||||
|
{
|
||||||
|
return m_subpassDependencies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Renderer/DebugOff.hpp>
|
#include <Nazara/Renderer/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,24 @@
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <Nazara/Utility/Enums.hpp>
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline std::optional<PixelFormat> FromVulkan(VkFormat format);
|
||||||
|
|
||||||
|
inline VkAttachmentLoadOp ToVulkan(AttachmentLoadOp loadOp);
|
||||||
|
inline VkAttachmentStoreOp ToVulkan(AttachmentStoreOp storeOp);
|
||||||
inline VkBufferUsageFlags ToVulkan(BufferType bufferType);
|
inline VkBufferUsageFlags ToVulkan(BufferType bufferType);
|
||||||
inline VkFormat ToVulkan(ComponentType componentType);
|
inline VkFormat ToVulkan(ComponentType componentType);
|
||||||
inline VkCullModeFlagBits ToVulkan(FaceSide faceSide);
|
inline VkCullModeFlagBits ToVulkan(FaceSide faceSide);
|
||||||
inline VkPolygonMode ToVulkan(FaceFilling faceFilling);
|
inline VkPolygonMode ToVulkan(FaceFilling faceFilling);
|
||||||
|
inline VkAccessFlagBits ToVulkan(MemoryAccess memoryAccess);
|
||||||
|
inline VkAccessFlags ToVulkan(MemoryAccessFlags memoryAccessFlags);
|
||||||
|
inline VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage);
|
||||||
|
inline VkPipelineStageFlags ToVulkan(PipelineStageFlags pipelineStages);
|
||||||
|
inline VkFormat ToVulkan(PixelFormat pixelFormat);
|
||||||
inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode);
|
inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode);
|
||||||
inline VkCompareOp ToVulkan(RendererComparison comparison);
|
inline VkCompareOp ToVulkan(RendererComparison comparison);
|
||||||
inline VkFilter ToVulkan(SamplerFilter samplerFilter);
|
inline VkFilter ToVulkan(SamplerFilter samplerFilter);
|
||||||
|
|
@ -28,6 +38,7 @@ namespace Nz
|
||||||
inline VkShaderStageFlagBits ToVulkan(ShaderStageType stageType);
|
inline VkShaderStageFlagBits ToVulkan(ShaderStageType stageType);
|
||||||
inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType);
|
inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType);
|
||||||
inline VkStencilOp ToVulkan(StencilOperation stencilOp);
|
inline VkStencilOp ToVulkan(StencilOperation stencilOp);
|
||||||
|
inline VkImageLayout ToVulkan(TextureLayout textureLayout);
|
||||||
inline VkVertexInputRate ToVulkan(VertexInputRate inputRate);
|
inline VkVertexInputRate ToVulkan(VertexInputRate inputRate);
|
||||||
|
|
||||||
NAZARA_VULKANRENDERER_API std::string TranslateVulkanError(VkResult code);
|
NAZARA_VULKANRENDERER_API std::string TranslateVulkanError(VkResult code);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,45 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
std::optional<PixelFormat> FromVulkan(VkFormat format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case VK_FORMAT_B8G8R8A8_UNORM: return PixelFormat::PixelFormat_BGRA8;
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT: return PixelFormat::PixelFormat_Depth24Stencil8;
|
||||||
|
case VK_FORMAT_D32_SFLOAT: return PixelFormat::PixelFormat_Depth32;
|
||||||
|
case VK_FORMAT_R8G8B8A8_UNORM: return PixelFormat::PixelFormat_RGBA8;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkAttachmentLoadOp ToVulkan(AttachmentLoadOp loadOp)
|
||||||
|
{
|
||||||
|
switch (loadOp)
|
||||||
|
{
|
||||||
|
case AttachmentLoadOp::Clear: return VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
|
case AttachmentLoadOp::Discard: return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
case AttachmentLoadOp::Load: return VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled AttachmentLoadOp 0x" + NumberToString(UnderlyingCast(loadOp), 16));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
VkAttachmentStoreOp ToVulkan(AttachmentStoreOp storeOp)
|
||||||
|
{
|
||||||
|
switch (storeOp)
|
||||||
|
{
|
||||||
|
case AttachmentStoreOp::Discard: return VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
case AttachmentStoreOp::Store: return VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled AttachmentStoreOp 0x" + NumberToString(UnderlyingCast(storeOp), 16));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
inline VkBufferUsageFlags ToVulkan(BufferType bufferType)
|
inline VkBufferUsageFlags ToVulkan(BufferType bufferType)
|
||||||
{
|
{
|
||||||
switch (bufferType)
|
switch (bufferType)
|
||||||
|
|
@ -74,6 +113,97 @@ namespace Nz
|
||||||
return VK_POLYGON_MODE_FILL;
|
return VK_POLYGON_MODE_FILL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline VkAccessFlagBits ToVulkan(MemoryAccess memoryAccess)
|
||||||
|
{
|
||||||
|
switch (memoryAccess)
|
||||||
|
{
|
||||||
|
case MemoryAccess::ColorRead: return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||||
|
case MemoryAccess::ColorWrite: return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
|
case MemoryAccess::DepthStencilRead: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||||
|
case MemoryAccess::DepthStencilWrite: return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
case MemoryAccess::IndexBufferRead: return VK_ACCESS_INDEX_READ_BIT;
|
||||||
|
case MemoryAccess::IndirectCommandRead: return VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
|
||||||
|
case MemoryAccess::HostRead: return VK_ACCESS_HOST_READ_BIT;
|
||||||
|
case MemoryAccess::HostWrite: return VK_ACCESS_HOST_WRITE_BIT;
|
||||||
|
case MemoryAccess::MemoryRead: return VK_ACCESS_MEMORY_READ_BIT;
|
||||||
|
case MemoryAccess::MemoryWrite: return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||||
|
case MemoryAccess::ShaderRead: return VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
case MemoryAccess::ShaderWrite: return VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
case MemoryAccess::TransferRead: return VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
case MemoryAccess::TransferWrite: return VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
case MemoryAccess::UniformBufferRead: return VK_ACCESS_UNIFORM_READ_BIT;
|
||||||
|
case MemoryAccess::VertexBufferRead: return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled MemoryAccess 0x" + NumberToString(UnderlyingCast(memoryAccess), 16));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VkAccessFlags ToVulkan(MemoryAccessFlags memoryAccessFlags)
|
||||||
|
{
|
||||||
|
VkShaderStageFlags accessBits = 0;
|
||||||
|
for (int i = 0; i <= UnderlyingCast(MemoryAccess::Max); ++i)
|
||||||
|
{
|
||||||
|
MemoryAccess memoryAccess = static_cast<MemoryAccess>(i);
|
||||||
|
if (memoryAccessFlags.Test(memoryAccess))
|
||||||
|
accessBits |= ToVulkan(memoryAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineStageFlagBits ToVulkan(PipelineStage pipelineStage)
|
||||||
|
{
|
||||||
|
switch (pipelineStage)
|
||||||
|
{
|
||||||
|
case PipelineStage::TopOfPipe: return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
|
case PipelineStage::ColorOutput: return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
case PipelineStage::DrawIndirect: return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
|
||||||
|
case PipelineStage::FragmentShader: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
|
case PipelineStage::FragmentTestsEarly: return VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
|
case PipelineStage::FragmentTestsLate: return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
|
case PipelineStage::GeometryShader: return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||||
|
case PipelineStage::TessellationControlShader: return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
|
||||||
|
case PipelineStage::TessellationEvaluationShader: return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
|
||||||
|
case PipelineStage::Transfer: return VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
case PipelineStage::TransformFeedback: return VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
|
||||||
|
case PipelineStage::VertexInput: return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
||||||
|
case PipelineStage::VertexShader: return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
||||||
|
case PipelineStage::BottomOfPipe: return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled PipelineStage 0x" + NumberToString(UnderlyingCast(pipelineStage), 16));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineStageFlags ToVulkan(PipelineStageFlags pipelineStages)
|
||||||
|
{
|
||||||
|
VkShaderStageFlags pipelineStageBits = 0;
|
||||||
|
for (int i = 0; i <= UnderlyingCast(PipelineStage::Max); ++i)
|
||||||
|
{
|
||||||
|
PipelineStage pipelineStage = static_cast<PipelineStage>(i);
|
||||||
|
if (pipelineStages.Test(pipelineStage))
|
||||||
|
pipelineStageBits |= ToVulkan(pipelineStage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipelineStageBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFormat ToVulkan(PixelFormat pixelFormat)
|
||||||
|
{
|
||||||
|
switch (pixelFormat)
|
||||||
|
{
|
||||||
|
case PixelFormat::PixelFormat_BGRA8: return VK_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
case PixelFormat::PixelFormat_Depth24Stencil8: return VK_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
case PixelFormat::PixelFormat_Depth32: return VK_FORMAT_D32_SFLOAT;
|
||||||
|
case PixelFormat::PixelFormat_RGBA8: return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled PixelFormat 0x" + NumberToString(pixelFormat, 16));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode)
|
inline VkPrimitiveTopology ToVulkan(PrimitiveMode primitiveMode)
|
||||||
{
|
{
|
||||||
switch (primitiveMode)
|
switch (primitiveMode)
|
||||||
|
|
@ -172,14 +302,12 @@ namespace Nz
|
||||||
inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType)
|
inline VkShaderStageFlags ToVulkan(ShaderStageTypeFlags stageType)
|
||||||
{
|
{
|
||||||
VkShaderStageFlags shaderStageBits = 0;
|
VkShaderStageFlags shaderStageBits = 0;
|
||||||
|
for (int i = 0; i <= UnderlyingCast(ShaderStageType::Max); ++i)
|
||||||
if (stageType.Test(ShaderStageType::Fragment))
|
{
|
||||||
shaderStageBits |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
ShaderStageType shaderStage = static_cast<ShaderStageType>(i);
|
||||||
|
if (stageType.Test(shaderStage))
|
||||||
if (stageType.Test(ShaderStageType::Vertex))
|
shaderStageBits |= ToVulkan(shaderStage);
|
||||||
shaderStageBits |= VK_SHADER_STAGE_VERTEX_BIT;
|
}
|
||||||
|
|
||||||
static_assert(UnderlyingCast(ShaderStageType::Max) + 1 == 2);
|
|
||||||
|
|
||||||
return shaderStageBits;
|
return shaderStageBits;
|
||||||
}
|
}
|
||||||
|
|
@ -198,8 +326,26 @@ namespace Nz
|
||||||
case StencilOperation_Zero: return VK_STENCIL_OP_ZERO;
|
case StencilOperation_Zero: return VK_STENCIL_OP_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
NazaraError("Unhandled RendererComparison 0x" + NumberToString(stencilOp, 16));
|
NazaraError("Unhandled StencilOperation 0x" + NumberToString(stencilOp, 16));
|
||||||
return VK_STENCIL_OP_KEEP;
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageLayout ToVulkan(TextureLayout textureLayout)
|
||||||
|
{
|
||||||
|
switch (textureLayout)
|
||||||
|
{
|
||||||
|
case TextureLayout::ColorInput: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
case TextureLayout::ColorOutput: return VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR;
|
||||||
|
case TextureLayout::DepthStencilInput: return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL;
|
||||||
|
case TextureLayout::DepthStencilOutput: return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
|
||||||
|
case TextureLayout::Present: return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
case TextureLayout::TransferSource: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
case TextureLayout::TransferDestination: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
case TextureLayout::Undefined: return VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled TextureLayout 0x" + NumberToString(UnderlyingCast(textureLayout), 16));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VkVertexInputRate ToVulkan(VertexInputRate inputRate)
|
inline VkVertexInputRate ToVulkan(VertexInputRate inputRate)
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,11 @@ namespace Nz
|
||||||
class NAZARA_VULKANRENDERER_API VulkanRenderPass final : public RenderPass
|
class NAZARA_VULKANRENDERER_API VulkanRenderPass final : public RenderPass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline VulkanRenderPass(Vk::RenderPass renderPass, std::initializer_list<PixelFormat> formats); //< FIXME
|
VulkanRenderPass(Vk::Device& device, std::vector<Attachment> attachments, std::vector<SubpassDescription> subpassDescriptions, std::vector<SubpassDependency> subpassDependencies);
|
||||||
VulkanRenderPass(const VulkanRenderPass&) = delete;
|
VulkanRenderPass(const VulkanRenderPass&) = delete;
|
||||||
VulkanRenderPass(VulkanRenderPass&&) noexcept = default;
|
VulkanRenderPass(VulkanRenderPass&&) noexcept = default;
|
||||||
~VulkanRenderPass() = default;
|
~VulkanRenderPass() = default;
|
||||||
|
|
||||||
inline PixelFormat GetAttachmentFormat(std::size_t attachmentIndex) const;
|
|
||||||
inline Vk::RenderPass& GetRenderPass();
|
inline Vk::RenderPass& GetRenderPass();
|
||||||
inline const Vk::RenderPass& GetRenderPass() const;
|
inline const Vk::RenderPass& GetRenderPass() const;
|
||||||
|
|
||||||
|
|
@ -31,7 +30,6 @@ namespace Nz
|
||||||
VulkanRenderPass& operator=(VulkanRenderPass&&) noexcept = default;
|
VulkanRenderPass& operator=(VulkanRenderPass&&) noexcept = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PixelFormat> m_formats;
|
|
||||||
Vk::RenderPass m_renderPass;
|
Vk::RenderPass m_renderPass;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,6 @@
|
||||||
|
|
||||||
namespace Nz
|
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()
|
inline Vk::RenderPass& VulkanRenderPass::GetRenderPass()
|
||||||
{
|
{
|
||||||
return m_renderPass;
|
return m_renderPass;
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ namespace Nz
|
||||||
VkRenderWindow::VkRenderWindow(RenderWindow& owner) :
|
VkRenderWindow::VkRenderWindow(RenderWindow& owner) :
|
||||||
m_currentFrame(0),
|
m_currentFrame(0),
|
||||||
m_owner(owner),
|
m_owner(owner),
|
||||||
m_depthStencilFormat(VK_FORMAT_MAX_ENUM),
|
|
||||||
m_shouldRecreateSwapchain(false)
|
m_shouldRecreateSwapchain(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +150,7 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
m_depthStencilFormat = VK_FORMAT_MAX_ENUM;
|
||||||
if (!parameters.depthFormats.empty())
|
if (!parameters.depthFormats.empty())
|
||||||
{
|
{
|
||||||
for (PixelFormat format : parameters.depthFormats)
|
for (PixelFormat format : parameters.depthFormats)
|
||||||
|
|
@ -177,8 +177,7 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PixelFormat_Stencil16:
|
case PixelFormat_Stencil16:
|
||||||
m_depthStencilFormat = VK_FORMAT_MAX_ENUM;
|
continue;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
@ -400,98 +399,92 @@ namespace Nz
|
||||||
|
|
||||||
bool VkRenderWindow::SetupRenderPass()
|
bool VkRenderWindow::SetupRenderPass()
|
||||||
{
|
{
|
||||||
std::array<VkAttachmentDescription, 2> attachments = {
|
std::optional<PixelFormat> colorFormat = FromVulkan(m_surfaceFormat.format);
|
||||||
|
if (!colorFormat)
|
||||||
{
|
{
|
||||||
{
|
NazaraError("unhandled vulkan pixel format (0x" + NumberToString(m_surfaceFormat.format, 16) + ")");
|
||||||
0, // VkAttachmentDescriptionFlags flags;
|
|
||||||
m_surfaceFormat.format, // VkFormat format;
|
|
||||||
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
|
|
||||||
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
|
|
||||||
VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
|
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
|
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
|
|
||||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0, // VkAttachmentDescriptionFlags flags;
|
|
||||||
m_depthStencilFormat, // VkFormat format;
|
|
||||||
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
|
|
||||||
VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
|
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
|
|
||||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
|
|
||||||
VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
|
|
||||||
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
|
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
VkAttachmentReference colorReference = {
|
|
||||||
0, // uint32_t attachment;
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
|
|
||||||
};
|
|
||||||
|
|
||||||
VkAttachmentReference depthReference = {
|
|
||||||
1, // uint32_t attachment;
|
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
|
|
||||||
};
|
|
||||||
|
|
||||||
VkSubpassDescription subpass = {
|
|
||||||
0, // VkSubpassDescriptionFlags flags;
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
|
|
||||||
0U, // uint32_t inputAttachmentCount;
|
|
||||||
nullptr, // const VkAttachmentReference* pInputAttachments;
|
|
||||||
1U, // uint32_t colorAttachmentCount;
|
|
||||||
&colorReference, // const VkAttachmentReference* pColorAttachments;
|
|
||||||
nullptr, // const VkAttachmentReference* pResolveAttachments;
|
|
||||||
(m_depthStencilFormat != VK_FORMAT_MAX_ENUM) ? &depthReference : nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
|
|
||||||
0U, // uint32_t preserveAttachmentCount;
|
|
||||||
nullptr // const uint32_t* pPreserveAttachments;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<VkSubpassDependency, 2> dependencies;
|
|
||||||
// First dependency at the start of the render pass
|
|
||||||
// Does the transition from final to initial layout
|
|
||||||
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency
|
|
||||||
dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution dependency
|
|
||||||
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
dependencies[0].srcAccessMask = 0;
|
|
||||||
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
|
||||||
|
|
||||||
// Second dependency at the end the render pass
|
|
||||||
// Does the transition from the initial to the final layout
|
|
||||||
dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass
|
|
||||||
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the render pass
|
|
||||||
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
|
||||||
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
|
||||||
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
|
|
||||||
|
|
||||||
VkRenderPassCreateInfo createInfo = {
|
|
||||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
|
|
||||||
nullptr, // const void* pNext;
|
|
||||||
0, // VkRenderPassCreateFlags flags;
|
|
||||||
(m_depthStencilFormat != VK_FORMAT_MAX_ENUM) ? 2U : 1U, // uint32_t attachmentCount;
|
|
||||||
attachments.data(), // const VkAttachmentDescription* pAttachments;
|
|
||||||
1U, // uint32_t subpassCount;
|
|
||||||
&subpass, // const VkSubpassDescription* pSubpasses;
|
|
||||||
UInt32(dependencies.size()), // uint32_t dependencyCount;
|
|
||||||
dependencies.data() // const VkSubpassDependency* pDependencies;
|
|
||||||
};
|
|
||||||
|
|
||||||
Vk::RenderPass renderPass;
|
|
||||||
if (!renderPass.Create(*m_device, createInfo))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to create render pass: " + TranslateVulkanError(renderPass.GetLastErrorCode()));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::initializer_list<PixelFormat> fixmeplease = { PixelFormat::PixelFormat_RGB8, PixelFormat::PixelFormat_Depth24Stencil8 };
|
std::vector<RenderPass::Attachment> attachments;
|
||||||
m_renderPass.emplace(std::move(renderPass), fixmeplease);
|
attachments.push_back({
|
||||||
|
*colorFormat,
|
||||||
|
AttachmentLoadOp::Clear,
|
||||||
|
AttachmentLoadOp::Discard,
|
||||||
|
AttachmentStoreOp::Store,
|
||||||
|
AttachmentStoreOp::Discard,
|
||||||
|
TextureLayout::Undefined,
|
||||||
|
TextureLayout::Present
|
||||||
|
});
|
||||||
|
|
||||||
|
RenderPass::AttachmentReference colorReference = {
|
||||||
|
0,
|
||||||
|
TextureLayout::ColorInput
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<RenderPass::SubpassDescription> subpasses = {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{ colorReference },
|
||||||
|
{},
|
||||||
|
std::nullopt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<RenderPass::SubpassDependency> subpassDependencies = {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
RenderPass::ExternalSubpassIndex,
|
||||||
|
PipelineStage::ColorOutput,
|
||||||
|
{},
|
||||||
|
|
||||||
|
0,
|
||||||
|
PipelineStage::ColorOutput,
|
||||||
|
MemoryAccess::ColorWrite,
|
||||||
|
|
||||||
|
true //< tilable
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
PipelineStage::ColorOutput,
|
||||||
|
MemoryAccess::ColorWrite,
|
||||||
|
|
||||||
|
RenderPass::ExternalSubpassIndex,
|
||||||
|
PipelineStage::BottomOfPipe,
|
||||||
|
MemoryAccess::MemoryRead,
|
||||||
|
|
||||||
|
true //< tilable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM)
|
||||||
|
{
|
||||||
|
std::optional<PixelFormat> depthStencilFormat = FromVulkan(m_depthStencilFormat);
|
||||||
|
if (!depthStencilFormat)
|
||||||
|
{
|
||||||
|
NazaraError("unhandled vulkan pixel format (0x" + NumberToString(m_depthStencilFormat, 16) + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments.push_back({
|
||||||
|
*depthStencilFormat,
|
||||||
|
AttachmentLoadOp::Clear,
|
||||||
|
AttachmentLoadOp::Discard,
|
||||||
|
AttachmentStoreOp::Discard,
|
||||||
|
AttachmentStoreOp::Discard,
|
||||||
|
TextureLayout::Undefined,
|
||||||
|
TextureLayout::DepthStencilInput
|
||||||
|
});
|
||||||
|
|
||||||
|
subpasses.front().depthStencilAttachment = RenderPass::AttachmentReference{
|
||||||
|
1,
|
||||||
|
TextureLayout::DepthStencilInput
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
m_renderPass.emplace(*m_device, std::move(attachments), std::move(subpasses), std::move(subpassDependencies));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
auto& vkValues = vkClearValues[index];
|
auto& vkValues = vkClearValues[index];
|
||||||
|
|
||||||
if (PixelFormatInfo::GetContent(vkRenderPass.GetAttachmentFormat(index)) == PixelFormatContent_ColorRGBA)
|
if (PixelFormatInfo::GetContent(vkRenderPass.GetAttachment(index).format) == PixelFormatContent_ColorRGBA)
|
||||||
{
|
{
|
||||||
vkValues.color.float32[0] = values.color.r / 255.f;
|
vkValues.color.float32[0] = values.color.r / 255.f;
|
||||||
vkValues.color.float32[1] = values.color.g / 255.f;
|
vkValues.color.float32[1] = values.color.g / 255.f;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,116 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
|
#include <Nazara/VulkanRenderer/VulkanRenderPass.hpp>
|
||||||
|
#include <Nazara/Core/StackVector.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Utils.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline VulkanRenderPass::VulkanRenderPass(Vk::Device& device, std::vector<Attachment> attachments, std::vector<SubpassDescription> subpassDescriptions, std::vector<SubpassDependency> subpassDependencies) :
|
||||||
|
RenderPass(std::move(attachments), std::move(subpassDescriptions), std::move(subpassDependencies))
|
||||||
|
{
|
||||||
|
std::size_t totalAttachmentReference = 0;
|
||||||
|
for (const SubpassDescription& subpassInfo : m_subpassDescriptions)
|
||||||
|
{
|
||||||
|
totalAttachmentReference += subpassInfo.colorAttachment.size();
|
||||||
|
totalAttachmentReference += subpassInfo.inputAttachments.size();
|
||||||
|
|
||||||
|
if (subpassInfo.depthStencilAttachment)
|
||||||
|
totalAttachmentReference++;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackVector<VkAttachmentDescription> vkAttachments = NazaraStackVector(VkAttachmentDescription, m_attachments.size());
|
||||||
|
for (const Attachment& attachmentInfo : m_attachments)
|
||||||
|
{
|
||||||
|
vkAttachments.push_back({
|
||||||
|
0,
|
||||||
|
ToVulkan(attachmentInfo.format),
|
||||||
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
ToVulkan(attachmentInfo.loadOp),
|
||||||
|
ToVulkan(attachmentInfo.storeOp),
|
||||||
|
ToVulkan(attachmentInfo.stencilLoadOp),
|
||||||
|
ToVulkan(attachmentInfo.stencilStoreOp),
|
||||||
|
ToVulkan(attachmentInfo.initialLayout),
|
||||||
|
ToVulkan(attachmentInfo.finalLayout)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
StackVector<VkAttachmentReference> vkAttachmentReferences = NazaraStackVector(VkAttachmentReference, totalAttachmentReference);
|
||||||
|
|
||||||
|
StackVector<VkSubpassDescription> vkSubpassDescs = NazaraStackVector(VkSubpassDescription, m_subpassDescriptions.size());
|
||||||
|
for (const SubpassDescription& subpassInfo : m_subpassDescriptions)
|
||||||
|
{
|
||||||
|
std::size_t colorAttachmentIndex = vkAttachmentReferences.size();
|
||||||
|
for (const AttachmentReference& attachmentRef : subpassInfo.colorAttachment)
|
||||||
|
{
|
||||||
|
vkAttachmentReferences.push_back({
|
||||||
|
UInt32(attachmentRef.attachmentIndex),
|
||||||
|
ToVulkan(attachmentRef.attachmentLayout)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t inputAttachmentIndex = vkAttachmentReferences.size();
|
||||||
|
for (const AttachmentReference& attachmentRef : subpassInfo.inputAttachments)
|
||||||
|
{
|
||||||
|
vkAttachmentReferences.push_back({
|
||||||
|
UInt32(attachmentRef.attachmentIndex),
|
||||||
|
ToVulkan(attachmentRef.attachmentLayout)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t depthStencilAttachmentIndex = vkAttachmentReferences.size();
|
||||||
|
if (subpassInfo.depthStencilAttachment)
|
||||||
|
{
|
||||||
|
auto& depthStencilRef = *subpassInfo.depthStencilAttachment;
|
||||||
|
vkAttachmentReferences.push_back({
|
||||||
|
UInt32(depthStencilRef.attachmentIndex),
|
||||||
|
ToVulkan(depthStencilRef.attachmentLayout)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
vkSubpassDescs.push_back({
|
||||||
|
VkSubpassDescriptionFlags(0),
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
UInt32(subpassInfo.inputAttachments.size()),
|
||||||
|
&vkAttachmentReferences[inputAttachmentIndex],
|
||||||
|
UInt32(subpassInfo.colorAttachment.size()),
|
||||||
|
&vkAttachmentReferences[colorAttachmentIndex],
|
||||||
|
nullptr,
|
||||||
|
(subpassInfo.depthStencilAttachment) ? &vkAttachmentReferences[depthStencilAttachmentIndex] : nullptr,
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
StackVector<VkSubpassDependency> vkSubpassDeps = NazaraStackVector(VkSubpassDependency, m_subpassDependencies.size());
|
||||||
|
for (const SubpassDependency& subpassDependency : m_subpassDependencies)
|
||||||
|
{
|
||||||
|
vkSubpassDeps.push_back({
|
||||||
|
UInt32(subpassDependency.fromSubpassIndex),
|
||||||
|
UInt32(subpassDependency.toSubpassIndex),
|
||||||
|
ToVulkan(subpassDependency.fromStages),
|
||||||
|
ToVulkan(subpassDependency.toStages),
|
||||||
|
ToVulkan(subpassDependency.fromAccessFlags),
|
||||||
|
ToVulkan(subpassDependency.toAccessFlags),
|
||||||
|
VkDependencyFlags((subpassDependency.tilable) ? VK_DEPENDENCY_BY_REGION_BIT : 0)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
VkRenderPassCreateInfo renderPassInfo = {
|
||||||
|
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
|
||||||
|
nullptr, // pNext
|
||||||
|
0, // flags
|
||||||
|
UInt32(vkAttachments.size()), // attachmentCount
|
||||||
|
vkAttachments.data(), // pAttachments
|
||||||
|
UInt32(vkSubpassDescs.size()), // subpassCount
|
||||||
|
vkSubpassDescs.data(), // pSubpasses
|
||||||
|
UInt32(vkSubpassDeps.size()), // dependencyCount
|
||||||
|
vkSubpassDeps.data() // pDependencies
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!m_renderPass.Create(device, renderPassInfo))
|
||||||
|
throw std::runtime_error("failed to instantiate Vulkan render pass: " + TranslateVulkanError(m_renderPass.GetLastErrorCode()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue