From 56b3a01a5949a20498d87b22d10e9fb0eb311cf1 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Tue, 7 Dec 2021 02:48:42 +0530 Subject: [PATCH] Track `VkRenderPass` and Subpass Index for Subpass Function Nodes We require a handle to the current renderpass and the index of the subpass in certain cases, this is now tracked by the `CommandExecutor` and passed in as a parameter to `NextSubpassFunctionNode` and the newly-introduced `SubpassFunctionNode`. --- .../gpu/interconnect/command_executor.cpp | 22 ++++++++++++++----- .../gpu/interconnect/command_executor.h | 2 +- .../gpu/interconnect/command_nodes.cpp | 4 +++- .../skyline/gpu/interconnect/command_nodes.h | 16 ++++++++------ .../gpu/interconnect/graphics_context.h | 2 +- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp index cfa55b71..f43ba19d 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp @@ -43,7 +43,7 @@ namespace skyline::gpu::interconnect { } } - void CommandExecutor::AddSubpass(const std::function &, GPU &)> &function, vk::Rect2D renderArea, span inputAttachments, span colorAttachments, TextureView *depthStencilAttachment) { + void CommandExecutor::AddSubpass(std::function &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span inputAttachments, span colorAttachments, TextureView *depthStencilAttachment) { for (const auto &attachments : {inputAttachments, colorAttachments}) for (const auto &attachment : attachments) AttachTexture(attachment->texture); @@ -53,9 +53,9 @@ namespace skyline::gpu::interconnect { bool newRenderPass{CreateRenderPass(renderArea)}; renderPass->AddSubpass(inputAttachments, colorAttachments, depthStencilAttachment ? &*depthStencilAttachment : nullptr); if (newRenderPass) - nodes.emplace_back(std::in_place_type_t(), function); + nodes.emplace_back(std::in_place_type_t(), std::forward &, GPU &, vk::RenderPass, u32)>>(function)); else - nodes.emplace_back(std::in_place_type_t(), function); + nodes.emplace_back(std::in_place_type_t(), std::forward &, GPU &, vk::RenderPass, u32)>>(function)); } void CommandExecutor::AddClearColorSubpass(TextureView *attachment, const vk::ClearColorValue &value) { @@ -83,7 +83,7 @@ namespace skyline::gpu::interconnect { }}; if (newRenderPass) - nodes.emplace_back(std::in_place_type_t(), function); + nodes.emplace_back(std::in_place_type_t(), function); else nodes.emplace_back(std::in_place_type_t(), function); } @@ -110,14 +110,24 @@ namespace skyline::gpu::interconnect { for (auto buffer : syncBuffers) buffer->SynchronizeHostWithCycle(cycle); + vk::RenderPass lRenderPass; + u32 subpassIndex; + using namespace node; for (NodeVariant &node : nodes) { #define NODE(name) [&](name& node) { node(commandBuffer, cycle, gpu); } std::visit(VariantVisitor{ NODE(FunctionNode), - NODE(RenderPassNode), + + [&](RenderPassNode &node) { + lRenderPass = node(commandBuffer, cycle, gpu); + subpassIndex = 0; + }, + NODE(NextSubpassNode), - NODE(NextSubpassFunctionNode), + [&](SubpassFunctionNode &node) { node(commandBuffer, cycle, gpu, lRenderPass, subpassIndex); }, + [&](NextSubpassFunctionNode &node) { node(commandBuffer, cycle, gpu, lRenderPass, ++subpassIndex); }, + NODE(RenderPassEndNode), }, node); #undef NODE diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h index 8b7c13d0..ede340d8 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.h @@ -49,7 +49,7 @@ namespace skyline::gpu::interconnect { * @note Any texture supplied to this **must** be locked by the calling thread, it should also undergo no persistent layout transitions till execution * @note All attachments will automatically be attached and aren't required to be attached prior */ - void AddSubpass(const std::function &, GPU &)> &&function, vk::Rect2D renderArea, span inputAttachments = {}, span colorAttachments = {}, TextureView *depthStencilAttachment = {}); + void AddSubpass(std::function &, GPU &, vk::RenderPass, u32)> &&function, vk::Rect2D renderArea, span inputAttachments = {}, span colorAttachments = {}, TextureView *depthStencilAttachment = {}); /** * @brief Adds a subpass that clears the entirety of the specified attachment with a value, it may utilize VK_ATTACHMENT_LOAD_OP_CLEAR for a more efficient clear when possible diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.cpp b/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.cpp index d128f9e1..23dc6fa1 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.cpp @@ -160,7 +160,7 @@ namespace skyline::gpu::interconnect::node { return false; } - void RenderPassNode::operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu) { + vk::RenderPass RenderPassNode::operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu) { storage->device = &gpu.vkDevice; auto preserveAttachmentIt{preserveAttachmentReferences.begin()}; @@ -220,5 +220,7 @@ namespace skyline::gpu::interconnect::node { texture->unlock(); texture->cycle = cycle; } + + return renderPass; } } diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.h b/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.h index b977ee2d..3368d58b 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_nodes.h @@ -13,7 +13,7 @@ namespace skyline::gpu::interconnect::node { struct FunctionNodeBase { std::function function; - FunctionNodeBase(std::function function) : function(function) {} + FunctionNodeBase(std::function &&function) : function(function) {} template void operator()(Args &&... args) { @@ -86,7 +86,7 @@ namespace skyline::gpu::interconnect::node { */ bool ClearColorAttachment(u32 colorAttachment, const vk::ClearColorValue &value); - void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu); + vk::RenderPass operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu); }; /** @@ -98,15 +98,17 @@ namespace skyline::gpu::interconnect::node { } }; + using SubpassFunctionNode = FunctionNodeBase &, GPU &, vk::RenderPass, u32)>; + /** * @brief A FunctionNode which progresses to the next subpass prior to calling the function */ - struct NextSubpassFunctionNode : private FunctionNode { - using FunctionNode::FunctionNode; + struct NextSubpassFunctionNode : private SubpassFunctionNode { + using SubpassFunctionNode::SubpassFunctionNode; - void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu) { + void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu, vk::RenderPass renderPass, u32 subpassIndex) { commandBuffer.nextSubpass(vk::SubpassContents::eInline); - FunctionNode::operator()(commandBuffer, cycle, gpu); + SubpassFunctionNode::operator()(commandBuffer, cycle, gpu, renderPass, subpassIndex); } }; @@ -119,5 +121,5 @@ namespace skyline::gpu::interconnect::node { } }; - using NodeVariant = std::variant; //!< A variant encompassing all command nodes types + using NodeVariant = std::variant; //!< A variant encompassing all command nodes types } diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index 11b8df99..79459d33 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -361,7 +361,7 @@ namespace skyline::gpu::interconnect { if (scissor.extent.width == renderTarget->texture->dimensions.width && scissor.extent.height == renderTarget->texture->dimensions.height && renderTarget->range.baseArrayLayer == 0 && renderTarget->range.layerCount == 1 && clear.layerId == 0) { executor.AddClearColorSubpass(renderTarget, clearColorValue); } else { - executor.AddSubpass([aspect, clearColorValue = clearColorValue, layerId = clear.layerId, scissor](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &, GPU &) { + executor.AddSubpass([aspect, clearColorValue = clearColorValue, layerId = clear.layerId, scissor](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &, GPU &, vk::RenderPass, u32) { commandBuffer.clearAttachments(vk::ClearAttachment{ .aspectMask = aspect, .colorAttachment = 0,