From 7871ec06ae7fa3f90e44d186252c24a6d13249f8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 1 Mar 2019 21:34:08 +0100 Subject: [PATCH] - add depth/stencil attachment to the render pass --- .../vulkan/renderer/vk_renderpass.cpp | 32 ++++++++-- src/rendering/vulkan/renderer/vk_renderpass.h | 6 +- .../vulkan/renderer/vk_renderstate.cpp | 61 +++++++++++++++++++ .../vulkan/renderer/vk_renderstate.h | 3 + src/rendering/vulkan/system/vk_builders.h | 22 +++---- 5 files changed, 106 insertions(+), 18 deletions(-) diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index c27be2e874..14c78eb183 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -154,18 +154,36 @@ void VkRenderPassManager::CreateDynamicSet() VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key) { - CreateRenderPass(); + CreateRenderPass(key); CreatePipeline(key); - CreateFramebuffer(); + CreateFramebuffer(key); } -void VkRenderPassSetup::CreateRenderPass() +void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key) { RenderPassBuilder builder; builder.addRgba16fAttachment(false, VK_IMAGE_LAYOUT_GENERAL); + if (key.DepthTest || key.DepthWrite) + builder.addDepthStencilAttachment(false, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); builder.addSubpass(); builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_GENERAL); - builder.addExternalSubpassDependency(); + if (key.DepthTest || key.DepthWrite) + { + builder.addSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + builder.addExternalSubpassDependency( + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); + } + else + { + builder.addExternalSubpassDependency( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); + } RenderPass = builder.create(GetVulkanFrameBuffer()->device); } @@ -265,6 +283,8 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key) blendequation = VK_BLEND_OP_ADD; } + builder.setDepthEnable(key.DepthTest, key.DepthWrite); + builder.setBlendMode((VkBlendOp)blendequation, (VkBlendFactor)srcblend, (VkBlendFactor)dstblend); builder.setLayout(fb->GetRenderPassManager()->PipelineLayout.get()); @@ -272,12 +292,14 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key) Pipeline = builder.create(fb->device); } -void VkRenderPassSetup::CreateFramebuffer() +void VkRenderPassSetup::CreateFramebuffer(const VkRenderPassKey &key) { auto fb = GetVulkanFrameBuffer(); FramebufferBuilder builder; builder.setRenderPass(RenderPass.get()); builder.setSize(SCREENWIDTH, SCREENHEIGHT); builder.addAttachment(fb->GetRenderPassManager()->SceneColorView.get()); + if (key.DepthTest || key.DepthWrite) + builder.addAttachment(fb->GetRenderPassManager()->SceneDepthStencilView.get()); Framebuffer = builder.create(GetVulkanFrameBuffer()->device); } diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 4d0b96e630..16475e7d68 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -15,6 +15,8 @@ public: int SpecialEffect; int EffectState; int AlphaTest; + int DepthWrite; + int DepthTest; int VertexFormat; int DrawType; @@ -35,8 +37,8 @@ public: private: void CreatePipeline(const VkRenderPassKey &key); - void CreateRenderPass(); - void CreateFramebuffer(); + void CreateRenderPass(const VkRenderPassKey &key); + void CreateFramebuffer(const VkRenderPassKey &key); }; class VkVertexFormat diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index 38f64df95b..cf0322e886 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -97,6 +97,63 @@ void VkRenderState::EnableClipDistance(int num, bool state) void VkRenderState::Clear(int targets) { + // We need an active render pass, and it must have a depth attachment.. + bool lastDepthTest = mDepthTest; + bool lastDepthWrite = mDepthWrite; + if (targets & (CT_Depth | CT_Stencil)) + { + mDepthTest = true; + mDepthWrite = true; + } + Apply(DT_TriangleFan); + mDepthTest = lastDepthTest; + mDepthWrite = lastDepthWrite; + + VkClearAttachment attachments[2] = { }; + VkClearRect rects[2] = { }; + + for (int i = 0; i < 2; i++) + { + rects[i].layerCount = 1; + if (mScissorWidth >= 0) + { + rects[0].rect.offset.x = mScissorX; + rects[0].rect.offset.y = mScissorY; + rects[0].rect.extent.width = mScissorWidth; + rects[0].rect.extent.height = mScissorHeight; + } + else + { + rects[0].rect.offset.x = 0; + rects[0].rect.offset.y = 0; + rects[0].rect.extent.width = SCREENWIDTH; + rects[0].rect.extent.height = SCREENHEIGHT; + } + } + + if (targets & CT_Depth) + { + attachments[1].aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; + attachments[1].clearValue.depthStencil.depth = 1.0f; + } + if (targets & CT_Stencil) + { + attachments[1].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + attachments[1].clearValue.depthStencil.stencil = 0; + } + if (targets & CT_Color) + { + attachments[0].aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT; + for (int i = 0; i < 4; i++) + attachments[0].clearValue.color.float32[i] = screen->mSceneClearColor[i]; + } + + if ((targets & CT_Color) && (targets & CT_Stencil) && (targets & CT_Depth)) + mCommandBuffer->clearAttachments(2, attachments, 2, rects); + else if (targets & (CT_Stencil | CT_Depth)) + mCommandBuffer->clearAttachments(1, attachments + 1, 1, rects + 1); + else if (targets & CT_Color) + mCommandBuffer->clearAttachments(1, attachments, 1, rects); } void VkRenderState::EnableStencil(bool on) @@ -123,6 +180,8 @@ void VkRenderState::SetViewport(int x, int y, int w, int h) void VkRenderState::EnableDepthTest(bool on) { + mDepthTest = on; + mDepthWrite = on; } void VkRenderState::EnableMultisampling(bool on) @@ -153,6 +212,8 @@ void VkRenderState::Apply(int dt) passKey.DrawType = dt; passKey.VertexFormat = static_cast(mVertexBuffer)->VertexFormat; passKey.RenderStyle = mRenderStyle; + passKey.DepthTest = mDepthTest; + passKey.DepthWrite = mDepthWrite; if (mSpecialEffect > EFF_NONE) { passKey.SpecialEffect = mSpecialEffect; diff --git a/src/rendering/vulkan/renderer/vk_renderstate.h b/src/rendering/vulkan/renderer/vk_renderstate.h index 4f99993928..6ace278b41 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.h +++ b/src/rendering/vulkan/renderer/vk_renderstate.h @@ -58,6 +58,9 @@ private: bool mScissorChanged = true; bool mViewportChanged = true; + bool mDepthTest = false; + bool mDepthWrite = false; + MatricesUBO mMatrices = {}; ColorsUBO mColors = {}; GlowingWallsUBO mGlowingWalls = {}; diff --git a/src/rendering/vulkan/system/vk_builders.h b/src/rendering/vulkan/system/vk_builders.h index a12e94d72c..fb23fdceb1 100644 --- a/src/rendering/vulkan/system/vk_builders.h +++ b/src/rendering/vulkan/system/vk_builders.h @@ -247,13 +247,13 @@ public: void addRgba16fAttachment(bool clear, VkImageLayout layout) { addColorAttachment(clear, VK_FORMAT_R16G16B16A16_SFLOAT, layout); } void addColorAttachment(bool clear, VkFormat format, VkImageLayout layout); - void addDepthAttachment(bool clear, VkImageLayout layout); + void addDepthStencilAttachment(bool clear, VkImageLayout layout); - void addExternalSubpassDependency(); + void addExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); void addSubpass(); void addSubpassColorAttachmentRef(uint32_t index, VkImageLayout layout); - void addSubpassDepthAttachmentRef(uint32_t index, VkImageLayout layout); + void addSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout); std::unique_ptr create(VulkanDevice *device); @@ -936,10 +936,10 @@ inline void RenderPassBuilder::addColorAttachment(bool clear, VkFormat format, V renderPassInfo.attachmentCount = (uint32_t)attachments.size(); } -inline void RenderPassBuilder::addDepthAttachment(bool clear, VkImageLayout layout) +inline void RenderPassBuilder::addDepthStencilAttachment(bool clear, VkImageLayout layout) { VkAttachmentDescription depthAttachment = {}; - depthAttachment.format = VK_FORMAT_D32_SFLOAT; + depthAttachment.format = VK_FORMAT_D32_SFLOAT_S8_UINT; depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; depthAttachment.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE/*VK_ATTACHMENT_STORE_OP_DONT_CARE*/; @@ -953,15 +953,15 @@ inline void RenderPassBuilder::addDepthAttachment(bool clear, VkImageLayout layo renderPassInfo.attachmentCount = (uint32_t)attachments.size(); } -inline void RenderPassBuilder::addExternalSubpassDependency() +inline void RenderPassBuilder::addExternalSubpassDependency(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) { VkSubpassDependency dependency = {}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependency.srcStageMask = srcStageMask; + dependency.srcAccessMask = srcAccessMask; + dependency.dstStageMask = dstStageMask; + dependency.dstAccessMask = dstAccessMask; dependencies.push_back(dependency); renderPassInfo.pDependencies = dependencies.data(); @@ -991,7 +991,7 @@ inline void RenderPassBuilder::addSubpassColorAttachmentRef(uint32_t index, VkIm subpasses.back().colorAttachmentCount = (uint32_t)subpassData.back()->colorRefs.size(); } -inline void RenderPassBuilder::addSubpassDepthAttachmentRef(uint32_t index, VkImageLayout layout) +inline void RenderPassBuilder::addSubpassDepthStencilAttachmentRef(uint32_t index, VkImageLayout layout) { VkAttachmentReference &depthAttachmentRef = subpassData.back()->depthRef; depthAttachmentRef.attachment = index;