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_data_store_default_staging.h"
17 
18 #include <cstdint>
19 
20 #include <render/datastore/intf_render_data_store_default_staging.h>
21 #include <render/device/gpu_resource_desc.h>
22 #include <render/device/intf_device.h>
23 #include <render/device/intf_gpu_resource_manager.h>
24 #include <render/intf_render_context.h>
25 #include <render/namespace.h>
26 #include <render/resource_handle.h>
27 
28 #include "device/gpu_resource_manager.h"
29 #include "util/log.h"
30 
31 using namespace BASE_NS;
32 
RENDER_BEGIN_NAMESPACE()33 RENDER_BEGIN_NAMESPACE()
34 RenderDataStoreDefaultStaging::RenderDataStoreDefaultStaging(IRenderContext& renderContext, const string_view name)
35     : gpuResourceMgr_(renderContext.GetDevice().GetGpuResourceManager()), name_(name)
36 {}
37 
~RenderDataStoreDefaultStaging()38 RenderDataStoreDefaultStaging::~RenderDataStoreDefaultStaging() {}
39 
PreRender()40 void RenderDataStoreDefaultStaging::PreRender()
41 {
42     // get stuff ready for render nodes
43 
44     std::lock_guard<std::mutex> lock(mutex_);
45 
46     frameStagingConsumeData_ = move(stagingConsumeData_);
47     frameStagingConsumeGpuBuffers_ = move(stagingGpuBuffers_);
48 }
49 
PostRender()50 void RenderDataStoreDefaultStaging::PostRender()
51 {
52     std::lock_guard<std::mutex> lock(mutex_);
53 
54     // destroy already consumed staging buffers
55     frameStagingConsumeGpuBuffers_.clear();
56 }
57 
Clear()58 void RenderDataStoreDefaultStaging::Clear()
59 {
60     // The data cannot be automatically cleared here
61 }
62 
CopyImageToBuffer(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const BufferImageCopy & bufferImageCopy,const ResourceCopyInfo copyInfo)63 void RenderDataStoreDefaultStaging::CopyImageToBuffer(const RenderHandleReference& srcHandle,
64     const RenderHandleReference& dstHandle, const BufferImageCopy& bufferImageCopy, const ResourceCopyInfo copyInfo)
65 {
66     if (gpuResourceMgr_.IsGpuImage(srcHandle) && gpuResourceMgr_.IsGpuBuffer(dstHandle)) {
67         std::lock_guard<std::mutex> lock(mutex_);
68 
69         auto& staging =
70             (copyInfo == ResourceCopyInfo::BEGIN_FRAME) ? stagingConsumeData_.beginFrame : stagingConsumeData_.endFrame;
71         const uint32_t beginIndex = static_cast<uint32_t>(staging.bufferImageCopies.size());
72         staging.bufferImageCopies.push_back(bufferImageCopy);
73 
74         staging.imageToBuffer.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_SRC_TO_DST_COPY,
75             srcHandle, dstHandle, beginIndex, 1u, {}, nullptr });
76     }
77 }
78 
CopyImageToImage(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const ImageCopy & imageCopy,const ResourceCopyInfo copyInfo)79 void RenderDataStoreDefaultStaging::CopyImageToImage(const RenderHandleReference& srcHandle,
80     const RenderHandleReference& dstHandle, const ImageCopy& imageCopy, const ResourceCopyInfo copyInfo)
81 {
82     if (gpuResourceMgr_.IsGpuImage(srcHandle) && gpuResourceMgr_.IsGpuImage(dstHandle)) {
83         std::lock_guard<std::mutex> lock(mutex_);
84 
85         auto& staging =
86             (copyInfo == ResourceCopyInfo::BEGIN_FRAME) ? stagingConsumeData_.beginFrame : stagingConsumeData_.endFrame;
87         const uint32_t beginIndex = static_cast<uint32_t>(staging.imageCopies.size());
88         staging.imageCopies.push_back(imageCopy);
89 
90         staging.imageToImage.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_SRC_TO_DST_COPY,
91             srcHandle, dstHandle, beginIndex, 1u, {}, nullptr });
92     }
93 }
94 
CopyBufferToBuffer(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const BufferCopy & bufferCopy,const ResourceCopyInfo copyInfo)95 void RenderDataStoreDefaultStaging::CopyBufferToBuffer(const RenderHandleReference& srcHandle,
96     const RenderHandleReference& dstHandle, const BufferCopy& bufferCopy, const ResourceCopyInfo copyInfo)
97 {
98     if (gpuResourceMgr_.IsGpuBuffer(srcHandle) && gpuResourceMgr_.IsGpuBuffer(dstHandle)) {
99         std::lock_guard<std::mutex> lock(mutex_);
100 
101         auto& staging =
102             (copyInfo == ResourceCopyInfo::BEGIN_FRAME) ? stagingConsumeData_.beginFrame : stagingConsumeData_.endFrame;
103         const uint32_t beginIndex = static_cast<uint32_t>(staging.bufferCopies.size());
104         staging.bufferCopies.push_back(bufferCopy);
105 
106         staging.bufferToBuffer.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_DIRECT_SRC_COPY,
107             srcHandle, dstHandle, beginIndex, 1u, {}, nullptr });
108     }
109 }
110 
CopyBufferToImage(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const BufferImageCopy & bufferImageCopy,const ResourceCopyInfo copyInfo)111 void RenderDataStoreDefaultStaging::CopyBufferToImage(const RenderHandleReference& srcHandle,
112     const RenderHandleReference& dstHandle, const BufferImageCopy& bufferImageCopy, const ResourceCopyInfo copyInfo)
113 {
114     if (gpuResourceMgr_.IsGpuBuffer(srcHandle) && gpuResourceMgr_.IsGpuImage(dstHandle)) {
115         std::lock_guard<std::mutex> lock(mutex_);
116 
117         auto& staging =
118             (copyInfo == ResourceCopyInfo::BEGIN_FRAME) ? stagingConsumeData_.beginFrame : stagingConsumeData_.endFrame;
119         const uint32_t beginIndex = static_cast<uint32_t>(staging.bufferImageCopies.size());
120         staging.bufferImageCopies.push_back(bufferImageCopy);
121 
122         staging.bufferToImage.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_DIRECT_SRC_COPY,
123             srcHandle, dstHandle, beginIndex, 1u, {}, nullptr });
124     }
125 }
126 
ClearColorImage(const RenderHandleReference & handle,const ClearColorValue color)127 void RenderDataStoreDefaultStaging::ClearColorImage(const RenderHandleReference& handle, const ClearColorValue color)
128 {
129     if (gpuResourceMgr_.IsGpuImage(handle) && (!RenderHandleUtil::IsDepthImage(handle.GetHandle()))) {
130         std::lock_guard<std::mutex> lock(mutex_);
131 
132         stagingConsumeData_.beginFrameClear.clears.push_back({ handle, color });
133     }
134 }
135 
CopyDataToBuffer(const array_view<const uint8_t> & dat,const RenderHandleReference & dstHandle,const BufferCopy & bufferCopy)136 void RenderDataStoreDefaultStaging::CopyDataToBuffer(
137     const array_view<const uint8_t>& dat, const RenderHandleReference& dstHandle, const BufferCopy& bufferCopy)
138 {
139     if ((dat.size_bytes() > 0) && gpuResourceMgr_.IsGpuBuffer(dstHandle)) {
140         // NOTE: validation
141         // create staging buffer
142         const GpuBufferDesc stagingBufferDesc =
143             GpuResourceManager::GetStagingBufferDesc(static_cast<uint32_t>(dat.size_bytes()));
144         const RenderHandleReference stagingBufferHandle = gpuResourceMgr_.Create(stagingBufferDesc);
145 
146         std::lock_guard<std::mutex> lock(mutex_);
147 
148         stagingGpuBuffers_.push_back(stagingBufferHandle);
149 
150         auto& staging = stagingConsumeData_.beginFrame;
151         const uint32_t beginIndex = static_cast<uint32_t>(staging.bufferCopies.size());
152         staging.bufferCopies.push_back(BufferCopy { 0, 0, static_cast<uint32_t>(dat.size_bytes()) });
153 
154         vector<uint8_t> copiedData(dat.cbegin().ptr(), dat.cend().ptr());
155         staging.bufferToBuffer.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_VECTOR,
156             stagingBufferHandle, dstHandle, beginIndex, 1, move(copiedData), nullptr });
157     }
158 }
159 
CopyDataToBufferOnCpu(const array_view<const uint8_t> & dat,const RenderHandleReference & dstHandle,const BufferCopy & bufferCopy)160 void RenderDataStoreDefaultStaging::CopyDataToBufferOnCpu(
161     const array_view<const uint8_t>& dat, const RenderHandleReference& dstHandle, const BufferCopy& bufferCopy)
162 {
163     if ((dat.size_bytes() > 0) && gpuResourceMgr_.IsGpuBuffer(dstHandle)) {
164         const GpuBufferDesc bufDesc = gpuResourceMgr_.GetBufferDescriptor(dstHandle);
165         if ((bufDesc.memoryPropertyFlags & CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
166             (bufDesc.memoryPropertyFlags & CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
167             PLUGIN_ASSERT(bufferCopy.size <= static_cast<uint32_t>(dat.size()));
168 
169             std::lock_guard<std::mutex> lock(mutex_);
170 
171             vector<uint8_t> copiedData(dat.cbegin().ptr(), dat.cend().ptr());
172             stagingConsumeData_.beginFrameDirect.dataCopies.push_back(
173                 DirectDataCopyOnCpu { dstHandle, bufferCopy, move(copiedData) });
174         } else {
175             PLUGIN_LOG_E("CopyDataToBufferOnCpu invalid buffer given (needs host_visibile and host_coherent).");
176         }
177     }
178 }
179 
CopyDataToImage(const array_view<const uint8_t> & dat,const RenderHandleReference & dstHandle,const BufferImageCopy & bufferImageCopy)180 void RenderDataStoreDefaultStaging::CopyDataToImage(const array_view<const uint8_t>& dat,
181     const RenderHandleReference& dstHandle, const BufferImageCopy& bufferImageCopy)
182 {
183     if ((dat.size_bytes() > 0) && gpuResourceMgr_.IsGpuImage(dstHandle)) {
184         // NOTE: validation
185         // create staging buffer
186         const GpuBufferDesc stagingBufferDesc =
187             GpuResourceManager::GetStagingBufferDesc(static_cast<uint32_t>(dat.size_bytes()));
188         const RenderHandleReference& stagingBufferHandle = gpuResourceMgr_.Create(stagingBufferDesc);
189 
190         std::lock_guard<std::mutex> lock(mutex_);
191 
192         stagingGpuBuffers_.push_back(stagingBufferHandle);
193 
194         auto& staging = stagingConsumeData_.beginFrame;
195         const uint32_t beginIndex = static_cast<uint32_t>(staging.bufferImageCopies.size());
196         staging.bufferImageCopies.push_back(bufferImageCopy);
197 
198         vector<uint8_t> copiedData(dat.cbegin().ptr(), dat.cend().ptr());
199         staging.bufferToImage.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_VECTOR,
200             stagingBufferHandle, dstHandle, beginIndex, 1, move(copiedData), nullptr });
201     }
202 }
203 
CopyBufferToImage(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,BASE_NS::array_view<const BufferImageCopy> bufferImageCopies)204 void RenderDataStoreDefaultStaging::CopyBufferToImage(const RenderHandleReference& srcHandle,
205     const RenderHandleReference& dstHandle, BASE_NS::array_view<const BufferImageCopy> bufferImageCopies)
206 {
207     if (gpuResourceMgr_.IsGpuBuffer(srcHandle) && gpuResourceMgr_.IsGpuImage(dstHandle)) {
208         std::lock_guard<std::mutex> lock(mutex_);
209 
210         auto& staging = stagingConsumeData_.beginFrame;
211         const uint32_t beginIndex = static_cast<uint32_t>(staging.bufferImageCopies.size());
212         staging.bufferImageCopies.insert(
213             staging.bufferImageCopies.end(), bufferImageCopies.begin(), bufferImageCopies.end());
214 
215         staging.bufferToImage.push_back(StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_DIRECT_SRC_COPY,
216             srcHandle, dstHandle, beginIndex, static_cast<uint32_t>(bufferImageCopies.size()), {}, nullptr });
217     }
218 }
219 
CopyBufferToBuffer(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const BufferCopy & bufferCopy)220 void RenderDataStoreDefaultStaging::CopyBufferToBuffer(
221     const RenderHandleReference& srcHandle, const RenderHandleReference& dstHandle, const BufferCopy& bufferCopy)
222 {
223     CopyBufferToBuffer(srcHandle, dstHandle, bufferCopy, ResourceCopyInfo::BEGIN_FRAME);
224 }
225 
CopyBufferToImage(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const BufferImageCopy & bufferImageCopy)226 void RenderDataStoreDefaultStaging::CopyBufferToImage(const RenderHandleReference& srcHandle,
227     const RenderHandleReference& dstHandle, const BufferImageCopy& bufferImageCopy)
228 {
229     CopyBufferToImage(srcHandle, dstHandle, bufferImageCopy, ResourceCopyInfo::BEGIN_FRAME);
230 }
231 
CopyImageToBuffer(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const BufferImageCopy & bufferImageCopy)232 void RenderDataStoreDefaultStaging::CopyImageToBuffer(const RenderHandleReference& srcHandle,
233     const RenderHandleReference& dstHandle, const BufferImageCopy& bufferImageCopy)
234 {
235     CopyImageToBuffer(srcHandle, dstHandle, bufferImageCopy, ResourceCopyInfo::BEGIN_FRAME);
236 }
237 
CopyImageToImage(const RenderHandleReference & srcHandle,const RenderHandleReference & dstHandle,const ImageCopy & imageCopy)238 void RenderDataStoreDefaultStaging::CopyImageToImage(
239     const RenderHandleReference& srcHandle, const RenderHandleReference& dstHandle, const ImageCopy& imageCopy)
240 {
241     CopyImageToImage(srcHandle, dstHandle, imageCopy, ResourceCopyInfo::BEGIN_FRAME);
242 }
243 
HasBeginStagingData() const244 bool RenderDataStoreDefaultStaging::HasBeginStagingData() const
245 {
246     const auto& staging = frameStagingConsumeData_;
247     const auto& begStaging = staging.beginFrame;
248     const bool noBeginStaging = begStaging.bufferToBuffer.empty() && begStaging.bufferToImage.empty() &&
249                                 begStaging.imageToBuffer.empty() && begStaging.imageToImage.empty() &&
250                                 begStaging.cpuToBuffer.empty() && begStaging.bufferCopies.empty() &&
251                                 begStaging.bufferImageCopies.empty() && begStaging.imageCopies.empty();
252     const bool noBeginDirectCopy = staging.beginFrameDirect.dataCopies.empty();
253     const bool noBeginClear = staging.beginFrameClear.clears.empty();
254     if (noBeginStaging && noBeginDirectCopy && noBeginClear) {
255         return false;
256     } else {
257         return true;
258     }
259 }
260 
HasEndStagingData() const261 bool RenderDataStoreDefaultStaging::HasEndStagingData() const
262 {
263     const auto& endStaging = frameStagingConsumeData_.endFrame;
264     const bool noEndStaging = endStaging.bufferToBuffer.empty() && endStaging.bufferToImage.empty() &&
265                               endStaging.imageToBuffer.empty() && endStaging.imageToImage.empty() &&
266                               endStaging.cpuToBuffer.empty() && endStaging.bufferCopies.empty() &&
267                               endStaging.bufferImageCopies.empty() && endStaging.imageCopies.empty();
268     if (noEndStaging) {
269         return false;
270     } else {
271         return true;
272     }
273 }
274 
ConsumeBeginStagingData()275 StagingConsumeStruct RenderDataStoreDefaultStaging::ConsumeBeginStagingData()
276 {
277     StagingConsumeStruct scs = move(frameStagingConsumeData_.beginFrame);
278     return scs;
279 }
280 
ConsumeBeginStagingDirectDataCopy()281 StagingDirectDataCopyConsumeStruct RenderDataStoreDefaultStaging::ConsumeBeginStagingDirectDataCopy()
282 {
283     StagingDirectDataCopyConsumeStruct scs = move(frameStagingConsumeData_.beginFrameDirect);
284     return scs;
285 }
286 
ConsumeBeginStagingImageClears()287 StagingImageClearConsumeStruct RenderDataStoreDefaultStaging::ConsumeBeginStagingImageClears()
288 {
289     StagingImageClearConsumeStruct scs = move(frameStagingConsumeData_.beginFrameClear);
290     return scs;
291 }
292 
ConsumeEndStagingData()293 StagingConsumeStruct RenderDataStoreDefaultStaging::ConsumeEndStagingData()
294 {
295     StagingConsumeStruct scs = move(frameStagingConsumeData_.endFrame);
296     return scs;
297 }
298 
GetImageClearByteSize() const299 uint32_t RenderDataStoreDefaultStaging::GetImageClearByteSize() const
300 {
301     uint32_t byteSize = 0;
302     for (const auto& ref : frameStagingConsumeData_.beginFrameClear.clears) {
303         const GpuImageDesc desc = gpuResourceMgr_.GetImageDescriptor(ref.handle);
304         const uint32_t pixelBytes = gpuResourceMgr_.GetFormatProperties(ref.handle).bytesPerPixel;
305         byteSize += (pixelBytes * desc.width * desc.height); // no 3D supported
306     }
307     return byteSize;
308 }
309 
310 // for plugin / factory interface
Create(IRenderContext & renderContext,char const * name)311 IRenderDataStore* RenderDataStoreDefaultStaging::Create(IRenderContext& renderContext, char const* name)
312 {
313     return new RenderDataStoreDefaultStaging(renderContext, name);
314 }
315 
Destroy(IRenderDataStore * instance)316 void RenderDataStoreDefaultStaging::Destroy(IRenderDataStore* instance)
317 {
318     delete static_cast<RenderDataStoreDefaultStaging*>(instance);
319 }
320 RENDER_END_NAMESPACE()
321