From 7f3e473f5631c4597fdde0f52ee12f519fbdf95e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 1 Mar 2019 00:42:51 +0100 Subject: [PATCH] - create a render pass for each blend setup --- .../vulkan/renderer/vk_renderpass.cpp | 50 ++++++++++++++++--- src/rendering/vulkan/renderer/vk_renderpass.h | 20 ++++++-- .../vulkan/renderer/vk_renderstate.cpp | 13 +++-- .../vulkan/renderer/vk_renderstate.h | 3 ++ src/rendering/vulkan/system/vk_builders.h | 12 +++++ 5 files changed, 83 insertions(+), 15 deletions(-) diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index c38f626f4..dc8ebfe40 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -23,7 +23,7 @@ void VkRenderPassManager::BeginFrame() { auto fb = GetVulkanFrameBuffer(); - RenderPassSetup.reset(); + RenderPassSetup.clear(); SceneColorView.reset(); SceneDepthStencilView.reset(); SceneDepthView.reset(); @@ -49,11 +49,17 @@ void VkRenderPassManager::BeginFrame() viewbuilder.setImage(SceneDepthStencil.get(), VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT); SceneDepthView = viewbuilder.create(fb->device); - - RenderPassSetup.reset(new VkRenderPassSetup()); } } +VkRenderPassSetup *VkRenderPassManager::GetRenderPass(const VkRenderPassKey &key) +{ + auto &item = RenderPassSetup[key]; + if (!item) + item.reset(new VkRenderPassSetup(key)); + return item.get(); +} + void VkRenderPassManager::CreateDynamicSetLayout() { DescriptorSetLayoutBuilder builder; @@ -114,24 +120,24 @@ void VkRenderPassManager::CreateDynamicSet() ///////////////////////////////////////////////////////////////////////////// -VkRenderPassSetup::VkRenderPassSetup() +VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key) { CreateRenderPass(); - CreatePipeline(); + CreatePipeline(key); CreateFramebuffer(); } void VkRenderPassSetup::CreateRenderPass() { RenderPassBuilder builder; - builder.addRgba16fAttachment(true, VK_IMAGE_LAYOUT_GENERAL); + builder.addRgba16fAttachment(false, VK_IMAGE_LAYOUT_GENERAL); builder.addSubpass(); builder.addSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_GENERAL); builder.addExternalSubpassDependency(); RenderPass = builder.create(GetVulkanFrameBuffer()->device); } -void VkRenderPassSetup::CreatePipeline() +void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key) { auto fb = GetVulkanFrameBuffer(); GraphicsPipelineBuilder builder; @@ -169,7 +175,35 @@ void VkRenderPassSetup::CreatePipeline() builder.setViewport(0.0f, 0.0f, (float)SCREENWIDTH, (float)SCREENHEIGHT); builder.setScissor(0, 0, SCREENWIDTH, SCREENHEIGHT); - builder.setAlphaBlendMode(); + + static const int blendstyles[] = { + VK_BLEND_FACTOR_ZERO, + VK_BLEND_FACTOR_ONE, + VK_BLEND_FACTOR_SRC_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + VK_BLEND_FACTOR_SRC_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + VK_BLEND_FACTOR_DST_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, + }; + + static const int renderops[] = { + 0, VK_BLEND_OP_ADD, VK_BLEND_OP_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + int srcblend = blendstyles[key.RenderStyle.SrcAlpha%STYLEALPHA_MAX]; + int dstblend = blendstyles[key.RenderStyle.DestAlpha%STYLEALPHA_MAX]; + int blendequation = renderops[key.RenderStyle.BlendOp & 15]; + + if (blendequation == -1) // This was a fuzz style. + { + srcblend = VK_BLEND_FACTOR_DST_COLOR; + dstblend = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blendequation = VK_BLEND_OP_ADD; + } + + builder.setBlendMode((VkBlendOp)blendequation, (VkBlendFactor)srcblend, (VkBlendFactor)dstblend); + builder.setLayout(fb->GetRenderPassManager()->PipelineLayout.get()); builder.setRenderPass(RenderPass.get()); Pipeline = builder.create(fb->device); diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 2ec1c0321..3ad6ce1be 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -2,20 +2,33 @@ #pragma once #include "vulkan/system/vk_objects.h" +#include "r_data/renderstyle.h" +#include class VKDataBuffer; +class VkRenderPassKey +{ +public: + FRenderStyle RenderStyle; + + bool operator<(const VkRenderPassKey &other) const + { + return RenderStyle.AsDWORD < other.RenderStyle.AsDWORD; + } +}; + class VkRenderPassSetup { public: - VkRenderPassSetup(); + VkRenderPassSetup(const VkRenderPassKey &key); std::unique_ptr RenderPass; std::unique_ptr Pipeline; std::unique_ptr Framebuffer; private: - void CreatePipeline(); + void CreatePipeline(const VkRenderPassKey &key); void CreateRenderPass(); void CreateFramebuffer(); }; @@ -26,12 +39,13 @@ public: VkRenderPassManager(); void BeginFrame(); + VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key); std::unique_ptr DynamicSetLayout; std::unique_ptr TextureSetLayout; std::unique_ptr PipelineLayout; std::unique_ptr DescriptorPool; - std::unique_ptr RenderPassSetup; + std::map> RenderPassSetup; std::unique_ptr SceneColor; std::unique_ptr SceneDepthStencil; diff --git a/src/rendering/vulkan/renderer/vk_renderstate.cpp b/src/rendering/vulkan/renderer/vk_renderstate.cpp index b56dd0766..0bfea790f 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.cpp +++ b/src/rendering/vulkan/renderer/vk_renderstate.cpp @@ -144,9 +144,14 @@ void VkRenderState::Apply(int dt) { auto fb = GetVulkanFrameBuffer(); auto passManager = fb->GetRenderPassManager(); - auto passSetup = passManager->RenderPassSetup.get(); - bool changingRenderPass = false; // To do: decide if the state matches current bound renderpass + // Find a render pass that matches our state + VkRenderPassKey passKey; + passKey.RenderStyle = mRenderStyle; + VkRenderPassSetup *passSetup = passManager->GetRenderPass(passKey); + + // Is this the one we already have or do we need to change render pass? + bool changingRenderPass = (passSetup != mRenderPassSetup); if (!mCommandBuffer) { @@ -166,10 +171,9 @@ void VkRenderState::Apply(int dt) beginInfo.setRenderPass(passSetup->RenderPass.get()); beginInfo.setRenderArea(0, 0, SCREENWIDTH, SCREENHEIGHT); beginInfo.setFramebuffer(passSetup->Framebuffer.get()); - beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 1.0f); - beginInfo.addClearDepthStencil(1.0f, 0); mCommandBuffer->beginRenderPass(beginInfo); mCommandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get()); + mRenderPassSetup = passSetup; } if (mScissorChanged) @@ -382,6 +386,7 @@ void VkRenderState::EndRenderPass() { mCommandBuffer->endRenderPass(); mCommandBuffer = nullptr; + mRenderPassSetup = nullptr; // To do: move this elsewhere or rename this function to make it clear this can only happen at the end of a frame mMatricesOffset = 0; diff --git a/src/rendering/vulkan/renderer/vk_renderstate.h b/src/rendering/vulkan/renderer/vk_renderstate.h index b2f40a727..4f9999392 100644 --- a/src/rendering/vulkan/renderer/vk_renderstate.h +++ b/src/rendering/vulkan/renderer/vk_renderstate.h @@ -10,6 +10,8 @@ #include "hwrenderer/scene/hw_renderstate.h" #include "hwrenderer/textures/hw_material.h" +class VkRenderPassSetup; + class VkRenderState : public FRenderState { public: @@ -47,6 +49,7 @@ private: bool mLastDepthClamp = true; VulkanCommandBuffer *mCommandBuffer = nullptr; + VkRenderPassSetup *mRenderPassSetup = nullptr; bool mDescriptorsChanged = true; int mScissorX = 0, mScissorY = 0, mScissorWidth = -1, mScissorHeight = -1; diff --git a/src/rendering/vulkan/system/vk_builders.h b/src/rendering/vulkan/system/vk_builders.h index 80d3e9670..27c6602e6 100644 --- a/src/rendering/vulkan/system/vk_builders.h +++ b/src/rendering/vulkan/system/vk_builders.h @@ -189,6 +189,7 @@ public: void setAdditiveBlendMode(); void setAlphaBlendMode(); + void setBlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst); void setSubpassColorAttachmentCount(int count); void addVertexShader(VulkanShader *shader); @@ -786,6 +787,17 @@ inline void GraphicsPipelineBuilder::setAlphaBlendMode() colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; } +inline void GraphicsPipelineBuilder::setBlendMode(VkBlendOp op, VkBlendFactor src, VkBlendFactor dst) +{ + colorBlendAttachment.blendEnable = VK_TRUE; + colorBlendAttachment.srcColorBlendFactor = src; + colorBlendAttachment.dstColorBlendFactor = dst; + colorBlendAttachment.colorBlendOp = op; + colorBlendAttachment.srcAlphaBlendFactor = src; + colorBlendAttachment.dstAlphaBlendFactor = dst; + colorBlendAttachment.alphaBlendOp = op; +} + inline void GraphicsPipelineBuilder::setSubpassColorAttachmentCount(int count) { colorBlendAttachments.resize(count, colorBlendAttachment);