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#include "render_graph.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <cinttypes>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include <base/containers/array_view.h>
218bf80f4bSopenharmony_ci#include <base/containers/fixed_string.h>
228bf80f4bSopenharmony_ci#include <base/math/mathf.h>
238bf80f4bSopenharmony_ci#include <render/namespace.h>
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ci#include "device/gpu_resource_cache.h"
268bf80f4bSopenharmony_ci#include "device/gpu_resource_handle_util.h"
278bf80f4bSopenharmony_ci#include "device/gpu_resource_manager.h"
288bf80f4bSopenharmony_ci#include "nodecontext/render_barrier_list.h"
298bf80f4bSopenharmony_ci#include "nodecontext/render_command_list.h"
308bf80f4bSopenharmony_ci#include "nodecontext/render_node_graph_node_store.h"
318bf80f4bSopenharmony_ci#include "util/log.h"
328bf80f4bSopenharmony_ci
338bf80f4bSopenharmony_ciusing namespace BASE_NS;
348bf80f4bSopenharmony_ci
358bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
368bf80f4bSopenharmony_cinamespace {
378bf80f4bSopenharmony_ciconstexpr uint32_t INVALID_TRACK_IDX { ~0u };
388bf80f4bSopenharmony_ci
398bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
408bf80f4bSopenharmony_ciconstexpr const bool CORE_RENDER_GRAPH_FULL_DEBUG_PRINT = false;
418bf80f4bSopenharmony_ciconstexpr const bool CORE_RENDER_GRAPH_FULL_DEBUG_ATTACHMENTS = false;
428bf80f4bSopenharmony_ciconstexpr const bool CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES = false;
438bf80f4bSopenharmony_ci
448bf80f4bSopenharmony_civoid DebugPrintCommandListCommand(const RenderCommandWithType& rc, GpuResourceManager& aMgr)
458bf80f4bSopenharmony_ci{
468bf80f4bSopenharmony_ci    switch (rc.type) {
478bf80f4bSopenharmony_ci        case RenderCommandType::BARRIER_POINT: {
488bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BarrierPoint");
498bf80f4bSopenharmony_ci            break;
508bf80f4bSopenharmony_ci        }
518bf80f4bSopenharmony_ci        case RenderCommandType::DRAW: {
528bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: Draw");
538bf80f4bSopenharmony_ci            break;
548bf80f4bSopenharmony_ci        }
558bf80f4bSopenharmony_ci        case RenderCommandType::DRAW_INDIRECT: {
568bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DrawIndirect");
578bf80f4bSopenharmony_ci            break;
588bf80f4bSopenharmony_ci        }
598bf80f4bSopenharmony_ci        case RenderCommandType::DISPATCH: {
608bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: Dispatch");
618bf80f4bSopenharmony_ci            break;
628bf80f4bSopenharmony_ci        }
638bf80f4bSopenharmony_ci        case RenderCommandType::DISPATCH_INDIRECT: {
648bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DispatchIndirect");
658bf80f4bSopenharmony_ci            break;
668bf80f4bSopenharmony_ci        }
678bf80f4bSopenharmony_ci        case RenderCommandType::BIND_PIPELINE: {
688bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BindPipeline");
698bf80f4bSopenharmony_ci            break;
708bf80f4bSopenharmony_ci        }
718bf80f4bSopenharmony_ci        case RenderCommandType::BEGIN_RENDER_PASS: {
728bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BeginRenderPass");
738bf80f4bSopenharmony_ci            if constexpr (CORE_RENDER_GRAPH_FULL_DEBUG_ATTACHMENTS) {
748bf80f4bSopenharmony_ci                const auto& beginRenderPass = *static_cast<RenderCommandBeginRenderPass*>(rc.rc);
758bf80f4bSopenharmony_ci                for (uint32_t idx = 0; idx < beginRenderPass.renderPassDesc.attachmentCount; ++idx) {
768bf80f4bSopenharmony_ci                    const RenderHandle handle = beginRenderPass.renderPassDesc.attachmentHandles[idx];
778bf80f4bSopenharmony_ci                    PLUGIN_LOG_I("    attachment idx: %u name: %s", idx, aMgr.GetName(handle).c_str());
788bf80f4bSopenharmony_ci                }
798bf80f4bSopenharmony_ci                PLUGIN_LOG_I("    subpass count: %u, subpass start idx: %u",
808bf80f4bSopenharmony_ci                    (uint32_t)beginRenderPass.renderPassDesc.subpassCount, beginRenderPass.subpassStartIndex);
818bf80f4bSopenharmony_ci            }
828bf80f4bSopenharmony_ci            break;
838bf80f4bSopenharmony_ci        }
848bf80f4bSopenharmony_ci        case RenderCommandType::NEXT_SUBPASS: {
858bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: NextSubpass");
868bf80f4bSopenharmony_ci            break;
878bf80f4bSopenharmony_ci        }
888bf80f4bSopenharmony_ci        case RenderCommandType::END_RENDER_PASS: {
898bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: EndRenderPass");
908bf80f4bSopenharmony_ci            break;
918bf80f4bSopenharmony_ci        }
928bf80f4bSopenharmony_ci        case RenderCommandType::BIND_VERTEX_BUFFERS: {
938bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BindVertexBuffers");
948bf80f4bSopenharmony_ci            break;
958bf80f4bSopenharmony_ci        }
968bf80f4bSopenharmony_ci        case RenderCommandType::BIND_INDEX_BUFFER: {
978bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BindIndexBuffer");
988bf80f4bSopenharmony_ci            break;
998bf80f4bSopenharmony_ci        }
1008bf80f4bSopenharmony_ci        case RenderCommandType::COPY_BUFFER: {
1018bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: CopyBuffer");
1028bf80f4bSopenharmony_ci            break;
1038bf80f4bSopenharmony_ci        }
1048bf80f4bSopenharmony_ci        case RenderCommandType::COPY_BUFFER_IMAGE: {
1058bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: CopyBufferImage");
1068bf80f4bSopenharmony_ci            break;
1078bf80f4bSopenharmony_ci        }
1088bf80f4bSopenharmony_ci        case RenderCommandType::BIND_DESCRIPTOR_SETS: {
1098bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BindDescriptorSets");
1108bf80f4bSopenharmony_ci            break;
1118bf80f4bSopenharmony_ci        }
1128bf80f4bSopenharmony_ci        case RenderCommandType::PUSH_CONSTANT: {
1138bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: PushConstant");
1148bf80f4bSopenharmony_ci            break;
1158bf80f4bSopenharmony_ci        }
1168bf80f4bSopenharmony_ci        case RenderCommandType::BLIT_IMAGE: {
1178bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: BlitImage");
1188bf80f4bSopenharmony_ci            break;
1198bf80f4bSopenharmony_ci        }
1208bf80f4bSopenharmony_ci            // dynamic states
1218bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_VIEWPORT: {
1228bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateViewport");
1238bf80f4bSopenharmony_ci            break;
1248bf80f4bSopenharmony_ci        }
1258bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_SCISSOR: {
1268bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateScissor");
1278bf80f4bSopenharmony_ci            break;
1288bf80f4bSopenharmony_ci        }
1298bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_LINE_WIDTH: {
1308bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateLineWidth");
1318bf80f4bSopenharmony_ci            break;
1328bf80f4bSopenharmony_ci        }
1338bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_DEPTH_BIAS: {
1348bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateDepthBias");
1358bf80f4bSopenharmony_ci            break;
1368bf80f4bSopenharmony_ci        }
1378bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_BLEND_CONSTANTS: {
1388bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateBlendConstants");
1398bf80f4bSopenharmony_ci            break;
1408bf80f4bSopenharmony_ci        }
1418bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_DEPTH_BOUNDS: {
1428bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateDepthBounds");
1438bf80f4bSopenharmony_ci            break;
1448bf80f4bSopenharmony_ci        }
1458bf80f4bSopenharmony_ci        case RenderCommandType::DYNAMIC_STATE_STENCIL: {
1468bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: DynamicStateStencil");
1478bf80f4bSopenharmony_ci            break;
1488bf80f4bSopenharmony_ci        }
1498bf80f4bSopenharmony_ci        case RenderCommandType::WRITE_TIMESTAMP: {
1508bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: WriteTimestamp");
1518bf80f4bSopenharmony_ci            break;
1528bf80f4bSopenharmony_ci        }
1538bf80f4bSopenharmony_ci        case RenderCommandType::GPU_QUEUE_TRANSFER_RELEASE: {
1548bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: GpuQueueTransferRelease");
1558bf80f4bSopenharmony_ci            break;
1568bf80f4bSopenharmony_ci        }
1578bf80f4bSopenharmony_ci        case RenderCommandType::GPU_QUEUE_TRANSFER_ACQUIRE: {
1588bf80f4bSopenharmony_ci            PLUGIN_LOG_I("rc: GpuQueueTransferAcquire");
1598bf80f4bSopenharmony_ci            break;
1608bf80f4bSopenharmony_ci        }
1618bf80f4bSopenharmony_ci        case RenderCommandType::UNDEFINED:
1628bf80f4bSopenharmony_ci        default: {
1638bf80f4bSopenharmony_ci            PLUGIN_ASSERT(false && "non-valid render command");
1648bf80f4bSopenharmony_ci            break;
1658bf80f4bSopenharmony_ci        }
1668bf80f4bSopenharmony_ci    }
1678bf80f4bSopenharmony_ci}
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_civoid DebugBarrierPrint(const GpuResourceManager& gpuResourceMgr, const vector<CommandBarrier>& combinedBarriers)
1708bf80f4bSopenharmony_ci{
1718bf80f4bSopenharmony_ci    PLUGIN_ASSERT(CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES); // do not call this function normally
1728bf80f4bSopenharmony_ci    for (const auto& ref : combinedBarriers) {
1738bf80f4bSopenharmony_ci        const RenderHandleType type = RenderHandleUtil::GetHandleType(ref.resourceHandle);
1748bf80f4bSopenharmony_ci        if (type == RenderHandleType::GPU_BUFFER) {
1758bf80f4bSopenharmony_ci            PLUGIN_LOG_I("barrier buffer    :: handle:0x%" PRIx64 " name:%s, src_stage:%u dst_stage:%u",
1768bf80f4bSopenharmony_ci                ref.resourceHandle.id, gpuResourceMgr.GetName(ref.resourceHandle).c_str(), ref.src.pipelineStageFlags,
1778bf80f4bSopenharmony_ci                ref.dst.pipelineStageFlags);
1788bf80f4bSopenharmony_ci        } else {
1798bf80f4bSopenharmony_ci            PLUGIN_ASSERT(type == RenderHandleType::GPU_IMAGE);
1808bf80f4bSopenharmony_ci            PLUGIN_LOG_I("barrier image     :: handle:0x%" PRIx64
1818bf80f4bSopenharmony_ci                         " name:%s, src_stage:%u dst_stage:%u, src_layout:%u dst_layout:%u",
1828bf80f4bSopenharmony_ci                ref.resourceHandle.id, gpuResourceMgr.GetName(ref.resourceHandle).c_str(), ref.src.pipelineStageFlags,
1838bf80f4bSopenharmony_ci                ref.dst.pipelineStageFlags, ref.src.optionalImageLayout, ref.dst.optionalImageLayout);
1848bf80f4bSopenharmony_ci        }
1858bf80f4bSopenharmony_ci    }
1868bf80f4bSopenharmony_ci}
1878bf80f4bSopenharmony_ci
1888bf80f4bSopenharmony_civoid DebugRenderPassLayoutPrint(const GpuResourceManager& gpuResourceMgr, const RenderCommandBeginRenderPass& rc)
1898bf80f4bSopenharmony_ci{
1908bf80f4bSopenharmony_ci    PLUGIN_ASSERT(CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES); // do not call this function normally
1918bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < rc.renderPassDesc.attachmentCount; ++idx) {
1928bf80f4bSopenharmony_ci        const auto handle = rc.renderPassDesc.attachmentHandles[idx];
1938bf80f4bSopenharmony_ci        const auto srcLayout = rc.imageLayouts.attachmentInitialLayouts[idx];
1948bf80f4bSopenharmony_ci        const auto dstLayout = rc.imageLayouts.attachmentFinalLayouts[idx];
1958bf80f4bSopenharmony_ci        PLUGIN_LOG_I("render_pass image :: handle:0x%" PRIx64 " name:%s, src_layout:%u dst_layout:%u (patched later)",
1968bf80f4bSopenharmony_ci            handle.id, gpuResourceMgr.GetName(handle).c_str(), srcLayout, dstLayout);
1978bf80f4bSopenharmony_ci    }
1988bf80f4bSopenharmony_ci}
1998bf80f4bSopenharmony_ci
2008bf80f4bSopenharmony_civoid DebugPrintImageState(const GpuResourceManager& gpuResourceMgr, const RenderGraph::RenderGraphImageState& resState)
2018bf80f4bSopenharmony_ci{
2028bf80f4bSopenharmony_ci    PLUGIN_ASSERT(CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES); // do not call this function normally
2038bf80f4bSopenharmony_ci    const EngineResourceHandle gpuHandle = gpuResourceMgr.GetGpuHandle(resState.resource.handle);
2048bf80f4bSopenharmony_ci    PLUGIN_LOG_I("image_state   :: handle:0x%" PRIx64 " name:%s, layout:%u, index:%u, gen:%u, gpu_gen:%u",
2058bf80f4bSopenharmony_ci        resState.resource.handle.id, gpuResourceMgr.GetName(resState.resource.handle).c_str(),
2068bf80f4bSopenharmony_ci        resState.resource.imageLayout, RenderHandleUtil::GetIndexPart(resState.resource.handle),
2078bf80f4bSopenharmony_ci        RenderHandleUtil::GetGenerationIndexPart(resState.resource.handle),
2088bf80f4bSopenharmony_ci        RenderHandleUtil::GetGenerationIndexPart(gpuHandle));
2098bf80f4bSopenharmony_ci    // one could fetch and print vulkan handle here as well e.g.
2108bf80f4bSopenharmony_ci    // 1. const GpuImagePlatformDataVk& plat =
2118bf80f4bSopenharmony_ci    // 2. (const GpuImagePlatformDataVk&)gpuResourceMgr.GetImage(ref.first)->GetBasePlatformData()
2128bf80f4bSopenharmony_ci    // 3. PLUGIN_LOG_I("end_frame image   :: vk_handle:0x%" PRIx64, VulkanHandleCast<uint64_t>(plat.image))
2138bf80f4bSopenharmony_ci}
2148bf80f4bSopenharmony_ci#endif // RENDER_DEV_ENABLED
2158bf80f4bSopenharmony_ci
2168bf80f4bSopenharmony_cistatic constexpr uint32_t WRITE_ACCESS_FLAGS = CORE_ACCESS_SHADER_WRITE_BIT | CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
2178bf80f4bSopenharmony_ci                                               CORE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
2188bf80f4bSopenharmony_ci                                               CORE_ACCESS_TRANSFER_WRITE_BIT | CORE_ACCESS_HOST_WRITE_BIT |
2198bf80f4bSopenharmony_ci                                               CORE_ACCESS_MEMORY_WRITE_BIT;
2208bf80f4bSopenharmony_ci
2218bf80f4bSopenharmony_civoid PatchRenderPassFinalLayout(const RenderHandle handle, const ImageLayout imageLayout,
2228bf80f4bSopenharmony_ci    RenderCommandBeginRenderPass& beginRenderPass, RenderGraph::RenderGraphImageState& storeState)
2238bf80f4bSopenharmony_ci{
2248bf80f4bSopenharmony_ci    const uint32_t attachmentCount = beginRenderPass.renderPassDesc.attachmentCount;
2258bf80f4bSopenharmony_ci    for (uint32_t attachmentIdx = 0; attachmentIdx < attachmentCount; ++attachmentIdx) {
2268bf80f4bSopenharmony_ci        if (beginRenderPass.renderPassDesc.attachmentHandles[attachmentIdx].id == handle.id) {
2278bf80f4bSopenharmony_ci            beginRenderPass.imageLayouts.attachmentFinalLayouts[attachmentIdx] = imageLayout;
2288bf80f4bSopenharmony_ci            storeState.resource.imageLayout = imageLayout;
2298bf80f4bSopenharmony_ci        }
2308bf80f4bSopenharmony_ci    }
2318bf80f4bSopenharmony_ci};
2328bf80f4bSopenharmony_ci
2338bf80f4bSopenharmony_civoid UpdateMultiRenderCommandListRenderPasses(RenderGraph::MultiRenderPassStore& store)
2348bf80f4bSopenharmony_ci{
2358bf80f4bSopenharmony_ci    const uint32_t renderPassCount = (uint32_t)store.renderPasses.size();
2368bf80f4bSopenharmony_ci    PLUGIN_ASSERT(renderPassCount > 1);
2378bf80f4bSopenharmony_ci
2388bf80f4bSopenharmony_ci    RenderCommandBeginRenderPass* firstRenderPass = store.renderPasses[0];
2398bf80f4bSopenharmony_ci    PLUGIN_ASSERT(firstRenderPass);
2408bf80f4bSopenharmony_ci    PLUGIN_ASSERT(firstRenderPass->subpasses.size() >= renderPassCount);
2418bf80f4bSopenharmony_ci    const RenderCommandBeginRenderPass* lastRenderPass = store.renderPasses[renderPassCount - 1];
2428bf80f4bSopenharmony_ci    PLUGIN_ASSERT(lastRenderPass);
2438bf80f4bSopenharmony_ci
2448bf80f4bSopenharmony_ci    const uint32_t attachmentCount = firstRenderPass->renderPassDesc.attachmentCount;
2458bf80f4bSopenharmony_ci
2468bf80f4bSopenharmony_ci    // take attachment loads from the first one, and stores from the last one
2478bf80f4bSopenharmony_ci    // take initial layouts from the first one, and final layouts from the last one (could take the next layout)
2488bf80f4bSopenharmony_ci    // initial store the correct render pass description to first render pass and then copy to others
2498bf80f4bSopenharmony_ci    // resource states are copied from valid subpasses to another render command list subpasses
2508bf80f4bSopenharmony_ci    for (uint32_t fromRpIdx = 0; fromRpIdx < renderPassCount; ++fromRpIdx) {
2518bf80f4bSopenharmony_ci        const auto& fromRenderPass = *(store.renderPasses[fromRpIdx]);
2528bf80f4bSopenharmony_ci        const uint32_t fromRpSubpassStartIndex = fromRenderPass.subpassStartIndex;
2538bf80f4bSopenharmony_ci        const auto& fromRpSubpassResourceStates = fromRenderPass.subpassResourceStates[fromRpSubpassStartIndex];
2548bf80f4bSopenharmony_ci        for (uint32_t toRpIdx = 0; toRpIdx < renderPassCount; ++toRpIdx) {
2558bf80f4bSopenharmony_ci            if (fromRpIdx != toRpIdx) {
2568bf80f4bSopenharmony_ci                auto& toRenderPass = *(store.renderPasses[toRpIdx]);
2578bf80f4bSopenharmony_ci                auto& toRpSubpassResourceStates = toRenderPass.subpassResourceStates[fromRpSubpassStartIndex];
2588bf80f4bSopenharmony_ci                for (uint32_t idx = 0; idx < attachmentCount; ++idx) {
2598bf80f4bSopenharmony_ci                    toRpSubpassResourceStates.states[idx] = fromRpSubpassResourceStates.states[idx];
2608bf80f4bSopenharmony_ci                    toRpSubpassResourceStates.layouts[idx] = fromRpSubpassResourceStates.layouts[idx];
2618bf80f4bSopenharmony_ci                }
2628bf80f4bSopenharmony_ci            }
2638bf80f4bSopenharmony_ci        }
2648bf80f4bSopenharmony_ci    }
2658bf80f4bSopenharmony_ci
2668bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < firstRenderPass->renderPassDesc.attachmentCount; ++idx) {
2678bf80f4bSopenharmony_ci        firstRenderPass->renderPassDesc.attachments[idx].storeOp =
2688bf80f4bSopenharmony_ci            lastRenderPass->renderPassDesc.attachments[idx].storeOp;
2698bf80f4bSopenharmony_ci        firstRenderPass->renderPassDesc.attachments[idx].stencilStoreOp =
2708bf80f4bSopenharmony_ci            lastRenderPass->renderPassDesc.attachments[idx].stencilStoreOp;
2718bf80f4bSopenharmony_ci
2728bf80f4bSopenharmony_ci        firstRenderPass->imageLayouts.attachmentFinalLayouts[idx] =
2738bf80f4bSopenharmony_ci            lastRenderPass->imageLayouts.attachmentFinalLayouts[idx];
2748bf80f4bSopenharmony_ci    }
2758bf80f4bSopenharmony_ci
2768bf80f4bSopenharmony_ci    // copy subpasses to first
2778bf80f4bSopenharmony_ci    for (uint32_t idx = 1; idx < renderPassCount; ++idx) {
2788bf80f4bSopenharmony_ci        firstRenderPass->subpasses[idx] = store.renderPasses[idx]->subpasses[idx];
2798bf80f4bSopenharmony_ci    }
2808bf80f4bSopenharmony_ci
2818bf80f4bSopenharmony_ci    // copy from first to following render passes
2828bf80f4bSopenharmony_ci    for (uint32_t idx = 1; idx < renderPassCount; ++idx) {
2838bf80f4bSopenharmony_ci        // subpass start index is the only changing variables
2848bf80f4bSopenharmony_ci        const uint32_t subpassStartIndex = store.renderPasses[idx]->subpassStartIndex;
2858bf80f4bSopenharmony_ci        store.renderPasses[idx]->renderPassDesc = firstRenderPass->renderPassDesc;
2868bf80f4bSopenharmony_ci        store.renderPasses[idx]->subpassStartIndex = subpassStartIndex;
2878bf80f4bSopenharmony_ci
2888bf80f4bSopenharmony_ci        // image layouts needs to match
2898bf80f4bSopenharmony_ci        store.renderPasses[idx]->imageLayouts = firstRenderPass->imageLayouts;
2908bf80f4bSopenharmony_ci        PLUGIN_ASSERT(store.renderPasses[idx]->subpasses.size() >= renderPassCount);
2918bf80f4bSopenharmony_ci        // copy all subpasses
2928bf80f4bSopenharmony_ci        if (!CloneData(store.renderPasses[idx]->subpasses.data(), sizeof(RenderPassSubpassDesc) * renderPassCount,
2938bf80f4bSopenharmony_ci                firstRenderPass->subpasses.data(), sizeof(RenderPassSubpassDesc) * renderPassCount)) {
2948bf80f4bSopenharmony_ci            PLUGIN_LOG_E("Copying of renderPasses failed.");
2958bf80f4bSopenharmony_ci        }
2968bf80f4bSopenharmony_ci        // copy input resource state
2978bf80f4bSopenharmony_ci        if (!CloneData(store.renderPasses[idx]->inputResourceStates.states, sizeof(GpuResourceState) * attachmentCount,
2988bf80f4bSopenharmony_ci                firstRenderPass->inputResourceStates.states, sizeof(GpuResourceState) * attachmentCount)) {
2998bf80f4bSopenharmony_ci            PLUGIN_LOG_E("Copying of renderPasses failed.");
3008bf80f4bSopenharmony_ci        }
3018bf80f4bSopenharmony_ci        // NOTE: subpassResourceStates are not copied to different render passes
3028bf80f4bSopenharmony_ci    }
3038bf80f4bSopenharmony_ci
3048bf80f4bSopenharmony_ci#if (RENDER_VULKAN_COMBINE_MULTI_COMMAND_LIST_MSAA_SUBPASSES_ENABLED == 1)
3058bf80f4bSopenharmony_ci    // copy the final layouts and resolves to first render pass
3068bf80f4bSopenharmony_ci    const uint32_t finalSubpassIdx = renderPassCount - 1U;
3078bf80f4bSopenharmony_ci    if ((renderPassCount > 1U) && (firstRenderPass->subpasses[finalSubpassIdx].resolveAttachmentCount > 0U)) {
3088bf80f4bSopenharmony_ci        firstRenderPass->renderPassDesc.subpassCount = 1U;
3098bf80f4bSopenharmony_ci        firstRenderPass->subpasses = { firstRenderPass->subpasses.data(), 1U };
3108bf80f4bSopenharmony_ci        firstRenderPass->subpassResourceStates = { firstRenderPass->subpassResourceStates.data(), 1U };
3118bf80f4bSopenharmony_ci        // copy resolve attachments from the final subpass
3128bf80f4bSopenharmony_ci        auto& firstSubpass = firstRenderPass->subpasses[0U];
3138bf80f4bSopenharmony_ci        const auto& finalSubpass = store.renderPasses[finalSubpassIdx]->subpasses[finalSubpassIdx];
3148bf80f4bSopenharmony_ci        firstSubpass.resolveAttachmentCount = finalSubpass.resolveAttachmentCount;
3158bf80f4bSopenharmony_ci        firstSubpass.depthResolveAttachmentCount = finalSubpass.depthResolveAttachmentCount;
3168bf80f4bSopenharmony_ci        firstSubpass.depthResolveAttachmentIndex = finalSubpass.depthResolveAttachmentIndex;
3178bf80f4bSopenharmony_ci        firstSubpass.depthResolveModeFlagBit = finalSubpass.depthResolveModeFlagBit;
3188bf80f4bSopenharmony_ci        CloneData(firstSubpass.resolveAttachmentIndices, sizeof(firstSubpass.resolveAttachmentIndices),
3198bf80f4bSopenharmony_ci            finalSubpass.resolveAttachmentIndices, sizeof(uint32_t) * firstSubpass.resolveAttachmentCount);
3208bf80f4bSopenharmony_ci        // layouts for resolve attachments
3218bf80f4bSopenharmony_ci        const auto& finalSubpassResourceStates =
3228bf80f4bSopenharmony_ci            store.renderPasses[finalSubpassIdx]->subpassResourceStates[finalSubpassIdx];
3238bf80f4bSopenharmony_ci        const uint32_t resolveAttachmentCount = firstSubpass.resolveAttachmentCount;
3248bf80f4bSopenharmony_ci        for (uint32_t resIdx = 0U; resIdx < resolveAttachmentCount; ++resIdx) {
3258bf80f4bSopenharmony_ci            const uint32_t resAttIdx = firstSubpass.resolveAttachmentIndices[resIdx];
3268bf80f4bSopenharmony_ci            firstRenderPass->subpassResourceStates[0U].layouts[resAttIdx] =
3278bf80f4bSopenharmony_ci                finalSubpassResourceStates.layouts[resAttIdx];
3288bf80f4bSopenharmony_ci            firstRenderPass->subpassResourceStates[0U].states[resAttIdx] = finalSubpassResourceStates.states[resAttIdx];
3298bf80f4bSopenharmony_ci        }
3308bf80f4bSopenharmony_ci        if ((firstSubpass.depthResolveAttachmentCount > 0U) &&
3318bf80f4bSopenharmony_ci            (firstSubpass.depthResolveAttachmentIndex < PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT)) {
3328bf80f4bSopenharmony_ci            const uint32_t resAttIdx = firstSubpass.resolveAttachmentIndices[firstSubpass.depthResolveAttachmentIndex];
3338bf80f4bSopenharmony_ci            firstRenderPass->subpassResourceStates[0U].layouts[resAttIdx] =
3348bf80f4bSopenharmony_ci                finalSubpassResourceStates.layouts[resAttIdx];
3358bf80f4bSopenharmony_ci            firstRenderPass->subpassResourceStates[0U].states[resAttIdx] = finalSubpassResourceStates.states[resAttIdx];
3368bf80f4bSopenharmony_ci        }
3378bf80f4bSopenharmony_ci
3388bf80f4bSopenharmony_ci        // fix render command list indices
3398bf80f4bSopenharmony_ci        for (uint32_t idx = 1; idx < renderPassCount; ++idx) {
3408bf80f4bSopenharmony_ci            store.renderPasses[idx]->renderPassDesc = firstRenderPass->renderPassDesc;
3418bf80f4bSopenharmony_ci            store.renderPasses[idx]->subpassStartIndex = 0U;
3428bf80f4bSopenharmony_ci            store.renderPasses[idx]->subpasses = firstRenderPass->subpasses;
3438bf80f4bSopenharmony_ci            store.renderPasses[idx]->subpassResourceStates = firstRenderPass->subpassResourceStates;
3448bf80f4bSopenharmony_ci        }
3458bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
3468bf80f4bSopenharmony_ci        PLUGIN_LOG_ONCE_I("combine_multi_command_list_msaa_subpasses_enabled",
3478bf80f4bSopenharmony_ci            "RENDER_VALIDATION: Combining multi-commandlist MSAA resolve subpasses");
3488bf80f4bSopenharmony_ci#endif
3498bf80f4bSopenharmony_ci    }
3508bf80f4bSopenharmony_ci#endif
3518bf80f4bSopenharmony_ci}
3528bf80f4bSopenharmony_ci
3538bf80f4bSopenharmony_ciResourceBarrier GetSrcBufferBarrier(const GpuResourceState& state, const BindableBuffer& res)
3548bf80f4bSopenharmony_ci{
3558bf80f4bSopenharmony_ci    return {
3568bf80f4bSopenharmony_ci        state.accessFlags,
3578bf80f4bSopenharmony_ci        state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
3588bf80f4bSopenharmony_ci        ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED,
3598bf80f4bSopenharmony_ci        res.byteOffset,
3608bf80f4bSopenharmony_ci        res.byteSize,
3618bf80f4bSopenharmony_ci    };
3628bf80f4bSopenharmony_ci}
3638bf80f4bSopenharmony_ci
3648bf80f4bSopenharmony_ciResourceBarrier GetSrcImageBarrier(const GpuResourceState& state, const BindableImage& res)
3658bf80f4bSopenharmony_ci{
3668bf80f4bSopenharmony_ci    return {
3678bf80f4bSopenharmony_ci        state.accessFlags,
3688bf80f4bSopenharmony_ci        state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
3698bf80f4bSopenharmony_ci        res.imageLayout,
3708bf80f4bSopenharmony_ci        0,
3718bf80f4bSopenharmony_ci        PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE,
3728bf80f4bSopenharmony_ci    };
3738bf80f4bSopenharmony_ci}
3748bf80f4bSopenharmony_ci
3758bf80f4bSopenharmony_ciResourceBarrier GetSrcImageBarrierMips(const GpuResourceState& state, const BindableImage& src,
3768bf80f4bSopenharmony_ci    const BindableImage& dst, const RenderGraph::RenderGraphAdditionalImageState& additionalImageState)
3778bf80f4bSopenharmony_ci{
3788bf80f4bSopenharmony_ci    uint32_t mipLevel = 0U;
3798bf80f4bSopenharmony_ci    uint32_t mipCount = PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS;
3808bf80f4bSopenharmony_ci    ImageLayout srcImageLayout = src.imageLayout;
3818bf80f4bSopenharmony_ci    if ((src.mip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS) ||
3828bf80f4bSopenharmony_ci        (dst.mip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS)) {
3838bf80f4bSopenharmony_ci        if (dst.mip < RenderGraph::MAX_MIP_STATE_COUNT) {
3848bf80f4bSopenharmony_ci            mipLevel = dst.mip;
3858bf80f4bSopenharmony_ci            mipCount = 1U;
3868bf80f4bSopenharmony_ci        } else {
3878bf80f4bSopenharmony_ci            mipLevel = src.mip;
3888bf80f4bSopenharmony_ci            // all mip levels
3898bf80f4bSopenharmony_ci        }
3908bf80f4bSopenharmony_ci        PLUGIN_ASSERT(additionalImageState.layouts);
3918bf80f4bSopenharmony_ci        srcImageLayout = additionalImageState.layouts[mipLevel];
3928bf80f4bSopenharmony_ci    }
3938bf80f4bSopenharmony_ci    return {
3948bf80f4bSopenharmony_ci        state.accessFlags,
3958bf80f4bSopenharmony_ci        state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
3968bf80f4bSopenharmony_ci        srcImageLayout,
3978bf80f4bSopenharmony_ci        0,
3988bf80f4bSopenharmony_ci        PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE,
3998bf80f4bSopenharmony_ci        { 0, mipLevel, mipCount, 0u, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS },
4008bf80f4bSopenharmony_ci    };
4018bf80f4bSopenharmony_ci}
4028bf80f4bSopenharmony_ci
4038bf80f4bSopenharmony_ciResourceBarrier GetDstBufferBarrier(const GpuResourceState& state, const BindableBuffer& res)
4048bf80f4bSopenharmony_ci{
4058bf80f4bSopenharmony_ci    return {
4068bf80f4bSopenharmony_ci        state.accessFlags,
4078bf80f4bSopenharmony_ci        state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
4088bf80f4bSopenharmony_ci        ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED,
4098bf80f4bSopenharmony_ci        res.byteOffset,
4108bf80f4bSopenharmony_ci        res.byteSize,
4118bf80f4bSopenharmony_ci    };
4128bf80f4bSopenharmony_ci}
4138bf80f4bSopenharmony_ci
4148bf80f4bSopenharmony_ciResourceBarrier GetDstImageBarrier(const GpuResourceState& state, const BindableImage& res)
4158bf80f4bSopenharmony_ci{
4168bf80f4bSopenharmony_ci    return {
4178bf80f4bSopenharmony_ci        state.accessFlags,
4188bf80f4bSopenharmony_ci        state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
4198bf80f4bSopenharmony_ci        res.imageLayout,
4208bf80f4bSopenharmony_ci        0,
4218bf80f4bSopenharmony_ci        PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE,
4228bf80f4bSopenharmony_ci    };
4238bf80f4bSopenharmony_ci}
4248bf80f4bSopenharmony_ci
4258bf80f4bSopenharmony_ciResourceBarrier GetDstImageBarrierMips(const GpuResourceState& state, const BindableImage& src,
4268bf80f4bSopenharmony_ci    const BindableImage& dst, const RenderGraph::RenderGraphAdditionalImageState& additionalImageState)
4278bf80f4bSopenharmony_ci{
4288bf80f4bSopenharmony_ci    uint32_t mipLevel = 0U;
4298bf80f4bSopenharmony_ci    uint32_t mipCount = PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS;
4308bf80f4bSopenharmony_ci    ImageLayout dstImageLayout = dst.imageLayout;
4318bf80f4bSopenharmony_ci    if ((src.mip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS) ||
4328bf80f4bSopenharmony_ci        (dst.mip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS)) {
4338bf80f4bSopenharmony_ci        if (dst.mip < RenderGraph::MAX_MIP_STATE_COUNT) {
4348bf80f4bSopenharmony_ci            mipLevel = dst.mip;
4358bf80f4bSopenharmony_ci            mipCount = 1U;
4368bf80f4bSopenharmony_ci        } else {
4378bf80f4bSopenharmony_ci            mipLevel = src.mip;
4388bf80f4bSopenharmony_ci            // all mip levels
4398bf80f4bSopenharmony_ci        }
4408bf80f4bSopenharmony_ci    }
4418bf80f4bSopenharmony_ci    return {
4428bf80f4bSopenharmony_ci        state.accessFlags,
4438bf80f4bSopenharmony_ci        state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
4448bf80f4bSopenharmony_ci        dstImageLayout,
4458bf80f4bSopenharmony_ci        0,
4468bf80f4bSopenharmony_ci        PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE,
4478bf80f4bSopenharmony_ci        { 0, mipLevel, mipCount, 0u, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS },
4488bf80f4bSopenharmony_ci    };
4498bf80f4bSopenharmony_ci}
4508bf80f4bSopenharmony_ci
4518bf80f4bSopenharmony_civoid ModifyAdditionalImageState(
4528bf80f4bSopenharmony_ci    const BindableImage& res, RenderGraph::RenderGraphAdditionalImageState& additionalStateRef)
4538bf80f4bSopenharmony_ci{
4548bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
4558bf80f4bSopenharmony_ci    // NOTE: should not be called for images without CORE_RESOURCE_HANDLE_ADDITIONAL_STATE
4568bf80f4bSopenharmony_ci    PLUGIN_ASSERT(RenderHandleUtil::IsDynamicAdditionalStateResource(res.handle));
4578bf80f4bSopenharmony_ci#endif
4588bf80f4bSopenharmony_ci    if (additionalStateRef.layouts) {
4598bf80f4bSopenharmony_ci        if ((res.mip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS) &&
4608bf80f4bSopenharmony_ci            (res.mip < RenderGraph::MAX_MIP_STATE_COUNT)) {
4618bf80f4bSopenharmony_ci            additionalStateRef.layouts[res.mip] = res.imageLayout;
4628bf80f4bSopenharmony_ci        } else {
4638bf80f4bSopenharmony_ci            // set layout for all mips
4648bf80f4bSopenharmony_ci            for (uint32_t idx = 0; idx < RenderGraph::MAX_MIP_STATE_COUNT; ++idx) {
4658bf80f4bSopenharmony_ci                additionalStateRef.layouts[idx] = res.imageLayout;
4668bf80f4bSopenharmony_ci            }
4678bf80f4bSopenharmony_ci        }
4688bf80f4bSopenharmony_ci    } else {
4698bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
4708bf80f4bSopenharmony_ci        PLUGIN_LOG_ONCE_E(to_hex(res.handle.id), "mip layouts missing");
4718bf80f4bSopenharmony_ci#endif
4728bf80f4bSopenharmony_ci    }
4738bf80f4bSopenharmony_ci}
4748bf80f4bSopenharmony_ci
4758bf80f4bSopenharmony_ciCommandBarrier GetQueueOwnershipTransferBarrier(const RenderHandle handle, const GpuQueue& srcGpuQueue,
4768bf80f4bSopenharmony_ci    const GpuQueue& dstGpuQueue, const ImageLayout srcImageLayout, const ImageLayout dstImageLayout)
4778bf80f4bSopenharmony_ci{
4788bf80f4bSopenharmony_ci    return {
4798bf80f4bSopenharmony_ci        handle,
4808bf80f4bSopenharmony_ci
4818bf80f4bSopenharmony_ci        ResourceBarrier {
4828bf80f4bSopenharmony_ci            0,
4838bf80f4bSopenharmony_ci            PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
4848bf80f4bSopenharmony_ci            srcImageLayout,
4858bf80f4bSopenharmony_ci            0,
4868bf80f4bSopenharmony_ci            PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE,
4878bf80f4bSopenharmony_ci            ImageSubresourceRange {},
4888bf80f4bSopenharmony_ci        },
4898bf80f4bSopenharmony_ci        srcGpuQueue,
4908bf80f4bSopenharmony_ci
4918bf80f4bSopenharmony_ci        ResourceBarrier {
4928bf80f4bSopenharmony_ci            0,
4938bf80f4bSopenharmony_ci            PipelineStageFlagBits::CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
4948bf80f4bSopenharmony_ci            dstImageLayout,
4958bf80f4bSopenharmony_ci            0,
4968bf80f4bSopenharmony_ci            PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE,
4978bf80f4bSopenharmony_ci            ImageSubresourceRange {},
4988bf80f4bSopenharmony_ci        },
4998bf80f4bSopenharmony_ci        dstGpuQueue,
5008bf80f4bSopenharmony_ci    };
5018bf80f4bSopenharmony_ci}
5028bf80f4bSopenharmony_ci
5038bf80f4bSopenharmony_civoid PatchGpuResourceQueueTransfers(array_view<const RenderNodeContextData> frameRenderNodeContextData,
5048bf80f4bSopenharmony_ci    array_view<const RenderGraph::GpuQueueTransferState> currNodeGpuResourceTransfers)
5058bf80f4bSopenharmony_ci{
5068bf80f4bSopenharmony_ci    for (const auto& transferRef : currNodeGpuResourceTransfers) {
5078bf80f4bSopenharmony_ci        PLUGIN_ASSERT(transferRef.acquireNodeIdx < (uint32_t)frameRenderNodeContextData.size());
5088bf80f4bSopenharmony_ci
5098bf80f4bSopenharmony_ci        auto& acquireNodeRef = frameRenderNodeContextData[transferRef.acquireNodeIdx];
5108bf80f4bSopenharmony_ci        const GpuQueue acquireGpuQueue = acquireNodeRef.renderCommandList->GetGpuQueue();
5118bf80f4bSopenharmony_ci        GpuQueue releaseGpuQueue = acquireGpuQueue;
5128bf80f4bSopenharmony_ci
5138bf80f4bSopenharmony_ci        if (transferRef.releaseNodeIdx < (uint32_t)frameRenderNodeContextData.size()) {
5148bf80f4bSopenharmony_ci            auto& releaseNodeRef = frameRenderNodeContextData[transferRef.releaseNodeIdx];
5158bf80f4bSopenharmony_ci            releaseGpuQueue = releaseNodeRef.renderCommandList->GetGpuQueue();
5168bf80f4bSopenharmony_ci        }
5178bf80f4bSopenharmony_ci
5188bf80f4bSopenharmony_ci        const CommandBarrier transferBarrier = GetQueueOwnershipTransferBarrier(transferRef.handle, releaseGpuQueue,
5198bf80f4bSopenharmony_ci            acquireGpuQueue, transferRef.optionalReleaseImageLayout, transferRef.optionalAcquireImageLayout);
5208bf80f4bSopenharmony_ci
5218bf80f4bSopenharmony_ci        // release ownership (NOTE: not done for previous frame)
5228bf80f4bSopenharmony_ci        if (transferRef.releaseNodeIdx < (uint32_t)frameRenderNodeContextData.size()) {
5238bf80f4bSopenharmony_ci            auto& releaseNodeRef = frameRenderNodeContextData[transferRef.releaseNodeIdx];
5248bf80f4bSopenharmony_ci            const uint32_t rcIndex = releaseNodeRef.renderCommandList->GetRenderCommandCount() - 1;
5258bf80f4bSopenharmony_ci            const RenderCommandWithType& cmdRef = releaseNodeRef.renderCommandList->GetRenderCommands()[rcIndex];
5268bf80f4bSopenharmony_ci            PLUGIN_ASSERT(cmdRef.type == RenderCommandType::BARRIER_POINT);
5278bf80f4bSopenharmony_ci            const auto& rcbp = *static_cast<RenderCommandBarrierPoint*>(cmdRef.rc);
5288bf80f4bSopenharmony_ci            PLUGIN_ASSERT(rcbp.renderCommandType == RenderCommandType::GPU_QUEUE_TRANSFER_RELEASE);
5298bf80f4bSopenharmony_ci
5308bf80f4bSopenharmony_ci            const uint32_t barrierPointIndex = rcbp.barrierPointIndex;
5318bf80f4bSopenharmony_ci            releaseNodeRef.renderBarrierList->AddBarriersToBarrierPoint(barrierPointIndex, { transferBarrier });
5328bf80f4bSopenharmony_ci
5338bf80f4bSopenharmony_ci            // inform that we are patching valid barriers
5348bf80f4bSopenharmony_ci            releaseNodeRef.renderCommandList->SetValidGpuQueueReleaseAcquireBarriers();
5358bf80f4bSopenharmony_ci        }
5368bf80f4bSopenharmony_ci        // acquire ownership
5378bf80f4bSopenharmony_ci        {
5388bf80f4bSopenharmony_ci            const uint32_t rcIndex = 0;
5398bf80f4bSopenharmony_ci            const RenderCommandWithType& cmdRef = acquireNodeRef.renderCommandList->GetRenderCommands()[rcIndex];
5408bf80f4bSopenharmony_ci            PLUGIN_ASSERT(cmdRef.type == RenderCommandType::BARRIER_POINT);
5418bf80f4bSopenharmony_ci            const auto& rcbp = *static_cast<RenderCommandBarrierPoint*>(cmdRef.rc);
5428bf80f4bSopenharmony_ci            PLUGIN_ASSERT(rcbp.renderCommandType == RenderCommandType::GPU_QUEUE_TRANSFER_ACQUIRE);
5438bf80f4bSopenharmony_ci
5448bf80f4bSopenharmony_ci            const uint32_t barrierPointIndex = rcbp.barrierPointIndex;
5458bf80f4bSopenharmony_ci            acquireNodeRef.renderBarrierList->AddBarriersToBarrierPoint(barrierPointIndex, { transferBarrier });
5468bf80f4bSopenharmony_ci
5478bf80f4bSopenharmony_ci            // inform that we are patching valid barriers
5488bf80f4bSopenharmony_ci            acquireNodeRef.renderCommandList->SetValidGpuQueueReleaseAcquireBarriers();
5498bf80f4bSopenharmony_ci        }
5508bf80f4bSopenharmony_ci    }
5518bf80f4bSopenharmony_ci}
5528bf80f4bSopenharmony_ci
5538bf80f4bSopenharmony_cibool CheckForBarrierNeed(const unordered_map<RenderHandle, uint32_t>& handledCustomBarriers,
5548bf80f4bSopenharmony_ci    const uint32_t customBarrierCount, const RenderHandle handle)
5558bf80f4bSopenharmony_ci{
5568bf80f4bSopenharmony_ci    bool needsBarrier = RenderHandleUtil::IsDynamicResource(handle);
5578bf80f4bSopenharmony_ci    if ((customBarrierCount > 0) && needsBarrier) {
5588bf80f4bSopenharmony_ci        needsBarrier = (handledCustomBarriers.count(handle) > 0) ? false : true;
5598bf80f4bSopenharmony_ci    }
5608bf80f4bSopenharmony_ci    return needsBarrier;
5618bf80f4bSopenharmony_ci}
5628bf80f4bSopenharmony_ci} // namespace
5638bf80f4bSopenharmony_ci
5648bf80f4bSopenharmony_ciRenderGraph::RenderGraph(GpuResourceManager& gpuResourceMgr) : gpuResourceMgr_(gpuResourceMgr) {}
5658bf80f4bSopenharmony_ci
5668bf80f4bSopenharmony_civoid RenderGraph::BeginFrame()
5678bf80f4bSopenharmony_ci{
5688bf80f4bSopenharmony_ci    stateCache_.multiRenderPassStore.renderPasses.clear();
5698bf80f4bSopenharmony_ci    stateCache_.multiRenderPassStore.firstRenderPassBarrierList = nullptr;
5708bf80f4bSopenharmony_ci    stateCache_.multiRenderPassStore.firstBarrierPointIndex = ~0u;
5718bf80f4bSopenharmony_ci    stateCache_.multiRenderPassStore.supportOpen = false;
5728bf80f4bSopenharmony_ci    stateCache_.nodeCounter = 0u;
5738bf80f4bSopenharmony_ci    stateCache_.checkForBackbufferDependency = false;
5748bf80f4bSopenharmony_ci    stateCache_.usesSwapchainImage = false;
5758bf80f4bSopenharmony_ci}
5768bf80f4bSopenharmony_ci
5778bf80f4bSopenharmony_civoid RenderGraph::ProcessRenderNodeGraph(
5788bf80f4bSopenharmony_ci    const bool checkBackbufferDependancy, const array_view<RenderNodeGraphNodeStore*> renderNodeGraphNodeStores)
5798bf80f4bSopenharmony_ci{
5808bf80f4bSopenharmony_ci    stateCache_.checkForBackbufferDependency = checkBackbufferDependancy;
5818bf80f4bSopenharmony_ci
5828bf80f4bSopenharmony_ci    // NOTE: separate gpu buffers and gpu images due to larger structs, layers, mips in images
5838bf80f4bSopenharmony_ci    // all levels of mips and layers are not currently tracked -> needs more fine grained modifications
5848bf80f4bSopenharmony_ci    // handles:
5858bf80f4bSopenharmony_ci    // gpu images in descriptor sets, render passes, blits, and custom barriers
5868bf80f4bSopenharmony_ci    // gpu buffers in descriptor sets, and custom barriers
5878bf80f4bSopenharmony_ci
5888bf80f4bSopenharmony_ci    {
5898bf80f4bSopenharmony_ci        // remove resources that will not be tracked anymore and release available slots
5908bf80f4bSopenharmony_ci        const GpuResourceManager::StateDestroyConsumeStruct stateResetData = gpuResourceMgr_.ConsumeStateDestroyData();
5918bf80f4bSopenharmony_ci        for (const auto& handle : stateResetData.resources) {
5928bf80f4bSopenharmony_ci            const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
5938bf80f4bSopenharmony_ci            const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
5948bf80f4bSopenharmony_ci            if ((handleType == RenderHandleType::GPU_IMAGE) &&
5958bf80f4bSopenharmony_ci                (arrayIndex < static_cast<uint32_t>(gpuImageDataIndices_.size()))) {
5968bf80f4bSopenharmony_ci                if (const uint32_t dataIdx = gpuImageDataIndices_[arrayIndex]; dataIdx != INVALID_TRACK_IDX) {
5978bf80f4bSopenharmony_ci                    PLUGIN_ASSERT(dataIdx < static_cast<uint32_t>(gpuImageTracking_.size()));
5988bf80f4bSopenharmony_ci                    gpuImageTracking_[dataIdx] = {}; // reset
5998bf80f4bSopenharmony_ci                    gpuImageAvailableIndices_.push_back(dataIdx);
6008bf80f4bSopenharmony_ci                }
6018bf80f4bSopenharmony_ci                gpuImageDataIndices_[arrayIndex] = INVALID_TRACK_IDX;
6028bf80f4bSopenharmony_ci            } else if (arrayIndex < static_cast<uint32_t>(gpuBufferDataIndices_.size())) {
6038bf80f4bSopenharmony_ci                if (const uint32_t dataIdx = gpuBufferDataIndices_[arrayIndex]; dataIdx != INVALID_TRACK_IDX) {
6048bf80f4bSopenharmony_ci                    PLUGIN_ASSERT(dataIdx < static_cast<uint32_t>(gpuBufferTracking_.size()));
6058bf80f4bSopenharmony_ci                    gpuBufferTracking_[dataIdx] = {}; // reset
6068bf80f4bSopenharmony_ci                    gpuBufferAvailableIndices_.push_back(dataIdx);
6078bf80f4bSopenharmony_ci                }
6088bf80f4bSopenharmony_ci                gpuBufferDataIndices_[arrayIndex] = INVALID_TRACK_IDX;
6098bf80f4bSopenharmony_ci            }
6108bf80f4bSopenharmony_ci        }
6118bf80f4bSopenharmony_ci    }
6128bf80f4bSopenharmony_ci
6138bf80f4bSopenharmony_ci    gpuBufferDataIndices_.resize(gpuResourceMgr_.GetBufferHandleCount(), INVALID_TRACK_IDX);
6148bf80f4bSopenharmony_ci    gpuImageDataIndices_.resize(gpuResourceMgr_.GetImageHandleCount(), INVALID_TRACK_IDX);
6158bf80f4bSopenharmony_ci
6168bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
6178bf80f4bSopenharmony_ci    if constexpr (CORE_RENDER_GRAPH_FULL_DEBUG_PRINT || CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES ||
6188bf80f4bSopenharmony_ci                  CORE_RENDER_GRAPH_FULL_DEBUG_ATTACHMENTS) {
6198bf80f4bSopenharmony_ci        static uint64_t debugFrame = 0;
6208bf80f4bSopenharmony_ci        debugFrame++;
6218bf80f4bSopenharmony_ci        PLUGIN_LOG_I("START RENDER GRAPH, FRAME %" PRIu64, debugFrame);
6228bf80f4bSopenharmony_ci    }
6238bf80f4bSopenharmony_ci#endif
6248bf80f4bSopenharmony_ci
6258bf80f4bSopenharmony_ci    // need to store some of the resource for frame state in undefined state (i.e. reset on frame boundaries)
6268bf80f4bSopenharmony_ci    ProcessRenderNodeGraphNodeStores(renderNodeGraphNodeStores, stateCache_);
6278bf80f4bSopenharmony_ci
6288bf80f4bSopenharmony_ci    // store final state for next frame
6298bf80f4bSopenharmony_ci    StoreFinalBufferState();
6308bf80f4bSopenharmony_ci    StoreFinalImageState(); // processes gpuImageBackbufferState_ as well
6318bf80f4bSopenharmony_ci}
6328bf80f4bSopenharmony_ci
6338bf80f4bSopenharmony_ciRenderGraph::SwapchainStates RenderGraph::GetSwapchainResourceStates() const
6348bf80f4bSopenharmony_ci{
6358bf80f4bSopenharmony_ci    return swapchainStates_;
6368bf80f4bSopenharmony_ci}
6378bf80f4bSopenharmony_ci
6388bf80f4bSopenharmony_civoid RenderGraph::ProcessRenderNodeGraphNodeStores(
6398bf80f4bSopenharmony_ci    const array_view<RenderNodeGraphNodeStore*>& renderNodeGraphNodeStores, StateCache& stateCache)
6408bf80f4bSopenharmony_ci{
6418bf80f4bSopenharmony_ci    for (RenderNodeGraphNodeStore* graphStore : renderNodeGraphNodeStores) {
6428bf80f4bSopenharmony_ci        PLUGIN_ASSERT(graphStore);
6438bf80f4bSopenharmony_ci        if (!graphStore) {
6448bf80f4bSopenharmony_ci            continue;
6458bf80f4bSopenharmony_ci        }
6468bf80f4bSopenharmony_ci
6478bf80f4bSopenharmony_ci        for (uint32_t nodeIdx = 0; nodeIdx < (uint32_t)graphStore->renderNodeContextData.size(); ++nodeIdx) {
6488bf80f4bSopenharmony_ci            auto& ref = graphStore->renderNodeContextData[nodeIdx];
6498bf80f4bSopenharmony_ci            ref.submitInfo.waitForSwapchainAcquireSignal = false; // reset
6508bf80f4bSopenharmony_ci            stateCache.usesSwapchainImage = false;                // reset
6518bf80f4bSopenharmony_ci
6528bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
6538bf80f4bSopenharmony_ci            if constexpr (CORE_RENDER_GRAPH_FULL_DEBUG_PRINT) {
6548bf80f4bSopenharmony_ci                PLUGIN_LOG_I("FULL NODENAME %s", graphStore->renderNodeData[nodeIdx].fullName.data());
6558bf80f4bSopenharmony_ci            }
6568bf80f4bSopenharmony_ci#endif
6578bf80f4bSopenharmony_ci
6588bf80f4bSopenharmony_ci            if (stateCache.multiRenderPassStore.supportOpen &&
6598bf80f4bSopenharmony_ci                (stateCache.multiRenderPassStore.renderPasses.size() == 0)) {
6608bf80f4bSopenharmony_ci                PLUGIN_LOG_E("invalid multi render node render pass subpass stitching");
6618bf80f4bSopenharmony_ci                // NOTE: add more error handling and invalidate render command lists
6628bf80f4bSopenharmony_ci            }
6638bf80f4bSopenharmony_ci            stateCache.multiRenderPassStore.supportOpen = ref.renderCommandList->HasMultiRenderCommandListSubpasses();
6648bf80f4bSopenharmony_ci            array_view<const RenderCommandWithType> cmdListRef = ref.renderCommandList->GetRenderCommands();
6658bf80f4bSopenharmony_ci            // go through commands that affect or need transitions and barriers
6668bf80f4bSopenharmony_ci            ProcessRenderNodeCommands(cmdListRef, nodeIdx, ref, stateCache);
6678bf80f4bSopenharmony_ci
6688bf80f4bSopenharmony_ci            // needs backbuffer/swapchain wait
6698bf80f4bSopenharmony_ci            if (stateCache.usesSwapchainImage) {
6708bf80f4bSopenharmony_ci                ref.submitInfo.waitForSwapchainAcquireSignal = true;
6718bf80f4bSopenharmony_ci            }
6728bf80f4bSopenharmony_ci
6738bf80f4bSopenharmony_ci            // patch gpu resource queue transfers
6748bf80f4bSopenharmony_ci            if (!currNodeGpuResourceTransfers_.empty()) {
6758bf80f4bSopenharmony_ci                PatchGpuResourceQueueTransfers(graphStore->renderNodeContextData, currNodeGpuResourceTransfers_);
6768bf80f4bSopenharmony_ci                // clear for next use
6778bf80f4bSopenharmony_ci                currNodeGpuResourceTransfers_.clear();
6788bf80f4bSopenharmony_ci            }
6798bf80f4bSopenharmony_ci
6808bf80f4bSopenharmony_ci            stateCache_.nodeCounter++;
6818bf80f4bSopenharmony_ci        }
6828bf80f4bSopenharmony_ci    }
6838bf80f4bSopenharmony_ci}
6848bf80f4bSopenharmony_ci
6858bf80f4bSopenharmony_civoid RenderGraph::ProcessRenderNodeCommands(array_view<const RenderCommandWithType>& cmdListRef,
6868bf80f4bSopenharmony_ci    const uint32_t& nodeIdx, RenderNodeContextData& ref, StateCache& stateCache)
6878bf80f4bSopenharmony_ci{
6888bf80f4bSopenharmony_ci    for (uint32_t listIdx = 0; listIdx < (uint32_t)cmdListRef.size(); ++listIdx) {
6898bf80f4bSopenharmony_ci        auto& cmdRef = cmdListRef[listIdx];
6908bf80f4bSopenharmony_ci
6918bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
6928bf80f4bSopenharmony_ci        if constexpr (CORE_RENDER_GRAPH_FULL_DEBUG_PRINT) {
6938bf80f4bSopenharmony_ci            DebugPrintCommandListCommand(cmdRef, gpuResourceMgr_);
6948bf80f4bSopenharmony_ci        }
6958bf80f4bSopenharmony_ci#endif
6968bf80f4bSopenharmony_ci
6978bf80f4bSopenharmony_ci        // most of the commands are handled within BarrierPoint
6988bf80f4bSopenharmony_ci        switch (cmdRef.type) {
6998bf80f4bSopenharmony_ci            case RenderCommandType::BARRIER_POINT:
7008bf80f4bSopenharmony_ci                RenderCommand(nodeIdx, listIdx, ref, *static_cast<RenderCommandBarrierPoint*>(cmdRef.rc), stateCache);
7018bf80f4bSopenharmony_ci                break;
7028bf80f4bSopenharmony_ci
7038bf80f4bSopenharmony_ci            case RenderCommandType::BEGIN_RENDER_PASS:
7048bf80f4bSopenharmony_ci                RenderCommand(
7058bf80f4bSopenharmony_ci                    nodeIdx, listIdx, ref, *static_cast<RenderCommandBeginRenderPass*>(cmdRef.rc), stateCache);
7068bf80f4bSopenharmony_ci                break;
7078bf80f4bSopenharmony_ci
7088bf80f4bSopenharmony_ci            case RenderCommandType::END_RENDER_PASS:
7098bf80f4bSopenharmony_ci                RenderCommand(nodeIdx, listIdx, ref, *static_cast<RenderCommandEndRenderPass*>(cmdRef.rc), stateCache);
7108bf80f4bSopenharmony_ci                break;
7118bf80f4bSopenharmony_ci
7128bf80f4bSopenharmony_ci            case RenderCommandType::NEXT_SUBPASS:
7138bf80f4bSopenharmony_ci            case RenderCommandType::DRAW:
7148bf80f4bSopenharmony_ci            case RenderCommandType::DRAW_INDIRECT:
7158bf80f4bSopenharmony_ci            case RenderCommandType::DISPATCH:
7168bf80f4bSopenharmony_ci            case RenderCommandType::DISPATCH_INDIRECT:
7178bf80f4bSopenharmony_ci            case RenderCommandType::BIND_PIPELINE:
7188bf80f4bSopenharmony_ci            case RenderCommandType::BIND_VERTEX_BUFFERS:
7198bf80f4bSopenharmony_ci            case RenderCommandType::BIND_INDEX_BUFFER:
7208bf80f4bSopenharmony_ci            case RenderCommandType::COPY_BUFFER:
7218bf80f4bSopenharmony_ci            case RenderCommandType::COPY_BUFFER_IMAGE:
7228bf80f4bSopenharmony_ci            case RenderCommandType::COPY_IMAGE:
7238bf80f4bSopenharmony_ci            case RenderCommandType::BIND_DESCRIPTOR_SETS:
7248bf80f4bSopenharmony_ci            case RenderCommandType::PUSH_CONSTANT:
7258bf80f4bSopenharmony_ci            case RenderCommandType::BLIT_IMAGE:
7268bf80f4bSopenharmony_ci            case RenderCommandType::BUILD_ACCELERATION_STRUCTURE:
7278bf80f4bSopenharmony_ci            case RenderCommandType::CLEAR_COLOR_IMAGE:
7288bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_VIEWPORT:
7298bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_SCISSOR:
7308bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_LINE_WIDTH:
7318bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_DEPTH_BIAS:
7328bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_BLEND_CONSTANTS:
7338bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_DEPTH_BOUNDS:
7348bf80f4bSopenharmony_ci            case RenderCommandType::DYNAMIC_STATE_STENCIL:
7358bf80f4bSopenharmony_ci            case RenderCommandType::WRITE_TIMESTAMP:
7368bf80f4bSopenharmony_ci            case RenderCommandType::GPU_QUEUE_TRANSFER_RELEASE:
7378bf80f4bSopenharmony_ci            case RenderCommandType::GPU_QUEUE_TRANSFER_ACQUIRE:
7388bf80f4bSopenharmony_ci            case RenderCommandType::UNDEFINED:
7398bf80f4bSopenharmony_ci            default: {
7408bf80f4bSopenharmony_ci                // nop
7418bf80f4bSopenharmony_ci                break;
7428bf80f4bSopenharmony_ci            }
7438bf80f4bSopenharmony_ci        }
7448bf80f4bSopenharmony_ci    } // end command for
7458bf80f4bSopenharmony_ci}
7468bf80f4bSopenharmony_ci
7478bf80f4bSopenharmony_civoid RenderGraph::StoreFinalBufferState()
7488bf80f4bSopenharmony_ci{
7498bf80f4bSopenharmony_ci    for (auto& ref : gpuBufferTracking_) {
7508bf80f4bSopenharmony_ci        if (!RenderHandleUtil::IsDynamicResource(ref.resource.handle)) {
7518bf80f4bSopenharmony_ci            ref = {};
7528bf80f4bSopenharmony_ci            continue;
7538bf80f4bSopenharmony_ci        }
7548bf80f4bSopenharmony_ci        if (RenderHandleUtil::IsResetOnFrameBorders(ref.resource.handle)) {
7558bf80f4bSopenharmony_ci            // reset, but we do not reset the handle, because the gpuImageTracking_ element is not removed
7568bf80f4bSopenharmony_ci            const RenderHandle handle = ref.resource.handle;
7578bf80f4bSopenharmony_ci            ref = {};
7588bf80f4bSopenharmony_ci            ref.resource.handle = handle;
7598bf80f4bSopenharmony_ci        }
7608bf80f4bSopenharmony_ci        // need to reset per frame variables for all buffers (so we do not try to patch or debug from previous
7618bf80f4bSopenharmony_ci        // frames)
7628bf80f4bSopenharmony_ci        ref.prevRc = {};
7638bf80f4bSopenharmony_ci        ref.prevRenderNodeIndex = { ~0u };
7648bf80f4bSopenharmony_ci    }
7658bf80f4bSopenharmony_ci}
7668bf80f4bSopenharmony_ci
7678bf80f4bSopenharmony_civoid RenderGraph::StoreFinalImageState()
7688bf80f4bSopenharmony_ci{
7698bf80f4bSopenharmony_ci    swapchainStates_ = {}; // reset
7708bf80f4bSopenharmony_ci
7718bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
7728bf80f4bSopenharmony_ci    if constexpr (CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES) {
7738bf80f4bSopenharmony_ci        PLUGIN_LOG_I("end_frame image_state:");
7748bf80f4bSopenharmony_ci    }
7758bf80f4bSopenharmony_ci#endif
7768bf80f4bSopenharmony_ci    for (auto& ref : gpuImageTracking_) {
7778bf80f4bSopenharmony_ci        // if resource is not dynamic, we do not track and care
7788bf80f4bSopenharmony_ci        if (!RenderHandleUtil::IsDynamicResource(ref.resource.handle)) {
7798bf80f4bSopenharmony_ci            ref = {};
7808bf80f4bSopenharmony_ci            continue;
7818bf80f4bSopenharmony_ci        }
7828bf80f4bSopenharmony_ci        // handle automatic presentation layout
7838bf80f4bSopenharmony_ci        if (stateCache_.checkForBackbufferDependency && RenderHandleUtil::IsSwapchain(ref.resource.handle)) {
7848bf80f4bSopenharmony_ci            if (ref.prevRc.type == RenderCommandType::BEGIN_RENDER_PASS) {
7858bf80f4bSopenharmony_ci                RenderCommandBeginRenderPass& beginRenderPass =
7868bf80f4bSopenharmony_ci                    *static_cast<RenderCommandBeginRenderPass*>(ref.prevRc.rc);
7878bf80f4bSopenharmony_ci                PatchRenderPassFinalLayout(
7888bf80f4bSopenharmony_ci                    ref.resource.handle, ImageLayout::CORE_IMAGE_LAYOUT_PRESENT_SRC, beginRenderPass, ref);
7898bf80f4bSopenharmony_ci            }
7908bf80f4bSopenharmony_ci            // NOTE: currently we handle automatic presentation layout in vulkan backend if not in render pass
7918bf80f4bSopenharmony_ci            // store final state for backbuffer
7928bf80f4bSopenharmony_ci            // currently we only swapchains if they are really in use in this frame
7938bf80f4bSopenharmony_ci            const uint32_t flags = ref.state.accessFlags | ref.state.shaderStageFlags | ref.state.pipelineStageFlags;
7948bf80f4bSopenharmony_ci            if (flags != 0) {
7958bf80f4bSopenharmony_ci                swapchainStates_.swapchains.push_back({ ref.resource.handle, ref.state, ref.resource.imageLayout });
7968bf80f4bSopenharmony_ci            }
7978bf80f4bSopenharmony_ci        }
7988bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
7998bf80f4bSopenharmony_ci        // print before reset for next frame
8008bf80f4bSopenharmony_ci        if constexpr (CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES) {
8018bf80f4bSopenharmony_ci            DebugPrintImageState(gpuResourceMgr_, ref);
8028bf80f4bSopenharmony_ci        }
8038bf80f4bSopenharmony_ci#endif
8048bf80f4bSopenharmony_ci        // shallow resources are not tracked
8058bf80f4bSopenharmony_ci        // they are always in undefined state in the beging of the frame
8068bf80f4bSopenharmony_ci        if (RenderHandleUtil::IsResetOnFrameBorders(ref.resource.handle)) {
8078bf80f4bSopenharmony_ci            const bool addMips = RenderHandleUtil::IsDynamicAdditionalStateResource(ref.resource.handle);
8088bf80f4bSopenharmony_ci            // reset, but we do not reset the handle, because the gpuImageTracking_ element is not removed
8098bf80f4bSopenharmony_ci            const RenderHandle handle = ref.resource.handle;
8108bf80f4bSopenharmony_ci            ref = {};
8118bf80f4bSopenharmony_ci            ref.resource.handle = handle;
8128bf80f4bSopenharmony_ci            if (addMips) {
8138bf80f4bSopenharmony_ci                PLUGIN_ASSERT(!ref.additionalState.layouts);
8148bf80f4bSopenharmony_ci                ref.additionalState.layouts = make_unique<ImageLayout[]>(MAX_MIP_STATE_COUNT);
8158bf80f4bSopenharmony_ci            }
8168bf80f4bSopenharmony_ci        }
8178bf80f4bSopenharmony_ci
8188bf80f4bSopenharmony_ci        // need to reset per frame variables for all images (so we do not try to patch from previous frames)
8198bf80f4bSopenharmony_ci        ref.prevRc = {};
8208bf80f4bSopenharmony_ci        ref.prevRenderNodeIndex = { ~0u };
8218bf80f4bSopenharmony_ci    }
8228bf80f4bSopenharmony_ci}
8238bf80f4bSopenharmony_ci
8248bf80f4bSopenharmony_civoid RenderGraph::RenderCommand(const uint32_t renderNodeIndex, const uint32_t commandListCommandIndex,
8258bf80f4bSopenharmony_ci    RenderNodeContextData& nodeData, RenderCommandBeginRenderPass& rc, StateCache& stateCache)
8268bf80f4bSopenharmony_ci{
8278bf80f4bSopenharmony_ci    // update layouts for attachments to gpu image state
8288bf80f4bSopenharmony_ci    BeginRenderPassParameters params { rc, stateCache, { RenderCommandType::BEGIN_RENDER_PASS, &rc } };
8298bf80f4bSopenharmony_ci
8308bf80f4bSopenharmony_ci    PLUGIN_ASSERT(rc.renderPassDesc.subpassCount > 0);
8318bf80f4bSopenharmony_ci
8328bf80f4bSopenharmony_ci    const bool hasRenderPassDependency = stateCache.multiRenderPassStore.supportOpen;
8338bf80f4bSopenharmony_ci    if (hasRenderPassDependency) { // stitch render pass subpasses
8348bf80f4bSopenharmony_ci        BeginRenderPassHandleDependency(params, commandListCommandIndex, nodeData);
8358bf80f4bSopenharmony_ci    }
8368bf80f4bSopenharmony_ci
8378bf80f4bSopenharmony_ci    const GpuQueue gpuQueue = nodeData.renderCommandList->GetGpuQueue();
8388bf80f4bSopenharmony_ci
8398bf80f4bSopenharmony_ci    auto finalImageLayouts =
8408bf80f4bSopenharmony_ci        array_view(rc.imageLayouts.attachmentFinalLayouts, countof(rc.imageLayouts.attachmentFinalLayouts));
8418bf80f4bSopenharmony_ci
8428bf80f4bSopenharmony_ci    BeginRenderPassUpdateImageStates(params, gpuQueue, finalImageLayouts, renderNodeIndex);
8438bf80f4bSopenharmony_ci
8448bf80f4bSopenharmony_ci    for (uint32_t subpassIdx = 0; subpassIdx < rc.renderPassDesc.subpassCount; ++subpassIdx) {
8458bf80f4bSopenharmony_ci        const auto& subpassRef = rc.subpasses[subpassIdx];
8468bf80f4bSopenharmony_ci        const auto& subpassResourceStatesRef = rc.subpassResourceStates[subpassIdx];
8478bf80f4bSopenharmony_ci
8488bf80f4bSopenharmony_ci        BeginRenderPassUpdateSubpassImageStates(
8498bf80f4bSopenharmony_ci            array_view(subpassRef.inputAttachmentIndices, subpassRef.inputAttachmentCount), rc.renderPassDesc,
8508bf80f4bSopenharmony_ci            subpassResourceStatesRef, finalImageLayouts, stateCache);
8518bf80f4bSopenharmony_ci
8528bf80f4bSopenharmony_ci        BeginRenderPassUpdateSubpassImageStates(
8538bf80f4bSopenharmony_ci            array_view(subpassRef.colorAttachmentIndices, subpassRef.colorAttachmentCount), rc.renderPassDesc,
8548bf80f4bSopenharmony_ci            subpassResourceStatesRef, finalImageLayouts, stateCache);
8558bf80f4bSopenharmony_ci
8568bf80f4bSopenharmony_ci        BeginRenderPassUpdateSubpassImageStates(
8578bf80f4bSopenharmony_ci            array_view(subpassRef.resolveAttachmentIndices, subpassRef.resolveAttachmentCount), rc.renderPassDesc,
8588bf80f4bSopenharmony_ci            subpassResourceStatesRef, finalImageLayouts, stateCache);
8598bf80f4bSopenharmony_ci
8608bf80f4bSopenharmony_ci        if (subpassRef.depthAttachmentCount == 1u) {
8618bf80f4bSopenharmony_ci            BeginRenderPassUpdateSubpassImageStates(
8628bf80f4bSopenharmony_ci                array_view(&subpassRef.depthAttachmentIndex, subpassRef.depthAttachmentCount), rc.renderPassDesc,
8638bf80f4bSopenharmony_ci                subpassResourceStatesRef, finalImageLayouts, stateCache);
8648bf80f4bSopenharmony_ci            if (subpassRef.depthResolveAttachmentCount == 1) {
8658bf80f4bSopenharmony_ci                BeginRenderPassUpdateSubpassImageStates(
8668bf80f4bSopenharmony_ci                    array_view(&subpassRef.depthResolveAttachmentIndex, subpassRef.depthResolveAttachmentCount),
8678bf80f4bSopenharmony_ci                    rc.renderPassDesc, subpassResourceStatesRef, finalImageLayouts, stateCache);
8688bf80f4bSopenharmony_ci            }
8698bf80f4bSopenharmony_ci        }
8708bf80f4bSopenharmony_ci        if (subpassRef.fragmentShadingRateAttachmentCount == 1u) {
8718bf80f4bSopenharmony_ci            BeginRenderPassUpdateSubpassImageStates(array_view(&subpassRef.fragmentShadingRateAttachmentIndex,
8728bf80f4bSopenharmony_ci                                                        subpassRef.fragmentShadingRateAttachmentCount),
8738bf80f4bSopenharmony_ci                rc.renderPassDesc, subpassResourceStatesRef, finalImageLayouts, stateCache);
8748bf80f4bSopenharmony_ci        }
8758bf80f4bSopenharmony_ci    }
8768bf80f4bSopenharmony_ci
8778bf80f4bSopenharmony_ci    if (hasRenderPassDependency) { // stitch render pass subpasses
8788bf80f4bSopenharmony_ci        if (rc.subpassStartIndex > 0) {
8798bf80f4bSopenharmony_ci            // stitched to behave as a nextSubpass() and not beginRenderPass()
8808bf80f4bSopenharmony_ci            rc.beginType = RenderPassBeginType::RENDER_PASS_SUBPASS_BEGIN;
8818bf80f4bSopenharmony_ci        }
8828bf80f4bSopenharmony_ci        const bool finalSubpass = (rc.subpassStartIndex == rc.renderPassDesc.subpassCount - 1);
8838bf80f4bSopenharmony_ci        if (finalSubpass) {
8848bf80f4bSopenharmony_ci            UpdateMultiRenderCommandListRenderPasses(stateCache.multiRenderPassStore);
8858bf80f4bSopenharmony_ci            // multiRenderPassStore cleared in EndRenderPass
8868bf80f4bSopenharmony_ci        }
8878bf80f4bSopenharmony_ci    }
8888bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
8898bf80f4bSopenharmony_ci    if (CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES) {
8908bf80f4bSopenharmony_ci        DebugRenderPassLayoutPrint(gpuResourceMgr_, rc);
8918bf80f4bSopenharmony_ci    }
8928bf80f4bSopenharmony_ci#endif
8938bf80f4bSopenharmony_ci}
8948bf80f4bSopenharmony_ci
8958bf80f4bSopenharmony_civoid RenderGraph::BeginRenderPassHandleDependency(
8968bf80f4bSopenharmony_ci    BeginRenderPassParameters& params, const uint32_t commandListCommandIndex, RenderNodeContextData& nodeData)
8978bf80f4bSopenharmony_ci{
8988bf80f4bSopenharmony_ci    params.stateCache.multiRenderPassStore.renderPasses.push_back(&params.rc);
8998bf80f4bSopenharmony_ci    // store the first begin render pass
9008bf80f4bSopenharmony_ci    params.rpForCmdRef = { RenderCommandType::BEGIN_RENDER_PASS,
9018bf80f4bSopenharmony_ci        params.stateCache.multiRenderPassStore.renderPasses[0] };
9028bf80f4bSopenharmony_ci
9038bf80f4bSopenharmony_ci    if (params.rc.subpassStartIndex == 0) { // store the first render pass barrier point
9048bf80f4bSopenharmony_ci        // barrier point must be previous command
9058bf80f4bSopenharmony_ci        PLUGIN_ASSERT(commandListCommandIndex >= 1);
9068bf80f4bSopenharmony_ci        const uint32_t prevCommandIndex = commandListCommandIndex - 1;
9078bf80f4bSopenharmony_ci
9088bf80f4bSopenharmony_ci        const RenderCommandWithType& barrierPointCmdRef =
9098bf80f4bSopenharmony_ci            nodeData.renderCommandList->GetRenderCommands()[prevCommandIndex];
9108bf80f4bSopenharmony_ci        PLUGIN_ASSERT(barrierPointCmdRef.type == RenderCommandType::BARRIER_POINT);
9118bf80f4bSopenharmony_ci        PLUGIN_ASSERT(static_cast<RenderCommandBarrierPoint*>(barrierPointCmdRef.rc));
9128bf80f4bSopenharmony_ci
9138bf80f4bSopenharmony_ci        params.stateCache.multiRenderPassStore.firstRenderPassBarrierList = nodeData.renderBarrierList.get();
9148bf80f4bSopenharmony_ci        params.stateCache.multiRenderPassStore.firstBarrierPointIndex =
9158bf80f4bSopenharmony_ci            static_cast<RenderCommandBarrierPoint*>(barrierPointCmdRef.rc)->barrierPointIndex;
9168bf80f4bSopenharmony_ci    }
9178bf80f4bSopenharmony_ci}
9188bf80f4bSopenharmony_ci
9198bf80f4bSopenharmony_civoid RenderGraph::BeginRenderPassUpdateImageStates(BeginRenderPassParameters& params, const GpuQueue& gpuQueue,
9208bf80f4bSopenharmony_ci    array_view<ImageLayout>& finalImageLayouts, const uint32_t renderNodeIndex)
9218bf80f4bSopenharmony_ci{
9228bf80f4bSopenharmony_ci    auto& initialImageLayouts = params.rc.imageLayouts.attachmentInitialLayouts;
9238bf80f4bSopenharmony_ci    const auto& attachmentHandles = params.rc.renderPassDesc.attachmentHandles;
9248bf80f4bSopenharmony_ci    auto& attachments = params.rc.renderPassDesc.attachments;
9258bf80f4bSopenharmony_ci    auto& attachmentInputResourceStates = params.rc.inputResourceStates;
9268bf80f4bSopenharmony_ci
9278bf80f4bSopenharmony_ci    for (uint32_t attachmentIdx = 0; attachmentIdx < params.rc.renderPassDesc.attachmentCount; ++attachmentIdx) {
9288bf80f4bSopenharmony_ci        const RenderHandle handle = attachmentHandles[attachmentIdx];
9298bf80f4bSopenharmony_ci        // NOTE: invalidate invalid handle commands already in render command list
9308bf80f4bSopenharmony_ci        if (!RenderHandleUtil::IsGpuImage(handle)) {
9318bf80f4bSopenharmony_ci#ifdef _DEBUG
9328bf80f4bSopenharmony_ci            PLUGIN_LOG_E("invalid handle in render node graph");
9338bf80f4bSopenharmony_ci#endif
9348bf80f4bSopenharmony_ci            continue;
9358bf80f4bSopenharmony_ci        }
9368bf80f4bSopenharmony_ci        auto& stateRef = GetImageResourceStateRef(handle, gpuQueue);
9378bf80f4bSopenharmony_ci        ImageLayout imgLayout = stateRef.resource.imageLayout;
9388bf80f4bSopenharmony_ci
9398bf80f4bSopenharmony_ci        const bool addMips = RenderHandleUtil::IsDynamicAdditionalStateResource(handle);
9408bf80f4bSopenharmony_ci        // image layout is undefined if automatic barriers have been disabled
9418bf80f4bSopenharmony_ci        if (params.rc.enableAutomaticLayoutChanges) {
9428bf80f4bSopenharmony_ci            const RenderPassDesc::AttachmentDesc& attachmentDesc = attachments[attachmentIdx];
9438bf80f4bSopenharmony_ci            if (addMips && (attachmentDesc.mipLevel < RenderGraph::MAX_MIP_STATE_COUNT)) {
9448bf80f4bSopenharmony_ci                if (stateRef.additionalState.layouts) {
9458bf80f4bSopenharmony_ci                    imgLayout = stateRef.additionalState.layouts[attachmentDesc.mipLevel];
9468bf80f4bSopenharmony_ci                } else {
9478bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
9488bf80f4bSopenharmony_ci                    PLUGIN_LOG_ONCE_E(to_hex(handle.id), "mip layouts missing");
9498bf80f4bSopenharmony_ci#endif
9508bf80f4bSopenharmony_ci                }
9518bf80f4bSopenharmony_ci            }
9528bf80f4bSopenharmony_ci
9538bf80f4bSopenharmony_ci            initialImageLayouts[attachmentIdx] = imgLayout;
9548bf80f4bSopenharmony_ci        }
9558bf80f4bSopenharmony_ci        // undefined layout with load_op_load -> we modify to dont_care (and remove validation warning)
9568bf80f4bSopenharmony_ci        if ((imgLayout == ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED) &&
9578bf80f4bSopenharmony_ci            (attachments[attachmentIdx].loadOp == AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_LOAD)) {
9588bf80f4bSopenharmony_ci            // dont care (user needs to be sure what is wanted, i.e. in first frame one should clear)
9598bf80f4bSopenharmony_ci            attachments[attachmentIdx].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
9608bf80f4bSopenharmony_ci        }
9618bf80f4bSopenharmony_ci        finalImageLayouts[attachmentIdx] = imgLayout;
9628bf80f4bSopenharmony_ci        attachmentInputResourceStates.states[attachmentIdx] = stateRef.state;
9638bf80f4bSopenharmony_ci        attachmentInputResourceStates.layouts[attachmentIdx] = imgLayout;
9648bf80f4bSopenharmony_ci
9658bf80f4bSopenharmony_ci        // store render pass for final layout patching
9668bf80f4bSopenharmony_ci        stateRef.prevRc = params.rpForCmdRef;
9678bf80f4bSopenharmony_ci        stateRef.prevRenderNodeIndex = renderNodeIndex;
9688bf80f4bSopenharmony_ci
9698bf80f4bSopenharmony_ci        // flag for backbuffer use
9708bf80f4bSopenharmony_ci        if (params.stateCache.checkForBackbufferDependency && RenderHandleUtil::IsSwapchain(handle)) {
9718bf80f4bSopenharmony_ci            params.stateCache.usesSwapchainImage = true;
9728bf80f4bSopenharmony_ci        }
9738bf80f4bSopenharmony_ci    }
9748bf80f4bSopenharmony_ci}
9758bf80f4bSopenharmony_ci
9768bf80f4bSopenharmony_civoid RenderGraph::BeginRenderPassUpdateSubpassImageStates(array_view<const uint32_t> attatchmentIndices,
9778bf80f4bSopenharmony_ci    const RenderPassDesc& renderPassDesc, const RenderPassAttachmentResourceStates& subpassResourceStatesRef,
9788bf80f4bSopenharmony_ci    array_view<ImageLayout> finalImageLayouts, StateCache& stateCache)
9798bf80f4bSopenharmony_ci{
9808bf80f4bSopenharmony_ci    for (const uint32_t attachmentIndex : attatchmentIndices) {
9818bf80f4bSopenharmony_ci        // NOTE: handle invalid commands already in render command list and invalidate draws etc.
9828bf80f4bSopenharmony_ci        PLUGIN_ASSERT(attachmentIndex < renderPassDesc.attachmentCount);
9838bf80f4bSopenharmony_ci        const RenderHandle handle = renderPassDesc.attachmentHandles[attachmentIndex];
9848bf80f4bSopenharmony_ci        PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(handle) == RenderHandleType::GPU_IMAGE);
9858bf80f4bSopenharmony_ci        const GpuResourceState& refState = subpassResourceStatesRef.states[attachmentIndex];
9868bf80f4bSopenharmony_ci        const ImageLayout& refImgLayout = subpassResourceStatesRef.layouts[attachmentIndex];
9878bf80f4bSopenharmony_ci        // NOTE: we should support non dynamicity and GENERAL
9888bf80f4bSopenharmony_ci
9898bf80f4bSopenharmony_ci        finalImageLayouts[attachmentIndex] = refImgLayout;
9908bf80f4bSopenharmony_ci        auto& ref = GetImageResourceStateRef(handle, refState.gpuQueue);
9918bf80f4bSopenharmony_ci        const bool addMips = RenderHandleUtil::IsDynamicAdditionalStateResource(handle);
9928bf80f4bSopenharmony_ci
9938bf80f4bSopenharmony_ci        ref.state = refState;
9948bf80f4bSopenharmony_ci        ref.resource.handle = handle;
9958bf80f4bSopenharmony_ci        ref.resource.imageLayout = refImgLayout;
9968bf80f4bSopenharmony_ci        if (addMips) {
9978bf80f4bSopenharmony_ci            const RenderPassDesc::AttachmentDesc& attachmentDesc = renderPassDesc.attachments[attachmentIndex];
9988bf80f4bSopenharmony_ci            const BindableImage image {
9998bf80f4bSopenharmony_ci                handle,
10008bf80f4bSopenharmony_ci                attachmentDesc.mipLevel,
10018bf80f4bSopenharmony_ci                attachmentDesc.layer,
10028bf80f4bSopenharmony_ci                refImgLayout,
10038bf80f4bSopenharmony_ci                RenderHandle {},
10048bf80f4bSopenharmony_ci            };
10058bf80f4bSopenharmony_ci            ModifyAdditionalImageState(image, ref.additionalState);
10068bf80f4bSopenharmony_ci        }
10078bf80f4bSopenharmony_ci    }
10088bf80f4bSopenharmony_ci}
10098bf80f4bSopenharmony_ci
10108bf80f4bSopenharmony_civoid RenderGraph::RenderCommand(const uint32_t renderNodeIndex, const uint32_t commandListCommandIndex,
10118bf80f4bSopenharmony_ci    const RenderNodeContextData& nodeData, RenderCommandEndRenderPass& rc, StateCache& stateCache)
10128bf80f4bSopenharmony_ci{
10138bf80f4bSopenharmony_ci    const bool hasRenderPassDependency = stateCache.multiRenderPassStore.supportOpen;
10148bf80f4bSopenharmony_ci    if (hasRenderPassDependency) {
10158bf80f4bSopenharmony_ci        const bool finalSubpass = (rc.subpassCount == (uint32_t)stateCache.multiRenderPassStore.renderPasses.size());
10168bf80f4bSopenharmony_ci        if (finalSubpass) {
10178bf80f4bSopenharmony_ci            if (rc.subpassStartIndex != (rc.subpassCount - 1)) {
10188bf80f4bSopenharmony_ci                PLUGIN_LOG_E("RenderGraph: error in multi render node render pass subpass ending");
10198bf80f4bSopenharmony_ci                // NOTE: add more error handling and invalidate render command lists
10208bf80f4bSopenharmony_ci            }
10218bf80f4bSopenharmony_ci            rc.endType = RenderPassEndType::END_RENDER_PASS;
10228bf80f4bSopenharmony_ci            stateCache.multiRenderPassStore.renderPasses.clear();
10238bf80f4bSopenharmony_ci            stateCache.multiRenderPassStore.firstRenderPassBarrierList = nullptr;
10248bf80f4bSopenharmony_ci            stateCache.multiRenderPassStore.firstBarrierPointIndex = ~0u;
10258bf80f4bSopenharmony_ci            stateCache.multiRenderPassStore.supportOpen = false;
10268bf80f4bSopenharmony_ci        } else {
10278bf80f4bSopenharmony_ci            rc.endType = RenderPassEndType::END_SUBPASS;
10288bf80f4bSopenharmony_ci        }
10298bf80f4bSopenharmony_ci    }
10308bf80f4bSopenharmony_ci}
10318bf80f4bSopenharmony_ci
10328bf80f4bSopenharmony_civoid RenderGraph::RenderCommand(const uint32_t renderNodeIndex, const uint32_t commandListCommandIndex,
10338bf80f4bSopenharmony_ci    RenderNodeContextData& nodeData, RenderCommandBarrierPoint& rc, StateCache& stateCache)
10348bf80f4bSopenharmony_ci{
10358bf80f4bSopenharmony_ci    // go through required descriptors for current upcoming event
10368bf80f4bSopenharmony_ci    const auto& customBarrierListRef = nodeData.renderCommandList->GetCustomBarriers();
10378bf80f4bSopenharmony_ci    const auto& cmdListRef = nodeData.renderCommandList->GetRenderCommands();
10388bf80f4bSopenharmony_ci    const auto& allDescriptorSetHandlesForBarriers = nodeData.renderCommandList->GetDescriptorSetHandles();
10398bf80f4bSopenharmony_ci    const auto& nodeDescriptorSetMgrRef = *nodeData.nodeContextDescriptorSetMgr;
10408bf80f4bSopenharmony_ci
10418bf80f4bSopenharmony_ci    parameterCachePools_.combinedBarriers.clear();
10428bf80f4bSopenharmony_ci    parameterCachePools_.handledCustomBarriers.clear();
10438bf80f4bSopenharmony_ci    ParameterCache parameters { parameterCachePools_.combinedBarriers, parameterCachePools_.handledCustomBarriers,
10448bf80f4bSopenharmony_ci        rc.customBarrierCount, rc.vertexIndexBarrierCount, rc.indirectBufferBarrierCount, renderNodeIndex,
10458bf80f4bSopenharmony_ci        nodeData.renderCommandList->GetGpuQueue(), { RenderCommandType::BARRIER_POINT, &rc }, stateCache };
10468bf80f4bSopenharmony_ci    // first check custom barriers
10478bf80f4bSopenharmony_ci    if (parameters.customBarrierCount > 0) {
10488bf80f4bSopenharmony_ci        HandleCustomBarriers(parameters, rc.customBarrierIndexBegin, customBarrierListRef);
10498bf80f4bSopenharmony_ci    }
10508bf80f4bSopenharmony_ci    // then vertex / index buffer barriers in the barrier point before render pass
10518bf80f4bSopenharmony_ci    if (parameters.vertexInputBarrierCount > 0) {
10528bf80f4bSopenharmony_ci        PLUGIN_ASSERT(rc.renderCommandType == RenderCommandType::BEGIN_RENDER_PASS);
10538bf80f4bSopenharmony_ci        HandleVertexInputBufferBarriers(parameters, rc.vertexIndexBarrierIndexBegin,
10548bf80f4bSopenharmony_ci            nodeData.renderCommandList->GetRenderpassVertexInputBufferBarriers());
10558bf80f4bSopenharmony_ci    }
10568bf80f4bSopenharmony_ci    if (parameters.indirectBufferBarrierCount > 0U) {
10578bf80f4bSopenharmony_ci        PLUGIN_ASSERT(rc.renderCommandType == RenderCommandType::BEGIN_RENDER_PASS);
10588bf80f4bSopenharmony_ci        HandleRenderpassIndirectBufferBarriers(parameters, rc.indirectBufferBarrierIndexBegin,
10598bf80f4bSopenharmony_ci            nodeData.renderCommandList->GetRenderpassIndirectBufferBarriers());
10608bf80f4bSopenharmony_ci    }
10618bf80f4bSopenharmony_ci
10628bf80f4bSopenharmony_ci    // in barrier point the next render command is known for which the barrier is needed
10638bf80f4bSopenharmony_ci    if (rc.renderCommandType == RenderCommandType::CLEAR_COLOR_IMAGE) {
10648bf80f4bSopenharmony_ci        HandleClearImage(parameters, commandListCommandIndex, cmdListRef);
10658bf80f4bSopenharmony_ci    } else if (rc.renderCommandType == RenderCommandType::BLIT_IMAGE) {
10668bf80f4bSopenharmony_ci        HandleBlitImage(parameters, commandListCommandIndex, cmdListRef);
10678bf80f4bSopenharmony_ci    } else if (rc.renderCommandType == RenderCommandType::COPY_BUFFER) {
10688bf80f4bSopenharmony_ci        HandleCopyBuffer(parameters, commandListCommandIndex, cmdListRef);
10698bf80f4bSopenharmony_ci    } else if (rc.renderCommandType == RenderCommandType::COPY_BUFFER_IMAGE) {
10708bf80f4bSopenharmony_ci        HandleCopyBufferImage(parameters, commandListCommandIndex, cmdListRef);
10718bf80f4bSopenharmony_ci    } else if (rc.renderCommandType == RenderCommandType::COPY_IMAGE) {
10728bf80f4bSopenharmony_ci        HandleCopyBufferImage(parameters, commandListCommandIndex, cmdListRef); // NOTE: handles image to image
10738bf80f4bSopenharmony_ci    } else {                                                                    // descriptor sets
10748bf80f4bSopenharmony_ci        if (rc.renderCommandType == RenderCommandType::DISPATCH_INDIRECT) {
10758bf80f4bSopenharmony_ci            HandleDispatchIndirect(parameters, commandListCommandIndex, cmdListRef);
10768bf80f4bSopenharmony_ci        }
10778bf80f4bSopenharmony_ci        const uint32_t descriptorSetHandleBeginIndex = rc.descriptorSetHandleIndexBegin;
10788bf80f4bSopenharmony_ci        const uint32_t descriptorSetHandleEndIndex = descriptorSetHandleBeginIndex + rc.descriptorSetHandleCount;
10798bf80f4bSopenharmony_ci        const uint32_t descriptorSetHandleMaxIndex =
10808bf80f4bSopenharmony_ci            Math::min(descriptorSetHandleEndIndex, static_cast<uint32_t>(allDescriptorSetHandlesForBarriers.size()));
10818bf80f4bSopenharmony_ci        const auto descriptorSetHandlesForBarriers =
10828bf80f4bSopenharmony_ci            array_view(allDescriptorSetHandlesForBarriers.data() + descriptorSetHandleBeginIndex,
10838bf80f4bSopenharmony_ci                allDescriptorSetHandlesForBarriers.data() + descriptorSetHandleMaxIndex);
10848bf80f4bSopenharmony_ci        HandleDescriptorSets(parameters, descriptorSetHandlesForBarriers, nodeDescriptorSetMgrRef);
10858bf80f4bSopenharmony_ci    }
10868bf80f4bSopenharmony_ci
10878bf80f4bSopenharmony_ci    if (!parameters.combinedBarriers.empty()) {
10888bf80f4bSopenharmony_ci        // use first render pass barrier point with following subpasses
10898bf80f4bSopenharmony_ci        // firstRenderPassBarrierPoint is null for the first subpass
10908bf80f4bSopenharmony_ci        const bool renderPassHasDependancy = stateCache.multiRenderPassStore.supportOpen;
10918bf80f4bSopenharmony_ci        if (renderPassHasDependancy && stateCache.multiRenderPassStore.firstRenderPassBarrierList) {
10928bf80f4bSopenharmony_ci            PLUGIN_ASSERT(!stateCache.multiRenderPassStore.renderPasses.empty());
10938bf80f4bSopenharmony_ci            stateCache.multiRenderPassStore.firstRenderPassBarrierList->AddBarriersToBarrierPoint(
10948bf80f4bSopenharmony_ci                rc.barrierPointIndex, parameters.combinedBarriers);
10958bf80f4bSopenharmony_ci        } else {
10968bf80f4bSopenharmony_ci            nodeData.renderBarrierList->AddBarriersToBarrierPoint(rc.barrierPointIndex, parameters.combinedBarriers);
10978bf80f4bSopenharmony_ci        }
10988bf80f4bSopenharmony_ci    }
10998bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1)
11008bf80f4bSopenharmony_ci    if (CORE_RENDER_GRAPH_PRINT_RESOURCE_STATES) {
11018bf80f4bSopenharmony_ci        DebugBarrierPrint(gpuResourceMgr_, parameters.combinedBarriers);
11028bf80f4bSopenharmony_ci    }
11038bf80f4bSopenharmony_ci#endif
11048bf80f4bSopenharmony_ci}
11058bf80f4bSopenharmony_ci
11068bf80f4bSopenharmony_ciinline void RenderGraph::UpdateBufferResourceState(
11078bf80f4bSopenharmony_ci    RenderGraphBufferState& stateRef, const ParameterCache& params, const CommandBarrier& cb)
11088bf80f4bSopenharmony_ci{
11098bf80f4bSopenharmony_ci    stateRef.resource.handle = cb.resourceHandle;
11108bf80f4bSopenharmony_ci    stateRef.state.shaderStageFlags = 0;
11118bf80f4bSopenharmony_ci    stateRef.state.accessFlags = cb.dst.accessFlags;
11128bf80f4bSopenharmony_ci    stateRef.state.pipelineStageFlags = cb.dst.pipelineStageFlags;
11138bf80f4bSopenharmony_ci    stateRef.state.gpuQueue = params.gpuQueue;
11148bf80f4bSopenharmony_ci    stateRef.prevRc = params.rcWithType;
11158bf80f4bSopenharmony_ci    stateRef.prevRenderNodeIndex = params.renderNodeIndex;
11168bf80f4bSopenharmony_ci}
11178bf80f4bSopenharmony_ci
11188bf80f4bSopenharmony_ciinline void RenderGraph::UpdateImageResourceState(
11198bf80f4bSopenharmony_ci    RenderGraphImageState& stateRef, const ParameterCache& params, const CommandBarrier& cb)
11208bf80f4bSopenharmony_ci{
11218bf80f4bSopenharmony_ci    stateRef.resource.handle = cb.resourceHandle;
11228bf80f4bSopenharmony_ci    stateRef.state.shaderStageFlags = 0;
11238bf80f4bSopenharmony_ci    stateRef.state.accessFlags = cb.dst.accessFlags;
11248bf80f4bSopenharmony_ci    stateRef.state.pipelineStageFlags = cb.dst.pipelineStageFlags;
11258bf80f4bSopenharmony_ci    stateRef.state.gpuQueue = params.gpuQueue;
11268bf80f4bSopenharmony_ci    stateRef.prevRc = params.rcWithType;
11278bf80f4bSopenharmony_ci    stateRef.prevRenderNodeIndex = params.renderNodeIndex;
11288bf80f4bSopenharmony_ci}
11298bf80f4bSopenharmony_ci
11308bf80f4bSopenharmony_civoid RenderGraph::HandleCustomBarriers(ParameterCache& params, const uint32_t barrierIndexBegin,
11318bf80f4bSopenharmony_ci    const array_view<const CommandBarrier>& customBarrierListRef)
11328bf80f4bSopenharmony_ci{
11338bf80f4bSopenharmony_ci    params.handledCustomBarriers.reserve(params.customBarrierCount);
11348bf80f4bSopenharmony_ci    PLUGIN_ASSERT(barrierIndexBegin + params.customBarrierCount <= customBarrierListRef.size());
11358bf80f4bSopenharmony_ci    for (auto begin = (customBarrierListRef.begin() + barrierIndexBegin),
11368bf80f4bSopenharmony_ci              end = Math::min(customBarrierListRef.end(), begin + params.customBarrierCount);
11378bf80f4bSopenharmony_ci         begin != end; ++begin) {
11388bf80f4bSopenharmony_ci        // add a copy and modify if needed
11398bf80f4bSopenharmony_ci        auto& cb = params.combinedBarriers.emplace_back(*begin);
11408bf80f4bSopenharmony_ci
11418bf80f4bSopenharmony_ci        // NOTE: undefined type is for non-resource memory/pipeline barriers
11428bf80f4bSopenharmony_ci        const RenderHandleType type = RenderHandleUtil::GetHandleType(cb.resourceHandle);
11438bf80f4bSopenharmony_ci        const bool isDynamicTrack = RenderHandleUtil::IsDynamicResource(cb.resourceHandle);
11448bf80f4bSopenharmony_ci        PLUGIN_ASSERT((type == RenderHandleType::UNDEFINED) || (type == RenderHandleType::GPU_BUFFER) ||
11458bf80f4bSopenharmony_ci                      (type == RenderHandleType::GPU_IMAGE));
11468bf80f4bSopenharmony_ci        if (type == RenderHandleType::GPU_BUFFER) {
11478bf80f4bSopenharmony_ci            if (isDynamicTrack) {
11488bf80f4bSopenharmony_ci                auto& stateRef = GetBufferResourceStateRef(cb.resourceHandle, params.gpuQueue);
11498bf80f4bSopenharmony_ci                UpdateBufferResourceState(stateRef, params, cb);
11508bf80f4bSopenharmony_ci            }
11518bf80f4bSopenharmony_ci            params.handledCustomBarriers[cb.resourceHandle] = 0;
11528bf80f4bSopenharmony_ci        } else if (type == RenderHandleType::GPU_IMAGE) {
11538bf80f4bSopenharmony_ci            if (isDynamicTrack) {
11548bf80f4bSopenharmony_ci                const bool isAddMips = RenderHandleUtil::IsDynamicAdditionalStateResource(cb.resourceHandle);
11558bf80f4bSopenharmony_ci                auto& stateRef = GetImageResourceStateRef(cb.resourceHandle, params.gpuQueue);
11568bf80f4bSopenharmony_ci                if (cb.src.optionalImageLayout == CORE_IMAGE_LAYOUT_MAX_ENUM) {
11578bf80f4bSopenharmony_ci                    uint32_t mipLevel = 0U;
11588bf80f4bSopenharmony_ci                    uint32_t mipCount = PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS;
11598bf80f4bSopenharmony_ci                    ImageLayout srcImageLayout = stateRef.resource.imageLayout;
11608bf80f4bSopenharmony_ci                    if (isAddMips) {
11618bf80f4bSopenharmony_ci                        const uint32_t srcMip = cb.src.optionalImageSubresourceRange.baseMipLevel;
11628bf80f4bSopenharmony_ci                        const uint32_t dstMip = cb.dst.optionalImageSubresourceRange.baseMipLevel;
11638bf80f4bSopenharmony_ci                        if ((srcMip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS) ||
11648bf80f4bSopenharmony_ci                            (dstMip != PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS)) {
11658bf80f4bSopenharmony_ci                            if (dstMip < RenderGraph::MAX_MIP_STATE_COUNT) {
11668bf80f4bSopenharmony_ci                                mipLevel = dstMip;
11678bf80f4bSopenharmony_ci                                mipCount = 1U;
11688bf80f4bSopenharmony_ci                            } else {
11698bf80f4bSopenharmony_ci                                mipLevel = srcMip;
11708bf80f4bSopenharmony_ci                                // all mip levels
11718bf80f4bSopenharmony_ci                            }
11728bf80f4bSopenharmony_ci                            if (stateRef.additionalState.layouts) {
11738bf80f4bSopenharmony_ci                                srcImageLayout = stateRef.additionalState.layouts[mipLevel];
11748bf80f4bSopenharmony_ci                            } else {
11758bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
11768bf80f4bSopenharmony_ci                                PLUGIN_LOG_ONCE_E(to_hex(cb.resourceHandle.id), "mip layouts missing");
11778bf80f4bSopenharmony_ci#endif
11788bf80f4bSopenharmony_ci                            }
11798bf80f4bSopenharmony_ci                        }
11808bf80f4bSopenharmony_ci                    }
11818bf80f4bSopenharmony_ci                    cb.src.accessFlags = stateRef.state.accessFlags;
11828bf80f4bSopenharmony_ci                    cb.src.pipelineStageFlags =
11838bf80f4bSopenharmony_ci                        stateRef.state.pipelineStageFlags | PipelineStageFlagBits::CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
11848bf80f4bSopenharmony_ci                    cb.src.optionalImageLayout = srcImageLayout;
11858bf80f4bSopenharmony_ci                    cb.src.optionalImageSubresourceRange = { 0, mipLevel, mipCount, 0u,
11868bf80f4bSopenharmony_ci                        PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
11878bf80f4bSopenharmony_ci                }
11888bf80f4bSopenharmony_ci                UpdateImageResourceState(stateRef, params, cb);
11898bf80f4bSopenharmony_ci                stateRef.resource.imageLayout = cb.dst.optionalImageLayout;
11908bf80f4bSopenharmony_ci                if (isAddMips) {
11918bf80f4bSopenharmony_ci                    const BindableImage image {
11928bf80f4bSopenharmony_ci                        cb.resourceHandle,
11938bf80f4bSopenharmony_ci                        cb.dst.optionalImageSubresourceRange.baseMipLevel,
11948bf80f4bSopenharmony_ci                        cb.dst.optionalImageSubresourceRange.baseArrayLayer,
11958bf80f4bSopenharmony_ci                        cb.dst.optionalImageLayout,
11968bf80f4bSopenharmony_ci                        RenderHandle {},
11978bf80f4bSopenharmony_ci                    };
11988bf80f4bSopenharmony_ci                    ModifyAdditionalImageState(image, stateRef.additionalState);
11998bf80f4bSopenharmony_ci                }
12008bf80f4bSopenharmony_ci            }
12018bf80f4bSopenharmony_ci            params.handledCustomBarriers[cb.resourceHandle] = 0;
12028bf80f4bSopenharmony_ci        }
12038bf80f4bSopenharmony_ci    }
12048bf80f4bSopenharmony_ci}
12058bf80f4bSopenharmony_ci
12068bf80f4bSopenharmony_civoid RenderGraph::HandleVertexInputBufferBarriers(ParameterCache& params, const uint32_t barrierIndexBegin,
12078bf80f4bSopenharmony_ci    const array_view<const VertexBuffer>& vertexInputBufferBarrierListRef)
12088bf80f4bSopenharmony_ci{
12098bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < params.vertexInputBarrierCount; ++idx) {
12108bf80f4bSopenharmony_ci        const uint32_t barrierIndex = barrierIndexBegin + idx;
12118bf80f4bSopenharmony_ci        PLUGIN_ASSERT(barrierIndex < (uint32_t)vertexInputBufferBarrierListRef.size());
12128bf80f4bSopenharmony_ci        if (barrierIndex < (uint32_t)vertexInputBufferBarrierListRef.size()) {
12138bf80f4bSopenharmony_ci            const VertexBuffer& vbInput = vertexInputBufferBarrierListRef[barrierIndex];
12148bf80f4bSopenharmony_ci            const GpuResourceState resourceState { CORE_SHADER_STAGE_VERTEX_BIT,
12158bf80f4bSopenharmony_ci                CORE_ACCESS_INDEX_READ_BIT | CORE_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
12168bf80f4bSopenharmony_ci                CORE_PIPELINE_STAGE_VERTEX_INPUT_BIT, params.gpuQueue };
12178bf80f4bSopenharmony_ci            UpdateStateAndCreateBarriersGpuBuffer(
12188bf80f4bSopenharmony_ci                resourceState, { vbInput.bufferHandle, vbInput.bufferOffset, vbInput.byteSize }, params);
12198bf80f4bSopenharmony_ci        }
12208bf80f4bSopenharmony_ci    }
12218bf80f4bSopenharmony_ci}
12228bf80f4bSopenharmony_ci
12238bf80f4bSopenharmony_civoid RenderGraph::HandleRenderpassIndirectBufferBarriers(ParameterCache& params, const uint32_t barrierIndexBegin,
12248bf80f4bSopenharmony_ci    const array_view<const VertexBuffer>& indirectBufferBarrierListRef)
12258bf80f4bSopenharmony_ci{
12268bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < params.indirectBufferBarrierCount; ++idx) {
12278bf80f4bSopenharmony_ci        const uint32_t barrierIndex = barrierIndexBegin + idx;
12288bf80f4bSopenharmony_ci        PLUGIN_ASSERT(barrierIndex < (uint32_t)indirectBufferBarrierListRef.size());
12298bf80f4bSopenharmony_ci        if (barrierIndex < (uint32_t)indirectBufferBarrierListRef.size()) {
12308bf80f4bSopenharmony_ci            const VertexBuffer& ib = indirectBufferBarrierListRef[barrierIndex];
12318bf80f4bSopenharmony_ci            const bool needsArgsBarrier =
12328bf80f4bSopenharmony_ci                CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, ib.bufferHandle);
12338bf80f4bSopenharmony_ci            if (needsArgsBarrier) {
12348bf80f4bSopenharmony_ci                const GpuResourceState resourceState { CORE_SHADER_STAGE_VERTEX_BIT,
12358bf80f4bSopenharmony_ci                    CORE_ACCESS_INDIRECT_COMMAND_READ_BIT, CORE_PIPELINE_STAGE_DRAW_INDIRECT_BIT, params.gpuQueue };
12368bf80f4bSopenharmony_ci                UpdateStateAndCreateBarriersGpuBuffer(
12378bf80f4bSopenharmony_ci                    resourceState, { ib.bufferHandle, ib.bufferOffset, ib.byteSize }, params);
12388bf80f4bSopenharmony_ci            }
12398bf80f4bSopenharmony_ci        }
12408bf80f4bSopenharmony_ci    }
12418bf80f4bSopenharmony_ci}
12428bf80f4bSopenharmony_ci
12438bf80f4bSopenharmony_civoid RenderGraph::HandleClearImage(ParameterCache& params, const uint32_t& commandListCommandIndex,
12448bf80f4bSopenharmony_ci    const array_view<const RenderCommandWithType>& cmdListRef)
12458bf80f4bSopenharmony_ci{
12468bf80f4bSopenharmony_ci    const uint32_t nextListIdx = commandListCommandIndex + 1;
12478bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextListIdx < cmdListRef.size());
12488bf80f4bSopenharmony_ci    const auto& nextCmdRef = cmdListRef[nextListIdx];
12498bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextCmdRef.type == RenderCommandType::CLEAR_COLOR_IMAGE);
12508bf80f4bSopenharmony_ci
12518bf80f4bSopenharmony_ci    const RenderCommandClearColorImage& nextRc = *static_cast<RenderCommandClearColorImage*>(nextCmdRef.rc);
12528bf80f4bSopenharmony_ci
12538bf80f4bSopenharmony_ci    const bool needsBarrier =
12548bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, nextRc.handle);
12558bf80f4bSopenharmony_ci    if (needsBarrier) {
12568bf80f4bSopenharmony_ci        BindableImage bRes = {};
12578bf80f4bSopenharmony_ci        bRes.handle = nextRc.handle;
12588bf80f4bSopenharmony_ci        bRes.imageLayout = nextRc.imageLayout;
12598bf80f4bSopenharmony_ci        AddCommandBarrierAndUpdateStateCacheImage(params.renderNodeIndex,
12608bf80f4bSopenharmony_ci            GpuResourceState { 0, CORE_ACCESS_TRANSFER_WRITE_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
12618bf80f4bSopenharmony_ci            bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
12628bf80f4bSopenharmony_ci    }
12638bf80f4bSopenharmony_ci}
12648bf80f4bSopenharmony_ci
12658bf80f4bSopenharmony_civoid RenderGraph::HandleBlitImage(ParameterCache& params, const uint32_t& commandListCommandIndex,
12668bf80f4bSopenharmony_ci    const array_view<const RenderCommandWithType>& cmdListRef)
12678bf80f4bSopenharmony_ci{
12688bf80f4bSopenharmony_ci    const uint32_t nextListIdx = commandListCommandIndex + 1;
12698bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextListIdx < cmdListRef.size());
12708bf80f4bSopenharmony_ci    const auto& nextCmdRef = cmdListRef[nextListIdx];
12718bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextCmdRef.type == RenderCommandType::BLIT_IMAGE);
12728bf80f4bSopenharmony_ci
12738bf80f4bSopenharmony_ci    const RenderCommandBlitImage& nextRc = *static_cast<RenderCommandBlitImage*>(nextCmdRef.rc);
12748bf80f4bSopenharmony_ci
12758bf80f4bSopenharmony_ci    const bool needsSrcBarrier =
12768bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, nextRc.srcHandle);
12778bf80f4bSopenharmony_ci    if (needsSrcBarrier) {
12788bf80f4bSopenharmony_ci        BindableImage bRes = {};
12798bf80f4bSopenharmony_ci        bRes.handle = nextRc.srcHandle;
12808bf80f4bSopenharmony_ci        bRes.imageLayout = nextRc.srcImageLayout;
12818bf80f4bSopenharmony_ci        AddCommandBarrierAndUpdateStateCacheImage(params.renderNodeIndex,
12828bf80f4bSopenharmony_ci            GpuResourceState { 0, CORE_ACCESS_TRANSFER_READ_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
12838bf80f4bSopenharmony_ci            bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
12848bf80f4bSopenharmony_ci    }
12858bf80f4bSopenharmony_ci
12868bf80f4bSopenharmony_ci    const bool needsDstBarrier =
12878bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, nextRc.dstHandle);
12888bf80f4bSopenharmony_ci    if (needsDstBarrier) {
12898bf80f4bSopenharmony_ci        BindableImage bRes = {};
12908bf80f4bSopenharmony_ci        bRes.handle = nextRc.dstHandle;
12918bf80f4bSopenharmony_ci        bRes.imageLayout = nextRc.dstImageLayout;
12928bf80f4bSopenharmony_ci        AddCommandBarrierAndUpdateStateCacheImage(params.renderNodeIndex,
12938bf80f4bSopenharmony_ci            GpuResourceState { 0, CORE_ACCESS_TRANSFER_WRITE_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
12948bf80f4bSopenharmony_ci            bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
12958bf80f4bSopenharmony_ci    }
12968bf80f4bSopenharmony_ci}
12978bf80f4bSopenharmony_ci
12988bf80f4bSopenharmony_civoid RenderGraph::HandleCopyBuffer(ParameterCache& params, const uint32_t& commandListCommandIndex,
12998bf80f4bSopenharmony_ci    const array_view<const RenderCommandWithType>& cmdListRef)
13008bf80f4bSopenharmony_ci{
13018bf80f4bSopenharmony_ci    const uint32_t nextListIdx = commandListCommandIndex + 1;
13028bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextListIdx < cmdListRef.size());
13038bf80f4bSopenharmony_ci    const auto& nextCmdRef = cmdListRef[nextListIdx];
13048bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextCmdRef.type == RenderCommandType::COPY_BUFFER);
13058bf80f4bSopenharmony_ci
13068bf80f4bSopenharmony_ci    const RenderCommandCopyBuffer& nextRc = *static_cast<RenderCommandCopyBuffer*>(nextCmdRef.rc);
13078bf80f4bSopenharmony_ci
13088bf80f4bSopenharmony_ci    const bool needsSrcBarrier =
13098bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, nextRc.srcHandle);
13108bf80f4bSopenharmony_ci    if (needsSrcBarrier) {
13118bf80f4bSopenharmony_ci        const BindableBuffer bRes = { nextRc.srcHandle, nextRc.bufferCopy.srcOffset, nextRc.bufferCopy.size };
13128bf80f4bSopenharmony_ci        AddCommandBarrierAndUpdateStateCacheBuffer(params.renderNodeIndex,
13138bf80f4bSopenharmony_ci            GpuResourceState { 0, CORE_ACCESS_TRANSFER_READ_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
13148bf80f4bSopenharmony_ci            bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
13158bf80f4bSopenharmony_ci    }
13168bf80f4bSopenharmony_ci
13178bf80f4bSopenharmony_ci    const bool needsDstBarrier =
13188bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, nextRc.dstHandle);
13198bf80f4bSopenharmony_ci    if (needsDstBarrier) {
13208bf80f4bSopenharmony_ci        const BindableBuffer bRes = { nextRc.dstHandle, nextRc.bufferCopy.dstOffset, nextRc.bufferCopy.size };
13218bf80f4bSopenharmony_ci        AddCommandBarrierAndUpdateStateCacheBuffer(params.renderNodeIndex,
13228bf80f4bSopenharmony_ci            GpuResourceState { 0, CORE_ACCESS_TRANSFER_WRITE_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
13238bf80f4bSopenharmony_ci            bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
13248bf80f4bSopenharmony_ci    }
13258bf80f4bSopenharmony_ci}
13268bf80f4bSopenharmony_ci
13278bf80f4bSopenharmony_civoid RenderGraph::HandleCopyBufferImage(ParameterCache& params, const uint32_t& commandListCommandIndex,
13288bf80f4bSopenharmony_ci    const array_view<const RenderCommandWithType>& cmdListRef)
13298bf80f4bSopenharmony_ci{
13308bf80f4bSopenharmony_ci    const uint32_t nextListIdx = commandListCommandIndex + 1;
13318bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextListIdx < cmdListRef.size());
13328bf80f4bSopenharmony_ci    const auto& nextCmdRef = cmdListRef[nextListIdx];
13338bf80f4bSopenharmony_ci    PLUGIN_ASSERT((nextCmdRef.type == RenderCommandType::COPY_BUFFER_IMAGE) ||
13348bf80f4bSopenharmony_ci                  (nextCmdRef.type == RenderCommandType::COPY_IMAGE));
13358bf80f4bSopenharmony_ci
13368bf80f4bSopenharmony_ci    // NOTE: two different command types supported
13378bf80f4bSopenharmony_ci    RenderHandle srcHandle;
13388bf80f4bSopenharmony_ci    RenderHandle dstHandle;
13398bf80f4bSopenharmony_ci    ImageSubresourceLayers srcImgLayers;
13408bf80f4bSopenharmony_ci    ImageSubresourceLayers dstImgLayers;
13418bf80f4bSopenharmony_ci    if (nextCmdRef.type == RenderCommandType::COPY_BUFFER_IMAGE) {
13428bf80f4bSopenharmony_ci        const RenderCommandCopyBufferImage& nextRc = *static_cast<RenderCommandCopyBufferImage*>(nextCmdRef.rc);
13438bf80f4bSopenharmony_ci        PLUGIN_ASSERT(nextRc.copyType != RenderCommandCopyBufferImage::CopyType::UNDEFINED);
13448bf80f4bSopenharmony_ci        srcHandle = nextRc.srcHandle;
13458bf80f4bSopenharmony_ci        dstHandle = nextRc.dstHandle;
13468bf80f4bSopenharmony_ci        srcImgLayers = nextRc.bufferImageCopy.imageSubresource;
13478bf80f4bSopenharmony_ci        dstImgLayers = nextRc.bufferImageCopy.imageSubresource;
13488bf80f4bSopenharmony_ci    } else if (nextCmdRef.type == RenderCommandType::COPY_IMAGE) {
13498bf80f4bSopenharmony_ci        const RenderCommandCopyImage& nextRc = *static_cast<RenderCommandCopyImage*>(nextCmdRef.rc);
13508bf80f4bSopenharmony_ci        srcHandle = nextRc.srcHandle;
13518bf80f4bSopenharmony_ci        dstHandle = nextRc.dstHandle;
13528bf80f4bSopenharmony_ci        srcImgLayers = nextRc.imageCopy.srcSubresource;
13538bf80f4bSopenharmony_ci        dstImgLayers = nextRc.imageCopy.dstSubresource;
13548bf80f4bSopenharmony_ci    }
13558bf80f4bSopenharmony_ci
13568bf80f4bSopenharmony_ci    const bool needsSrcBarrier =
13578bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, srcHandle);
13588bf80f4bSopenharmony_ci    if (needsSrcBarrier) {
13598bf80f4bSopenharmony_ci        const RenderHandleType handleType = RenderHandleUtil::GetHandleType(srcHandle);
13608bf80f4bSopenharmony_ci        PLUGIN_UNUSED(handleType);
13618bf80f4bSopenharmony_ci        PLUGIN_ASSERT(handleType == RenderHandleType::GPU_IMAGE || handleType == RenderHandleType::GPU_BUFFER);
13628bf80f4bSopenharmony_ci        if (handleType == RenderHandleType::GPU_BUFFER) {
13638bf80f4bSopenharmony_ci            BindableBuffer bRes;
13648bf80f4bSopenharmony_ci            bRes.handle = srcHandle;
13658bf80f4bSopenharmony_ci            AddCommandBarrierAndUpdateStateCacheBuffer(params.renderNodeIndex,
13668bf80f4bSopenharmony_ci                GpuResourceState {
13678bf80f4bSopenharmony_ci                    0, CORE_ACCESS_TRANSFER_READ_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
13688bf80f4bSopenharmony_ci                bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
13698bf80f4bSopenharmony_ci        } else {
13708bf80f4bSopenharmony_ci            BindableImage bRes;
13718bf80f4bSopenharmony_ci            bRes.handle = srcHandle;
13728bf80f4bSopenharmony_ci            bRes.mip = srcImgLayers.mipLevel;
13738bf80f4bSopenharmony_ci            bRes.layer = srcImgLayers.baseArrayLayer;
13748bf80f4bSopenharmony_ci            bRes.imageLayout = CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
13758bf80f4bSopenharmony_ci            AddCommandBarrierAndUpdateStateCacheImage(params.renderNodeIndex,
13768bf80f4bSopenharmony_ci                GpuResourceState {
13778bf80f4bSopenharmony_ci                    0, CORE_ACCESS_TRANSFER_READ_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
13788bf80f4bSopenharmony_ci                bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
13798bf80f4bSopenharmony_ci        }
13808bf80f4bSopenharmony_ci    }
13818bf80f4bSopenharmony_ci
13828bf80f4bSopenharmony_ci    const bool needsDstBarrier =
13838bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, dstHandle);
13848bf80f4bSopenharmony_ci    if (needsDstBarrier) {
13858bf80f4bSopenharmony_ci        const RenderHandleType handleType = RenderHandleUtil::GetHandleType(dstHandle);
13868bf80f4bSopenharmony_ci        PLUGIN_UNUSED(handleType);
13878bf80f4bSopenharmony_ci        PLUGIN_ASSERT(handleType == RenderHandleType::GPU_IMAGE || handleType == RenderHandleType::GPU_BUFFER);
13888bf80f4bSopenharmony_ci        if (handleType == RenderHandleType::GPU_BUFFER) {
13898bf80f4bSopenharmony_ci            BindableBuffer bRes;
13908bf80f4bSopenharmony_ci            bRes.handle = dstHandle;
13918bf80f4bSopenharmony_ci            AddCommandBarrierAndUpdateStateCacheBuffer(params.renderNodeIndex,
13928bf80f4bSopenharmony_ci                GpuResourceState {
13938bf80f4bSopenharmony_ci                    0, CORE_ACCESS_TRANSFER_WRITE_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
13948bf80f4bSopenharmony_ci                bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
13958bf80f4bSopenharmony_ci        } else {
13968bf80f4bSopenharmony_ci            BindableImage bRes;
13978bf80f4bSopenharmony_ci            bRes.handle = dstHandle;
13988bf80f4bSopenharmony_ci            bRes.mip = dstImgLayers.mipLevel;
13998bf80f4bSopenharmony_ci            bRes.layer = dstImgLayers.baseArrayLayer;
14008bf80f4bSopenharmony_ci            bRes.imageLayout = CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
14018bf80f4bSopenharmony_ci            AddCommandBarrierAndUpdateStateCacheImage(params.renderNodeIndex,
14028bf80f4bSopenharmony_ci                GpuResourceState {
14038bf80f4bSopenharmony_ci                    0, CORE_ACCESS_TRANSFER_WRITE_BIT, CORE_PIPELINE_STAGE_TRANSFER_BIT, params.gpuQueue },
14048bf80f4bSopenharmony_ci                bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
14058bf80f4bSopenharmony_ci        }
14068bf80f4bSopenharmony_ci    }
14078bf80f4bSopenharmony_ci}
14088bf80f4bSopenharmony_ci
14098bf80f4bSopenharmony_civoid RenderGraph::HandleDispatchIndirect(ParameterCache& params, const uint32_t& commandListCommandIndex,
14108bf80f4bSopenharmony_ci    const BASE_NS::array_view<const RenderCommandWithType>& cmdListRef)
14118bf80f4bSopenharmony_ci{
14128bf80f4bSopenharmony_ci    const uint32_t nextListIdx = commandListCommandIndex + 1;
14138bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextListIdx < cmdListRef.size());
14148bf80f4bSopenharmony_ci    const auto& nextCmdRef = cmdListRef[nextListIdx];
14158bf80f4bSopenharmony_ci    PLUGIN_ASSERT(nextCmdRef.type == RenderCommandType::DISPATCH_INDIRECT);
14168bf80f4bSopenharmony_ci
14178bf80f4bSopenharmony_ci    const auto& nextRc = *static_cast<RenderCommandDispatchIndirect*>(nextCmdRef.rc);
14188bf80f4bSopenharmony_ci
14198bf80f4bSopenharmony_ci    const bool needsArgsBarrier =
14208bf80f4bSopenharmony_ci        CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, nextRc.argsHandle);
14218bf80f4bSopenharmony_ci    if (needsArgsBarrier) {
14228bf80f4bSopenharmony_ci        const BindableBuffer bRes = { nextRc.argsHandle, nextRc.offset, PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE };
14238bf80f4bSopenharmony_ci        AddCommandBarrierAndUpdateStateCacheBuffer(params.renderNodeIndex,
14248bf80f4bSopenharmony_ci            GpuResourceState { CORE_SHADER_STAGE_COMPUTE_BIT, CORE_ACCESS_INDIRECT_COMMAND_READ_BIT,
14258bf80f4bSopenharmony_ci                CORE_PIPELINE_STAGE_DRAW_INDIRECT_BIT, params.gpuQueue },
14268bf80f4bSopenharmony_ci            bRes, params.rcWithType, params.combinedBarriers, currNodeGpuResourceTransfers_);
14278bf80f4bSopenharmony_ci    }
14288bf80f4bSopenharmony_ci}
14298bf80f4bSopenharmony_ci
14308bf80f4bSopenharmony_civoid RenderGraph::HandleDescriptorSets(ParameterCache& params,
14318bf80f4bSopenharmony_ci    const array_view<const RenderHandle>& descriptorSetHandlesForBarriers,
14328bf80f4bSopenharmony_ci    const NodeContextDescriptorSetManager& nodeDescriptorSetMgrRef)
14338bf80f4bSopenharmony_ci{
14348bf80f4bSopenharmony_ci    for (const RenderHandle descriptorSetHandle : descriptorSetHandlesForBarriers) {
14358bf80f4bSopenharmony_ci        PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(descriptorSetHandle) == RenderHandleType::DESCRIPTOR_SET);
14368bf80f4bSopenharmony_ci
14378bf80f4bSopenharmony_ci        const auto bindingResources = nodeDescriptorSetMgrRef.GetCpuDescriptorSetData(descriptorSetHandle);
14388bf80f4bSopenharmony_ci        const auto& buffers = bindingResources.buffers;
14398bf80f4bSopenharmony_ci        const auto& images = bindingResources.images;
14408bf80f4bSopenharmony_ci        for (const auto& ref : buffers) {
14418bf80f4bSopenharmony_ci            const uint32_t descriptorCount = ref.binding.descriptorCount;
14428bf80f4bSopenharmony_ci            // skip, array bindings which are bound from first index, they have also descriptorCount 0
14438bf80f4bSopenharmony_ci            if (descriptorCount == 0) {
14448bf80f4bSopenharmony_ci                continue;
14458bf80f4bSopenharmony_ci            }
14468bf80f4bSopenharmony_ci            const uint32_t arrayOffset = ref.arrayOffset;
14478bf80f4bSopenharmony_ci            PLUGIN_ASSERT((arrayOffset + descriptorCount - 1) <= buffers.size());
14488bf80f4bSopenharmony_ci            for (uint32_t idx = 0; idx < descriptorCount; ++idx) {
14498bf80f4bSopenharmony_ci                // first is the ref, starting from 1 we use array offsets
14508bf80f4bSopenharmony_ci                const auto& bRes = (idx == 0) ? ref : buffers[arrayOffset + idx - 1];
14518bf80f4bSopenharmony_ci                if (CheckForBarrierNeed(params.handledCustomBarriers, params.customBarrierCount, ref.resource.handle)) {
14528bf80f4bSopenharmony_ci                    UpdateStateAndCreateBarriersGpuBuffer(bRes.state, bRes.resource, params);
14538bf80f4bSopenharmony_ci                }
14548bf80f4bSopenharmony_ci            }
14558bf80f4bSopenharmony_ci        }
14568bf80f4bSopenharmony_ci        for (const auto& ref : images) {
14578bf80f4bSopenharmony_ci            const uint32_t descriptorCount = ref.binding.descriptorCount;
14588bf80f4bSopenharmony_ci            // skip, array bindings which are bound from first index, they have also descriptorCount 0
14598bf80f4bSopenharmony_ci            if (descriptorCount == 0) {
14608bf80f4bSopenharmony_ci                continue;
14618bf80f4bSopenharmony_ci            }
14628bf80f4bSopenharmony_ci            const uint32_t arrayOffset = ref.arrayOffset;
14638bf80f4bSopenharmony_ci            PLUGIN_ASSERT((arrayOffset + descriptorCount - 1) <= images.size());
14648bf80f4bSopenharmony_ci            for (uint32_t idx = 0; idx < descriptorCount; ++idx) {
14658bf80f4bSopenharmony_ci                // first is the ref, starting from 1 we use array offsets
14668bf80f4bSopenharmony_ci                const auto& bRes = (idx == 0) ? ref : images[arrayOffset + idx - 1];
14678bf80f4bSopenharmony_ci                if (CheckForBarrierNeed(
14688bf80f4bSopenharmony_ci                    params.handledCustomBarriers, params.customBarrierCount, bRes.resource.handle)) {
14698bf80f4bSopenharmony_ci                    UpdateStateAndCreateBarriersGpuImage(bRes.state, bRes.resource, params);
14708bf80f4bSopenharmony_ci                }
14718bf80f4bSopenharmony_ci            }
14728bf80f4bSopenharmony_ci        }
14738bf80f4bSopenharmony_ci    } // end for
14748bf80f4bSopenharmony_ci}
14758bf80f4bSopenharmony_ci
14768bf80f4bSopenharmony_civoid RenderGraph::UpdateStateAndCreateBarriersGpuImage(
14778bf80f4bSopenharmony_ci    const GpuResourceState& state, const BindableImage& res, RenderGraph::ParameterCache& params)
14788bf80f4bSopenharmony_ci{
14798bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(res.handle);
14808bf80f4bSopenharmony_ci    if (arrayIndex >= static_cast<uint32_t>(gpuImageDataIndices_.size())) {
14818bf80f4bSopenharmony_ci        return;
14828bf80f4bSopenharmony_ci    }
14838bf80f4bSopenharmony_ci
14848bf80f4bSopenharmony_ci    auto& ref = GetImageResourceStateRef(res.handle, state.gpuQueue);
14858bf80f4bSopenharmony_ci    // NOTE: we previous patched the final render pass layouts here
14868bf80f4bSopenharmony_ci    // ATM: we only path the swapchain image if needed
14878bf80f4bSopenharmony_ci
14888bf80f4bSopenharmony_ci    const GpuResourceState& prevState = ref.state;
14898bf80f4bSopenharmony_ci    const BindableImage& prevImage = ref.resource;
14908bf80f4bSopenharmony_ci    const bool addMips = RenderHandleUtil::IsDynamicAdditionalStateResource(res.handle);
14918bf80f4bSopenharmony_ci    const ResourceBarrier prevStateRb = addMips ? GetSrcImageBarrierMips(prevState, prevImage, res, ref.additionalState)
14928bf80f4bSopenharmony_ci                                                : GetSrcImageBarrier(prevState, prevImage);
14938bf80f4bSopenharmony_ci
14948bf80f4bSopenharmony_ci    const bool layoutChanged = (prevStateRb.optionalImageLayout != res.imageLayout);
14958bf80f4bSopenharmony_ci    const bool accessFlagsChanged = (prevStateRb.accessFlags != state.accessFlags);
14968bf80f4bSopenharmony_ci    const bool writeTarget = (prevStateRb.accessFlags & WRITE_ACCESS_FLAGS);
14978bf80f4bSopenharmony_ci    const bool inputAttachment = (state.accessFlags == CORE_ACCESS_INPUT_ATTACHMENT_READ_BIT);
14988bf80f4bSopenharmony_ci    // input attachments are handled with render passes and not with barriers
14998bf80f4bSopenharmony_ci    if ((layoutChanged || accessFlagsChanged || writeTarget) && (!inputAttachment)) {
15008bf80f4bSopenharmony_ci        if ((prevState.gpuQueue.type != GpuQueue::QueueType::UNDEFINED) &&
15018bf80f4bSopenharmony_ci            (prevState.gpuQueue.type != state.gpuQueue.type)) {
15028bf80f4bSopenharmony_ci            PLUGIN_ASSERT(state.gpuQueue.type != GpuQueue::QueueType::UNDEFINED);
15038bf80f4bSopenharmony_ci
15048bf80f4bSopenharmony_ci            PLUGIN_ASSERT(ref.prevRenderNodeIndex != params.renderNodeIndex);
15058bf80f4bSopenharmony_ci            currNodeGpuResourceTransfers_.push_back(RenderGraph::GpuQueueTransferState {
15068bf80f4bSopenharmony_ci                res.handle, ref.prevRenderNodeIndex, params.renderNodeIndex, prevImage.imageLayout, res.imageLayout });
15078bf80f4bSopenharmony_ci        } else {
15088bf80f4bSopenharmony_ci            const ResourceBarrier dstImageBarrier =
15098bf80f4bSopenharmony_ci                addMips ? GetDstImageBarrierMips(state, prevImage, res, ref.additionalState)
15108bf80f4bSopenharmony_ci                        : GetDstImageBarrier(state, res);
15118bf80f4bSopenharmony_ci            params.combinedBarriers.push_back(
15128bf80f4bSopenharmony_ci                CommandBarrier { res.handle, prevStateRb, prevState.gpuQueue, dstImageBarrier, params.gpuQueue });
15138bf80f4bSopenharmony_ci        }
15148bf80f4bSopenharmony_ci
15158bf80f4bSopenharmony_ci        ref.state = state;
15168bf80f4bSopenharmony_ci        ref.resource = res;
15178bf80f4bSopenharmony_ci        ref.prevRc = params.rcWithType;
15188bf80f4bSopenharmony_ci        ref.prevRenderNodeIndex = params.renderNodeIndex;
15198bf80f4bSopenharmony_ci        if (addMips) {
15208bf80f4bSopenharmony_ci            ModifyAdditionalImageState(res, ref.additionalState);
15218bf80f4bSopenharmony_ci        }
15228bf80f4bSopenharmony_ci    }
15238bf80f4bSopenharmony_ci}
15248bf80f4bSopenharmony_ci
15258bf80f4bSopenharmony_civoid RenderGraph::UpdateStateAndCreateBarriersGpuBuffer(
15268bf80f4bSopenharmony_ci    const GpuResourceState& dstState, const BindableBuffer& res, RenderGraph::ParameterCache& params)
15278bf80f4bSopenharmony_ci{
15288bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(res.handle);
15298bf80f4bSopenharmony_ci    if (arrayIndex >= static_cast<uint32_t>(gpuBufferDataIndices_.size())) {
15308bf80f4bSopenharmony_ci        return;
15318bf80f4bSopenharmony_ci    }
15328bf80f4bSopenharmony_ci
15338bf80f4bSopenharmony_ci    // get the current state of the buffer
15348bf80f4bSopenharmony_ci    auto& srcStateRef = GetBufferResourceStateRef(res.handle, dstState.gpuQueue);
15358bf80f4bSopenharmony_ci    const ResourceBarrier prevStateRb = GetSrcBufferBarrier(srcStateRef.state, res);
15368bf80f4bSopenharmony_ci    if ((prevStateRb.accessFlags != dstState.accessFlags) || (prevStateRb.accessFlags & WRITE_ACCESS_FLAGS)) {
15378bf80f4bSopenharmony_ci        params.combinedBarriers.push_back(CommandBarrier {
15388bf80f4bSopenharmony_ci            res.handle, prevStateRb, dstState.gpuQueue, GetDstBufferBarrier(dstState, res), params.gpuQueue });
15398bf80f4bSopenharmony_ci    }
15408bf80f4bSopenharmony_ci
15418bf80f4bSopenharmony_ci    // update the cached state to match the situation after the barrier
15428bf80f4bSopenharmony_ci    srcStateRef.state = dstState;
15438bf80f4bSopenharmony_ci    srcStateRef.resource = res;
15448bf80f4bSopenharmony_ci    srcStateRef.prevRc = params.rcWithType;
15458bf80f4bSopenharmony_ci    srcStateRef.prevRenderNodeIndex = params.renderNodeIndex;
15468bf80f4bSopenharmony_ci}
15478bf80f4bSopenharmony_ci
15488bf80f4bSopenharmony_civoid RenderGraph::AddCommandBarrierAndUpdateStateCacheBuffer(const uint32_t renderNodeIndex,
15498bf80f4bSopenharmony_ci    const GpuResourceState& newGpuResourceState, const BindableBuffer& newBuffer,
15508bf80f4bSopenharmony_ci    const RenderCommandWithType& rcWithType, vector<CommandBarrier>& barriers,
15518bf80f4bSopenharmony_ci    vector<RenderGraph::GpuQueueTransferState>& currNodeGpuResourceTransfer)
15528bf80f4bSopenharmony_ci{
15538bf80f4bSopenharmony_ci    auto& stateRef = GetBufferResourceStateRef(newBuffer.handle, newGpuResourceState.gpuQueue);
15548bf80f4bSopenharmony_ci    const GpuResourceState srcState = stateRef.state;
15558bf80f4bSopenharmony_ci    const BindableBuffer srcBuffer = stateRef.resource;
15568bf80f4bSopenharmony_ci
15578bf80f4bSopenharmony_ci    if ((srcState.gpuQueue.type != GpuQueue::QueueType::UNDEFINED) &&
15588bf80f4bSopenharmony_ci        (srcState.gpuQueue.type != newGpuResourceState.gpuQueue.type)) {
15598bf80f4bSopenharmony_ci        PLUGIN_ASSERT(newGpuResourceState.gpuQueue.type != GpuQueue::QueueType::UNDEFINED);
15608bf80f4bSopenharmony_ci        PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(newBuffer.handle) == RenderHandleType::GPU_IMAGE);
15618bf80f4bSopenharmony_ci        PLUGIN_ASSERT(stateRef.prevRenderNodeIndex != renderNodeIndex);
15628bf80f4bSopenharmony_ci        currNodeGpuResourceTransfer.push_back(
15638bf80f4bSopenharmony_ci            RenderGraph::GpuQueueTransferState { newBuffer.handle, stateRef.prevRenderNodeIndex, renderNodeIndex,
15648bf80f4bSopenharmony_ci                ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED, ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED });
15658bf80f4bSopenharmony_ci    } else {
15668bf80f4bSopenharmony_ci        const ResourceBarrier srcBarrier = GetSrcBufferBarrier(srcState, srcBuffer);
15678bf80f4bSopenharmony_ci        const ResourceBarrier dstBarrier = GetDstBufferBarrier(newGpuResourceState, newBuffer);
15688bf80f4bSopenharmony_ci
15698bf80f4bSopenharmony_ci        barriers.push_back(CommandBarrier {
15708bf80f4bSopenharmony_ci            newBuffer.handle, srcBarrier, srcState.gpuQueue, dstBarrier, newGpuResourceState.gpuQueue });
15718bf80f4bSopenharmony_ci    }
15728bf80f4bSopenharmony_ci
15738bf80f4bSopenharmony_ci    stateRef.state = newGpuResourceState;
15748bf80f4bSopenharmony_ci    stateRef.resource = newBuffer;
15758bf80f4bSopenharmony_ci    stateRef.prevRc = rcWithType;
15768bf80f4bSopenharmony_ci    stateRef.prevRenderNodeIndex = renderNodeIndex;
15778bf80f4bSopenharmony_ci}
15788bf80f4bSopenharmony_ci
15798bf80f4bSopenharmony_civoid RenderGraph::AddCommandBarrierAndUpdateStateCacheImage(const uint32_t renderNodeIndex,
15808bf80f4bSopenharmony_ci    const GpuResourceState& newGpuResourceState, const BindableImage& newImage, const RenderCommandWithType& rcWithType,
15818bf80f4bSopenharmony_ci    vector<CommandBarrier>& barriers, vector<RenderGraph::GpuQueueTransferState>& currNodeGpuResourceTransfer)
15828bf80f4bSopenharmony_ci{
15838bf80f4bSopenharmony_ci    // newGpuResourceState has queue transfer image layout in old optionalImageLayout
15848bf80f4bSopenharmony_ci
15858bf80f4bSopenharmony_ci    auto& stateRef = GetImageResourceStateRef(newImage.handle, newGpuResourceState.gpuQueue);
15868bf80f4bSopenharmony_ci    const GpuResourceState srcState = stateRef.state;
15878bf80f4bSopenharmony_ci    const BindableImage srcImage = stateRef.resource;
15888bf80f4bSopenharmony_ci    const bool addMips = RenderHandleUtil::IsDynamicAdditionalStateResource(newImage.handle);
15898bf80f4bSopenharmony_ci
15908bf80f4bSopenharmony_ci    if ((srcState.gpuQueue.type != GpuQueue::QueueType::UNDEFINED) &&
15918bf80f4bSopenharmony_ci        (srcState.gpuQueue.type != newGpuResourceState.gpuQueue.type)) {
15928bf80f4bSopenharmony_ci        PLUGIN_ASSERT(newGpuResourceState.gpuQueue.type != GpuQueue::QueueType::UNDEFINED);
15938bf80f4bSopenharmony_ci        PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(newImage.handle) == RenderHandleType::GPU_IMAGE);
15948bf80f4bSopenharmony_ci        PLUGIN_ASSERT(stateRef.prevRenderNodeIndex != renderNodeIndex);
15958bf80f4bSopenharmony_ci        currNodeGpuResourceTransfer.push_back(RenderGraph::GpuQueueTransferState { newImage.handle,
15968bf80f4bSopenharmony_ci            stateRef.prevRenderNodeIndex, renderNodeIndex, srcImage.imageLayout, newImage.imageLayout });
15978bf80f4bSopenharmony_ci    } else {
15988bf80f4bSopenharmony_ci        const ResourceBarrier srcBarrier =
15998bf80f4bSopenharmony_ci            addMips ? GetSrcImageBarrierMips(srcState, srcImage, newImage, stateRef.additionalState)
16008bf80f4bSopenharmony_ci                    : GetSrcImageBarrier(srcState, srcImage);
16018bf80f4bSopenharmony_ci        const ResourceBarrier dstBarrier =
16028bf80f4bSopenharmony_ci            addMips ? GetDstImageBarrierMips(newGpuResourceState, srcImage, newImage, stateRef.additionalState)
16038bf80f4bSopenharmony_ci                    : GetDstImageBarrier(newGpuResourceState, newImage);
16048bf80f4bSopenharmony_ci
16058bf80f4bSopenharmony_ci        barriers.push_back(CommandBarrier {
16068bf80f4bSopenharmony_ci            newImage.handle, srcBarrier, srcState.gpuQueue, dstBarrier, newGpuResourceState.gpuQueue });
16078bf80f4bSopenharmony_ci    }
16088bf80f4bSopenharmony_ci
16098bf80f4bSopenharmony_ci    stateRef.state = newGpuResourceState;
16108bf80f4bSopenharmony_ci    stateRef.resource = newImage;
16118bf80f4bSopenharmony_ci    stateRef.prevRc = rcWithType;
16128bf80f4bSopenharmony_ci    stateRef.prevRenderNodeIndex = renderNodeIndex;
16138bf80f4bSopenharmony_ci    if (addMips) {
16148bf80f4bSopenharmony_ci        ModifyAdditionalImageState(newImage, stateRef.additionalState);
16158bf80f4bSopenharmony_ci    }
16168bf80f4bSopenharmony_ci}
16178bf80f4bSopenharmony_ci
16188bf80f4bSopenharmony_ciRenderGraph::RenderGraphBufferState& RenderGraph::GetBufferResourceStateRef(
16198bf80f4bSopenharmony_ci    const RenderHandle handle, const GpuQueue& queue)
16208bf80f4bSopenharmony_ci{
16218bf80f4bSopenharmony_ci    // NOTE: Do not call with non dynamic trackable
16228bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
16238bf80f4bSopenharmony_ci    PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(handle) == RenderHandleType::GPU_BUFFER);
16248bf80f4bSopenharmony_ci    if (arrayIndex < gpuBufferDataIndices_.size()) {
16258bf80f4bSopenharmony_ci        PLUGIN_ASSERT(RenderHandleUtil::IsDynamicResource(handle));
16268bf80f4bSopenharmony_ci        uint32_t dataIdx = gpuBufferDataIndices_[arrayIndex];
16278bf80f4bSopenharmony_ci        if (dataIdx == INVALID_TRACK_IDX) {
16288bf80f4bSopenharmony_ci            if (!gpuBufferAvailableIndices_.empty()) {
16298bf80f4bSopenharmony_ci                dataIdx = gpuBufferAvailableIndices_.back();
16308bf80f4bSopenharmony_ci                gpuBufferAvailableIndices_.pop_back();
16318bf80f4bSopenharmony_ci            } else {
16328bf80f4bSopenharmony_ci                dataIdx = static_cast<uint32_t>(gpuBufferTracking_.size());
16338bf80f4bSopenharmony_ci                gpuBufferTracking_.emplace_back();
16348bf80f4bSopenharmony_ci            }
16358bf80f4bSopenharmony_ci            gpuBufferDataIndices_[arrayIndex] = dataIdx;
16368bf80f4bSopenharmony_ci
16378bf80f4bSopenharmony_ci            gpuBufferTracking_[dataIdx].resource.handle = handle;
16388bf80f4bSopenharmony_ci            gpuBufferTracking_[dataIdx].state.gpuQueue = queue; // current queue for default state
16398bf80f4bSopenharmony_ci        }
16408bf80f4bSopenharmony_ci        return gpuBufferTracking_[dataIdx];
16418bf80f4bSopenharmony_ci    }
16428bf80f4bSopenharmony_ci
16438bf80f4bSopenharmony_ci    return defaultBufferState_;
16448bf80f4bSopenharmony_ci}
16458bf80f4bSopenharmony_ci
16468bf80f4bSopenharmony_ciRenderGraph::RenderGraphImageState& RenderGraph::GetImageResourceStateRef(
16478bf80f4bSopenharmony_ci    const RenderHandle handle, const GpuQueue& queue)
16488bf80f4bSopenharmony_ci{
16498bf80f4bSopenharmony_ci    // NOTE: Do not call with non dynamic trackable
16508bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
16518bf80f4bSopenharmony_ci    PLUGIN_ASSERT(RenderHandleUtil::GetHandleType(handle) == RenderHandleType::GPU_IMAGE);
16528bf80f4bSopenharmony_ci    if (arrayIndex < gpuImageDataIndices_.size()) {
16538bf80f4bSopenharmony_ci        // NOTE: render pass attachments expected to be dynamic resources always
16548bf80f4bSopenharmony_ci        PLUGIN_ASSERT(RenderHandleUtil::IsDynamicResource(handle));
16558bf80f4bSopenharmony_ci        uint32_t dataIdx = gpuImageDataIndices_[arrayIndex];
16568bf80f4bSopenharmony_ci        if (dataIdx == INVALID_TRACK_IDX) {
16578bf80f4bSopenharmony_ci            if (!gpuImageAvailableIndices_.empty()) {
16588bf80f4bSopenharmony_ci                dataIdx = gpuImageAvailableIndices_.back();
16598bf80f4bSopenharmony_ci                gpuImageAvailableIndices_.pop_back();
16608bf80f4bSopenharmony_ci            } else {
16618bf80f4bSopenharmony_ci                dataIdx = static_cast<uint32_t>(gpuImageTracking_.size());
16628bf80f4bSopenharmony_ci                gpuImageTracking_.emplace_back();
16638bf80f4bSopenharmony_ci            }
16648bf80f4bSopenharmony_ci            gpuImageDataIndices_[arrayIndex] = dataIdx;
16658bf80f4bSopenharmony_ci
16668bf80f4bSopenharmony_ci            gpuImageTracking_[dataIdx].resource.handle = handle;
16678bf80f4bSopenharmony_ci            gpuImageTracking_[dataIdx].state.gpuQueue = queue; // current queue for default state
16688bf80f4bSopenharmony_ci            if (RenderHandleUtil::IsDynamicAdditionalStateResource(handle) &&
16698bf80f4bSopenharmony_ci                (!gpuImageTracking_[dataIdx].additionalState.layouts)) {
16708bf80f4bSopenharmony_ci                gpuImageTracking_[dataIdx].additionalState.layouts = make_unique<ImageLayout[]>(MAX_MIP_STATE_COUNT);
16718bf80f4bSopenharmony_ci            }
16728bf80f4bSopenharmony_ci        }
16738bf80f4bSopenharmony_ci        return gpuImageTracking_[dataIdx];
16748bf80f4bSopenharmony_ci    }
16758bf80f4bSopenharmony_ci
16768bf80f4bSopenharmony_ci    return defaultImageState_;
16778bf80f4bSopenharmony_ci}
16788bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
1679