From e1ae8bbc594424a0e622ea908ff52231e52a9882 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 May 2019 01:58:36 +0200 Subject: [PATCH] - rendering to texture requires a separate depth/stencil image as the image used by the main view may be using multisampling --- .../vulkan/renderer/vk_postprocess.cpp | 2 +- .../vulkan/renderer/vk_renderbuffers.cpp | 26 +++++++++++++++++++ .../vulkan/renderer/vk_renderbuffers.h | 4 +++ .../vulkan/renderer/vk_renderpass.cpp | 12 ++++++--- src/rendering/vulkan/renderer/vk_renderpass.h | 1 + .../vulkan/renderer/vk_renderstate.cpp | 6 +++-- .../vulkan/renderer/vk_renderstate.h | 3 ++- .../vulkan/system/vk_framebuffer.cpp | 6 ++--- 8 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index db82eb3bf..f57f74a70 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -34,7 +34,7 @@ void VkPostprocess::SetActiveRenderTarget() imageTransition.addImage(buffers->PipelineImage[mCurrentPipelineImage].get(), &buffers->PipelineLayout[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); imageTransition.execute(fb->GetDrawCommands()); - fb->GetRenderState()->SetRenderTarget(buffers->PipelineView[mCurrentPipelineImage].get(), buffers->GetWidth(), buffers->GetHeight(), VK_SAMPLE_COUNT_1_BIT); + fb->GetRenderState()->SetRenderTarget(buffers->PipelineView[mCurrentPipelineImage].get(), buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT); } void VkPostprocess::PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp index 29524599f..e87cb6982 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -55,6 +55,7 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen if (width != mWidth || height != mHeight || mSamples != samples) CreateScene(width, height, samples); + CreateCamTexDepthStencil(); CreateShadowmap(); mWidth = width; @@ -142,6 +143,31 @@ void VkRenderBuffers::CreateSceneColor(int width, int height, VkSampleCountFlagB SceneColorView->SetDebugName("VkRenderBuffers.SceneColorView"); } +void VkRenderBuffers::CreateCamTexDepthStencil() +{ + if (CamtexDepthStencil) + return; + + auto fb = GetVulkanFrameBuffer(); + + ImageBuilder builder; + builder.setSize(1024, 1024); + builder.setSamples(VK_SAMPLE_COUNT_1_BIT); + builder.setFormat(SceneDepthStencilFormat); + builder.setUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + CamtexDepthStencil = builder.create(fb->device); + CamtexDepthStencil->SetDebugName("VkRenderBuffers.CamtexDepthStencil"); + + ImageViewBuilder viewbuilder; + viewbuilder.setImage(CamtexDepthStencil.get(), SceneDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + CamtexDepthStencilView = viewbuilder.create(fb->device); + CamtexDepthStencilView->SetDebugName("VkRenderBuffers.CamtexDepthStencilView"); + + PipelineBarrier barrier; + barrier.addImage(CamtexDepthStencil.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); +} + void VkRenderBuffers::CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples) { auto fb = GetVulkanFrameBuffer(); diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.h b/src/rendering/vulkan/renderer/vk_renderbuffers.h index 63b84f996..75ba8fb65 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.h @@ -32,6 +32,9 @@ public: VkImageLayout SceneNormalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkImageLayout SceneFogLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + std::unique_ptr CamtexDepthStencil; + std::unique_ptr CamtexDepthStencilView; + static const int NumPipelineImages = 2; std::unique_ptr PipelineImage[NumPipelineImages]; std::unique_ptr PipelineView[NumPipelineImages]; @@ -50,6 +53,7 @@ private: void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples); void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples); void CreateShadowmap(); + void CreateCamTexDepthStencil(); VkSampleCountFlagBits GetBestSampleCount(); int mWidth = 0; diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index 7972cf0f5..616668cec 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -208,17 +208,23 @@ void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key) VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A2R10G10B10_UNORM_PACK32 }; RenderPassBuilder builder; - for (int i = 0; i < key.DrawBuffers; i++) + + builder.addAttachment( + key.DrawBufferFormat, (VkSampleCountFlagBits)key.Samples, + (key.ClearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + for (int i = 1; i < key.DrawBuffers; i++) { builder.addAttachment( - drawBufferFormats[i], i == 0 ? (VkSampleCountFlagBits)key.Samples : buffers->GetSceneSamples(), + drawBufferFormats[i], buffers->GetSceneSamples(), (key.ClearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } if (key.UsesDepthStencil()) { builder.addDepthStencilAttachment( - buffers->SceneDepthStencilFormat, buffers->GetSceneSamples(), + buffers->SceneDepthStencilFormat, key.DrawBufferFormat == VK_FORMAT_R8G8B8A8_UNORM ? VK_SAMPLE_COUNT_1_BIT : buffers->GetSceneSamples(), (key.ClearTargets & CT_Depth) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, (key.ClearTargets & CT_Stencil) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 0294c93c3..dab149a19 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -32,6 +32,7 @@ public: int ClearTargets; int DrawBuffers; int NumTextureLayers; + VkFormat DrawBufferFormat; bool UsesDepthStencil() const { return DepthTest || DepthWrite || StencilTest || (ClearTargets & (CT_Depth | CT_Stencil)); } diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index 594ee755c..f500edc38 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -210,6 +210,7 @@ void VkRenderState::ApplyRenderPass(int dt) passKey.StencilPassOp = mStencilOp; passKey.ColorMask = mColorMask; passKey.CullMode = mCullMode; + passKey.DrawBufferFormat = mRenderTarget.Format; passKey.Samples = mRenderTarget.Samples; passKey.DrawBuffers = mRenderTarget.DrawBuffers; passKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 0; @@ -535,13 +536,14 @@ void VkRenderState::EnableDrawBuffers(int count) } } -void VkRenderState::SetRenderTarget(VulkanImageView *view, int width, int height, VkSampleCountFlagBits samples) +void VkRenderState::SetRenderTarget(VulkanImageView *view, int width, int height, VkFormat format, VkSampleCountFlagBits samples) { EndRenderPass(); mRenderTarget.View = view; mRenderTarget.Width = width; mRenderTarget.Height = height; + mRenderTarget.Format = format; mRenderTarget.Samples = samples; } @@ -564,7 +566,7 @@ void VkRenderState::BeginRenderPass(const VkRenderPassKey &key, VulkanCommandBuf if (key.DrawBuffers > 2) builder.addAttachment(buffers->SceneNormalView.get()); if (key.UsesDepthStencil()) - builder.addAttachment(buffers->SceneDepthStencilView.get()); + builder.addAttachment(mRenderTarget.Format == VK_FORMAT_R8G8B8A8_UNORM ? buffers->CamtexDepthStencilView.get() : buffers->SceneDepthStencilView.get()); framebuffer = builder.create(GetVulkanFrameBuffer()->device); framebuffer->SetDebugName("VkRenderPassSetup.Framebuffer"); } diff --git a/src/rendering/vulkan/renderer/vk_renderstate.h b/src/rendering/vulkan/renderer/vk_renderstate.h index 329c4c5b3..eb15164c9 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.h +++ b/src/rendering/vulkan/renderer/vk_renderstate.h @@ -43,7 +43,7 @@ public: void EnableDrawBuffers(int count) override; void BeginFrame(); - void SetRenderTarget(VulkanImageView *view, int width, int height, VkSampleCountFlagBits samples); + void SetRenderTarget(VulkanImageView *view, int width, int height, VkFormat Format, VkSampleCountFlagBits samples); void Bind(int bindingpoint, uint32_t offset); void EndRenderPass(); void EndFrame(); @@ -114,6 +114,7 @@ protected: VulkanImageView *View = nullptr; int Width = 0; int Height = 0; + VkFormat Format = VK_FORMAT_R16G16B16A16_SFLOAT; VkSampleCountFlagBits Samples = VK_SAMPLE_COUNT_1_BIT; int DrawBuffers = 1; } mRenderTarget; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index adc004d37..a4d4028be 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -442,7 +442,7 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao { - mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), GetBuffers()->GetSceneSamples()); + mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); bool useSSAO = (gl_ssao != 0); GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); @@ -513,7 +513,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint barrier0.addImage(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); barrier0.execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - mRenderState->SetRenderTarget(view, image->width, image->height, VK_SAMPLE_COUNT_1_BIT); + mRenderState->SetRenderTarget(view, image->width, image->height, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT); IntRect bounds; bounds.left = bounds.top = 0; @@ -529,7 +529,7 @@ void VulkanFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint barrier1.addImage(image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); barrier1.execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); - mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), GetBuffers()->GetSceneSamples()); + mRenderState->SetRenderTarget(GetBuffers()->SceneColorView.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples()); tex->SetUpdated(true); }