diff --git a/src/rendering/gl/renderer/gl_renderstate.cpp b/src/rendering/gl/renderer/gl_renderstate.cpp index 57f20646ee..a27e651402 100644 --- a/src/rendering/gl/renderer/gl_renderstate.cpp +++ b/src/rendering/gl/renderer/gl_renderstate.cpp @@ -77,7 +77,6 @@ void FGLRenderState::Reset() mEffectState = 0; activeShader = nullptr; - mPassType = NORMAL_PASS; mCurrentVertexBuffer = nullptr; mCurrentVertexOffsets[0] = mVertexOffsets[0] = 0; @@ -435,11 +434,6 @@ void FGLRenderState::SetColorMask(bool r, bool g, bool b, bool a) glColorMask(r, g, b, a); } -void FGLRenderState::EnableDrawBufferAttachments(bool on) -{ - EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1); -} - void FGLRenderState::SetStencil(int offs, int op, int flags = -1) { static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR }; diff --git a/src/rendering/gl/renderer/gl_renderstate.h b/src/rendering/gl/renderer/gl_renderstate.h index 671a7e506e..c28d8963d0 100644 --- a/src/rendering/gl/renderer/gl_renderstate.h +++ b/src/rendering/gl/renderer/gl_renderstate.h @@ -40,14 +40,6 @@ namespace OpenGLRenderer class FShader; struct GLSectorPlane; -enum EPassType -{ - NORMAL_PASS, - GBUFFER_PASS, - MAX_PASS_TYPES -}; - - class FGLRenderState : public FRenderState { uint64_t firstFrame = 0; @@ -68,7 +60,6 @@ class FGLRenderState : public FRenderState FShader *activeShader; - EPassType mPassType = NORMAL_PASS; int mNumDrawBuffers = 1; bool ApplyShader(); @@ -119,17 +110,7 @@ public: mSpecularLevel = specularLevel; } - void SetPassType(EPassType passType) - { - mPassType = passType; - } - - EPassType GetPassType() - { - return mPassType; - } - - void EnableDrawBuffers(int count) + void EnableDrawBuffers(int count) override { count = MIN(count, 3); if (mNumDrawBuffers != count) @@ -140,11 +121,6 @@ public: } } - int GetPassDrawBufferCount() - { - return mPassType == GBUFFER_PASS ? 3 : 1; - } - void ToggleState(int state, bool on); void ClearScreen() override; @@ -156,7 +132,6 @@ public: void SetDepthFunc(int func) override; void SetDepthRange(float min, float max) override; void SetColorMask(bool r, bool g, bool b, bool a) override; - void EnableDrawBufferAttachments(bool on) override; void SetStencil(int offs, int op, int flags) override; void SetCulling(int mode) override; void EnableClipDistance(int num, bool state) override; diff --git a/src/rendering/hwrenderer/scene/hw_renderstate.h b/src/rendering/hwrenderer/scene/hw_renderstate.h index 9715ba3de8..c7d894fcf9 100644 --- a/src/rendering/hwrenderer/scene/hw_renderstate.h +++ b/src/rendering/hwrenderer/scene/hw_renderstate.h @@ -120,6 +120,13 @@ struct FDepthBiasState } }; +enum EPassType +{ + NORMAL_PASS, + GBUFFER_PASS, + MAX_PASS_TYPES +}; + class FRenderState { protected: @@ -163,6 +170,7 @@ protected: int mVertexOffsets[2]; // one per binding point IIndexBuffer *mIndexBuffer; + EPassType mPassType = NORMAL_PASS; public: VSMatrix mModelMatrix; @@ -193,6 +201,7 @@ public: mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); mBias.Reset(); + mPassType = NORMAL_PASS; mVertexBuffer = nullptr; mVertexOffsets[0] = mVertexOffsets[1] = 0; @@ -502,6 +511,26 @@ public: return mInterpolationFactor; } + void EnableDrawBufferAttachments(bool on) // Used by fog boundary drawer + { + EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1); + } + + int GetPassDrawBufferCount() + { + return mPassType == GBUFFER_PASS ? 3 : 1; + } + + void SetPassType(EPassType passType) + { + mPassType = passType; + } + + EPassType GetPassType() + { + return mPassType; + } + // API-dependent render interface // Draw commands @@ -515,7 +544,6 @@ public: virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces. virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup. virtual void SetColorMask(bool r, bool g, bool b, bool a) = 0; // Used by portals. - virtual void EnableDrawBufferAttachments(bool on) = 0; // Used by fog boundary drawer. virtual void SetStencil(int offs, int op, int flags=-1) = 0; // Used by portal setup and render hacks. virtual void SetCulling(int mode) = 0; // Used by model drawer only. virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits. @@ -526,6 +554,7 @@ public: virtual void EnableDepthTest(bool on) = 0; // used by 2D, portals and render hacks. virtual void EnableMultisampling(bool on) = 0; // only active for 2D virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation + virtual void EnableDrawBuffers(int count) = 0; // Used by SSAO and EnableDrawBufferAttachments void SetColorMask(bool on) { diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index 12ff156394..8d5c8a9d7e 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -59,7 +59,7 @@ void VkPostprocess::PostProcessScene(int fixedcm, const std::function &a //mCustomPostProcessShaders->Run("scene"); } -void VkPostprocess::BlitSceneToTexture() +void VkPostprocess::BlitSceneToPostprocess() { auto fb = GetVulkanFrameBuffer(); @@ -116,11 +116,19 @@ void VkPostprocess::BlitSceneToTexture() buffers->PipelineImage[mCurrentPipelineImage]->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); } +} - // Note: this destroys the SceneColor contents - VkPPImageTransition imageTransition1; - imageTransition1.addImage(buffers->SceneColor.get(), &buffers->SceneColorLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true); - imageTransition1.execute(fb->GetDrawCommands()); +void VkPostprocess::ImageTransitionScene(bool undefinedSrcLayout) +{ + auto fb = GetVulkanFrameBuffer(); + auto buffers = fb->GetBuffers(); + + VkPPImageTransition imageTransition; + imageTransition.addImage(buffers->SceneColor.get(), &buffers->SceneColorLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.addImage(buffers->SceneFog.get(), &buffers->SceneFogLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.addImage(buffers->SceneNormal.get(), &buffers->SceneNormalLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.addImage(buffers->SceneDepthStencil.get(), &buffers->SceneDepthStencilLayout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, undefinedSrcLayout); + imageTransition.execute(fb->GetDrawCommands()); } void VkPostprocess::BlitCurrentToImage(VulkanImage *dstimage, VkImageLayout *dstlayout, VkImageLayout finallayout) @@ -207,6 +215,8 @@ void VkPostprocess::AmbientOccludeScene(float m5) VkPPRenderState renderstate; hw_postprocess.ssao.Render(&renderstate, m5, sceneWidth, sceneHeight); + + ImageTransitionScene(false); } void VkPostprocess::BlurScene(float gameinfobluramount) @@ -242,7 +252,7 @@ void VkPostprocess::UpdateShadowMap() auto buffers = fb->GetBuffers(); VkPPImageTransition imageTransition; - imageTransition.addImage(buffers->Shadowmap.get(), &buffers->ShadowmapLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); + imageTransition.addImage(buffers->Shadowmap.get(), &buffers->ShadowmapLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); imageTransition.execute(fb->GetDrawCommands()); screen->mShadowMap.FinishUpdate(); @@ -426,6 +436,11 @@ void VkPPRenderState::Draw() else key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT; + if (Output.Type == PPTextureType::SceneColor) + key.Samples = fb->GetBuffers()->GetSceneSamples(); + else + key.Samples = VK_SAMPLE_COUNT_1_BIT; + auto &passSetup = pp->mRenderPassSetup[key]; if (!passSetup) passSetup.reset(new VkPPRenderPassSetup(key)); @@ -692,10 +707,12 @@ void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey &key) builder.addVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(FFlatVertex, u)); builder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT); builder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR); - builder.setViewport(0.0f, 0.0f, (float)SCREENWIDTH, (float)SCREENHEIGHT); - builder.setScissor(0.0f, 0.0f, (float)SCREENWIDTH, (float)SCREENHEIGHT); + // Note: the actual values are ignored since we use dynamic viewport+scissor states + builder.setViewport(0.0f, 0.0f, 320.0f, 200.0f); + builder.setScissor(0.0f, 0.0f, 320.0f, 200.0f); builder.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); builder.setBlendMode(key.BlendMode); + builder.setRasterizationSamples(key.Samples); builder.setLayout(PipelineLayout.get()); builder.setRenderPass(RenderPass.get()); Pipeline = builder.create(GetVulkanFrameBuffer()->device); @@ -706,9 +723,9 @@ void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey &key) { RenderPassBuilder builder; if (key.SwapChain) - builder.addAttachment(key.OutputFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); else - builder.addAttachment(key.OutputFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + builder.addAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); builder.addSubpass(); builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); builder.addExternalSubpassDependency( @@ -729,6 +746,7 @@ void VkPPImageTransition::addImage(VulkanImage *image, VkImageLayout *layout, Vk VkAccessFlags srcAccess = 0; VkAccessFlags dstAccess = 0; + VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; switch (*layout) { @@ -748,6 +766,11 @@ void VkPPImageTransition::addImage(VulkanImage *image, VkImageLayout *layout, Vk srcAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; srcStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + break; default: I_FatalError("Unimplemented src image layout transition\n"); } @@ -770,11 +793,16 @@ void VkPPImageTransition::addImage(VulkanImage *image, VkImageLayout *layout, Vk dstAccess = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dstStageMask |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + srcAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + srcStageMask |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + break; default: I_FatalError("Unimplemented dst image layout transition\n"); } - barrier.addImage(image, undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : *layout, targetLayout, srcAccess, dstAccess); + barrier.addImage(image, undefinedSrcLayout ? VK_IMAGE_LAYOUT_UNDEFINED : *layout, targetLayout, srcAccess, dstAccess, aspectMask); needbarrier = true; *layout = targetLayout; } diff --git a/src/rendering/vulkan/renderer/vk_postprocess.h b/src/rendering/vulkan/renderer/vk_postprocess.h index 2ba858ccbf..50a5549f3d 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/rendering/vulkan/renderer/vk_postprocess.h @@ -26,6 +26,7 @@ public: VkFormat OutputFormat; int SwapChain; int ShadowMapBuffers; + VkSampleCountFlagBits Samples; bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; } bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; } @@ -63,7 +64,9 @@ public: void UpdateShadowMap(); - void BlitSceneToTexture(); + void ImageTransitionScene(bool undefinedSrcLayout); + + void BlitSceneToPostprocess(); void BlitCurrentToImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders); diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp index 2e8c0d7a52..29524599fc 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -232,8 +232,8 @@ void VkRenderBuffers::CreateShadowmap() ShadowmapView->SetDebugName("VkRenderBuffers.ShadowmapView"); PipelineBarrier barrier; - barrier.addImage(Shadowmap.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); - barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + barrier.addImage(Shadowmap.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); + barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); if (!ShadowmapSampler) { diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.h b/src/rendering/vulkan/renderer/vk_renderbuffers.h index 2041852f0e..9e783bb48a 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.h @@ -40,7 +40,7 @@ public: std::unique_ptr Shadowmap; std::unique_ptr ShadowmapView; std::unique_ptr ShadowmapSampler; - VkImageLayout ShadowmapLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkImageLayout ShadowmapLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; private: void CreatePipeline(int width, int height); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index 18dfb99624..4c0a65d736 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -146,11 +146,16 @@ void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key) { auto buffers = GetVulkanFrameBuffer()->GetBuffers(); + VkFormat drawBufferFormats[] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_A2R10G10B10_UNORM_PACK32 }; + RenderPassBuilder builder; - builder.addAttachment( - VK_FORMAT_R16G16B16A16_SFLOAT, (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 = 0; i < key.DrawBuffers; i++) + { + builder.addAttachment( + drawBufferFormats[i], i == 0 ? (VkSampleCountFlagBits)key.Samples : 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( @@ -160,10 +165,11 @@ void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key) VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } builder.addSubpass(); - builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + for (int i = 0; i < key.DrawBuffers; i++) + builder.addSubpassColorAttachmentRef(i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); if (key.UsesDepthStencil()) { - builder.addSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + builder.addSubpassDepthStencilAttachmentRef(key.DrawBuffers, 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, @@ -194,7 +200,7 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key) } else { - program = fb->GetShaderManager()->Get(key.EffectState, key.AlphaTest); + program = fb->GetShaderManager()->Get(key.EffectState, key.AlphaTest, key.DrawBuffers > 1 ? GBUFFER_PASS : NORMAL_PASS); } builder.addVertexShader(program->vert.get()); builder.addFragmentShader(program->frag.get()); @@ -263,6 +269,7 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key) builder.setColorWriteMask((VkColorComponentFlags)key.ColorMask); builder.setStencil(VK_STENCIL_OP_KEEP, op2vk[key.StencilPassOp], VK_STENCIL_OP_KEEP, VK_COMPARE_OP_EQUAL, 0xffffffff, 0xffffffff, 0); builder.setBlendMode(key.RenderStyle); + builder.setSubpassColorAttachmentCount(key.DrawBuffers); builder.setRasterizationSamples((VkSampleCountFlagBits)key.Samples); builder.setLayout(fb->GetRenderPassManager()->PipelineLayout.get()); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 195d940332..b00220b08f 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -30,6 +30,7 @@ public: int DrawType; int Samples; int ClearTargets; + int DrawBuffers; 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 12149e89c0..e65daf23a1 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -86,10 +86,6 @@ void VkRenderState::SetColorMask(bool r, bool g, bool b, bool a) mNeedApply = true; } -void VkRenderState::EnableDrawBufferAttachments(bool on) -{ -} - void VkRenderState::SetStencil(int offs, int op, int flags) { mStencilRef = screen->stencilValue + offs; @@ -205,6 +201,7 @@ void VkRenderState::ApplyRenderPass(int dt) passKey.ColorMask = mColorMask; passKey.CullMode = mCullMode; passKey.Samples = mRenderTarget.Samples; + passKey.DrawBuffers = mRenderTarget.DrawBuffers; if (mSpecialEffect > EFF_NONE) { passKey.SpecialEffect = mSpecialEffect; @@ -567,6 +564,15 @@ void VkRenderState::EndFrame() mDataIndex = -1; } +void VkRenderState::EnableDrawBuffers(int count) +{ + if (mRenderTarget.DrawBuffers != count) + { + EndRenderPass(); + mRenderTarget.DrawBuffers = count; + } +} + void VkRenderState::SetRenderTarget(VulkanImageView *view, int width, int height, VkSampleCountFlagBits samples) { EndRenderPass(); @@ -586,12 +592,17 @@ void VkRenderState::BeginRenderPass(const VkRenderPassKey &key, VulkanCommandBuf auto &framebuffer = passSetup->Framebuffer[mRenderTarget.View->view]; if (!framebuffer) { + auto buffers = fb->GetBuffers(); FramebufferBuilder builder; builder.setRenderPass(passSetup->RenderPass.get()); builder.setSize(mRenderTarget.Width, mRenderTarget.Height); - builder.addAttachment(mRenderTarget.View->view); + builder.addAttachment(mRenderTarget.View); + if (key.DrawBuffers > 1) + builder.addAttachment(buffers->SceneFogView.get()); + if (key.DrawBuffers > 2) + builder.addAttachment(buffers->SceneNormalView.get()); if (key.UsesDepthStencil()) - builder.addAttachment(fb->GetBuffers()->SceneDepthStencilView.get()); + builder.addAttachment(buffers->SceneDepthStencilView.get()); framebuffer = builder.create(GetVulkanFrameBuffer()->device); framebuffer->SetDebugName("VkRenderPassSetup.Framebuffer"); } @@ -601,6 +612,10 @@ void VkRenderState::BeginRenderPass(const VkRenderPassKey &key, VulkanCommandBuf beginInfo.setRenderArea(0, 0, mRenderTarget.Width, mRenderTarget.Height); beginInfo.setFramebuffer(framebuffer.get()); beginInfo.addClearColor(screen->mSceneClearColor[0], screen->mSceneClearColor[1], screen->mSceneClearColor[2], screen->mSceneClearColor[3]); + if (key.DrawBuffers > 1) + beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 0.0f); + if (key.DrawBuffers > 2) + beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 0.0f); beginInfo.addClearDepthStencil(1.0f, 0); cmdbuffer->beginRenderPass(beginInfo); cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get()); diff --git a/src/rendering/vulkan/renderer/vk_renderstate.h b/src/rendering/vulkan/renderer/vk_renderstate.h index 0a9be61cf9..ba510ae4e5 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.h +++ b/src/rendering/vulkan/renderer/vk_renderstate.h @@ -30,7 +30,6 @@ public: void SetDepthFunc(int func) override; void SetDepthRange(float min, float max) override; void SetColorMask(bool r, bool g, bool b, bool a) override; - void EnableDrawBufferAttachments(bool on) override; void SetStencil(int offs, int op, int flags = -1) override; void SetCulling(int mode) override; void EnableClipDistance(int num, bool state) override; @@ -41,6 +40,7 @@ public: void EnableDepthTest(bool on) override; void EnableMultisampling(bool on) override; void EnableLineSmooth(bool on) override; + void EnableDrawBuffers(int count) override; void SetRenderTarget(VulkanImageView *view, int width, int height, VkSampleCountFlagBits samples); void Bind(int bindingpoint, uint32_t offset); @@ -117,6 +117,7 @@ protected: int Width = 0; int Height = 0; VkSampleCountFlagBits Samples = VK_SAMPLE_COUNT_1_BIT; + int DrawBuffers = 1; } mRenderTarget; }; diff --git a/src/rendering/vulkan/shaders/vk_shader.cpp b/src/rendering/vulkan/shaders/vk_shader.cpp index af3ba3740a..af9de97ce7 100644 --- a/src/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/rendering/vulkan/shaders/vk_shader.cpp @@ -12,33 +12,36 @@ VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device) const char *mainvp = "shaders/glsl/main.vp"; const char *mainfp = "shaders/glsl/main.fp"; - bool gbufferpass = false; - for (int i = 0; defaultshaders[i].ShaderName != NULL; i++) + for (int j = 0; j < MAX_PASS_TYPES; j++) { - VkShaderProgram prog; - prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); - prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass); - mMaterialShaders.push_back(std::move(prog)); - - if (i < SHADER_NoTexture) + bool gbufferpass = j; + for (int i = 0; defaultshaders[i].ShaderName != nullptr; i++) { - VkShaderProgram natprog; - natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); - natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass); - mMaterialShadersNAT.push_back(std::move(natprog)); + VkShaderProgram prog; + prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); + prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass); + mMaterialShaders[j].push_back(std::move(prog)); + + if (i < SHADER_NoTexture) + { + VkShaderProgram natprog; + natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); + natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass); + mMaterialShadersNAT[j].push_back(std::move(natprog)); + } } - } - for (unsigned i = 0; i < usershaders.Size(); i++) - { - FString name = ExtractFileBase(usershaders[i].shader); - FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; + for (unsigned i = 0; i < usershaders.Size(); i++) + { + FString name = ExtractFileBase(usershaders[i].shader); + FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; - VkShaderProgram prog; - prog.vert = LoadVertShader(name, mainvp, defaultshaders[i].Defines); - prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass); - mMaterialShaders.push_back(std::move(prog)); + VkShaderProgram prog; + prog.vert = LoadVertShader(name, mainvp, defaultshaders[i].Defines); + prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass); + mMaterialShaders[j].push_back(std::move(prog)); + } } for (int i = 0; i < MAX_EFFECTS; i++) @@ -64,16 +67,16 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect) return nullptr; } -VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston) +VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType) { // indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom if (!alphateston && eff <= 3) { - return &mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway + return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway } - else if (eff < (unsigned int)mMaterialShaders.size()) + else if (eff < (unsigned int)mMaterialShaders[passType].size()) { - return &mMaterialShaders[eff]; + return &mMaterialShaders[passType][eff]; } return nullptr; } diff --git a/src/rendering/vulkan/shaders/vk_shader.h b/src/rendering/vulkan/shaders/vk_shader.h index 5dd636e126..f869dd6944 100644 --- a/src/rendering/vulkan/shaders/vk_shader.h +++ b/src/rendering/vulkan/shaders/vk_shader.h @@ -88,7 +88,7 @@ public: ~VkShaderManager(); VkShaderProgram *GetEffect(int effect); - VkShaderProgram *Get(unsigned int eff, bool alphateston); + VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType); private: std::unique_ptr LoadVertShader(FString shadername, const char *vert_lump, const char *defines); @@ -100,7 +100,7 @@ private: VulkanDevice *device; - std::vector mMaterialShaders; - std::vector mMaterialShadersNAT; + std::vector mMaterialShaders[MAX_PASS_TYPES]; + std::vector mMaterialShadersNAT[MAX_PASS_TYPES]; VkShaderProgram mEffectShaders[MAX_EFFECTS]; }; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 61f083ab77..1103ffdbc1 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -33,6 +33,7 @@ #include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_vrmodes.h" +#include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/models/hw_models.h" #include "hwrenderer/scene/hw_skydome.h" #include "hwrenderer/scene/hw_fakeflat.h" @@ -381,6 +382,8 @@ sector_t *VulkanFrameBuffer::RenderView(player_t *player) fovratio = ratio; } + mPostprocess->ImageTransitionScene(true); // This is the only line that differs compared to FGLRenderer::RenderView + retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); } All.Unclock(); @@ -411,12 +414,9 @@ 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()); -#if 0 bool useSSAO = (gl_ssao != 0); GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); - GetRenderState()->EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); - GetRenderState()->Apply(); -#endif + GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); } auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr); @@ -443,15 +443,13 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * PostProcess.Clock(); if (toscreen) di->EndDrawScene(mainvp.sector, *GetRenderState()); // do not call this for camera textures. -#if 0 if (GetRenderState()->GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers { GetRenderState()->SetPassType(NORMAL_PASS); GetRenderState()->EnableDrawBuffers(1); } -#endif - mPostprocess->BlitSceneToTexture(); // Copy the resulting scene to the current post process texture + mPostprocess->BlitSceneToPostprocess(); // Copy the resulting scene to the current post process texture PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector, *GetRenderState()); }); @@ -515,7 +513,6 @@ void VulkanFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) static int ssao_portals_available = 0; const auto &vp = di->Viewpoint; -#if 0 bool applySSAO = false; if (drawmode == DM_MAINVIEW) { @@ -531,7 +528,6 @@ void VulkanFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) applySSAO = true; ssao_portals_available--; } -#endif if (vp.camera != nullptr) { @@ -549,18 +545,11 @@ void VulkanFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode) di->RenderScene(*GetRenderState()); -#if 0 if (applySSAO && GetRenderState()->GetPassType() == GBUFFER_PASS) { - GetRenderState()->EnableDrawBuffers(1); - GLRenderer->AmbientOccludeScene(di->VPUniforms.mProjectionMatrix.get()[5]); - glViewport(screen->mSceneViewport.left, screen->mSceneViewport.top, screen->mSceneViewport.width, screen->mSceneViewport.height); - GLRenderer->mBuffers->BindSceneFB(true); - GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount()); - GetRenderState()->Apply(); + mPostprocess->AmbientOccludeScene(di->VPUniforms.mProjectionMatrix.get()[5]); screen->mViewpoints->Bind(*GetRenderState(), di->vpIndex); } -#endif // Handle all portals after rendering the opaque objects but before // doing all translucent stuff