#pragma once #include "cocos/renderer/pipeline/custom/LayoutGraphGraphs.h" #include "cocos/renderer/pipeline/custom/NativeTypes.h" #include "cocos/renderer/pipeline/custom/RenderGraphGraphs.h" #include "cocos/renderer/pipeline/custom/details/GslUtils.h" #include "pipeline/custom/RenderGraphTypes.h" namespace cc { namespace render { template RenderGraph::vertex_descriptor addVertex2(Tag tag, Component0 &&c0, Component1 &&c1, Component2 &&c2, Component3 &&c3, ValueT &&val, RenderGraph &g, RenderGraph::vertex_descriptor u = RenderGraph::null_vertex()) { auto v = addVertex( tag, std::forward(c0), std::forward(c1), std::forward(c2), std::forward(c3), std::forward(val), g, u); g.sortedVertices.emplace_back(v); CC_EXPECTS(g.sortedVertices.size() == num_vertices(g)); return v; } inline LayoutGraphData::vertex_descriptor getSubpassOrPassID( RenderGraph::vertex_descriptor vertID, const RenderGraph &rg, const LayoutGraphData &lg) { const auto queueID = parent(vertID, rg); CC_ENSURES(queueID != RenderGraph::null_vertex()); const auto subpassOrPassID = parent(queueID, rg); CC_ENSURES(subpassOrPassID != RenderGraph::null_vertex()); const auto passID = parent(subpassOrPassID, rg); auto layoutID = LayoutGraphData::null_vertex(); if (passID == RenderGraph::null_vertex()) { // single render pass const auto &layoutName = get(RenderGraph::LayoutTag{}, rg, subpassOrPassID); CC_ENSURES(!layoutName.empty()); layoutID = locate(LayoutGraphData::null_vertex(), layoutName, lg); } else { // render pass const auto &passLayoutName = get(RenderGraph::LayoutTag{}, rg, passID); CC_ENSURES(!passLayoutName.empty()); const auto passLayoutID = locate(LayoutGraphData::null_vertex(), passLayoutName, lg); CC_ENSURES(passLayoutID != LayoutGraphData::null_vertex()); const auto &subpassLayoutName = get(RenderGraph::LayoutTag{}, rg, subpassOrPassID); if (subpassLayoutName.empty()) { layoutID = passLayoutID; // expect to be multisample pass } else { const auto subpassLayoutID = locate(passLayoutID, subpassLayoutName, lg); CC_ENSURES(subpassLayoutID != LayoutGraphData::null_vertex()); layoutID = subpassLayoutID; } } CC_ENSURES(layoutID != LayoutGraphData::null_vertex()); return layoutID; } inline std::tuple addRenderPassVertex( RenderGraph &renderGraph, const LayoutGraphData &layoutGraph, uint32_t width, uint32_t height, // NOLINT(bugprone-easily-swappable-parameters) uint32_t count, uint32_t quality, // NOLINT(bugprone-easily-swappable-parameters) const ccstd::string &passName) { RasterPass pass(renderGraph.get_allocator()); pass.width = width; pass.height = height; pass.viewport.width = width; pass.viewport.height = height; pass.count = count; pass.quality = quality; auto passID = addVertex2( RasterPassTag{}, std::forward_as_tuple(passName), std::forward_as_tuple(passName), std::forward_as_tuple(), std::forward_as_tuple(), std::forward_as_tuple(std::move(pass)), renderGraph); auto passLayoutID = locate(LayoutGraphData::null_vertex(), passName, layoutGraph); CC_EXPECTS(passLayoutID != LayoutGraphData::null_vertex()); return {passID, passLayoutID}; } inline std::tuple addRenderSubpassVertex( RasterPass &pass, RenderGraph &renderGraph, RenderGraph::vertex_descriptor passID, const LayoutGraphData &layoutGraph, LayoutGraphData::vertex_descriptor passLayoutID, const ccstd::string &subpassName, uint32_t count, uint32_t quality) { // NOLINT(bugprone-easily-swappable-parameters) // if subpassName is empty, it must be basic multisample render pass CC_EXPECTS(!subpassName.empty() || count > 1); auto &subpassGraph = pass.subpassGraph; const auto subpassIndex = num_vertices(pass.subpassGraph); { auto id = addVertex( std::piecewise_construct, std::forward_as_tuple(subpassName), std::forward_as_tuple(), subpassGraph); CC_ENSURES(id == subpassIndex); } RasterSubpass subpass(subpassIndex, count, quality, renderGraph.get_allocator()); subpass.viewport.width = pass.width; subpass.viewport.height = pass.height; auto subpassID = addVertex2( RasterSubpassTag{}, std::forward_as_tuple(subpassName), std::forward_as_tuple(subpassName), std::forward_as_tuple(), std::forward_as_tuple(), std::forward_as_tuple(std::move(subpass)), renderGraph, passID); auto subpassLayoutID = LayoutGraphData::null_vertex(); if (subpassName.empty()) { // Basic multisample render pass (single subpass) CC_EXPECTS(count > 1); subpassLayoutID = passLayoutID; } else { if constexpr (ENABLE_SUBPASS) { subpassLayoutID = locate(passLayoutID, subpassName, layoutGraph); } else { subpassLayoutID = locate(LayoutGraphData::null_vertex(), subpassName, layoutGraph); } } CC_ENSURES(subpassLayoutID != LayoutGraphData::null_vertex()); return {subpassID, subpassLayoutID}; } template void addPassComputeViewImpl( Tag tag, RenderGraph &renderGraph, RenderGraph::vertex_descriptor passID, const ccstd::string &name, const ComputeView &view) { std::ignore = tag; CC_EXPECTS(!name.empty()); CC_EXPECTS(!view.name.empty()); auto &pass = get(Tag{}, passID, renderGraph); auto iter = pass.computeViews.find(name.c_str()); if (iter == pass.computeViews.end()) { bool added = false; std::tie(iter, added) = pass.computeViews.emplace( std::piecewise_construct, std::forward_as_tuple(name.c_str()), std::forward_as_tuple()); CC_ENSURES(added); } iter->second.emplace_back(view); } template void addSubpassComputeViewImpl( Tag tag, RenderGraph &renderGraph, RenderGraph::vertex_descriptor subpassID, const ccstd::string &name, const ComputeView &view) { std::ignore = tag; CC_EXPECTS(!name.empty()); CC_EXPECTS(!view.name.empty()); auto &subpass = get(Tag{}, subpassID, renderGraph); const auto passID = parent(subpassID, renderGraph); CC_EXPECTS(passID != RenderGraph::null_vertex()); CC_EXPECTS(holds(passID, renderGraph)); auto &pass = get(RasterPassTag{}, passID, renderGraph); CC_EXPECTS(subpass.subpassID < num_vertices(pass.subpassGraph)); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); CC_EXPECTS(subpass.computeViews.size() == subpassData.computeViews.size()); { auto iter = subpassData.computeViews.find(name.c_str()); if (iter == subpassData.computeViews.end()) { bool added = false; std::tie(iter, added) = subpassData.computeViews.emplace( std::piecewise_construct, std::forward_as_tuple(name.c_str()), std::forward_as_tuple()); CC_ENSURES(added); } iter->second.emplace_back(view); } { auto iter = subpass.computeViews.find(name.c_str()); if (iter == subpass.computeViews.end()) { bool added = false; std::tie(iter, added) = subpass.computeViews.emplace( std::piecewise_construct, std::forward_as_tuple(name.c_str()), std::forward_as_tuple()); CC_ENSURES(added); } iter->second.emplace_back(view); } CC_ENSURES(subpass.computeViews.size() == subpassData.computeViews.size()); CC_ENSURES(subpass.computeViews.find(std::string_view{name}) != subpass.computeViews.end()); CC_ENSURES(subpassData.computeViews.find(std::string_view{name}) != subpassData.computeViews.end()); CC_ENSURES(subpass.computeViews.find(std::string_view{name})->second.size() == subpassData.computeViews.find(std::string_view{name})->second.size()); } inline bool defaultAttachment(std::string_view slotName) { return slotName.empty() || slotName == "_"; } static constexpr std::string_view DEPTH_PLANE_NAME = "depth"; static constexpr std::string_view STENCIL_PLANE_NAME = "stencil"; static constexpr std::string_view CUBE_TOP_NAME = "top"; static constexpr std::string_view CUBE_BOTTOM_NAME = "bottom"; static constexpr std::string_view CUBE_FRONT_NAME = "front"; static constexpr std::string_view CUBE_REAR_NAME = "rear"; static constexpr std::string_view CUBE_LEFT_NAME = "left"; static constexpr std::string_view CUBE_RIGHT_NAME = "right"; } // namespace render } // namespace cc