• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "util/render_frame_util.h"
17 
18 #include <limits>
19 
20 #include <base/containers/fixed_string.h>
21 #include <render/datastore/intf_render_data_store_default_gpu_resource_data_copy.h>
22 #include <render/datastore/intf_render_data_store_default_staging.h>
23 #include <render/datastore/intf_render_data_store_manager.h>
24 #include <render/datastore/intf_render_data_store_pod.h>
25 #include <render/datastore/render_data_store_render_pods.h>
26 #include <render/device/intf_device.h>
27 #include <render/device/intf_gpu_resource_manager.h>
28 #include <render/intf_render_context.h>
29 
30 #include "device/device.h"
31 #include "device/gpu_resource_manager.h"
32 #include "device/gpu_semaphore.h"
33 #include "util/log.h"
34 
35 RENDER_BEGIN_NAMESPACE()
36 using namespace BASE_NS;
37 
38 namespace {
39 const string_view RENDER_DATA_STORE_DEFAULT_STAGING { "RenderDataStoreDefaultStaging" };
40 const string_view RENDER_DATA_STORE_DEFAULT_DATA_COPY { "RenderDataStoreDefaultGpuResourceDataCopy" };
41 const string_view RENDER_DATA_STORE_POD { "RenderDataStorePod" };
42 const string_view POD_NAME { "NodeGraphBackBufferConfiguration" };
43 
GetStagingBufferDesc(const uint32_t byteSize,const EngineBufferCreationFlags engineBufferCreationAdditionalFlags)44 GpuBufferDesc GetStagingBufferDesc(
45     const uint32_t byteSize, const EngineBufferCreationFlags engineBufferCreationAdditionalFlags)
46 {
47     return GpuBufferDesc {
48         CORE_BUFFER_USAGE_TRANSFER_DST_BIT,
49         CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT | CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
50         CORE_ENGINE_BUFFER_CREATION_DYNAMIC_BARRIERS | engineBufferCreationAdditionalFlags,
51         byteSize,
52         {},
53     };
54 }
55 } // namespace
56 
RenderFrameUtil(const IRenderContext & renderContext)57 RenderFrameUtil::RenderFrameUtil(const IRenderContext& renderContext)
58     : renderContext_(renderContext), device_(renderContext_.GetDevice())
59 {
60     bufferedPostFrame_.resize(device_.GetDeviceConfiguration().bufferingCount);
61     defaultCopyData_.byteBuffer = make_unique<ByteArray>(0U);
62 
63     const IRenderDataStoreManager& dsManager = renderContext.GetRenderDataStoreManager();
64     dsStaging_ = static_cast<IRenderDataStoreDefaultStaging*>(
65         dsManager.GetRenderDataStore(RENDER_DATA_STORE_DEFAULT_STAGING).get());
66     PLUGIN_ASSERT(dsStaging_);
67     dsCpuToGpuCopy_ = static_cast<IRenderDataStoreDefaultGpuResourceDataCopy*>(
68         dsManager.GetRenderDataStore(RENDER_DATA_STORE_DEFAULT_DATA_COPY).get());
69     PLUGIN_ASSERT(dsCpuToGpuCopy_);
70 }
71 
BeginFrame()72 void RenderFrameUtil::BeginFrame()
73 {
74     frameHasWaitForIdle_ = false;
75     {
76         auto ClearAndReserve = [](const size_t count, auto& frameData) {
77             frameData.copyData.clear();
78             frameData.copyData.reserve(count);
79         };
80 
81         const auto lock = std::lock_guard(mutex_);
82 
83         thisFrameCopiedData_.clear();
84         const uint64_t frameIndex = device_.GetFrameCount();
85         for (auto& ref : thisFrameSignalData_.gpuSemaphores) {
86             if (ref) {
87                 gpuSignalDeferredDestroy_.push_back({ frameIndex, move(ref) });
88             }
89         }
90         thisFrameSignalData_.gpuSemaphores.clear();
91         thisFrameSignalData_.signalData.clear();
92 
93         // process backbuffer
94         postBackBufferConfig_ = preBackBufferConfig_; // NOTE: copy
95         // process copies
96         const size_t count = preFrame_.copyData.size();
97         auto& bufferedPostFrame = bufferedPostFrame_[bufferedIndex_];
98         ClearAndReserve(count, postFrame_);
99         ClearAndReserve(count, bufferedPostFrame);
100         for (size_t idx = 0; idx < count; ++idx) {
101             if (preFrame_.copyData[idx].copyFlags == CopyFlagBits::WAIT_FOR_IDLE) {
102                 postFrame_.copyData.push_back(preFrame_.copyData[idx]);
103                 frameHasWaitForIdle_ = true;
104             } else {
105                 bufferedPostFrame.copyData.push_back(preFrame_.copyData[idx]);
106             }
107         }
108         preFrame_.copyData.clear();
109         // process signals
110         postSignalData_ = move(preSignalData_);
111         preSignalData_.clear();
112     }
113     // advance to next buffer position, the copies are done for the oldest data
114     bufferedIndex_ = (bufferedIndex_ + 1) % bufferedPostFrame_.size();
115 
116     // process deferred destruction
117     ProcessFrameSignalDeferredDestroy();
118 
119     ProcessFrameCopyData();
120     ProcessFrameSignalData();
121     ProcessFrameBackBufferConfiguration();
122 }
123 
ProcessFrameCopyData()124 void RenderFrameUtil::ProcessFrameCopyData()
125 {
126     // try to reserve
127     thisFrameCopiedData_.reserve(postFrame_.copyData.size() + bufferedPostFrame_[bufferedIndex_].copyData.size());
128 
129     // wait for idle
130     ProcessFrameInputCopyData(postFrame_);
131     // copy everything if wait for idle has been added
132     if (frameHasWaitForIdle_) {
133         for (auto& ref : bufferedPostFrame_) {
134             ProcessFrameInputCopyData(ref);
135         }
136     } else {
137         ProcessFrameInputCopyData(bufferedPostFrame_[bufferedIndex_]);
138     }
139 }
140 
ProcessFrameInputCopyData(const RenderFrameUtil::CopyData & copyData)141 void RenderFrameUtil::ProcessFrameInputCopyData(const RenderFrameUtil::CopyData& copyData)
142 {
143     IGpuResourceManager& gpuResourceMgr = device_.GetGpuResourceManager();
144     const auto count = static_cast<uint32_t>(copyData.copyData.size());
145     for (uint32_t idx = 0; idx < count; ++idx) {
146         const auto& dataToBeCopied = copyData.copyData[idx];
147         const RenderHandleType type = dataToBeCopied.handle.GetHandleType();
148         thisFrameCopiedData_.push_back({});
149         auto& copyDataRef = thisFrameCopiedData_.back();
150         copyDataRef = { {}, dataToBeCopied.frameIndex, dataToBeCopied.handle, dataToBeCopied.copyFlags, {} };
151 
152         const bool byteBufferCopy = ((dataToBeCopied.copyFlags & IRenderFrameUtil::GPU_BUFFER_ONLY) == 0);
153         const EngineBufferCreationFlags ebcf =
154             byteBufferCopy
155                 ? 0U
156                 : (CORE_ENGINE_BUFFER_CREATION_MAP_OUTSIDE_RENDERER | CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE);
157         if (type == RenderHandleType::GPU_BUFFER) {
158             const GpuBufferDesc desc = gpuResourceMgr.GetBufferDescriptor(dataToBeCopied.handle);
159             const uint32_t byteSize = desc.byteSize;
160 
161             copyDataRef.bufferHandle = gpuResourceMgr.Create(GetStagingBufferDesc(byteSize, ebcf));
162             // byte buffer only created if needed
163             if (byteBufferCopy) {
164                 copyDataRef.byteBuffer = make_unique<ByteArray>(byteSize);
165             }
166 
167             const BufferCopy bc {
168                 0,        // srcOffset
169                 0,        // dstOffset
170                 byteSize, // size
171             };
172             dsStaging_->CopyBufferToBuffer(dataToBeCopied.handle, copyDataRef.bufferHandle, bc,
173                 IRenderDataStoreDefaultStaging::ResourceCopyInfo::END_FRAME);
174         } else if (type == RenderHandleType::GPU_IMAGE) {
175             const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(dataToBeCopied.handle);
176             const uint32_t bytesPerPixel = gpuResourceMgr.GetFormatProperties(dataToBeCopied.handle).bytesPerPixel;
177             const uint32_t byteSize = desc.width * desc.height * bytesPerPixel;
178 
179             copyDataRef.bufferHandle = gpuResourceMgr.Create(GetStagingBufferDesc(byteSize, ebcf));
180             if (byteBufferCopy) {
181                 copyDataRef.byteBuffer = make_unique<ByteArray>(byteSize);
182             }
183 
184             const BufferImageCopy bic {
185                 0,                                                                // bufferOffset
186                 0,                                                                // bufferRowLength
187                 0,                                                                // bufferImageHeight
188                 ImageSubresourceLayers { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1u }, // imageSubresource
189                 Size3D { 0, 0, 0 },                                               // imageOffset
190                 Size3D { desc.width, desc.height, 1u },                           // imageExtent
191             };
192             dsStaging_->CopyImageToBuffer(dataToBeCopied.handle, copyDataRef.bufferHandle, bic,
193                 IRenderDataStoreDefaultStaging::ResourceCopyInfo::END_FRAME);
194         }
195 
196         if (copyDataRef.byteBuffer && copyDataRef.bufferHandle) {
197             IRenderDataStoreDefaultGpuResourceDataCopy::GpuResourceDataCopy dataCopy;
198             if (copyDataRef.copyFlags & CopyFlagBits::WAIT_FOR_IDLE) {
199                 dataCopy.copyType = IRenderDataStoreDefaultGpuResourceDataCopy::CopyType::WAIT_FOR_IDLE;
200             }
201             dataCopy.gpuHandle = copyDataRef.bufferHandle;
202             dataCopy.byteArray = copyDataRef.byteBuffer.get();
203             dsCpuToGpuCopy_->AddCopyOperation(dataCopy);
204         }
205     }
206 }
207 
ProcessFrameSignalData()208 void RenderFrameUtil::ProcessFrameSignalData()
209 {
210     // try to reserve
211     thisFrameSignalData_.gpuSemaphores.reserve(postSignalData_.size());
212     thisFrameSignalData_.signalData.reserve(postSignalData_.size());
213 
214     auto& device = (Device&)device_;
215     const DeviceBackendType backendType = device.GetBackendType();
216     // check the input data and create possible semaphores
217     for (const auto& ref : postSignalData_) {
218         SignalData sd = ref;
219         sd.signalResourceType = (backendType == DeviceBackendType::VULKAN) ? SignalResourceType::GPU_SEMAPHORE
220                                                                            : SignalResourceType::GPU_FENCE;
221         if (ref.gpuSignalResourceHandle) { // input signal handle given
222                                            // validity checked with input method
223             // create a view to external handle
224             thisFrameSignalData_.gpuSemaphores.push_back(device.CreateGpuSemaphoreView(ref.gpuSignalResourceHandle));
225         } else {
226             // create semaphore
227             thisFrameSignalData_.gpuSemaphores.push_back(device.CreateGpuSemaphore());
228         }
229         sd.gpuSignalResourceHandle = thisFrameSignalData_.gpuSemaphores.back()->GetHandle();
230         thisFrameSignalData_.signalData.push_back(sd);
231     }
232 }
233 
ProcessFrameBackBufferConfiguration()234 void RenderFrameUtil::ProcessFrameBackBufferConfiguration()
235 {
236     if (postBackBufferConfig_.force) {
237         const auto& rdsMgr = renderContext_.GetRenderDataStoreManager();
238         if (refcnt_ptr<IRenderDataStorePod> dataStorePod = rdsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD)) {
239             NodeGraphBackBufferConfiguration ngbbc;
240             ngbbc.backBufferName[postBackBufferConfig_.bbc.backBufferName.copy(
241                 ngbbc.backBufferName, countof(ngbbc.backBufferName) - 1)] = '\0';
242             ngbbc.backBufferType =
243                 static_cast<NodeGraphBackBufferConfiguration::BackBufferType>(postBackBufferConfig_.bbc.backBufferType);
244             ngbbc.backBufferHandle = postBackBufferConfig_.bbc.backBufferHandle.GetHandle();
245             ngbbc.gpuBufferHandle = postBackBufferConfig_.bbc.gpuBufferHandle.GetHandle();
246             ngbbc.present = postBackBufferConfig_.bbc.present;
247             ngbbc.gpuSemaphoreHandle = postBackBufferConfig_.bbc.gpuSemaphoreHandle;
248 
249             dataStorePod->Set(POD_NAME, arrayviewU8(ngbbc));
250         }
251     }
252 }
253 
ProcessFrameSignalDeferredDestroy()254 void RenderFrameUtil::ProcessFrameSignalDeferredDestroy()
255 {
256     // already used in previous frame
257     const auto& device = (const Device&)device_;
258     const uint64_t frameCount = device.GetFrameCount();
259     const auto minAge = device.GetCommandBufferingCount();
260     const auto ageLimit = (frameCount < minAge) ? 0 : (frameCount - minAge);
261 
262     for (auto iter = gpuSignalDeferredDestroy_.begin(); iter != gpuSignalDeferredDestroy_.end();) {
263         if (iter->frameUseIndex < ageLimit) {
264             iter = gpuSignalDeferredDestroy_.erase(iter);
265         } else {
266             ++iter;
267         }
268     }
269 }
270 
EndFrame()271 void RenderFrameUtil::EndFrame()
272 {
273     frameHasWaitForIdle_ = false;
274 
275     postFrame_.copyData.clear();
276     if (frameHasWaitForIdle_) {
277         for (auto& ref : bufferedPostFrame_) {
278             ref.copyData.clear();
279         }
280     } else {
281         bufferedPostFrame_[bufferedIndex_].copyData.clear();
282     }
283 }
284 
CopyToCpu(const RenderHandleReference & handle,const CopyFlags flags)285 void RenderFrameUtil::CopyToCpu(const RenderHandleReference& handle, const CopyFlags flags)
286 {
287     if (!ValidateInput(handle)) {
288         return;
289     }
290 
291     const auto lock = std::lock_guard(mutex_);
292 
293     const uint64_t frameIndex = device_.GetFrameCount();
294     preFrame_.copyData.push_back({ frameIndex, handle, flags });
295 }
296 
ValidateInput(const RenderHandleReference & handle)297 bool RenderFrameUtil::ValidateInput(const RenderHandleReference& handle)
298 {
299     bool valid = true;
300     const RenderHandleType type = handle.GetHandleType();
301     IGpuResourceManager& gpuResourceMgr = device_.GetGpuResourceManager();
302     if (type == RenderHandleType::GPU_BUFFER) {
303         const GpuBufferDesc desc = gpuResourceMgr.GetBufferDescriptor(handle);
304         if ((desc.usageFlags & BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_SRC_BIT) == 0) {
305             valid = false;
306 #if (RENDER_VALIDATION_ENABLED == 1)
307             const string strId = string("rfu_CopyToCpu_") + BASE_NS::to_string(handle.GetHandle().id);
308             PLUGIN_LOG_ONCE_W(strId.c_str(),
309                 "Render frame util needs usage flag CORE_BUFFER_USAGE_TRANSFER_SRC_BIT to CPU copies. (name:%s)",
310                 gpuResourceMgr.GetName(handle).c_str());
311 #endif
312         }
313     } else if (type == RenderHandleType::GPU_IMAGE) {
314         const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(handle);
315         if ((desc.usageFlags & BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_SRC_BIT) == 0) {
316             valid = false;
317 #if (RENDER_VALIDATION_ENABLED == 1)
318             const string strId = string("rfu_CopyToCpu_") + BASE_NS::to_string(handle.GetHandle().id);
319             PLUGIN_LOG_ONCE_W(strId.c_str(),
320                 "Render frame util needs usage flag CORE_BUFFER_USAGE_TRANSFER_SRC_BIT to CPU copies. (name:%s)",
321                 gpuResourceMgr.GetName(handle).c_str());
322 #endif
323         }
324     } else {
325         valid = false;
326 #if (RENDER_VALIDATION_ENABLED == 1)
327         const string strId = string("rfu_CopyToCpu_") + BASE_NS::to_string(handle.GetHandle().id);
328         PLUGIN_LOG_ONCE_W(strId.c_str(), "Render frame util CopyToCpu works only on GPU buffers and images.");
329 #endif
330     }
331     return valid;
332 }
333 
GetFrameCopyData()334 array_view<IRenderFrameUtil::FrameCopyData> RenderFrameUtil::GetFrameCopyData()
335 {
336     // NOTE: not thread safe (should not be called during rendering)
337     return thisFrameCopiedData_;
338 }
339 
GetFrameCopyData(const RenderHandleReference & handle)340 const IRenderFrameUtil::FrameCopyData& RenderFrameUtil::GetFrameCopyData(const RenderHandleReference& handle)
341 {
342     // NOTE: not thread safe (should not be called during rendering)
343     if (handle) {
344         const RenderHandle rawHandle = handle.GetHandle();
345         for (const auto& ref : thisFrameCopiedData_) {
346             if (ref.handle.GetHandle() == rawHandle) {
347                 return ref;
348             }
349         }
350     }
351     return defaultCopyData_;
352 }
353 
SetBackBufferConfiguration(const BackBufferConfiguration & backBufferConfiguration)354 void RenderFrameUtil::SetBackBufferConfiguration(const BackBufferConfiguration& backBufferConfiguration)
355 {
356     const auto lock = std::lock_guard(mutex_);
357 
358     preBackBufferConfig_.force = true;
359     preBackBufferConfig_.bbc = backBufferConfiguration;
360 }
361 
AddGpuSignal(const SignalData & signalData)362 void RenderFrameUtil::AddGpuSignal(const SignalData& signalData)
363 {
364     bool valid = true;
365     if (signalData.signaled) {
366         valid = false;
367         PLUGIN_LOG_E("Already signalled GPU signal cannot be processed. (Not supported)");
368     }
369     if (signalData.gpuSignalResourceHandle) {
370         const DeviceBackendType backendType = device_.GetBackendType();
371         const SignalResourceType signalResourceType = signalData.signalResourceType;
372         if ((backendType == DeviceBackendType::VULKAN) && (signalResourceType != SignalResourceType::GPU_SEMAPHORE)) {
373             valid = false;
374         } else if ((backendType != DeviceBackendType::VULKAN) &&
375                    (signalResourceType != SignalResourceType::GPU_FENCE)) {
376             valid = false;
377         }
378         if (!valid) {
379             PLUGIN_LOG_E("Invalid signal type (%u) for platform (%u)", static_cast<uint32_t>(signalResourceType),
380                 static_cast<uint32_t>(backendType));
381         }
382     }
383 
384     if (valid) {
385         const auto lock = std::lock_guard(mutex_);
386 
387         preSignalData_.push_back(signalData);
388     }
389 }
390 
GetFrameGpuSignalData()391 BASE_NS::array_view<IRenderFrameUtil::SignalData> RenderFrameUtil::GetFrameGpuSignalData()
392 {
393     // NOTE: not thread safe (should not be called during rendering)
394     return thisFrameSignalData_.signalData;
395 }
396 
GetFrameGpuSignalData(const RenderHandleReference & handle)397 IRenderFrameUtil::SignalData RenderFrameUtil::GetFrameGpuSignalData(const RenderHandleReference& handle)
398 {
399     // NOTE: not thread safe (should not be called during rendering)
400     if (handle) {
401         const RenderHandle rawHandle = handle.GetHandle();
402         for (const auto& ref : thisFrameSignalData_.signalData) {
403             if (ref.handle.GetHandle() == rawHandle) {
404                 return ref;
405             }
406         }
407     }
408     return {};
409 }
410 
HasGpuSignals() const411 bool RenderFrameUtil::HasGpuSignals() const
412 {
413     return !thisFrameSignalData_.gpuSemaphores.empty();
414 }
415 
GetGpuSemaphores()416 array_view<unique_ptr<GpuSemaphore>> RenderFrameUtil::GetGpuSemaphores()
417 {
418     return thisFrameSignalData_.gpuSemaphores;
419 }
420 
421 RENDER_END_NAMESPACE()
422