// SPDX-License-Identifier: MPL-2.0 // Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) #pragma once #include namespace skyline::gpu::interconnect::node { /** * @brief A generic node for simply executing a function */ template &, GPU &)> struct FunctionNodeBase { std::function function; FunctionNodeBase(std::function function) : function(function) {} template void operator()(Args &&... args) { function(std::forward(args)...); } }; using FunctionNode = FunctionNodeBase<>; /** * @brief Creates and begins a VkRenderPass alongside managing all resources bound to it and to the subpasses inside it */ struct RenderPassNode { private: /** * @brief Storage for all resources in the VkRenderPass that have their lifetimes bond to the completion fence */ struct Storage : public FenceCycleDependency { vk::raii::Device *device{}; vk::Framebuffer framebuffer{}; vk::RenderPass renderPass{}; std::vector> textures; ~Storage(); }; std::shared_ptr storage; std::vector attachments; std::vector attachmentDescriptions; std::vector attachmentReferences; std::vector> preserveAttachmentReferences; //!< Any attachment that must be preserved to be utilized by a future subpass, these are stored per-subpass to ensure contiguity constexpr static uintptr_t NoDepthStencil{std::numeric_limits::max()}; //!< A sentinel value to denote the lack of a depth stencil attachment in a VkSubpassDescription /** * @brief Rebases a pointer containing an offset relative to the beginning of a container */ template constexpr T *RebasePointer(const Container &container, const T *offset) { return reinterpret_cast(reinterpret_cast(container.data()) + reinterpret_cast(offset)); } public: std::vector subpassDescriptions; std::vector subpassDependencies; vk::Rect2D renderArea; std::vector clearValues; RenderPassNode(vk::Rect2D renderArea) : storage(std::make_shared()), renderArea(renderArea) {} /** * @note Any preservation of attachments from previous subpasses is automatically handled by this * @return The index of the attachment in the render pass which can be utilized with VkAttachmentReference */ u32 AddAttachment(TextureView *view); /** * @brief Creates a subpass with the attachments bound in the specified order */ void AddSubpass(span inputAttachments, span colorAttachments, TextureView *depthStencilAttachment); /** * @brief Clears a color attachment in the current subpass with VK_ATTACHMENT_LOAD_OP_LOAD * @param colorAttachment The index of the attachment in the attachments bound to the current subpass * @return If the attachment could be cleared or not due to conflicts with other operations * @note We require a subpass to be attached during this as the clear will not take place unless it's referenced by a subpass */ bool ClearColorAttachment(u32 colorAttachment, const vk::ClearColorValue &value); void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu); }; /** * @brief A node which progresses to the next subpass during a render pass */ struct NextSubpassNode { void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu) { commandBuffer.nextSubpass(vk::SubpassContents::eInline); } }; /** * @brief A FunctionNode which progresses to the next subpass prior to calling the function */ struct NextSubpassFunctionNode : private FunctionNode { using FunctionNode::FunctionNode; void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu) { commandBuffer.nextSubpass(vk::SubpassContents::eInline); FunctionNode::operator()(commandBuffer, cycle, gpu); } }; /** * @brief Ends a VkRenderPass that would be created prior with RenderPassNode */ struct RenderPassEndNode { void operator()(vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &gpu) { commandBuffer.endRenderPass(); } }; using NodeVariant = std::variant; //!< A variant encompassing all command nodes types }