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 "renderer.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <algorithm> 198bf80f4bSopenharmony_ci#include <chrono> 208bf80f4bSopenharmony_ci#include <cinttypes> 218bf80f4bSopenharmony_ci#include <utility> 228bf80f4bSopenharmony_ci 238bf80f4bSopenharmony_ci#include <base/containers/string.h> 248bf80f4bSopenharmony_ci#include <base/containers/string_view.h> 258bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 268bf80f4bSopenharmony_ci#include <base/containers/vector.h> 278bf80f4bSopenharmony_ci#include <core/perf/intf_performance_data_manager.h> 288bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_default_staging.h> 298bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_manager.h> 308bf80f4bSopenharmony_ci#include <render/datastore/render_data_store_render_pods.h> 318bf80f4bSopenharmony_ci#include <render/intf_render_context.h> 328bf80f4bSopenharmony_ci#include <render/intf_renderer.h> 338bf80f4bSopenharmony_ci#include <render/namespace.h> 348bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_node.h> 358bf80f4bSopenharmony_ci#include <render/render_data_structures.h> 368bf80f4bSopenharmony_ci 378bf80f4bSopenharmony_ci#include "perf/cpu_perf_scope.h" 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1) 408bf80f4bSopenharmony_ci#include <cinttypes> 418bf80f4bSopenharmony_ci#endif 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_ci#include "datastore/render_data_store_manager.h" 448bf80f4bSopenharmony_ci#include "datastore/render_data_store_pod.h" 458bf80f4bSopenharmony_ci#include "default_engine_constants.h" 468bf80f4bSopenharmony_ci#include "device/device.h" 478bf80f4bSopenharmony_ci#include "device/gpu_resource_cache.h" 488bf80f4bSopenharmony_ci#include "device/gpu_resource_manager.h" 498bf80f4bSopenharmony_ci#include "device/gpu_resource_util.h" 508bf80f4bSopenharmony_ci#include "device/render_frame_sync.h" 518bf80f4bSopenharmony_ci#include "device/shader_manager.h" 528bf80f4bSopenharmony_ci#include "nodecontext/node_context_descriptor_set_manager.h" 538bf80f4bSopenharmony_ci#include "nodecontext/node_context_pso_manager.h" 548bf80f4bSopenharmony_ci#include "nodecontext/render_node_context_manager.h" 558bf80f4bSopenharmony_ci#include "nodecontext/render_node_graph_manager.h" 568bf80f4bSopenharmony_ci#include "nodecontext/render_node_graph_node_store.h" 578bf80f4bSopenharmony_ci#include "perf/cpu_timer.h" 588bf80f4bSopenharmony_ci#include "render_backend.h" 598bf80f4bSopenharmony_ci#include "render_context.h" 608bf80f4bSopenharmony_ci#include "render_graph.h" 618bf80f4bSopenharmony_ci#include "util/log.h" 628bf80f4bSopenharmony_ci#include "util/render_util.h" 638bf80f4bSopenharmony_ci 648bf80f4bSopenharmony_ciusing namespace BASE_NS; 658bf80f4bSopenharmony_ciusing namespace CORE_NS; 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE() 688bf80f4bSopenharmony_cinamespace { 698bf80f4bSopenharmony_ciconst string_view RENDER_DATA_STORE_DEFAULT_STAGING { "RenderDataStoreDefaultStaging" }; 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_ci// Helper class for running lambda as a ThreadPool task. 728bf80f4bSopenharmony_citemplate<typename Fn> 738bf80f4bSopenharmony_ciclass FunctionTask final : public IThreadPool::ITask { 748bf80f4bSopenharmony_cipublic: 758bf80f4bSopenharmony_ci explicit FunctionTask(Fn&& func) : func_(BASE_NS::move(func)) {}; 768bf80f4bSopenharmony_ci 778bf80f4bSopenharmony_ci void operator()() override 788bf80f4bSopenharmony_ci { 798bf80f4bSopenharmony_ci func_(); 808bf80f4bSopenharmony_ci } 818bf80f4bSopenharmony_ci 828bf80f4bSopenharmony_ciprotected: 838bf80f4bSopenharmony_ci void Destroy() override 848bf80f4bSopenharmony_ci { 858bf80f4bSopenharmony_ci delete this; 868bf80f4bSopenharmony_ci } 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_ciprivate: 898bf80f4bSopenharmony_ci Fn func_; 908bf80f4bSopenharmony_ci}; 918bf80f4bSopenharmony_ci 928bf80f4bSopenharmony_citemplate<typename Fn> 938bf80f4bSopenharmony_ciinline IThreadPool::ITask::Ptr CreateFunctionTask(Fn&& func) 948bf80f4bSopenharmony_ci{ 958bf80f4bSopenharmony_ci return IThreadPool::ITask::Ptr { new FunctionTask<Fn>(BASE_NS::move(func)) }; 968bf80f4bSopenharmony_ci} 978bf80f4bSopenharmony_ci 988bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 998bf80f4bSopenharmony_cistruct NodeTimerData { 1008bf80f4bSopenharmony_ci CpuTimer timer; 1018bf80f4bSopenharmony_ci string_view debugName; 1028bf80f4bSopenharmony_ci}; 1038bf80f4bSopenharmony_ci#endif 1048bf80f4bSopenharmony_ci 1058bf80f4bSopenharmony_cistruct RenderNodeExecutionParameters { 1068bf80f4bSopenharmony_ci const array_view<RenderNodeGraphNodeStore*> renderNodeGraphNodeStores; 1078bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 1088bf80f4bSopenharmony_ci vector<NodeTimerData>& nodeTimers; 1098bf80f4bSopenharmony_ci#endif 1108bf80f4bSopenharmony_ci ITaskQueue* queue; 1118bf80f4bSopenharmony_ci IRenderDataStoreManager& renderData; 1128bf80f4bSopenharmony_ci ShaderManager& shaderManager; 1138bf80f4bSopenharmony_ci RenderingConfiguration& renderConfig; 1148bf80f4bSopenharmony_ci}; 1158bf80f4bSopenharmony_ci 1168bf80f4bSopenharmony_ci// Helper for Renderer::InitNodeGraph 1178bf80f4bSopenharmony_ciunordered_map<string, uint32_t> InitializeRenderNodeContextData(IRenderContext& renderContext, 1188bf80f4bSopenharmony_ci RenderNodeGraphNodeStore& nodeStore, const bool enableMultiQueue, const RenderingConfiguration& renderConfig) 1198bf80f4bSopenharmony_ci{ 1208bf80f4bSopenharmony_ci unordered_map<string, uint32_t> renderNodeNameToIndex(nodeStore.renderNodeData.size()); 1218bf80f4bSopenharmony_ci vector<ContextInitDescription> contextInitDescs(nodeStore.renderNodeData.size()); 1228bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeStore.renderNodeData.size(); ++nodeIdx) { 1238bf80f4bSopenharmony_ci const auto& renderNodeData = nodeStore.renderNodeData[nodeIdx]; 1248bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeData.inputData); 1258bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeData.node); 1268bf80f4bSopenharmony_ci auto& inputData = *(renderNodeData.inputData); 1278bf80f4bSopenharmony_ci auto& nodeContextData = nodeStore.renderNodeContextData[nodeIdx]; 1288bf80f4bSopenharmony_ci 1298bf80f4bSopenharmony_ci renderNodeNameToIndex[renderNodeData.fullName] = (uint32_t)nodeIdx; 1308bf80f4bSopenharmony_ci 1318bf80f4bSopenharmony_ci // reset always, dependencies are redone with new nodes 1328bf80f4bSopenharmony_ci nodeContextData.submitInfo.signalSemaphore = false; 1338bf80f4bSopenharmony_ci nodeContextData.submitInfo.waitSemaphoreCount = 0; 1348bf80f4bSopenharmony_ci nodeContextData.submitInfo.waitForSwapchainAcquireSignal = false; 1358bf80f4bSopenharmony_ci 1368bf80f4bSopenharmony_ci // with dynamic render node graphs, single nodes can be initialized 1378bf80f4bSopenharmony_ci // set to true when doing the renderNode->InitNode(); 1388bf80f4bSopenharmony_ci if (nodeContextData.initialized) { 1398bf80f4bSopenharmony_ci continue; 1408bf80f4bSopenharmony_ci } 1418bf80f4bSopenharmony_ci 1428bf80f4bSopenharmony_ci auto& contextInitRef = contextInitDescs[nodeIdx]; 1438bf80f4bSopenharmony_ci contextInitRef.requestedQueue = inputData.queue; 1448bf80f4bSopenharmony_ci 1458bf80f4bSopenharmony_ci Device& device = (Device&)renderContext.GetDevice(); 1468bf80f4bSopenharmony_ci contextInitRef.requestedQueue = device.GetValidGpuQueue(contextInitRef.requestedQueue); 1478bf80f4bSopenharmony_ci 1488bf80f4bSopenharmony_ci ShaderManager& shaderMgr = (ShaderManager&)renderContext.GetDevice().GetShaderManager(); 1498bf80f4bSopenharmony_ci GpuResourceManager& gpuResourceMgr = (GpuResourceManager&)renderContext.GetDevice().GetGpuResourceManager(); 1508bf80f4bSopenharmony_ci // ordering is important 1518bf80f4bSopenharmony_ci nodeContextData.nodeContextPsoMgr = make_unique<NodeContextPsoManager>(device, shaderMgr); 1528bf80f4bSopenharmony_ci nodeContextData.nodeContextDescriptorSetMgr = device.CreateNodeContextDescriptorSetManager(); 1538bf80f4bSopenharmony_ci nodeContextData.renderCommandList = 1548bf80f4bSopenharmony_ci make_unique<RenderCommandList>(renderNodeData.fullName, *nodeContextData.nodeContextDescriptorSetMgr, 1558bf80f4bSopenharmony_ci gpuResourceMgr, *nodeContextData.nodeContextPsoMgr, contextInitRef.requestedQueue, enableMultiQueue); 1568bf80f4bSopenharmony_ci nodeContextData.nodeContextPoolMgr = 1578bf80f4bSopenharmony_ci device.CreateNodeContextPoolManager(gpuResourceMgr, contextInitRef.requestedQueue); 1588bf80f4bSopenharmony_ci RenderNodeGraphData rngd = { nodeStore.renderNodeGraphName, nodeStore.renderNodeGraphDataStoreName, 1598bf80f4bSopenharmony_ci renderConfig }; 1608bf80f4bSopenharmony_ci RenderNodeContextManager::CreateInfo rncmci { renderContext, rngd, *renderNodeData.inputData, 1618bf80f4bSopenharmony_ci renderNodeData.nodeName, renderNodeData.nodeJson, *nodeContextData.nodeContextDescriptorSetMgr, 1628bf80f4bSopenharmony_ci *nodeContextData.nodeContextPsoMgr, *nodeContextData.renderCommandList, 1638bf80f4bSopenharmony_ci *nodeStore.renderNodeGraphShareDataMgr }; 1648bf80f4bSopenharmony_ci nodeContextData.renderNodeContextManager = make_unique<RenderNodeContextManager>(rncmci); 1658bf80f4bSopenharmony_ci#if ((RENDER_VALIDATION_ENABLED == 1) || (RENDER_VULKAN_VALIDATION_ENABLED == 1)) 1668bf80f4bSopenharmony_ci nodeContextData.nodeContextDescriptorSetMgr->SetValidationDebugName(renderNodeData.fullName); 1678bf80f4bSopenharmony_ci nodeContextData.nodeContextPoolMgr->SetValidationDebugName(renderNodeData.fullName); 1688bf80f4bSopenharmony_ci#endif 1698bf80f4bSopenharmony_ci nodeContextData.renderBarrierList = make_unique<RenderBarrierList>( 1708bf80f4bSopenharmony_ci (contextInitRef.requestedQueue.type != GpuQueue::QueueType::UNDEFINED) ? 4u : 0u); 1718bf80f4bSopenharmony_ci } 1728bf80f4bSopenharmony_ci return renderNodeNameToIndex; 1738bf80f4bSopenharmony_ci} 1748bf80f4bSopenharmony_ci 1758bf80f4bSopenharmony_ci// Helper for Renderer::InitNodeGraph 1768bf80f4bSopenharmony_civoid PatchSignaling(RenderNodeGraphNodeStore& nodeStore, const unordered_map<string, uint32_t>& renderNodeNameToIndex) 1778bf80f4bSopenharmony_ci{ 1788bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeNameToIndex.size() == nodeStore.renderNodeData.size()); 1798bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeStore.renderNodeData.size(); ++nodeIdx) { 1808bf80f4bSopenharmony_ci PLUGIN_ASSERT(nodeStore.renderNodeData[nodeIdx].inputData); 1818bf80f4bSopenharmony_ci const auto& nodeInputDataRef = *(nodeStore.renderNodeData[nodeIdx].inputData); 1828bf80f4bSopenharmony_ci auto& submitInfo = nodeStore.renderNodeContextData[nodeIdx].submitInfo; 1838bf80f4bSopenharmony_ci 1848bf80f4bSopenharmony_ci for (const auto& nodeNameRef : nodeInputDataRef.gpuQueueWaitForSignals.nodeNames) { 1858bf80f4bSopenharmony_ci if (const auto iter = renderNodeNameToIndex.find(nodeNameRef); iter != renderNodeNameToIndex.cend()) { 1868bf80f4bSopenharmony_ci if (submitInfo.waitSemaphoreCount < PipelineStateConstants::MAX_RENDER_NODE_GPU_WAIT_SIGNALS) { 1878bf80f4bSopenharmony_ci const uint32_t index = iter->second; 1888bf80f4bSopenharmony_ci // mark node to signal 1898bf80f4bSopenharmony_ci nodeStore.renderNodeContextData[index].submitInfo.signalSemaphore = true; 1908bf80f4bSopenharmony_ci 1918bf80f4bSopenharmony_ci submitInfo.waitSemaphoreNodeIndices[submitInfo.waitSemaphoreCount] = index; 1928bf80f4bSopenharmony_ci submitInfo.waitSemaphoreCount++; 1938bf80f4bSopenharmony_ci } else { 1948bf80f4bSopenharmony_ci PLUGIN_LOG_E("render node can wait only for (%u) render node signals", 1958bf80f4bSopenharmony_ci PipelineStateConstants::MAX_RENDER_NODE_GPU_WAIT_SIGNALS); 1968bf80f4bSopenharmony_ci PLUGIN_ASSERT(false); 1978bf80f4bSopenharmony_ci } 1988bf80f4bSopenharmony_ci } else { 1998bf80f4bSopenharmony_ci PLUGIN_LOG_E("invalid render node wait signal dependency"); 2008bf80f4bSopenharmony_ci PLUGIN_ASSERT(false); 2018bf80f4bSopenharmony_ci } 2028bf80f4bSopenharmony_ci } 2038bf80f4bSopenharmony_ci } 2048bf80f4bSopenharmony_ci} 2058bf80f4bSopenharmony_ci 2068bf80f4bSopenharmony_ci// Helper for Renderer::RenderFrame 2078bf80f4bSopenharmony_civoid BeginRenderNodeGraph(RenderNodeGraphGlobalShareDataManager* rngGlobalShareDataMgr, 2088bf80f4bSopenharmony_ci const vector<RenderNodeGraphNodeStore*>& renderNodeGraphNodeStores, 2098bf80f4bSopenharmony_ci const RenderNodeContextManager::PerFrameTimings& timings) 2108bf80f4bSopenharmony_ci{ 2118bf80f4bSopenharmony_ci RenderNodeGraphShareDataManager* prevRngShareDataMgr = nullptr; 2128bf80f4bSopenharmony_ci if (rngGlobalShareDataMgr) { 2138bf80f4bSopenharmony_ci rngGlobalShareDataMgr->BeginFrame(); 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci for (const RenderNodeGraphNodeStore* renderNodeDataStore : renderNodeGraphNodeStores) { 2168bf80f4bSopenharmony_ci const uint32_t renderNodeCount = static_cast<uint32_t>(renderNodeDataStore->renderNodeContextData.size()); 2178bf80f4bSopenharmony_ci auto& rngShareData = renderNodeDataStore->renderNodeGraphShareData; 2188bf80f4bSopenharmony_ci renderNodeDataStore->renderNodeGraphShareDataMgr->BeginFrame(rngGlobalShareDataMgr, prevRngShareDataMgr, 2198bf80f4bSopenharmony_ci renderNodeCount, { rngShareData.inputs, rngShareData.inputCount }, 2208bf80f4bSopenharmony_ci { rngShareData.outputs, rngShareData.outputCount }); 2218bf80f4bSopenharmony_ci for (uint32_t idx = 0; idx < renderNodeCount; ++idx) { 2228bf80f4bSopenharmony_ci const RenderNodeContextData& contextData = renderNodeDataStore->renderNodeContextData[idx]; 2238bf80f4bSopenharmony_ci contextData.renderCommandList->BeginFrame(); 2248bf80f4bSopenharmony_ci contextData.renderBarrierList->BeginFrame(); 2258bf80f4bSopenharmony_ci contextData.nodeContextPoolMgr->BeginFrame(); 2268bf80f4bSopenharmony_ci contextData.nodeContextDescriptorSetMgr->BeginFrame(); 2278bf80f4bSopenharmony_ci contextData.renderNodeContextManager->BeginFrame(idx, timings); 2288bf80f4bSopenharmony_ci } 2298bf80f4bSopenharmony_ci prevRngShareDataMgr = renderNodeDataStore->renderNodeGraphShareDataMgr.get(); 2308bf80f4bSopenharmony_ci } 2318bf80f4bSopenharmony_ci} 2328bf80f4bSopenharmony_ci 2338bf80f4bSopenharmony_ci// Helper for Renderer::RenderFrame 2348bf80f4bSopenharmony_ciinline void FillRngNodeStores(array_view<const RenderHandle> inputs, RenderNodeGraphManager& renderNodeGraphMgr, 2358bf80f4bSopenharmony_ci vector<RenderNodeGraphNodeStore*>& rngNodeStores) 2368bf80f4bSopenharmony_ci{ 2378bf80f4bSopenharmony_ci rngNodeStores.reserve(inputs.size()); 2388bf80f4bSopenharmony_ci for (auto const& input : inputs) { 2398bf80f4bSopenharmony_ci rngNodeStores.push_back(renderNodeGraphMgr.Get(input)); 2408bf80f4bSopenharmony_ci } 2418bf80f4bSopenharmony_ci} 2428bf80f4bSopenharmony_ci 2438bf80f4bSopenharmony_ci// Helper for Renderer::RenderFrame 2448bf80f4bSopenharmony_ciinline bool WaitForFence(const Device& device, RenderFrameSync& renderFrameSync) 2458bf80f4bSopenharmony_ci{ 2468bf80f4bSopenharmony_ci RENDER_CPU_PERF_SCOPE("Renderer", "Renderer", "WaitForFrameFence_Cpu"); 2478bf80f4bSopenharmony_ci renderFrameSync.WaitForFrameFence(); 2488bf80f4bSopenharmony_ci 2498bf80f4bSopenharmony_ci return device.GetDeviceStatus(); 2508bf80f4bSopenharmony_ci} 2518bf80f4bSopenharmony_ci 2528bf80f4bSopenharmony_ci// Helper for Renderer::RenderFrame 2538bf80f4bSopenharmony_ciinline void ProcessRenderNodeGraph( 2548bf80f4bSopenharmony_ci Device& device, RenderGraph& renderGraph, array_view<RenderNodeGraphNodeStore*> graphNodeStoreView) 2558bf80f4bSopenharmony_ci{ 2568bf80f4bSopenharmony_ci RENDER_CPU_PERF_SCOPE("Renderer", "Renderer", "RenderGraph_Cpu"); 2578bf80f4bSopenharmony_ci renderGraph.ProcessRenderNodeGraph(device.HasSwapchain(), graphNodeStoreView); 2588bf80f4bSopenharmony_ci} 2598bf80f4bSopenharmony_ci 2608bf80f4bSopenharmony_ci// Helper for Renderer::ExecuteRenderNodes 2618bf80f4bSopenharmony_civoid CreateGpuResourcesWithRenderNodes(const array_view<RenderNodeGraphNodeStore*>& renderNodeGraphNodeStores, 2628bf80f4bSopenharmony_ci IRenderDataStoreManager& renderData, ShaderManager& shaderMgr) 2638bf80f4bSopenharmony_ci{ 2648bf80f4bSopenharmony_ci for (size_t graphIdx = 0; graphIdx < renderNodeGraphNodeStores.size(); ++graphIdx) { 2658bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeGraphNodeStores[graphIdx]); 2668bf80f4bSopenharmony_ci 2678bf80f4bSopenharmony_ci RenderNodeGraphNodeStore const& nodeStore = *renderNodeGraphNodeStores[graphIdx]; 2688bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeStore.renderNodeData.size(); ++nodeIdx) { 2698bf80f4bSopenharmony_ci IRenderNode& renderNode = *(nodeStore.renderNodeData[nodeIdx].node); 2708bf80f4bSopenharmony_ci renderNode.PreExecuteFrame(); 2718bf80f4bSopenharmony_ci } 2728bf80f4bSopenharmony_ci } 2738bf80f4bSopenharmony_ci} 2748bf80f4bSopenharmony_ci 2758bf80f4bSopenharmony_ci// Helper for Renderer::ExecuteRenderNodes 2768bf80f4bSopenharmony_civoid RenderNodeExecution(RenderNodeExecutionParameters& params) 2778bf80f4bSopenharmony_ci{ 2788bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 2798bf80f4bSopenharmony_ci size_t allNodeIdx = 0; 2808bf80f4bSopenharmony_ci#endif 2818bf80f4bSopenharmony_ci uint64_t taskId = 0; 2828bf80f4bSopenharmony_ci for (const auto* nodeStorePtr : params.renderNodeGraphNodeStores) { 2838bf80f4bSopenharmony_ci // there shouldn't be nullptrs but let's play it safe 2848bf80f4bSopenharmony_ci PLUGIN_ASSERT(nodeStorePtr); 2858bf80f4bSopenharmony_ci if (nodeStorePtr) { 2868bf80f4bSopenharmony_ci const auto& nodeStore = *nodeStorePtr; 2878bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeStore.renderNodeData.size(); ++nodeIdx) { 2888bf80f4bSopenharmony_ci PLUGIN_ASSERT(nodeStore.renderNodeData[nodeIdx].node); 2898bf80f4bSopenharmony_ci if (nodeStore.renderNodeData[nodeIdx].node) { 2908bf80f4bSopenharmony_ci IRenderNode& renderNode = *(nodeStore.renderNodeData[nodeIdx].node); 2918bf80f4bSopenharmony_ci RenderNodeContextData const& renderNodeContextData = nodeStore.renderNodeContextData[nodeIdx]; 2928bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeContextData.renderCommandList); 2938bf80f4bSopenharmony_ci RenderCommandList& renderCommandList = *renderNodeContextData.renderCommandList; 2948bf80f4bSopenharmony_ci 2958bf80f4bSopenharmony_ci // Do not run render node if the flag is set 2968bf80f4bSopenharmony_ci const uint32_t flags = renderNode.GetExecuteFlags(); 2978bf80f4bSopenharmony_ci if ((renderNode.GetExecuteFlags() & 2988bf80f4bSopenharmony_ci IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE) == 0) { 2998bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 3008bf80f4bSopenharmony_ci auto& timerRef = params.nodeTimers[allNodeIdx++]; 3018bf80f4bSopenharmony_ci timerRef.debugName = nodeStore.renderNodeData[nodeIdx].fullName; 3028bf80f4bSopenharmony_ci params.queue->Submit( 3038bf80f4bSopenharmony_ci taskId++, CreateFunctionTask([&timerRef, &renderNode, &renderCommandList]() { 3048bf80f4bSopenharmony_ci timerRef.timer.Begin(); 3058bf80f4bSopenharmony_ci 3068bf80f4bSopenharmony_ci renderCommandList.BeforeRenderNodeExecuteFrame(); 3078bf80f4bSopenharmony_ci renderNode.ExecuteFrame(renderCommandList); 3088bf80f4bSopenharmony_ci renderCommandList.AfterRenderNodeExecuteFrame(); 3098bf80f4bSopenharmony_ci 3108bf80f4bSopenharmony_ci timerRef.timer.End(); 3118bf80f4bSopenharmony_ci })); 3128bf80f4bSopenharmony_ci#else 3138bf80f4bSopenharmony_ci params.queue->Submit(taskId++, CreateFunctionTask([&renderCommandList, &renderNode]() { 3148bf80f4bSopenharmony_ci renderCommandList.BeforeRenderNodeExecuteFrame(); 3158bf80f4bSopenharmony_ci renderNode.ExecuteFrame(renderCommandList); 3168bf80f4bSopenharmony_ci renderCommandList.AfterRenderNodeExecuteFrame(); 3178bf80f4bSopenharmony_ci })); 3188bf80f4bSopenharmony_ci#endif 3198bf80f4bSopenharmony_ci } 3208bf80f4bSopenharmony_ci } 3218bf80f4bSopenharmony_ci } 3228bf80f4bSopenharmony_ci } 3238bf80f4bSopenharmony_ci } 3248bf80f4bSopenharmony_ci 3258bf80f4bSopenharmony_ci // Execute and wait for completion. 3268bf80f4bSopenharmony_ci params.queue->Execute(); 3278bf80f4bSopenharmony_ci} 3288bf80f4bSopenharmony_ci 3298bf80f4bSopenharmony_ci// Helper for Renderer::ExecuteRenderBackend 3308bf80f4bSopenharmony_civoid IterateRenderBackendNodeGraphNodeStores(const array_view<RenderNodeGraphNodeStore*>& renderNodeGraphNodeStores, 3318bf80f4bSopenharmony_ci const bool multiQueueEnabled, RenderCommandFrameData& rcfd) 3328bf80f4bSopenharmony_ci{ 3338bf80f4bSopenharmony_ci for (size_t graphIdx = 0; graphIdx < renderNodeGraphNodeStores.size(); ++graphIdx) { 3348bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeGraphNodeStores[graphIdx]); 3358bf80f4bSopenharmony_ci 3368bf80f4bSopenharmony_ci RenderNodeGraphNodeStore const& nodeStore = *renderNodeGraphNodeStores[graphIdx]; 3378bf80f4bSopenharmony_ci 3388bf80f4bSopenharmony_ci unordered_map<uint32_t, uint32_t> nodeIdxToRenderCommandContextIdx; 3398bf80f4bSopenharmony_ci const uint32_t multiQueuePatchBeginIdx = (uint32_t)rcfd.renderCommandContexts.size(); 3408bf80f4bSopenharmony_ci uint32_t multiQueuePatchCount = 0; 3418bf80f4bSopenharmony_ci if (multiQueueEnabled) { 3428bf80f4bSopenharmony_ci nodeIdxToRenderCommandContextIdx.reserve(nodeStore.renderNodeContextData.size()); 3438bf80f4bSopenharmony_ci } 3448bf80f4bSopenharmony_ci 3458bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeStore.renderNodeContextData.size(); ++nodeIdx) { 3468bf80f4bSopenharmony_ci const auto& ref = nodeStore.renderNodeContextData[nodeIdx]; 3478bf80f4bSopenharmony_ci PLUGIN_ASSERT((ref.renderCommandList != nullptr) && (ref.renderBarrierList != nullptr) && 3488bf80f4bSopenharmony_ci (ref.nodeContextPsoMgr != nullptr) && (ref.nodeContextPoolMgr != nullptr)); 3498bf80f4bSopenharmony_ci const bool valid = (ref.renderCommandList->HasValidRenderCommands()) ? true : false; 3508bf80f4bSopenharmony_ci if (valid) { 3518bf80f4bSopenharmony_ci if (multiQueueEnabled) { 3528bf80f4bSopenharmony_ci nodeIdxToRenderCommandContextIdx[(uint32_t)nodeIdx] = (uint32_t)rcfd.renderCommandContexts.size(); 3538bf80f4bSopenharmony_ci multiQueuePatchCount++; 3548bf80f4bSopenharmony_ci } 3558bf80f4bSopenharmony_ci // get final backend node index of the first render node which uses the swapchain image 3568bf80f4bSopenharmony_ci const uint32_t backendNodeIdx = static_cast<uint32_t>(rcfd.renderCommandContexts.size()); 3578bf80f4bSopenharmony_ci if ((rcfd.firstSwapchainNodeIdx > backendNodeIdx) && (ref.submitInfo.waitForSwapchainAcquireSignal)) { 3588bf80f4bSopenharmony_ci rcfd.firstSwapchainNodeIdx = static_cast<uint32_t>(rcfd.renderCommandContexts.size()); 3598bf80f4bSopenharmony_ci } 3608bf80f4bSopenharmony_ci rcfd.renderCommandContexts.push_back({ ref.renderBackendNode, ref.renderCommandList.get(), 3618bf80f4bSopenharmony_ci ref.renderBarrierList.get(), ref.nodeContextPsoMgr.get(), ref.nodeContextDescriptorSetMgr.get(), 3628bf80f4bSopenharmony_ci ref.nodeContextPoolMgr.get(), (uint32_t)nodeIdx, ref.submitInfo, 3638bf80f4bSopenharmony_ci nodeStore.renderNodeData[nodeIdx].fullName }); 3648bf80f4bSopenharmony_ci } 3658bf80f4bSopenharmony_ci } 3668bf80f4bSopenharmony_ci 3678bf80f4bSopenharmony_ci if (multiQueueEnabled) { // patch correct render command context indices 3688bf80f4bSopenharmony_ci for (uint32_t idx = multiQueuePatchBeginIdx; idx < multiQueuePatchCount; ++idx) { 3698bf80f4bSopenharmony_ci auto& ref = rcfd.renderCommandContexts[idx]; 3708bf80f4bSopenharmony_ci const auto& nodeContextRef = nodeStore.renderNodeContextData[ref.renderGraphRenderNodeIndex]; 3718bf80f4bSopenharmony_ci 3728bf80f4bSopenharmony_ci ref.submitDepencies.signalSemaphore = nodeContextRef.submitInfo.signalSemaphore; 3738bf80f4bSopenharmony_ci ref.submitDepencies.waitSemaphoreCount = nodeContextRef.submitInfo.waitSemaphoreCount; 3748bf80f4bSopenharmony_ci for (uint32_t waitIdx = 0; waitIdx < ref.submitDepencies.waitSemaphoreCount; ++waitIdx) { 3758bf80f4bSopenharmony_ci const uint32_t currRenderNodeIdx = nodeContextRef.submitInfo.waitSemaphoreNodeIndices[waitIdx]; 3768bf80f4bSopenharmony_ci PLUGIN_ASSERT(nodeIdxToRenderCommandContextIdx.count(currRenderNodeIdx) == 1); 3778bf80f4bSopenharmony_ci 3788bf80f4bSopenharmony_ci ref.submitDepencies.waitSemaphoreNodeIndices[waitIdx] = 3798bf80f4bSopenharmony_ci nodeIdxToRenderCommandContextIdx[currRenderNodeIdx]; 3808bf80f4bSopenharmony_ci } 3818bf80f4bSopenharmony_ci } 3828bf80f4bSopenharmony_ci } 3838bf80f4bSopenharmony_ci } 3848bf80f4bSopenharmony_ci} 3858bf80f4bSopenharmony_ci 3868bf80f4bSopenharmony_citemplate<typename T> 3878bf80f4bSopenharmony_ciinline bool IsNull(T* ptr) 3888bf80f4bSopenharmony_ci{ 3898bf80f4bSopenharmony_ci return ptr == nullptr; 3908bf80f4bSopenharmony_ci} 3918bf80f4bSopenharmony_ci 3928bf80f4bSopenharmony_ciinline int64_t GetTimeStampNow() 3938bf80f4bSopenharmony_ci{ 3948bf80f4bSopenharmony_ci using namespace std::chrono; 3958bf80f4bSopenharmony_ci using Clock = system_clock; 3968bf80f4bSopenharmony_ci return Clock::now().time_since_epoch().count(); 3978bf80f4bSopenharmony_ci} 3988bf80f4bSopenharmony_ci 3998bf80f4bSopenharmony_civoid CreateDefaultRenderNodeGraphs(const Device& device, RenderNodeGraphManager& rngMgr, 4008bf80f4bSopenharmony_ci RenderHandleReference& defaultStaging, RenderHandleReference& defaultEndFrameStaging) 4018bf80f4bSopenharmony_ci{ 4028bf80f4bSopenharmony_ci { 4038bf80f4bSopenharmony_ci RenderNodeGraphDesc rngd; 4048bf80f4bSopenharmony_ci { 4058bf80f4bSopenharmony_ci RenderNodeDesc rnd; 4068bf80f4bSopenharmony_ci rnd.typeName = "CORE_RN_STAGING"; 4078bf80f4bSopenharmony_ci rnd.nodeName = "CORE_RN_STAGING_I"; 4088bf80f4bSopenharmony_ci rnd.description.queue = { GpuQueue::QueueType::GRAPHICS, 0u }; 4098bf80f4bSopenharmony_ci rngd.nodes.push_back(move(rnd)); 4108bf80f4bSopenharmony_ci } 4118bf80f4bSopenharmony_ci#if (RENDER_VULKAN_RT_ENABLED == 1) 4128bf80f4bSopenharmony_ci if (device.GetBackendType() == DeviceBackendType::VULKAN) { 4138bf80f4bSopenharmony_ci RenderNodeDesc rnd; 4148bf80f4bSopenharmony_ci rnd.typeName = "CORE_RN_DEFAULT_ACCELERATION_STRUCTURE_STAGING"; 4158bf80f4bSopenharmony_ci rnd.nodeName = "CORE_RN_DEFAULT_ACCELERATION_STRUCTURE_STAGING_I"; 4168bf80f4bSopenharmony_ci rnd.description.queue = { GpuQueue::QueueType::GRAPHICS, 0u }; 4178bf80f4bSopenharmony_ci rngd.nodes.push_back(move(rnd)); 4188bf80f4bSopenharmony_ci } 4198bf80f4bSopenharmony_ci#endif 4208bf80f4bSopenharmony_ci defaultStaging = 4218bf80f4bSopenharmony_ci rngMgr.Create(IRenderNodeGraphManager::RenderNodeGraphUsageType::RENDER_NODE_GRAPH_STATIC, rngd); 4228bf80f4bSopenharmony_ci } 4238bf80f4bSopenharmony_ci { 4248bf80f4bSopenharmony_ci RenderNodeGraphDesc rngd; 4258bf80f4bSopenharmony_ci { 4268bf80f4bSopenharmony_ci RenderNodeDesc rnd; 4278bf80f4bSopenharmony_ci rnd.typeName = "CORE_RN_END_FRAME_STAGING"; 4288bf80f4bSopenharmony_ci rnd.nodeName = "CORE_RN_END_FRAME_STAGING_I"; 4298bf80f4bSopenharmony_ci rnd.description.queue = { GpuQueue::QueueType::GRAPHICS, 0u }; 4308bf80f4bSopenharmony_ci rngd.nodes.push_back(move(rnd)); 4318bf80f4bSopenharmony_ci } 4328bf80f4bSopenharmony_ci defaultEndFrameStaging = 4338bf80f4bSopenharmony_ci rngMgr.Create(IRenderNodeGraphManager::RenderNodeGraphUsageType::RENDER_NODE_GRAPH_STATIC, rngd); 4348bf80f4bSopenharmony_ci } 4358bf80f4bSopenharmony_ci} 4368bf80f4bSopenharmony_ci 4378bf80f4bSopenharmony_ciconstexpr uint32_t CHECK_RENDER_FLAGS { RenderCreateInfo::CreateInfoFlagBits::SEPARATE_RENDER_FRAME_BACKEND | 4388bf80f4bSopenharmony_ci RenderCreateInfo::CreateInfoFlagBits::SEPARATE_RENDER_FRAME_PRESENT }; 4398bf80f4bSopenharmony_ci 4408bf80f4bSopenharmony_ci} // namespace 4418bf80f4bSopenharmony_ci 4428bf80f4bSopenharmony_ciRenderer::Renderer(IRenderContext& context) 4438bf80f4bSopenharmony_ci : renderContext_(context), device_(static_cast<Device&>(context.GetDevice())), 4448bf80f4bSopenharmony_ci gpuResourceMgr_(static_cast<GpuResourceManager&>(device_.GetGpuResourceManager())), 4458bf80f4bSopenharmony_ci shaderMgr_(static_cast<ShaderManager&>(device_.GetShaderManager())), 4468bf80f4bSopenharmony_ci renderNodeGraphMgr_(static_cast<RenderNodeGraphManager&>(context.GetRenderNodeGraphManager())), 4478bf80f4bSopenharmony_ci renderDataStoreMgr_(static_cast<RenderDataStoreManager&>(context.GetRenderDataStoreManager())), 4488bf80f4bSopenharmony_ci renderUtil_(static_cast<RenderUtil&>(context.GetRenderUtil())) 4498bf80f4bSopenharmony_ci 4508bf80f4bSopenharmony_ci{ 4518bf80f4bSopenharmony_ci const RenderCreateInfo rci = ((const RenderContext&)renderContext_).GetCreateInfo(); 4528bf80f4bSopenharmony_ci if (rci.createFlags & RenderCreateInfo::CreateInfoFlagBits::SEPARATE_RENDER_FRAME_BACKEND) { 4538bf80f4bSopenharmony_ci separatedRendering_.separateBackend = true; 4548bf80f4bSopenharmony_ci } 4558bf80f4bSopenharmony_ci if (rci.createFlags & RenderCreateInfo::CreateInfoFlagBits::SEPARATE_RENDER_FRAME_PRESENT) { 4568bf80f4bSopenharmony_ci separatedRendering_.separatePresent = true; 4578bf80f4bSopenharmony_ci } 4588bf80f4bSopenharmony_ci 4598bf80f4bSopenharmony_ci const auto factory = GetInstance<ITaskQueueFactory>(UID_TASK_QUEUE_FACTORY); 4608bf80f4bSopenharmony_ci threadPool_ = factory->CreateThreadPool(factory->GetNumberOfCores()); 4618bf80f4bSopenharmony_ci parallelQueue_ = factory->CreateParallelTaskQueue(threadPool_); 4628bf80f4bSopenharmony_ci sequentialQueue_ = factory->CreateSequentialTaskQueue(threadPool_); 4638bf80f4bSopenharmony_ci 4648bf80f4bSopenharmony_ci renderConfig_ = { device_.GetBackendType(), RenderingConfiguration::NdcOrigin::TOP_LEFT }; 4658bf80f4bSopenharmony_ci#if ((RENDER_HAS_GL_BACKEND) || (RENDER_HAS_GLES_BACKEND)) && (RENDER_GL_FLIP_Y_SWAPCHAIN == 0) 4668bf80f4bSopenharmony_ci // The flag is for informative purposes only. 4678bf80f4bSopenharmony_ci if ((renderConfig_.renderBackend == DeviceBackendType::OPENGL) || 4688bf80f4bSopenharmony_ci (renderConfig_.renderBackend == DeviceBackendType::OPENGLES)) { 4698bf80f4bSopenharmony_ci renderConfig_.ndcOrigin = RenderingConfiguration::NdcOrigin::BOTTOM_LEFT; 4708bf80f4bSopenharmony_ci } 4718bf80f4bSopenharmony_ci#endif 4728bf80f4bSopenharmony_ci 4738bf80f4bSopenharmony_ci renderGraph_ = make_unique<RenderGraph>(gpuResourceMgr_); 4748bf80f4bSopenharmony_ci renderBackend_ = device_.CreateRenderBackend(gpuResourceMgr_, parallelQueue_); 4758bf80f4bSopenharmony_ci renderFrameSync_ = device_.CreateRenderFrameSync(); 4768bf80f4bSopenharmony_ci rngGlobalShareDataMgr_ = make_unique<RenderNodeGraphGlobalShareDataManager>(); 4778bf80f4bSopenharmony_ci 4788bf80f4bSopenharmony_ci CreateDefaultRenderNodeGraphs(device_, renderNodeGraphMgr_, defaultStagingRng_, defaultEndFrameStagingRng_); 4798bf80f4bSopenharmony_ci 4808bf80f4bSopenharmony_ci dsStaging_ = static_cast<IRenderDataStoreDefaultStaging*>( 4818bf80f4bSopenharmony_ci renderDataStoreMgr_.GetRenderDataStore(RENDER_DATA_STORE_DEFAULT_STAGING)); 4828bf80f4bSopenharmony_ci} 4838bf80f4bSopenharmony_ci 4848bf80f4bSopenharmony_ciRenderer::~Renderer() {} 4858bf80f4bSopenharmony_ci 4868bf80f4bSopenharmony_civoid Renderer::InitNodeGraphs(const array_view<const RenderHandle> renderNodeGraphs) 4878bf80f4bSopenharmony_ci{ 4888bf80f4bSopenharmony_ci const RenderNodeGraphShareDataManager* prevRngShareDataMgr = nullptr; 4898bf80f4bSopenharmony_ci for (const auto& rng : renderNodeGraphs) { 4908bf80f4bSopenharmony_ci auto renderNodeDataStore = renderNodeGraphMgr_.Get(rng); 4918bf80f4bSopenharmony_ci if (!renderNodeDataStore) { 4928bf80f4bSopenharmony_ci continue; 4938bf80f4bSopenharmony_ci } 4948bf80f4bSopenharmony_ci 4958bf80f4bSopenharmony_ci RenderNodeGraphNodeStore& nodeStore = *renderNodeDataStore; 4968bf80f4bSopenharmony_ci if (nodeStore.initialized) { 4978bf80f4bSopenharmony_ci continue; 4988bf80f4bSopenharmony_ci } 4998bf80f4bSopenharmony_ci nodeStore.initialized = true; 5008bf80f4bSopenharmony_ci 5018bf80f4bSopenharmony_ci const bool enableMultiQueue = (device_.GetGpuQueueCount() > 1); 5028bf80f4bSopenharmony_ci 5038bf80f4bSopenharmony_ci // serial, initialize render node context data 5048bf80f4bSopenharmony_ci auto renderNodeNameToIndex = 5058bf80f4bSopenharmony_ci InitializeRenderNodeContextData(renderContext_, nodeStore, enableMultiQueue, renderConfig_); 5068bf80f4bSopenharmony_ci 5078bf80f4bSopenharmony_ci if (enableMultiQueue) { 5088bf80f4bSopenharmony_ci // patch gpu queue signaling 5098bf80f4bSopenharmony_ci PatchSignaling(nodeStore, renderNodeNameToIndex); 5108bf80f4bSopenharmony_ci } 5118bf80f4bSopenharmony_ci 5128bf80f4bSopenharmony_ci // NOTE: needs to be called once before init. every frame called in BeginRenderNodeGraph() 5138bf80f4bSopenharmony_ci nodeStore.renderNodeGraphShareDataMgr->BeginFrame(rngGlobalShareDataMgr_.get(), prevRngShareDataMgr, 5148bf80f4bSopenharmony_ci static_cast<uint32_t>(nodeStore.renderNodeData.size()), 5158bf80f4bSopenharmony_ci { nodeStore.renderNodeGraphShareData.inputs, nodeStore.renderNodeGraphShareData.inputCount }, 5168bf80f4bSopenharmony_ci { nodeStore.renderNodeGraphShareData.outputs, nodeStore.renderNodeGraphShareData.outputCount }); 5178bf80f4bSopenharmony_ci prevRngShareDataMgr = nodeStore.renderNodeGraphShareDataMgr.get(); 5188bf80f4bSopenharmony_ci 5198bf80f4bSopenharmony_ci const RenderNodeContextManager::PerFrameTimings timings { 0, 0, device_.GetFrameCount() }; 5208bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeStore.renderNodeData.size(); ++nodeIdx) { 5218bf80f4bSopenharmony_ci auto& nodeContextData = nodeStore.renderNodeContextData[nodeIdx]; 5228bf80f4bSopenharmony_ci if (nodeContextData.initialized) { 5238bf80f4bSopenharmony_ci continue; 5248bf80f4bSopenharmony_ci } 5258bf80f4bSopenharmony_ci nodeContextData.initialized = true; 5268bf80f4bSopenharmony_ci 5278bf80f4bSopenharmony_ci // NOTE: needs to be called once before init. every frame called in BeginRenderNodeGraph() 5288bf80f4bSopenharmony_ci nodeContextData.renderNodeContextManager->BeginFrame(static_cast<uint32_t>(nodeIdx), timings); 5298bf80f4bSopenharmony_ci 5308bf80f4bSopenharmony_ci auto& renderNodeData = nodeStore.renderNodeData[nodeIdx]; 5318bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeData.inputData); 5328bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderNodeData.node); 5338bf80f4bSopenharmony_ci 5348bf80f4bSopenharmony_ci RENDER_CPU_PERF_SCOPE("Renderer", "Renderer_InitNode_Cpu", renderNodeData.fullName); 5358bf80f4bSopenharmony_ci renderNodeData.node->InitNode(*(nodeContextData.renderNodeContextManager)); 5368bf80f4bSopenharmony_ci } 5378bf80f4bSopenharmony_ci } 5388bf80f4bSopenharmony_ci} 5398bf80f4bSopenharmony_ci 5408bf80f4bSopenharmony_ci// Helper for Renderer::RenderFrame 5418bf80f4bSopenharmony_civoid Renderer::RemapBackBufferHandle(const IRenderDataStoreManager& renderData) 5428bf80f4bSopenharmony_ci{ 5438bf80f4bSopenharmony_ci const auto* dataStorePod = 5448bf80f4bSopenharmony_ci static_cast<IRenderDataStorePod*>(renderData.GetRenderDataStore(RenderDataStorePod::TYPE_NAME)); 5458bf80f4bSopenharmony_ci if (dataStorePod) { 5468bf80f4bSopenharmony_ci auto const dataView = dataStorePod->Get("NodeGraphBackBufferConfiguration"); 5478bf80f4bSopenharmony_ci const auto bb = reinterpret_cast<const NodeGraphBackBufferConfiguration*>(dataView.data()); 5488bf80f4bSopenharmony_ci if (bb->backBufferType == NodeGraphBackBufferConfiguration::BackBufferType::SWAPCHAIN) { 5498bf80f4bSopenharmony_ci if (!device_.HasSwapchain()) { 5508bf80f4bSopenharmony_ci PLUGIN_LOG_E("Using swapchain rendering without swapchain"); 5518bf80f4bSopenharmony_ci } 5528bf80f4bSopenharmony_ci } else if (bb->backBufferType == NodeGraphBackBufferConfiguration::BackBufferType::GPU_IMAGE) { 5538bf80f4bSopenharmony_ci const RenderHandle handle = gpuResourceMgr_.GetImageRawHandle(bb->backBufferName); 5548bf80f4bSopenharmony_ci if (RenderHandleUtil::IsValid(handle) && RenderHandleUtil::IsValid(bb->backBufferHandle)) { 5558bf80f4bSopenharmony_ci gpuResourceMgr_.RemapGpuImageHandle(handle, bb->backBufferHandle); 5568bf80f4bSopenharmony_ci } 5578bf80f4bSopenharmony_ci } else if (bb->backBufferType == NodeGraphBackBufferConfiguration::BackBufferType::GPU_IMAGE_BUFFER_COPY) { 5588bf80f4bSopenharmony_ci const RenderHandle handle = gpuResourceMgr_.GetImageRawHandle(bb->backBufferName); 5598bf80f4bSopenharmony_ci if (RenderHandleUtil::IsValid(handle) && RenderHandleUtil::IsValid(bb->backBufferHandle) && 5608bf80f4bSopenharmony_ci RenderHandleUtil::IsValid(bb->gpuBufferHandle)) { 5618bf80f4bSopenharmony_ci gpuResourceMgr_.RemapGpuImageHandle(handle, bb->backBufferHandle); 5628bf80f4bSopenharmony_ci } 5638bf80f4bSopenharmony_ci // handle image to buffer copy via post frame staging 5648bf80f4bSopenharmony_ci { 5658bf80f4bSopenharmony_ci RenderHandle backbufferHandle = bb->backBufferHandle; 5668bf80f4bSopenharmony_ci if (bb->backBufferName == DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER) { 5678bf80f4bSopenharmony_ci // we need to use the core default backbuffer handle and not the replaced handle in this situation 5688bf80f4bSopenharmony_ci backbufferHandle = 5698bf80f4bSopenharmony_ci gpuResourceMgr_.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_BACKBUFFER) 5708bf80f4bSopenharmony_ci .GetHandle(); 5718bf80f4bSopenharmony_ci } 5728bf80f4bSopenharmony_ci const GpuImageDesc desc = gpuResourceMgr_.GetImageDescriptor(backbufferHandle); 5738bf80f4bSopenharmony_ci const BufferImageCopy bic { 5748bf80f4bSopenharmony_ci 0, // bufferOffset 5758bf80f4bSopenharmony_ci 0, // bufferRowLength 5768bf80f4bSopenharmony_ci 0, // bufferImageHeight 5778bf80f4bSopenharmony_ci ImageSubresourceLayers { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1u }, // imageSubresource 5788bf80f4bSopenharmony_ci Size3D { 0, 0, 0 }, // imageOffset 5798bf80f4bSopenharmony_ci Size3D { desc.width, desc.height, 1u }, // imageExtent 5808bf80f4bSopenharmony_ci }; 5818bf80f4bSopenharmony_ci dsStaging_->CopyImageToBuffer(gpuResourceMgr_.Get(backbufferHandle), 5828bf80f4bSopenharmony_ci gpuResourceMgr_.Get(bb->gpuBufferHandle), bic, 5838bf80f4bSopenharmony_ci IRenderDataStoreDefaultStaging::ResourceCopyInfo::END_FRAME); 5848bf80f4bSopenharmony_ci } 5858bf80f4bSopenharmony_ci } 5868bf80f4bSopenharmony_ci } 5878bf80f4bSopenharmony_ci} 5888bf80f4bSopenharmony_ci 5898bf80f4bSopenharmony_civoid Renderer::RenderFrameImpl(const array_view<const RenderHandle> renderNodeGraphs) 5908bf80f4bSopenharmony_ci{ 5918bf80f4bSopenharmony_ci if (separatedRendering_.separateBackend || separatedRendering_.separatePresent) { 5928bf80f4bSopenharmony_ci separatedRendering_.frontMtx.lock(); 5938bf80f4bSopenharmony_ci } 5948bf80f4bSopenharmony_ci 5958bf80f4bSopenharmony_ci Tick(); 5968bf80f4bSopenharmony_ci frameTimes_.begin = GetTimeStampNow(); 5978bf80f4bSopenharmony_ci RENDER_CPU_PERF_SCOPE("Renderer", "Frame", "RenderFrame"); 5988bf80f4bSopenharmony_ci 5998bf80f4bSopenharmony_ci if (device_.GetDeviceStatus() == false) { 6008bf80f4bSopenharmony_ci ProcessTimeStampEnd(); 6018bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1) 6028bf80f4bSopenharmony_ci PLUGIN_LOG_ONCE_E("invalid_device_status_render_frame", "invalid device for rendering"); 6038bf80f4bSopenharmony_ci#endif 6048bf80f4bSopenharmony_ci return; 6058bf80f4bSopenharmony_ci } 6068bf80f4bSopenharmony_ci const IRenderDataStoreManager::RenderDataStoreFlags rdsFlags = renderDataStoreMgr_.GetRenderDataStoreFlags(); 6078bf80f4bSopenharmony_ci if (rdsFlags & IRenderDataStoreManager::DOUBLE_BUFFERED_RENDER_DATA_STORES) { 6088bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1) 6098bf80f4bSopenharmony_ci renderDataStoreMgr_.ValidateCommitFrameData(); 6108bf80f4bSopenharmony_ci#endif 6118bf80f4bSopenharmony_ci } 6128bf80f4bSopenharmony_ci renderDataStoreMgr_.CommitFrameData(); 6138bf80f4bSopenharmony_ci 6148bf80f4bSopenharmony_ci device_.Activate(); 6158bf80f4bSopenharmony_ci device_.FrameStart(); 6168bf80f4bSopenharmony_ci renderFrameTimeData_.frameIndex = device_.GetFrameCount(); 6178bf80f4bSopenharmony_ci 6188bf80f4bSopenharmony_ci (static_cast<GpuResourceCache&>(gpuResourceMgr_.GetGpuResourceCache())).BeginFrame(device_.GetFrameCount()); 6198bf80f4bSopenharmony_ci 6208bf80f4bSopenharmony_ci // handle utils (needs to be called before render data store pre renders) 6218bf80f4bSopenharmony_ci renderUtil_.BeginFrame(); 6228bf80f4bSopenharmony_ci 6238bf80f4bSopenharmony_ci // remap the default back buffer (needs to be called before render data store pre renders) 6248bf80f4bSopenharmony_ci RemapBackBufferHandle(renderDataStoreMgr_); 6258bf80f4bSopenharmony_ci 6268bf80f4bSopenharmony_ci renderNodeGraphMgr_.HandlePendingAllocations(); 6278bf80f4bSopenharmony_ci renderDataStoreMgr_.PreRender(); 6288bf80f4bSopenharmony_ci 6298bf80f4bSopenharmony_ci // create new shaders if any created this frame (needs to be called before render node init) 6308bf80f4bSopenharmony_ci shaderMgr_.HandlePendingAllocations(); 6318bf80f4bSopenharmony_ci 6328bf80f4bSopenharmony_ci auto& rngInputs = renderFrameTimeData_.rngInputs; 6338bf80f4bSopenharmony_ci auto& rngNodeStores = renderFrameTimeData_.rngNodeStores; 6348bf80f4bSopenharmony_ci PLUGIN_ASSERT(rngInputs.empty()); 6358bf80f4bSopenharmony_ci PLUGIN_ASSERT(rngNodeStores.empty()); 6368bf80f4bSopenharmony_ci 6378bf80f4bSopenharmony_ci // update render node graphs with default staging 6388bf80f4bSopenharmony_ci FillRngInputs(renderNodeGraphs, rngInputs); 6398bf80f4bSopenharmony_ci const auto renderNodeGraphInputs = array_view(rngInputs.data(), rngInputs.size()); 6408bf80f4bSopenharmony_ci 6418bf80f4bSopenharmony_ci InitNodeGraphs(renderNodeGraphInputs); 6428bf80f4bSopenharmony_ci device_.Deactivate(); 6438bf80f4bSopenharmony_ci 6448bf80f4bSopenharmony_ci renderGraph_->BeginFrame(); 6458bf80f4bSopenharmony_ci 6468bf80f4bSopenharmony_ci FillRngNodeStores(renderNodeGraphInputs, renderNodeGraphMgr_, rngNodeStores); 6478bf80f4bSopenharmony_ci if (std::any_of(rngNodeStores.begin(), rngNodeStores.end(), IsNull<RenderNodeGraphNodeStore>)) { 6488bf80f4bSopenharmony_ci ProcessTimeStampEnd(); 6498bf80f4bSopenharmony_ci PLUGIN_LOG_W("invalid render node graphs for rendering"); 6508bf80f4bSopenharmony_ci return; 6518bf80f4bSopenharmony_ci } 6528bf80f4bSopenharmony_ci 6538bf80f4bSopenharmony_ci // NodeContextPoolManagerGLES::BeginFrame may delete FBOs and device must be active. 6548bf80f4bSopenharmony_ci device_.Activate(); 6558bf80f4bSopenharmony_ci 6568bf80f4bSopenharmony_ci renderFrameSync_->BeginFrame(); 6578bf80f4bSopenharmony_ci // begin frame (advance ring buffers etc.) 6588bf80f4bSopenharmony_ci const RenderNodeContextManager::PerFrameTimings timings { previousFrameTime_ - firstTime_, deltaTime_, 6598bf80f4bSopenharmony_ci device_.GetFrameCount() }; 6608bf80f4bSopenharmony_ci BeginRenderNodeGraph(rngGlobalShareDataMgr_.get(), rngNodeStores, timings); 6618bf80f4bSopenharmony_ci 6628bf80f4bSopenharmony_ci // synchronize, needed for persistantly mapped gpu buffer writing 6638bf80f4bSopenharmony_ci if (!WaitForFence(device_, *renderFrameSync_)) { 6648bf80f4bSopenharmony_ci device_.Deactivate(); 6658bf80f4bSopenharmony_ci return; // possible lost device with frame fence 6668bf80f4bSopenharmony_ci } 6678bf80f4bSopenharmony_ci 6688bf80f4bSopenharmony_ci // gpu resource allocation and deallocation 6698bf80f4bSopenharmony_ci gpuResourceMgr_.HandlePendingAllocations(); 6708bf80f4bSopenharmony_ci 6718bf80f4bSopenharmony_ci device_.Deactivate(); 6728bf80f4bSopenharmony_ci 6738bf80f4bSopenharmony_ci const auto nodeStoresView = array_view<RenderNodeGraphNodeStore*>(rngNodeStores); 6748bf80f4bSopenharmony_ci ExecuteRenderNodes(renderNodeGraphInputs, nodeStoresView); 6758bf80f4bSopenharmony_ci 6768bf80f4bSopenharmony_ci // render graph process for all render nodes of all render graphs 6778bf80f4bSopenharmony_ci ProcessRenderNodeGraph(device_, *renderGraph_, nodeStoresView); 6788bf80f4bSopenharmony_ci 6798bf80f4bSopenharmony_ci renderDataStoreMgr_.PostRender(); 6808bf80f4bSopenharmony_ci 6818bf80f4bSopenharmony_ci // set front-end index (before mutexes) 6828bf80f4bSopenharmony_ci renderStatus_.frontEndIndex = renderFrameTimeData_.frameIndex; 6838bf80f4bSopenharmony_ci if (separatedRendering_.separateBackend || separatedRendering_.separatePresent) { 6848bf80f4bSopenharmony_ci separatedRendering_.frontMtx.unlock(); 6858bf80f4bSopenharmony_ci } 6868bf80f4bSopenharmony_ci if (!separatedRendering_.separateBackend) { 6878bf80f4bSopenharmony_ci RenderFrameBackendImpl(); 6888bf80f4bSopenharmony_ci } 6898bf80f4bSopenharmony_ci} 6908bf80f4bSopenharmony_ci 6918bf80f4bSopenharmony_civoid Renderer::RenderFrameBackendImpl() 6928bf80f4bSopenharmony_ci{ 6938bf80f4bSopenharmony_ci if (separatedRendering_.separateBackend || separatedRendering_.separatePresent) { 6948bf80f4bSopenharmony_ci separatedRendering_.frontMtx.lock(); 6958bf80f4bSopenharmony_ci separatedRendering_.backMtx.lock(); 6968bf80f4bSopenharmony_ci } 6978bf80f4bSopenharmony_ci 6988bf80f4bSopenharmony_ci auto& rngInputs = renderFrameTimeData_.rngInputs; 6998bf80f4bSopenharmony_ci auto& rngNodeStores = renderFrameTimeData_.rngNodeStores; 7008bf80f4bSopenharmony_ci 7018bf80f4bSopenharmony_ci device_.SetLockResourceBackendAccess(true); 7028bf80f4bSopenharmony_ci renderDataStoreMgr_.PreRenderBackend(); 7038bf80f4bSopenharmony_ci 7048bf80f4bSopenharmony_ci size_t allRenderNodeCount = 0; 7058bf80f4bSopenharmony_ci for (const auto* nodeStore : rngNodeStores) { 7068bf80f4bSopenharmony_ci PLUGIN_ASSERT(nodeStore); 7078bf80f4bSopenharmony_ci allRenderNodeCount += nodeStore->renderNodeData.size(); 7088bf80f4bSopenharmony_ci } 7098bf80f4bSopenharmony_ci 7108bf80f4bSopenharmony_ci RenderCommandFrameData rcfd; 7118bf80f4bSopenharmony_ci PLUGIN_ASSERT(renderFrameSync_); 7128bf80f4bSopenharmony_ci rcfd.renderFrameSync = renderFrameSync_.get(); 7138bf80f4bSopenharmony_ci rcfd.renderFrameUtil = &(static_cast<RenderFrameUtil&>(renderContext_.GetRenderUtil().GetRenderFrameUtil())); 7148bf80f4bSopenharmony_ci rcfd.renderCommandContexts.reserve(allRenderNodeCount); 7158bf80f4bSopenharmony_ci 7168bf80f4bSopenharmony_ci const bool multiQueueEnabled = (device_.GetGpuQueueCount() > 1u); 7178bf80f4bSopenharmony_ci IterateRenderBackendNodeGraphNodeStores(rngNodeStores, multiQueueEnabled, rcfd); 7188bf80f4bSopenharmony_ci 7198bf80f4bSopenharmony_ci // NOTE: by node graph name 7208bf80f4bSopenharmony_ci // NOTE: deprecate this 7218bf80f4bSopenharmony_ci const RenderGraph::SwapchainStates bbState = renderGraph_->GetSwapchainResourceStates(); 7228bf80f4bSopenharmony_ci RenderBackendBackBufferConfiguration config; 7238bf80f4bSopenharmony_ci for (const auto& swapState : bbState.swapchains) { 7248bf80f4bSopenharmony_ci config.swapchainData.push_back({ swapState.handle, swapState.state, swapState.layout, {} }); 7258bf80f4bSopenharmony_ci } 7268bf80f4bSopenharmony_ci if (!config.swapchainData.empty()) { 7278bf80f4bSopenharmony_ci // NOTE: this is a backwards compatibility for a single (default) swapchain config data 7288bf80f4bSopenharmony_ci // should be removed 7298bf80f4bSopenharmony_ci if (auto const dataStorePod = static_cast<IRenderDataStorePod const*>( 7308bf80f4bSopenharmony_ci renderDataStoreMgr_.GetRenderDataStore(RenderDataStorePod::TYPE_NAME)); 7318bf80f4bSopenharmony_ci dataStorePod) { 7328bf80f4bSopenharmony_ci auto const dataView = dataStorePod->Get("NodeGraphBackBufferConfiguration"); 7338bf80f4bSopenharmony_ci if (dataView.size_bytes() == sizeof(NodeGraphBackBufferConfiguration)) { 7348bf80f4bSopenharmony_ci // expects to be the first swapchain in the list 7358bf80f4bSopenharmony_ci const NodeGraphBackBufferConfiguration* bb = (const NodeGraphBackBufferConfiguration*)dataView.data(); 7368bf80f4bSopenharmony_ci config.swapchainData[0U].config = *bb; 7378bf80f4bSopenharmony_ci } 7388bf80f4bSopenharmony_ci } 7398bf80f4bSopenharmony_ci } 7408bf80f4bSopenharmony_ci renderFrameTimeData_.config = config; 7418bf80f4bSopenharmony_ci renderFrameTimeData_.hasBackendWork = (!rcfd.renderCommandContexts.empty()); 7428bf80f4bSopenharmony_ci 7438bf80f4bSopenharmony_ci device_.Activate(); 7448bf80f4bSopenharmony_ci 7458bf80f4bSopenharmony_ci if (renderFrameTimeData_.hasBackendWork) { // do not execute backend with zero work 7468bf80f4bSopenharmony_ci device_.SetRenderBackendRunning(true); 7478bf80f4bSopenharmony_ci 7488bf80f4bSopenharmony_ci frameTimes_.beginBackend = GetTimeStampNow(); 7498bf80f4bSopenharmony_ci renderBackend_->Render(rcfd, config); 7508bf80f4bSopenharmony_ci frameTimes_.endBackend = GetTimeStampNow(); 7518bf80f4bSopenharmony_ci 7528bf80f4bSopenharmony_ci device_.SetRenderBackendRunning(false); 7538bf80f4bSopenharmony_ci } 7548bf80f4bSopenharmony_ci gpuResourceMgr_.EndFrame(); 7558bf80f4bSopenharmony_ci 7568bf80f4bSopenharmony_ci if (separatedRendering_.separatePresent) { 7578bf80f4bSopenharmony_ci device_.Deactivate(); 7588bf80f4bSopenharmony_ci } 7598bf80f4bSopenharmony_ci 7608bf80f4bSopenharmony_ci device_.SetLockResourceBackendAccess(false); 7618bf80f4bSopenharmony_ci 7628bf80f4bSopenharmony_ci // clear 7638bf80f4bSopenharmony_ci rngInputs.clear(); 7648bf80f4bSopenharmony_ci rngNodeStores.clear(); 7658bf80f4bSopenharmony_ci 7668bf80f4bSopenharmony_ci // set backend-end index (before mutexes) 7678bf80f4bSopenharmony_ci renderStatus_.backEndIndex = renderStatus_.frontEndIndex; 7688bf80f4bSopenharmony_ci if (separatedRendering_.separateBackend || separatedRendering_.separatePresent) { 7698bf80f4bSopenharmony_ci separatedRendering_.frontMtx.unlock(); 7708bf80f4bSopenharmony_ci separatedRendering_.backMtx.unlock(); 7718bf80f4bSopenharmony_ci } 7728bf80f4bSopenharmony_ci if (!separatedRendering_.separatePresent) { 7738bf80f4bSopenharmony_ci RenderFramePresentImpl(); 7748bf80f4bSopenharmony_ci } 7758bf80f4bSopenharmony_ci} 7768bf80f4bSopenharmony_ci 7778bf80f4bSopenharmony_civoid Renderer::RenderFramePresentImpl() 7788bf80f4bSopenharmony_ci{ 7798bf80f4bSopenharmony_ci if (separatedRendering_.separatePresent) { 7808bf80f4bSopenharmony_ci separatedRendering_.backMtx.lock(); 7818bf80f4bSopenharmony_ci } 7828bf80f4bSopenharmony_ci 7838bf80f4bSopenharmony_ci if (renderFrameTimeData_.hasBackendWork) { // do not execute backend with zero work 7848bf80f4bSopenharmony_ci if (separatedRendering_.separatePresent) { 7858bf80f4bSopenharmony_ci device_.Activate(); 7868bf80f4bSopenharmony_ci } 7878bf80f4bSopenharmony_ci 7888bf80f4bSopenharmony_ci frameTimes_.beginBackendPresent = GetTimeStampNow(); 7898bf80f4bSopenharmony_ci renderBackend_->Present(renderFrameTimeData_.config); 7908bf80f4bSopenharmony_ci frameTimes_.endBackendPresent = GetTimeStampNow(); 7918bf80f4bSopenharmony_ci 7928bf80f4bSopenharmony_ci if (separatedRendering_.separatePresent) { 7938bf80f4bSopenharmony_ci device_.Deactivate(); 7948bf80f4bSopenharmony_ci } 7958bf80f4bSopenharmony_ci } 7968bf80f4bSopenharmony_ci if (!separatedRendering_.separatePresent) { 7978bf80f4bSopenharmony_ci device_.Deactivate(); 7988bf80f4bSopenharmony_ci } 7998bf80f4bSopenharmony_ci 8008bf80f4bSopenharmony_ci renderDataStoreMgr_.PostRenderBackend(); 8018bf80f4bSopenharmony_ci 8028bf80f4bSopenharmony_ci renderFrameTimeData_.config = {}; 8038bf80f4bSopenharmony_ci 8048bf80f4bSopenharmony_ci // needs to be called after render data store post render 8058bf80f4bSopenharmony_ci renderUtil_.EndFrame(); 8068bf80f4bSopenharmony_ci 8078bf80f4bSopenharmony_ci // RenderFramePresentImpl() needs to be called every frame even thought there isn't presenting 8088bf80f4bSopenharmony_ci device_.FrameEnd(); 8098bf80f4bSopenharmony_ci ProcessTimeStampEnd(); 8108bf80f4bSopenharmony_ci 8118bf80f4bSopenharmony_ci // set presentation index (before mutexes) 8128bf80f4bSopenharmony_ci renderStatus_.presentIndex = renderStatus_.backEndIndex; 8138bf80f4bSopenharmony_ci if (separatedRendering_.separatePresent) { 8148bf80f4bSopenharmony_ci separatedRendering_.backMtx.unlock(); 8158bf80f4bSopenharmony_ci } 8168bf80f4bSopenharmony_ci} 8178bf80f4bSopenharmony_ci 8188bf80f4bSopenharmony_ciuint64_t Renderer::RenderFrame(const array_view<const RenderHandleReference> renderNodeGraphs) 8198bf80f4bSopenharmony_ci{ 8208bf80f4bSopenharmony_ci const auto lock = std::lock_guard(renderMutex_); 8218bf80f4bSopenharmony_ci 8228bf80f4bSopenharmony_ci // add only unique and valid handles to list for rendering 8238bf80f4bSopenharmony_ci vector<RenderHandle> rngs; 8248bf80f4bSopenharmony_ci rngs.reserve(renderNodeGraphs.size()); 8258bf80f4bSopenharmony_ci for (size_t iIdx = 0; iIdx < renderNodeGraphs.size(); ++iIdx) { 8268bf80f4bSopenharmony_ci const RenderHandle& handle = renderNodeGraphs[iIdx].GetHandle(); 8278bf80f4bSopenharmony_ci bool duplicate = false; 8288bf80f4bSopenharmony_ci for (auto& ref : rngs) { 8298bf80f4bSopenharmony_ci if (ref == handle) { 8308bf80f4bSopenharmony_ci duplicate = true; 8318bf80f4bSopenharmony_ci } 8328bf80f4bSopenharmony_ci } 8338bf80f4bSopenharmony_ci if ((RenderHandleUtil::GetHandleType(handle) == RenderHandleType::RENDER_NODE_GRAPH) && (!duplicate)) { 8348bf80f4bSopenharmony_ci rngs.push_back(handle); 8358bf80f4bSopenharmony_ci } 8368bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1) 8378bf80f4bSopenharmony_ci if (duplicate) { 8388bf80f4bSopenharmony_ci PLUGIN_LOG_ONCE_E("renderer_rf_duplicate_rng", 8398bf80f4bSopenharmony_ci "RENDER_VALIDATION: duplicate render node graphs are not supported (idx: %u, id: %" PRIx64, 8408bf80f4bSopenharmony_ci static_cast<uint32_t>(iIdx), handle.id); 8418bf80f4bSopenharmony_ci } 8428bf80f4bSopenharmony_ci#endif 8438bf80f4bSopenharmony_ci } 8448bf80f4bSopenharmony_ci device_.SetRenderFrameRunning(true); 8458bf80f4bSopenharmony_ci // NOTE: this is the only place from where RenderFrameImpl is called 8468bf80f4bSopenharmony_ci RenderFrameImpl(rngs); 8478bf80f4bSopenharmony_ci device_.SetRenderFrameRunning(false); 8488bf80f4bSopenharmony_ci 8498bf80f4bSopenharmony_ci return renderStatus_.frontEndIndex; 8508bf80f4bSopenharmony_ci} 8518bf80f4bSopenharmony_ci 8528bf80f4bSopenharmony_ciuint64_t Renderer::RenderDeferred(const array_view<const RenderHandleReference> renderNodeGraphs) 8538bf80f4bSopenharmony_ci{ 8548bf80f4bSopenharmony_ci const auto lock = std::lock_guard(deferredMutex_); 8558bf80f4bSopenharmony_ci for (const auto& ref : renderNodeGraphs) { 8568bf80f4bSopenharmony_ci deferredRenderNodeGraphs_.push_back(ref); 8578bf80f4bSopenharmony_ci } 8588bf80f4bSopenharmony_ci return renderStatusDeferred_ + 1; 8598bf80f4bSopenharmony_ci} 8608bf80f4bSopenharmony_ci 8618bf80f4bSopenharmony_ciuint64_t Renderer::RenderDeferredFrame() 8628bf80f4bSopenharmony_ci{ 8638bf80f4bSopenharmony_ci deferredMutex_.lock(); 8648bf80f4bSopenharmony_ci decltype(deferredRenderNodeGraphs_) renderNodeGraphs = move(deferredRenderNodeGraphs_); 8658bf80f4bSopenharmony_ci renderStatusDeferred_ = renderStatus_.frontEndIndex + 1; 8668bf80f4bSopenharmony_ci deferredMutex_.unlock(); 8678bf80f4bSopenharmony_ci RenderFrame(renderNodeGraphs); 8688bf80f4bSopenharmony_ci 8698bf80f4bSopenharmony_ci return renderStatus_.frontEndIndex; 8708bf80f4bSopenharmony_ci} 8718bf80f4bSopenharmony_ci 8728bf80f4bSopenharmony_civoid Renderer::ExecuteRenderNodes(const array_view<const RenderHandle> renderNodeGraphInputs, 8738bf80f4bSopenharmony_ci const array_view<RenderNodeGraphNodeStore*> renderNodeGraphNodeStores) 8748bf80f4bSopenharmony_ci{ 8758bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 8768bf80f4bSopenharmony_ci RENDER_CPU_PERF_BEGIN(fullExecuteCpuTimer, "Renderer", "Renderer", "ExecuteAllNodes_Cpu"); 8778bf80f4bSopenharmony_ci 8788bf80f4bSopenharmony_ci size_t allRenderNodeCount = 0; 8798bf80f4bSopenharmony_ci for (size_t graphIdx = 0; graphIdx < renderNodeGraphNodeStores.size(); ++graphIdx) { 8808bf80f4bSopenharmony_ci allRenderNodeCount += renderNodeGraphNodeStores[graphIdx]->renderNodeData.size(); 8818bf80f4bSopenharmony_ci } 8828bf80f4bSopenharmony_ci 8838bf80f4bSopenharmony_ci vector<NodeTimerData> nodeTimers(allRenderNodeCount); 8848bf80f4bSopenharmony_ci#endif 8858bf80f4bSopenharmony_ci 8868bf80f4bSopenharmony_ci ITaskQueue* queue = nullptr; 8878bf80f4bSopenharmony_ci if (device_.AllowThreadedProcessing()) { 8888bf80f4bSopenharmony_ci queue = parallelQueue_.get(); 8898bf80f4bSopenharmony_ci } else { 8908bf80f4bSopenharmony_ci queue = sequentialQueue_.get(); 8918bf80f4bSopenharmony_ci } 8928bf80f4bSopenharmony_ci 8938bf80f4bSopenharmony_ci // single threaded gpu resource creation with render nodes 8948bf80f4bSopenharmony_ci CreateGpuResourcesWithRenderNodes(renderNodeGraphNodeStores, renderDataStoreMgr_, shaderMgr_); 8958bf80f4bSopenharmony_ci 8968bf80f4bSopenharmony_ci // lock staging data for this frame 8978bf80f4bSopenharmony_ci // NOTE: should be done with double buffering earlier 8988bf80f4bSopenharmony_ci gpuResourceMgr_.LockFrameStagingData(); 8998bf80f4bSopenharmony_ci // final gpu resource allocation and deallocation before render node execute, and render graph 9008bf80f4bSopenharmony_ci device_.Activate(); 9018bf80f4bSopenharmony_ci gpuResourceMgr_.HandlePendingAllocations(); 9028bf80f4bSopenharmony_ci device_.Deactivate(); 9038bf80f4bSopenharmony_ci 9048bf80f4bSopenharmony_ci // process render node graph render node share preparations 9058bf80f4bSopenharmony_ci for (auto& ref : renderNodeGraphNodeStores) { 9068bf80f4bSopenharmony_ci ref->renderNodeGraphShareDataMgr->PrepareExecuteFrame(); 9078bf80f4bSopenharmony_ci } 9088bf80f4bSopenharmony_ci 9098bf80f4bSopenharmony_ci RenderNodeExecutionParameters params = { 9108bf80f4bSopenharmony_ci renderNodeGraphNodeStores, 9118bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 9128bf80f4bSopenharmony_ci nodeTimers, 9138bf80f4bSopenharmony_ci#endif 9148bf80f4bSopenharmony_ci queue, 9158bf80f4bSopenharmony_ci renderDataStoreMgr_, 9168bf80f4bSopenharmony_ci shaderMgr_, 9178bf80f4bSopenharmony_ci renderConfig_ 9188bf80f4bSopenharmony_ci }; 9198bf80f4bSopenharmony_ci 9208bf80f4bSopenharmony_ci // multi-threaded render node execution 9218bf80f4bSopenharmony_ci RenderNodeExecution(params); 9228bf80f4bSopenharmony_ci 9238bf80f4bSopenharmony_ci // Remove tasks. 9248bf80f4bSopenharmony_ci queue->Clear(); 9258bf80f4bSopenharmony_ci 9268bf80f4bSopenharmony_ci#if (RENDER_PERF_ENABLED == 1) 9278bf80f4bSopenharmony_ci RENDER_CPU_PERF_END(fullExecuteCpuTimer); 9288bf80f4bSopenharmony_ci 9298bf80f4bSopenharmony_ci if (auto* inst = GetInstance<IPerformanceDataManagerFactory>(UID_PERFORMANCE_FACTORY); inst) { 9308bf80f4bSopenharmony_ci if (IPerformanceDataManager* perfData = inst->Get("RenderNode"); perfData) { 9318bf80f4bSopenharmony_ci for (size_t nodeIdx = 0; nodeIdx < nodeTimers.size(); ++nodeIdx) { 9328bf80f4bSopenharmony_ci const auto& timerRef = nodeTimers[nodeIdx]; 9338bf80f4bSopenharmony_ci perfData->UpdateData(timerRef.debugName, "RenderNodeExecute_Cpu", timerRef.timer.GetMicroseconds()); 9348bf80f4bSopenharmony_ci } 9358bf80f4bSopenharmony_ci } 9368bf80f4bSopenharmony_ci } 9378bf80f4bSopenharmony_ci#endif 9388bf80f4bSopenharmony_ci} 9398bf80f4bSopenharmony_ci 9408bf80f4bSopenharmony_ciuint64_t Renderer::RenderFrameBackend(const RenderFrameBackendInfo& info) 9418bf80f4bSopenharmony_ci{ 9428bf80f4bSopenharmony_ci if (separatedRendering_.separateBackend) { 9438bf80f4bSopenharmony_ci RenderFrameBackendImpl(); 9448bf80f4bSopenharmony_ci } else { 9458bf80f4bSopenharmony_ci PLUGIN_LOG_E("RenderFrameBackend called separately even though render context not created as separate"); 9468bf80f4bSopenharmony_ci } 9478bf80f4bSopenharmony_ci 9488bf80f4bSopenharmony_ci return renderStatus_.backEndIndex; 9498bf80f4bSopenharmony_ci} 9508bf80f4bSopenharmony_ci 9518bf80f4bSopenharmony_ciuint64_t Renderer::RenderFramePresent(const RenderFramePresentInfo& info) 9528bf80f4bSopenharmony_ci{ 9538bf80f4bSopenharmony_ci if (separatedRendering_.separatePresent) { 9548bf80f4bSopenharmony_ci RenderFramePresentImpl(); 9558bf80f4bSopenharmony_ci } else { 9568bf80f4bSopenharmony_ci PLUGIN_LOG_E("RenderFramePresent called separately even though render context not created as separate"); 9578bf80f4bSopenharmony_ci } 9588bf80f4bSopenharmony_ci 9598bf80f4bSopenharmony_ci return renderStatus_.presentIndex; 9608bf80f4bSopenharmony_ci} 9618bf80f4bSopenharmony_ci 9628bf80f4bSopenharmony_ciIRenderer::RenderStatus Renderer::GetFrameStatus() const 9638bf80f4bSopenharmony_ci{ 9648bf80f4bSopenharmony_ci return renderStatus_; 9658bf80f4bSopenharmony_ci} 9668bf80f4bSopenharmony_ci 9678bf80f4bSopenharmony_civoid Renderer::FillRngInputs( 9688bf80f4bSopenharmony_ci const array_view<const RenderHandle> renderNodeGraphInputList, vector<RenderHandle>& rngInputs) 9698bf80f4bSopenharmony_ci{ 9708bf80f4bSopenharmony_ci constexpr size_t defaultRenderNodeGraphCount = 2; 9718bf80f4bSopenharmony_ci rngInputs.reserve(renderNodeGraphInputList.size() + defaultRenderNodeGraphCount); 9728bf80f4bSopenharmony_ci rngInputs.push_back(defaultStagingRng_.GetHandle()); 9738bf80f4bSopenharmony_ci rngInputs.insert(rngInputs.end(), renderNodeGraphInputList.begin().ptr(), renderNodeGraphInputList.end().ptr()); 9748bf80f4bSopenharmony_ci rngInputs.push_back(defaultEndFrameStagingRng_.GetHandle()); 9758bf80f4bSopenharmony_ci} 9768bf80f4bSopenharmony_ci 9778bf80f4bSopenharmony_civoid Renderer::ProcessTimeStampEnd() 9788bf80f4bSopenharmony_ci{ 9798bf80f4bSopenharmony_ci frameTimes_.end = GetTimeStampNow(); 9808bf80f4bSopenharmony_ci 9818bf80f4bSopenharmony_ci int64_t finalTime = frameTimes_.begin; 9828bf80f4bSopenharmony_ci finalTime = Math::max(finalTime, frameTimes_.beginBackend); 9838bf80f4bSopenharmony_ci frameTimes_.beginBackend = finalTime; 9848bf80f4bSopenharmony_ci 9858bf80f4bSopenharmony_ci finalTime = Math::max(finalTime, frameTimes_.endBackend); 9868bf80f4bSopenharmony_ci frameTimes_.endBackend = finalTime; 9878bf80f4bSopenharmony_ci 9888bf80f4bSopenharmony_ci finalTime = Math::max(finalTime, frameTimes_.beginBackendPresent); 9898bf80f4bSopenharmony_ci frameTimes_.beginBackendPresent = finalTime; 9908bf80f4bSopenharmony_ci 9918bf80f4bSopenharmony_ci finalTime = Math::max(finalTime, frameTimes_.endBackendPresent); 9928bf80f4bSopenharmony_ci frameTimes_.endBackendPresent = finalTime; 9938bf80f4bSopenharmony_ci 9948bf80f4bSopenharmony_ci finalTime = Math::max(finalTime, frameTimes_.end); 9958bf80f4bSopenharmony_ci frameTimes_.end = finalTime; 9968bf80f4bSopenharmony_ci 9978bf80f4bSopenharmony_ci PLUGIN_ASSERT(frameTimes_.end >= frameTimes_.endBackend); 9988bf80f4bSopenharmony_ci PLUGIN_ASSERT(frameTimes_.endBackend >= frameTimes_.beginBackend); 9998bf80f4bSopenharmony_ci PLUGIN_ASSERT(frameTimes_.beginBackendPresent >= frameTimes_.beginBackend); 10008bf80f4bSopenharmony_ci PLUGIN_ASSERT(frameTimes_.endBackendPresent >= frameTimes_.beginBackendPresent); 10018bf80f4bSopenharmony_ci 10028bf80f4bSopenharmony_ci renderUtil_.SetRenderTimings(frameTimes_); 10038bf80f4bSopenharmony_ci frameTimes_ = {}; 10048bf80f4bSopenharmony_ci} 10058bf80f4bSopenharmony_ci 10068bf80f4bSopenharmony_civoid Renderer::Tick() 10078bf80f4bSopenharmony_ci{ 10088bf80f4bSopenharmony_ci using namespace std::chrono; 10098bf80f4bSopenharmony_ci const auto currentTime = 10108bf80f4bSopenharmony_ci static_cast<uint64_t>(duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count()); 10118bf80f4bSopenharmony_ci 10128bf80f4bSopenharmony_ci if (firstTime_ == ~0u) { 10138bf80f4bSopenharmony_ci previousFrameTime_ = firstTime_ = currentTime; 10148bf80f4bSopenharmony_ci } 10158bf80f4bSopenharmony_ci deltaTime_ = currentTime - previousFrameTime_; 10168bf80f4bSopenharmony_ci constexpr auto limitHz = duration_cast<microseconds>(duration<float, std::ratio<1, 15u>>(1)).count(); 10178bf80f4bSopenharmony_ci if (deltaTime_ > limitHz) { 10188bf80f4bSopenharmony_ci deltaTime_ = limitHz; // clamp the time step to no longer than 15hz. 10198bf80f4bSopenharmony_ci } 10208bf80f4bSopenharmony_ci previousFrameTime_ = currentTime; 10218bf80f4bSopenharmony_ci} 10228bf80f4bSopenharmony_ciRENDER_END_NAMESPACE() 1023