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