]> git.tdb.fi Git - libs/gl.git/commitdiff
Refactor render pass operations into a helper struct
authorMikko Rasa <tdb@tdb.fi>
Tue, 22 Mar 2022 07:53:09 +0000 (09:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Tue, 22 Mar 2022 07:53:09 +0000 (09:53 +0200)
source/backends/vulkan/commands_backend.cpp
source/backends/vulkan/pipelinecache.cpp
source/backends/vulkan/pipelinecache.h
source/backends/vulkan/pipelinestate_backend.cpp
source/backends/vulkan/renderpass.cpp [new file with mode: 0644]
source/backends/vulkan/renderpass.h [new file with mode: 0644]

index 777d1a6b8b3a17a7ca882c2e9f0a4ea5f82433bf..ff9e6cf62da0ae0b851e11f572dd416cabddd968 100644 (file)
@@ -8,8 +8,8 @@
 #include "frameformat.h"
 #include "pipelinestate.h"
 #include "rect.h"
+#include "renderpass.h"
 #include "semaphore.h"
-#include "structurebuilder.h"
 #include "swapchaintexture.h"
 #include "vulkan.h"
 
@@ -98,52 +98,20 @@ void VulkanCommands::begin_render_pass(bool clear, const ClearValue *clear_value
                if(dynamic_cast<const SwapChainTexture *>(framebuffer->get_attachment(i)))
                        fb_is_swapchain = true;
 
-       Rect fb_rect = framebuffer->get_rect();
-       Rect render_area = fb_rect.intersect(viewport);
-       bool full_viewport = render_area==fb_rect;
-       discard_fb_contents = (clear && full_viewport);
-
        framebuffer->refresh();
 
-       VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(framebuffer->get_format(),
-               clear, (!clear_values && full_viewport), fb_is_swapchain);
-       begin_buffer(render_pass);
-
-       StructureBuilder sb(pass_begin_info, 2);
-       VkRenderPassBeginInfo *const &begin_info = sb.add<VkRenderPassBeginInfo>(1);
-       VkClearValue *const &vk_clear_values = sb.add<VkClearValue>(FrameFormat::MAX_ATTACHMENTS);
-
-       begin_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
-       begin_info->renderPass = handle_cast<::VkRenderPass>(render_pass);
-       begin_info->framebuffer = handle_cast<::VkFramebuffer>(framebuffer->handle);
+       RenderPass render_pass;
+       render_pass.framebuffer = framebuffer;
+       render_pass.render_area = viewport;
+       render_pass.clear = clear;
+       render_pass.clear_values = clear_values;
+       render_pass.to_present = fb_is_swapchain;
+       render_pass.update(device);
 
-       begin_info->renderArea.offset.x = render_area.left;
-       begin_info->renderArea.offset.y = render_area.bottom;
-       begin_info->renderArea.extent.width = render_area.width;
-       begin_info->renderArea.extent.height = render_area.height;
+       discard_fb_contents = render_pass.discard_fb_contents;
 
-       if(clear_values)
-       {
-               unsigned i = 0;
-               for(FrameAttachment a: framebuffer->get_format())
-               {
-                       if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
-                               vk_clear_values[i].depthStencil.depth = clear_values[i].depth_stencil.depth;
-                       else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
-                               vk_clear_values[i].depthStencil.stencil = clear_values[i].depth_stencil.stencil;
-                       else
-                       {
-                               vk_clear_values[i].color.float32[0] = clear_values[i].color.r;
-                               vk_clear_values[i].color.float32[1] = clear_values[i].color.g;
-                               vk_clear_values[i].color.float32[2] = clear_values[i].color.b;
-                               vk_clear_values[i].color.float32[3] = clear_values[i].color.a;
-                       }
-                       ++i;
-               }
-
-               begin_info->clearValueCount = framebuffer->get_format().size();
-               begin_info->pClearValues = vk_clear_values;
-       }
+       begin_buffer(render_pass.handle);
+       render_pass.fill_begin_info(pass_begin_info);
 }
 
 void VulkanCommands::end_render_pass()
index 646d79324b6b65692f7bd7a43ddab33892c062be..951d33f3bea801fe72a2516dd984edbd1e50a669 100644 (file)
@@ -1,8 +1,7 @@
-#include <msp/core/hash.h>
 #include "device.h"
-#include "framebuffer.h"
 #include "pipelinecache.h"
 #include "pipelinestate.h"
+#include "renderpass.h"
 #include "vulkan.h"
 
 using namespace std;
@@ -24,85 +23,21 @@ PipelineCache::~PipelineCache()
                vk.DestroyPipeline(kvp.second);
 }
 
-VkRenderPass PipelineCache::get_render_pass(const FrameFormat &format, bool clear, bool discard, bool to_present)
+VkRenderPass PipelineCache::get_render_pass(const RenderPass &rp)
 {
+       uint64_t key = rp.compute_hash();
+       auto i = render_passes.find(key);
+       if(i!=render_passes.end())
+               return i->second;
+
        const VulkanFunctions &vk = device.get_functions();
 
-       uint64_t key = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
-       for(FrameAttachment a: format)
-               key = hash_update<64>(key, a);
-
-       auto j = render_passes.find(key);
-       if(j!=render_passes.end())
-               return j->second;
-
-       VkAttachmentDescription attachments[FrameFormat::MAX_ATTACHMENTS] = { };
-       VkAttachmentReference color_refs[FrameFormat::MAX_ATTACHMENTS] = { };
-       VkAttachmentReference depth_stencil_ref = { };
-       depth_stencil_ref.attachment = VK_ATTACHMENT_UNUSED;
-
-       VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
-
-       unsigned i = 0;
-       unsigned color_count = 0;
-       for(FrameAttachment a: format)
-       {
-               VkImageLayout subpass_layout = static_cast<VkImageLayout>(get_vulkan_attachment_layout(get_components(get_attachment_pixelformat(a))));
-               VkImageLayout external_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : subpass_layout);
-
-               attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
-               attachments[i].samples = vk_samples;
-               attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
-               attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
-               attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
-               attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
-               attachments[i].initialLayout = ((clear && discard) ? VK_IMAGE_LAYOUT_UNDEFINED : external_layout);
-               attachments[i].finalLayout = external_layout;
-
-               if(subpass_layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
-               {
-                       color_refs[color_count].attachment = i;
-                       color_refs[color_count].layout = subpass_layout;
-                       ++color_count;
-               }
-               else
-               {
-                       depth_stencil_ref.attachment = i;
-                       depth_stencil_ref.layout = subpass_layout;
-               }
-
-               ++i;
-       }
-
-       VkSubpassDescription subpass = { };
-       subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
-       subpass.colorAttachmentCount = color_count;
-       subpass.pColorAttachments = color_refs;
-       subpass.pDepthStencilAttachment = &depth_stencil_ref;
-
-       VkSubpassDependency dependency = { };
-       VkRenderPassCreateInfo render_pass_info = { };
-       render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
-       render_pass_info.attachmentCount = format.size();
-       render_pass_info.pAttachments = attachments;
-       render_pass_info.subpassCount = 1;
-       render_pass_info.pSubpasses = &subpass;
-
-       if(to_present)
-       {
-               dependency.srcSubpass = 0;
-               dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
-               dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
-               dependency.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
-               dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
-               dependency.dstAccessMask = 0;
-
-               render_pass_info.dependencyCount = 1;
-               render_pass_info.pDependencies = &dependency;
-       }
+       vector<char> buffer;
+       rp.fill_creation_info(buffer);
+       const VkRenderPassCreateInfo *creation_info = reinterpret_cast<const VkRenderPassCreateInfo *>(buffer.data());
 
        VkRenderPass render_pass;
-       vk.CreateRenderPass(render_pass_info, render_pass);
+       vk.CreateRenderPass(*creation_info, render_pass);
 
        render_passes.insert(make_pair(key, render_pass));
 
index 5023b40c38a2f0cf1a7bfdfdcdcce9aae5482992..2f3251198f55589ab28891fe96c1197568b8b921 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <cstdint>
 #include <map>
-#include "frameformat.h"
 #include "handles.h"
 
 namespace Msp {
@@ -11,6 +10,7 @@ namespace GL {
 
 class Device;
 class PipelineState;
+struct RenderPass;
 
 class PipelineCache
 {
@@ -24,7 +24,7 @@ public:
        PipelineCache(PipelineCache &&);
        ~PipelineCache();
 
-       VkRenderPass get_render_pass(const FrameFormat &, bool, bool, bool);
+       VkRenderPass get_render_pass(const RenderPass &);
        VkPipeline get_pipeline(const PipelineState &);
 };
 
index 87e03242d329ae90fb66d5346cefe9a4af4e195e..b7e50873aec14f1cb16a841916adb5a6ccfb97cd 100644 (file)
@@ -10,6 +10,7 @@
 #include "pipelinestate_backend.h"
 #include "program.h"
 #include "rect.h"
+#include "renderpass.h"
 #include "sampler.h"
 #include "stenciltest.h"
 #include "structurebuilder.h"
@@ -149,7 +150,9 @@ void VulkanPipelineState::fill_creation_info(vector<char> &buffer) const
        const PipelineState &self = *static_cast<const PipelineState *>(this);
 
        const FrameFormat &format = self.framebuffer->get_format();
-       VkRenderPass render_pass = device.get_pipeline_cache().get_render_pass(format, false, false, false);
+       RenderPass render_pass;
+       render_pass.framebuffer = self.framebuffer;
+       render_pass.update(device);
 
        unsigned n_color_attachments = 0;
        for(FrameAttachment a: format)
@@ -253,7 +256,7 @@ void VulkanPipelineState::fill_creation_info(vector<char> &buffer) const
        pipeline_info->pDepthStencilState = depth_stencil_info;
        pipeline_info->pColorBlendState = blend_info;
        pipeline_info->pDynamicState = dynamic_info;
-       pipeline_info->renderPass = handle_cast<::VkRenderPass>(render_pass);
+       pipeline_info->renderPass = handle_cast<::VkRenderPass>(render_pass.handle);
        pipeline_info->subpass = 0;
 
        if(self.shprog)
diff --git a/source/backends/vulkan/renderpass.cpp b/source/backends/vulkan/renderpass.cpp
new file mode 100644 (file)
index 0000000..fb2389e
--- /dev/null
@@ -0,0 +1,151 @@
+#include <msp/core/hash.h>
+#include "device.h"
+#include "framebuffer.h"
+#include "renderpass.h"
+#include "structurebuilder.h"
+#include "vulkan.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+void RenderPass::update(Device &device)
+{
+       Rect fb_rect = framebuffer->get_rect();
+       render_area = fb_rect.intersect(render_area);
+       discard_fb_contents = (clear && render_area==fb_rect);
+       handle = device.get_pipeline_cache().get_render_pass(*this);
+}
+
+uint64_t RenderPass::compute_hash() const
+{
+       bool discard = (!clear_values && discard_fb_contents);
+       uint64_t result = hash<64>(static_cast<uint8_t>(clear | (discard*2) | (to_present*4)));
+       for(FrameAttachment a: framebuffer->get_format())
+               result = hash_update<64>(result, a);
+
+       return result;
+}
+
+void RenderPass::fill_creation_info(vector<char> &buffer) const
+{
+       const FrameFormat &format = framebuffer->get_format();
+
+       bool discard = (!clear_values && discard_fb_contents);
+       bool has_depth = any_of(format.begin(), format.end(), [](FrameAttachment a){
+               return get_components(get_attachment_pixelformat(a))==DEPTH_COMPONENT;
+       });
+       unsigned color_count = format.size()-has_depth;
+
+       StructureBuilder sb(buffer, 6);
+       VkRenderPassCreateInfo *const &render_pass_info = sb.add<VkRenderPassCreateInfo>();
+       VkSubpassDescription *const &subpass = sb.add<VkSubpassDescription>();
+       VkAttachmentDescription *const &attachments = sb.add<VkAttachmentDescription>(format.size());
+       VkAttachmentReference *const &color_refs = sb.add<VkAttachmentReference>(color_count);
+       VkAttachmentReference *const &depth_stencil_ref = sb.add<VkAttachmentReference>(has_depth);
+       VkSubpassDependency *const &dependency = sb.add<VkSubpassDependency>(to_present);
+
+       VkSampleCountFlagBits vk_samples = static_cast<VkSampleCountFlagBits>(get_vulkan_samples(format.get_samples()));
+
+       VkAttachmentReference *color_ptr = color_refs;
+       unsigned i = 0;
+       for(FrameAttachment a: format)
+       {
+               VkImageLayout subpass_layout = static_cast<VkImageLayout>(get_vulkan_attachment_layout(get_components(get_attachment_pixelformat(a))));
+               VkImageLayout external_layout = (to_present ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : subpass_layout);
+
+               attachments[i].format = static_cast<VkFormat>(get_vulkan_pixelformat(get_attachment_pixelformat(a)));
+               attachments[i].samples = vk_samples;
+               attachments[i].loadOp = (clear ? discard ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD);
+               attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+               attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+               attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+               attachments[i].initialLayout = ((clear && discard) ? VK_IMAGE_LAYOUT_UNDEFINED : external_layout);
+               attachments[i].finalLayout = external_layout;
+
+               if(subpass_layout==VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
+               {
+                       color_ptr->attachment = i;
+                       color_ptr->layout = subpass_layout;
+                       ++color_ptr;
+               }
+               else
+               {
+                       depth_stencil_ref->attachment = i;
+                       depth_stencil_ref->layout = subpass_layout;
+               }
+
+               ++i;
+       }
+
+       subpass->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+       subpass->colorAttachmentCount = color_count;
+       if(color_count)
+               subpass->pColorAttachments = color_refs;
+       if(has_depth)
+               subpass->pDepthStencilAttachment = depth_stencil_ref;
+
+       render_pass_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+       render_pass_info->attachmentCount = format.size();
+       render_pass_info->pAttachments = attachments;
+       render_pass_info->subpassCount = 1;
+       render_pass_info->pSubpasses = subpass;
+
+       if(to_present)
+       {
+               dependency->srcSubpass = 0;
+               dependency->dstSubpass = VK_SUBPASS_EXTERNAL;
+               dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dependency->srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
+               dependency->dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+               dependency->dstAccessMask = 0;
+
+               render_pass_info->dependencyCount = 1;
+               render_pass_info->pDependencies = dependency;
+       }
+}
+
+void RenderPass::fill_begin_info(vector<char> &buffer) const
+{
+       const FrameFormat &format = framebuffer->get_format();
+
+       StructureBuilder sb(buffer, 2);
+       VkRenderPassBeginInfo *const &begin_info = sb.add<VkRenderPassBeginInfo>(1);
+       VkClearValue *const &vk_clear_values = sb.add<VkClearValue>(format.size());
+
+       begin_info->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+       begin_info->renderPass = handle_cast<::VkRenderPass>(handle);
+       begin_info->framebuffer = handle_cast<::VkFramebuffer>(framebuffer->handle);
+
+       begin_info->renderArea.offset.x = render_area.left;
+       begin_info->renderArea.offset.y = render_area.bottom;
+       begin_info->renderArea.extent.width = render_area.width;
+       begin_info->renderArea.extent.height = render_area.height;
+
+       if(clear_values)
+       {
+               unsigned i = 0;
+               for(FrameAttachment a: format)
+               {
+                       if(get_attach_point(a)==get_attach_point(DEPTH_ATTACHMENT))
+                               vk_clear_values[i].depthStencil.depth = clear_values[i].depth_stencil.depth;
+                       else if(get_attach_point(a)==get_attach_point(STENCIL_ATTACHMENT))
+                               vk_clear_values[i].depthStencil.stencil = clear_values[i].depth_stencil.stencil;
+                       else
+                       {
+                               vk_clear_values[i].color.float32[0] = clear_values[i].color.r;
+                               vk_clear_values[i].color.float32[1] = clear_values[i].color.g;
+                               vk_clear_values[i].color.float32[2] = clear_values[i].color.b;
+                               vk_clear_values[i].color.float32[3] = clear_values[i].color.a;
+                       }
+                       ++i;
+               }
+
+               begin_info->clearValueCount = format.size();
+               begin_info->pClearValues = vk_clear_values;
+       }
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/backends/vulkan/renderpass.h b/source/backends/vulkan/renderpass.h
new file mode 100644 (file)
index 0000000..e59dc16
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef MSP_GL_RENDERPASS_H_
+#define MSP_GL_RENDERPASS_H_
+
+#include <vector>
+#include "handles.h"
+
+namespace Msp {
+namespace GL {
+
+class Device;
+class Framebuffer;
+union ClearValue;
+
+struct RenderPass
+{
+       const Framebuffer *framebuffer = 0;
+       Rect render_area;
+       bool clear = false;
+       const ClearValue *clear_values = 0;
+       bool to_present = false;
+       bool discard_fb_contents = false;
+       VkRenderPass handle = 0;
+
+       void update(Device &);
+
+       std::uint64_t compute_hash() const;
+       bool discards_framebuffer_contents() const;
+       void fill_creation_info(std::vector<char> &) const;
+       void fill_begin_info(std::vector<char> &) const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif