1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_node_staging.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstring>
21 
22 #include <render/datastore/intf_render_data_store_manager.h>
23 #include <render/device/intf_gpu_resource_manager.h>
24 #include <render/namespace.h>
25 #include <render/nodecontext/intf_node_context_pso_manager.h>
26 #include <render/nodecontext/intf_render_command_list.h>
27 #include <render/nodecontext/intf_render_node_context_manager.h>
28 
29 #include "datastore/render_data_store_default_staging.h"
30 #include "util/log.h"
31 
32 using namespace BASE_NS;
33 
34 RENDER_BEGIN_NAMESPACE()
35 namespace {
CopyHostDirectlyToBuffer(const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingConsumeStruct & stagingConsumeStruct)36 void CopyHostDirectlyToBuffer(
37     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingConsumeStruct& stagingConsumeStruct)
38 {
39     for (const auto& ref : stagingConsumeStruct.cpuToBuffer) {
40         if (ref.invalidOperation) {
41             continue;
42         }
43         uint8_t* baseDstDataBegin = static_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ref.dstHandle.GetHandle()));
44         if (!baseDstDataBegin) {
45             PLUGIN_LOG_E("staging: direct dstHandle %" PRIu64, ref.dstHandle.GetHandle().id);
46             return;
47         }
48         auto const& bufferDesc = gpuResourceMgr.GetBufferDescriptor(ref.dstHandle.GetHandle());
49         const uint8_t* baseDstDataEnd = baseDstDataBegin + bufferDesc.byteSize;
50 
51         const uint8_t* baseSrcDataBegin = static_cast<const uint8_t*>(ref.stagingData.data());
52         const uint32_t bufferBeginIndex = ref.beginIndex;
53         const uint32_t bufferEndIndex = bufferBeginIndex + ref.count;
54         for (uint32_t bufferIdx = bufferBeginIndex; bufferIdx < bufferEndIndex; ++bufferIdx) {
55             PLUGIN_ASSERT(bufferIdx < stagingConsumeStruct.bufferCopies.size());
56             const BufferCopy& currBufferCopy = stagingConsumeStruct.bufferCopies[bufferIdx];
57             uint8_t* dstData = baseDstDataBegin + currBufferCopy.dstOffset;
58             const uint8_t* srcPtr = nullptr;
59             size_t srcSize = 0;
60             if (ref.dataType == StagingCopyStruct::DataType::DATA_TYPE_VECTOR) {
61                 srcPtr = baseSrcDataBegin + currBufferCopy.srcOffset;
62                 srcSize = currBufferCopy.size;
63             }
64             if ((srcPtr) && (srcSize > 0)) {
65                 PLUGIN_ASSERT(bufferDesc.byteSize >= srcSize);
66                 if (!CloneData(dstData, size_t(baseDstDataEnd - dstData), srcPtr, srcSize)) {
67                     PLUGIN_LOG_E("Copying of CPU data directly failed");
68                 }
69             }
70         }
71         gpuResourceMgr.UnmapBuffer(ref.dstHandle.GetHandle());
72     }
73 }
74 
CopyHostDirectlyToBuffer(const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingDirectDataCopyConsumeStruct & stagingData)75 void CopyHostDirectlyToBuffer(
76     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingDirectDataCopyConsumeStruct& stagingData)
77 {
78     for (const auto& ref : stagingData.dataCopies) {
79         uint8_t* data = static_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ref.dstHandle.GetHandle()));
80         if (!data) {
81             PLUGIN_LOG_E("staging: dstHandle %" PRIu64, ref.dstHandle.GetHandle().id);
82             return;
83         }
84         const size_t dstOffset = ref.bufferCopy.dstOffset;
85         data += dstOffset;
86         auto const& bufferDesc = gpuResourceMgr.GetBufferDescriptor(ref.dstHandle.GetHandle());
87         const uint8_t* srcPtr = ref.data.data() + ref.bufferCopy.srcOffset;
88         const size_t copySize =
89             std::min(ref.data.size() - size_t(ref.bufferCopy.srcOffset), size_t(ref.bufferCopy.size));
90         if ((srcPtr) && (copySize > 0)) {
91             PLUGIN_ASSERT((size_t(bufferDesc.byteSize) - dstOffset) >= copySize);
92             if (!CloneData(data, bufferDesc.byteSize - dstOffset, srcPtr, copySize)) {
93                 PLUGIN_LOG_E("Copying of staging data failed");
94             }
95         }
96         gpuResourceMgr.UnmapBuffer(ref.dstHandle.GetHandle());
97     }
98 }
99 } // namespace
100 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)101 void RenderNodeStaging::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
102 {
103     renderNodeContextMgr_ = &renderNodeContextMgr;
104     renderStaging.Init(*renderNodeContextMgr_);
105 
106     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
107     dataStoreNameStaging_ = renderNodeGraphData.renderNodeGraphName + "RenderDataStoreDefaultStaging";
108 }
109 
PreExecuteFrame()110 void RenderNodeStaging::PreExecuteFrame()
111 {
112     // re-create needed gpu resources
113     if (renderNodeContextMgr_->GetRenderNodeGraphData().renderingConfiguration.renderBackend ==
114         DeviceBackendType::OPENGLES) {
115         const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
116         if (RenderDataStoreDefaultStaging* dataStoreDefaultStaging = static_cast<RenderDataStoreDefaultStaging*>(
117                 renderDataStoreMgr.GetRenderDataStore(dataStoreNameStaging_));
118             dataStoreDefaultStaging) {
119             renderStaging.PreExecuteFrame(dataStoreDefaultStaging->GetImageClearByteSize());
120         }
121     }
122 }
123 
ExecuteFrame(IRenderCommandList & cmdList)124 void RenderNodeStaging::ExecuteFrame(IRenderCommandList& cmdList)
125 {
126     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
127     auto& gpuResourceMgrImpl =
128         static_cast<RenderNodeGpuResourceManager&>(renderNodeContextMgr_->GetGpuResourceManager());
129     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
130     bool hasData = gpuResourceMgrImpl.HasStagingData();
131 
132     StagingConsumeStruct renderDataStoreStaging;
133     StagingDirectDataCopyConsumeStruct renderDataStoreStagingDirectCopy;
134     StagingImageClearConsumeStruct renderDataStoreImageClear;
135     if (RenderDataStoreDefaultStaging* dataStoreDefaultStaging =
136             static_cast<RenderDataStoreDefaultStaging*>(renderDataStoreMgr.GetRenderDataStore(dataStoreNameStaging_));
137         dataStoreDefaultStaging) {
138         hasData = hasData || dataStoreDefaultStaging->HasBeginStagingData();
139         renderDataStoreStaging = dataStoreDefaultStaging->ConsumeBeginStagingData();
140         renderDataStoreStagingDirectCopy = dataStoreDefaultStaging->ConsumeBeginStagingDirectDataCopy();
141         renderDataStoreImageClear = dataStoreDefaultStaging->ConsumeBeginStagingImageClears();
142     }
143 
144     // early out, no data
145     if (!hasData) {
146         return;
147     }
148 
149     // memcpy to staging
150     const StagingConsumeStruct staging = gpuResourceMgrImpl.ConsumeStagingData();
151     renderStaging.CopyHostToStaging(gpuResourceMgr, staging);
152     renderStaging.CopyHostToStaging(gpuResourceMgr, renderDataStoreStaging);
153     // direct memcpy
154     CopyHostDirectlyToBuffer(gpuResourceMgr, staging);
155     CopyHostDirectlyToBuffer(gpuResourceMgr, renderDataStoreStagingDirectCopy);
156 
157     // images
158     renderStaging.ClearImages(cmdList, gpuResourceMgr, renderDataStoreImageClear);
159     renderStaging.CopyStagingToImages(cmdList, gpuResourceMgr, staging, renderDataStoreStaging);
160     renderStaging.CopyImagesToBuffers(cmdList, gpuResourceMgr, staging, renderDataStoreStaging);
161     renderStaging.CopyImagesToImages(cmdList, gpuResourceMgr, staging, renderDataStoreStaging);
162 
163     // buffers
164     renderStaging.CopyBuffersToBuffers(cmdList, staging, renderDataStoreStaging);
165 }
166 
167 // for plugin / factory interface
Create()168 IRenderNode* RenderNodeStaging::Create()
169 {
170     return new RenderNodeStaging();
171 }
172 
Destroy(IRenderNode * instance)173 void RenderNodeStaging::Destroy(IRenderNode* instance)
174 {
175     delete static_cast<RenderNodeStaging*>(instance);
176 }
177 RENDER_END_NAMESPACE()
178