18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef RENDER_GRAPH_H
178bf80f4bSopenharmony_ci#define RENDER_GRAPH_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <cstdint>
208bf80f4bSopenharmony_ci
218bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
228bf80f4bSopenharmony_ci#include <base/containers/vector.h>
238bf80f4bSopenharmony_ci#include <render/device/pipeline_state_desc.h>
248bf80f4bSopenharmony_ci#include <render/namespace.h>
258bf80f4bSopenharmony_ci#include <render/resource_handle.h>
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_ci#include "device/gpu_resource_handle_util.h"
288bf80f4bSopenharmony_ci#include "nodecontext/render_command_list.h"
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
318bf80f4bSopenharmony_ciclass Device;
328bf80f4bSopenharmony_ciclass GpuResourceManager;
338bf80f4bSopenharmony_ciclass RenderBarrierList;
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_cistruct RenderNodeGraphNodeStore;
368bf80f4bSopenharmony_cistruct RenderNodeContextData;
378bf80f4bSopenharmony_ci
388bf80f4bSopenharmony_ci/**
398bf80f4bSopenharmony_ciRenderGraph.
408bf80f4bSopenharmony_ciCreates dependencies between resources (used in render nodes) and queues.
418bf80f4bSopenharmony_ciAutomatically creates transitions and barriers to command lists.
428bf80f4bSopenharmony_ci*/
438bf80f4bSopenharmony_ciclass RenderGraph final {
448bf80f4bSopenharmony_cipublic:
458bf80f4bSopenharmony_ci    explicit RenderGraph(GpuResourceManager& gpuResourceMgr);
468bf80f4bSopenharmony_ci    ~RenderGraph() = default;
478bf80f4bSopenharmony_ci
488bf80f4bSopenharmony_ci    RenderGraph(const RenderGraph&) = delete;
498bf80f4bSopenharmony_ci    RenderGraph operator=(const RenderGraph&) = delete;
508bf80f4bSopenharmony_ci
518bf80f4bSopenharmony_ci    void BeginFrame();
528bf80f4bSopenharmony_ci
538bf80f4bSopenharmony_ci    /** Process all render nodes and patch needed barriers.
548bf80f4bSopenharmony_ci     * backbufferHandle Backbuffer handle for automatic backbuffer/swapchain dependency.
558bf80f4bSopenharmony_ci     * renderNodeGraphNodeStore All render node graph render nodes.
568bf80f4bSopenharmony_ci     */
578bf80f4bSopenharmony_ci    void ProcessRenderNodeGraph(const bool checkBackbufferDependancy,
588bf80f4bSopenharmony_ci        const BASE_NS::array_view<RenderNodeGraphNodeStore*> renderNodeGraphNodeStores);
598bf80f4bSopenharmony_ci
608bf80f4bSopenharmony_ci    struct RenderGraphBufferState {
618bf80f4bSopenharmony_ci        GpuResourceState state;
628bf80f4bSopenharmony_ci        BindableBuffer resource;
638bf80f4bSopenharmony_ci        RenderCommandWithType prevRc;
648bf80f4bSopenharmony_ci        uint32_t prevRenderNodeIndex { ~0u };
658bf80f4bSopenharmony_ci    };
668bf80f4bSopenharmony_ci    static constexpr uint32_t MAX_MIP_STATE_COUNT { 16u };
678bf80f4bSopenharmony_ci    struct RenderGraphAdditionalImageState {
688bf80f4bSopenharmony_ci        BASE_NS::unique_ptr<ImageLayout[]> layouts;
698bf80f4bSopenharmony_ci        // NOTE: layers not handled yet
708bf80f4bSopenharmony_ci    };
718bf80f4bSopenharmony_ci    struct RenderGraphImageState {
728bf80f4bSopenharmony_ci        GpuResourceState state;
738bf80f4bSopenharmony_ci        BindableImage resource;
748bf80f4bSopenharmony_ci        RenderCommandWithType prevRc;
758bf80f4bSopenharmony_ci        uint32_t prevRenderNodeIndex { ~0u };
768bf80f4bSopenharmony_ci        RenderGraphAdditionalImageState additionalState;
778bf80f4bSopenharmony_ci    };
788bf80f4bSopenharmony_ci    struct MultiRenderPassStore {
798bf80f4bSopenharmony_ci        BASE_NS::vector<RenderCommandBeginRenderPass*> renderPasses;
808bf80f4bSopenharmony_ci
818bf80f4bSopenharmony_ci        // batch barriers to the first render pass
828bf80f4bSopenharmony_ci        RenderBarrierList* firstRenderPassBarrierList { nullptr };
838bf80f4bSopenharmony_ci        uint32_t firstBarrierPointIndex { ~0u };
848bf80f4bSopenharmony_ci        bool supportOpen { false };
858bf80f4bSopenharmony_ci    };
868bf80f4bSopenharmony_ci
878bf80f4bSopenharmony_ci    struct GpuQueueTransferState {
888bf80f4bSopenharmony_ci        RenderHandle handle;
898bf80f4bSopenharmony_ci        uint32_t releaseNodeIdx { 0 };
908bf80f4bSopenharmony_ci        uint32_t acquireNodeIdx { 0 };
918bf80f4bSopenharmony_ci
928bf80f4bSopenharmony_ci        ImageLayout optionalReleaseImageLayout { CORE_IMAGE_LAYOUT_UNDEFINED };
938bf80f4bSopenharmony_ci        ImageLayout optionalAcquireImageLayout { CORE_IMAGE_LAYOUT_UNDEFINED };
948bf80f4bSopenharmony_ci    };
958bf80f4bSopenharmony_ci
968bf80f4bSopenharmony_ci    struct SwapchainStates {
978bf80f4bSopenharmony_ci        struct SwapchainState {
988bf80f4bSopenharmony_ci            RenderHandle handle;
998bf80f4bSopenharmony_ci            // state after render node graph processing
1008bf80f4bSopenharmony_ci            GpuResourceState state;
1018bf80f4bSopenharmony_ci            // layout after render node graph processing
1028bf80f4bSopenharmony_ci            ImageLayout layout { ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED };
1038bf80f4bSopenharmony_ci        };
1048bf80f4bSopenharmony_ci        BASE_NS::vector<SwapchainState> swapchains;
1058bf80f4bSopenharmony_ci    };
1068bf80f4bSopenharmony_ci
1078bf80f4bSopenharmony_ci    /** Get backbuffer resource state after render node graph for further processing.
1088bf80f4bSopenharmony_ci     * There might different configurations, or state where backbuffer has not been touched, but we want to present.
1098bf80f4bSopenharmony_ci     */
1108bf80f4bSopenharmony_ci    SwapchainStates GetSwapchainResourceStates() const;
1118bf80f4bSopenharmony_ci
1128bf80f4bSopenharmony_ciprivate:
1138bf80f4bSopenharmony_ci    struct StateCache {
1148bf80f4bSopenharmony_ci        MultiRenderPassStore multiRenderPassStore;
1158bf80f4bSopenharmony_ci
1168bf80f4bSopenharmony_ci        uint32_t nodeCounter { 0u };
1178bf80f4bSopenharmony_ci
1188bf80f4bSopenharmony_ci        bool checkForBackbufferDependency { false };
1198bf80f4bSopenharmony_ci        bool usesSwapchainImage { false };
1208bf80f4bSopenharmony_ci    };
1218bf80f4bSopenharmony_ci    StateCache stateCache_;
1228bf80f4bSopenharmony_ci
1238bf80f4bSopenharmony_ci    struct BeginRenderPassParameters {
1248bf80f4bSopenharmony_ci        RenderCommandBeginRenderPass& rc;
1258bf80f4bSopenharmony_ci        StateCache& stateCache;
1268bf80f4bSopenharmony_ci        RenderCommandWithType rpForCmdRef;
1278bf80f4bSopenharmony_ci    };
1288bf80f4bSopenharmony_ci    void ProcessRenderNodeGraphNodeStores(
1298bf80f4bSopenharmony_ci        const BASE_NS::array_view<RenderNodeGraphNodeStore*>& renderNodeGraphNodeStores, StateCache& stateCache);
1308bf80f4bSopenharmony_ci    void ProcessRenderNodeCommands(BASE_NS::array_view<const RenderCommandWithType>& cmdListRef,
1318bf80f4bSopenharmony_ci        const uint32_t& nodeIdx, RenderNodeContextData& ref, StateCache& stateCache);
1328bf80f4bSopenharmony_ci    void StoreFinalBufferState();
1338bf80f4bSopenharmony_ci    // handles backbuffer layouts as well
1348bf80f4bSopenharmony_ci    void StoreFinalImageState();
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_ci    void RenderCommand(const uint32_t renderNodeIndex, const uint32_t commandListCommandIndex,
1378bf80f4bSopenharmony_ci        RenderNodeContextData& nodeData, RenderCommandBeginRenderPass& rc, StateCache& stateCache);
1388bf80f4bSopenharmony_ci    void BeginRenderPassHandleDependency(
1398bf80f4bSopenharmony_ci        BeginRenderPassParameters& params, const uint32_t commandListCommandIndex, RenderNodeContextData& nodeData);
1408bf80f4bSopenharmony_ci    void BeginRenderPassUpdateImageStates(BeginRenderPassParameters& params, const GpuQueue& gpuQueue,
1418bf80f4bSopenharmony_ci        BASE_NS::array_view<ImageLayout>& finalImageLayouts, const uint32_t renderNodeIndex);
1428bf80f4bSopenharmony_ci    void BeginRenderPassUpdateSubpassImageStates(BASE_NS::array_view<const uint32_t> attatchmentIndices,
1438bf80f4bSopenharmony_ci        const RenderPassDesc& renderPassDesc, const RenderPassAttachmentResourceStates& subpassResourceStatesRef,
1448bf80f4bSopenharmony_ci        BASE_NS::array_view<ImageLayout> finalImageLayouts, StateCache& stateCache);
1458bf80f4bSopenharmony_ci
1468bf80f4bSopenharmony_ci    void RenderCommand(const uint32_t renderNodeIndex, const uint32_t commandListCommandIndex,
1478bf80f4bSopenharmony_ci        const RenderNodeContextData& nodeData, RenderCommandEndRenderPass& rc, StateCache& stateCache);
1488bf80f4bSopenharmony_ci    void RenderCommand(const uint32_t renderNodeIndex, const uint32_t commandListCommandIndex,
1498bf80f4bSopenharmony_ci        RenderNodeContextData& nodeData, RenderCommandBarrierPoint& rc, StateCache& stateCache);
1508bf80f4bSopenharmony_ci
1518bf80f4bSopenharmony_ci    struct ParameterCacheAllocOpt {
1528bf80f4bSopenharmony_ci        BASE_NS::vector<CommandBarrier> combinedBarriers;
1538bf80f4bSopenharmony_ci        BASE_NS::unordered_map<RenderHandle, uint32_t> handledCustomBarriers;
1548bf80f4bSopenharmony_ci    };
1558bf80f4bSopenharmony_ci    ParameterCacheAllocOpt parameterCachePools_;
1568bf80f4bSopenharmony_ci    struct ParameterCache {
1578bf80f4bSopenharmony_ci        BASE_NS::vector<CommandBarrier>& combinedBarriers;
1588bf80f4bSopenharmony_ci        BASE_NS::unordered_map<RenderHandle, uint32_t>& handledCustomBarriers;
1598bf80f4bSopenharmony_ci        const uint32_t customBarrierCount;
1608bf80f4bSopenharmony_ci        const uint32_t vertexInputBarrierCount;
1618bf80f4bSopenharmony_ci        const uint32_t indirectBufferBarrierCount;
1628bf80f4bSopenharmony_ci        const uint32_t renderNodeIndex;
1638bf80f4bSopenharmony_ci        const GpuQueue gpuQueue;
1648bf80f4bSopenharmony_ci        const RenderCommandWithType rcWithType;
1658bf80f4bSopenharmony_ci        StateCache& stateCache;
1668bf80f4bSopenharmony_ci    };
1678bf80f4bSopenharmony_ci    static void UpdateBufferResourceState(
1688bf80f4bSopenharmony_ci        RenderGraphBufferState& stateRef, const ParameterCache& params, const CommandBarrier& cb);
1698bf80f4bSopenharmony_ci    static void UpdateImageResourceState(
1708bf80f4bSopenharmony_ci        RenderGraphImageState& stateRef, const ParameterCache& params, const CommandBarrier& cb);
1718bf80f4bSopenharmony_ci
1728bf80f4bSopenharmony_ci    void HandleCustomBarriers(ParameterCache& params, const uint32_t barrierIndexBegin,
1738bf80f4bSopenharmony_ci        const BASE_NS::array_view<const CommandBarrier>& customBarrierListRef);
1748bf80f4bSopenharmony_ci    void HandleVertexInputBufferBarriers(ParameterCache& params, const uint32_t barrierIndexBegin,
1758bf80f4bSopenharmony_ci        const BASE_NS::array_view<const VertexBuffer>& vertexInputBufferBarrierListRef);
1768bf80f4bSopenharmony_ci    void HandleRenderpassIndirectBufferBarriers(ParameterCache& params, const uint32_t barrierIndexBegin,
1778bf80f4bSopenharmony_ci        const BASE_NS::array_view<const VertexBuffer>& indirectBufferBarrierListRef);
1788bf80f4bSopenharmony_ci
1798bf80f4bSopenharmony_ci    void HandleClearImage(ParameterCache& params, const uint32_t& commandListCommandIndex,
1808bf80f4bSopenharmony_ci        const BASE_NS::array_view<const RenderCommandWithType>& cmdListRef);
1818bf80f4bSopenharmony_ci    void HandleBlitImage(ParameterCache& params, const uint32_t& commandListCommandIndex,
1828bf80f4bSopenharmony_ci        const BASE_NS::array_view<const RenderCommandWithType>& cmdListRef);
1838bf80f4bSopenharmony_ci    void HandleCopyBuffer(ParameterCache& params, const uint32_t& commandListCommandIndex,
1848bf80f4bSopenharmony_ci        const BASE_NS::array_view<const RenderCommandWithType>& cmdListRef);
1858bf80f4bSopenharmony_ci    void HandleCopyBufferImage(ParameterCache& params, const uint32_t& commandListCommandIndex,
1868bf80f4bSopenharmony_ci        const BASE_NS::array_view<const RenderCommandWithType>& cmdListRef);
1878bf80f4bSopenharmony_ci    void HandleDispatchIndirect(ParameterCache& params, const uint32_t& commandListCommandIndex,
1888bf80f4bSopenharmony_ci        const BASE_NS::array_view<const RenderCommandWithType>& cmdListRef);
1898bf80f4bSopenharmony_ci
1908bf80f4bSopenharmony_ci    void HandleDescriptorSets(ParameterCache& params,
1918bf80f4bSopenharmony_ci        const BASE_NS::array_view<const RenderHandle>& descriptorSetHandlesForBarriers,
1928bf80f4bSopenharmony_ci        const NodeContextDescriptorSetManager& nodeDescriptorSetMgrRef);
1938bf80f4bSopenharmony_ci
1948bf80f4bSopenharmony_ci    void UpdateStateAndCreateBarriersGpuImage(
1958bf80f4bSopenharmony_ci        const GpuResourceState& resourceState, const BindableImage& res, RenderGraph::ParameterCache& params);
1968bf80f4bSopenharmony_ci
1978bf80f4bSopenharmony_ci    void UpdateStateAndCreateBarriersGpuBuffer(
1988bf80f4bSopenharmony_ci        const GpuResourceState& resourceState, const BindableBuffer& res, RenderGraph::ParameterCache& params);
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_ci    void AddCommandBarrierAndUpdateStateCache(const uint32_t renderNodeIndex,
2018bf80f4bSopenharmony_ci        const GpuResourceState& newGpuResourceState, const RenderCommandWithType& rcWithType,
2028bf80f4bSopenharmony_ci        BASE_NS::vector<CommandBarrier>& barriers, BASE_NS::vector<GpuQueueTransferState>& currNodeGpuResourceTransfer);
2038bf80f4bSopenharmony_ci
2048bf80f4bSopenharmony_ci    void AddCommandBarrierAndUpdateStateCacheBuffer(const uint32_t renderNodeIndex,
2058bf80f4bSopenharmony_ci        const GpuResourceState& newGpuResourceState, const BindableBuffer& newBuffer,
2068bf80f4bSopenharmony_ci        const RenderCommandWithType& rcWithType, BASE_NS::vector<CommandBarrier>& barriers,
2078bf80f4bSopenharmony_ci        BASE_NS::vector<GpuQueueTransferState>& currNodeGpuResourceTransfer);
2088bf80f4bSopenharmony_ci
2098bf80f4bSopenharmony_ci    void AddCommandBarrierAndUpdateStateCacheImage(const uint32_t renderNodeIndex,
2108bf80f4bSopenharmony_ci        const GpuResourceState& newGpuResourceState, const BindableImage& newImage,
2118bf80f4bSopenharmony_ci        const RenderCommandWithType& rcWithType, BASE_NS::vector<CommandBarrier>& barriers,
2128bf80f4bSopenharmony_ci        BASE_NS::vector<GpuQueueTransferState>& currNodeGpuResourceTransfer);
2138bf80f4bSopenharmony_ci
2148bf80f4bSopenharmony_ci    // if there's no state ATM, a undefined/invalid starting state is created
2158bf80f4bSopenharmony_ci    // do not call this method with non dynamic trackable resources
2168bf80f4bSopenharmony_ci    RenderGraphBufferState& GetBufferResourceStateRef(const RenderHandle handle, const GpuQueue& queue);
2178bf80f4bSopenharmony_ci    RenderGraphImageState& GetImageResourceStateRef(const RenderHandle handle, const GpuQueue& queue);
2188bf80f4bSopenharmony_ci
2198bf80f4bSopenharmony_ci    GpuResourceManager& gpuResourceMgr_;
2208bf80f4bSopenharmony_ci
2218bf80f4bSopenharmony_ci    // stored every time at the end of the frame
2228bf80f4bSopenharmony_ci    SwapchainStates swapchainStates_;
2238bf80f4bSopenharmony_ci
2248bf80f4bSopenharmony_ci    // helper to access current render node transfers
2258bf80f4bSopenharmony_ci    BASE_NS::vector<GpuQueueTransferState> currNodeGpuResourceTransfers_;
2268bf80f4bSopenharmony_ci
2278bf80f4bSopenharmony_ci    // ~0u is invalid index, i.e. no state tracking
2288bf80f4bSopenharmony_ci    BASE_NS::vector<uint32_t> gpuBufferDataIndices_;
2298bf80f4bSopenharmony_ci    // ~0u is invalid index, i.e. no state tracking
2308bf80f4bSopenharmony_ci    BASE_NS::vector<uint32_t> gpuImageDataIndices_;
2318bf80f4bSopenharmony_ci
2328bf80f4bSopenharmony_ci    // resources that are tracked
2338bf80f4bSopenharmony_ci    BASE_NS::vector<RenderGraphBufferState> gpuBufferTracking_;
2348bf80f4bSopenharmony_ci    BASE_NS::vector<RenderGraphImageState> gpuImageTracking_;
2358bf80f4bSopenharmony_ci
2368bf80f4bSopenharmony_ci    // available positions from gpuXXXTracking_
2378bf80f4bSopenharmony_ci    BASE_NS::vector<uint32_t> gpuBufferAvailableIndices_;
2388bf80f4bSopenharmony_ci    BASE_NS::vector<uint32_t> gpuImageAvailableIndices_;
2398bf80f4bSopenharmony_ci
2408bf80f4bSopenharmony_ci    RenderGraphBufferState defaultBufferState_ {};
2418bf80f4bSopenharmony_ci    RenderGraphImageState defaultImageState_ {};
2428bf80f4bSopenharmony_ci};
2438bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
2448bf80f4bSopenharmony_ci
2458bf80f4bSopenharmony_ci#endif // RENDER_GRAPH_H
246