• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 {
36 constexpr uint32_t MIP_MAP_TILING_FEATURES { CORE_FORMAT_FEATURE_BLIT_DST_BIT | CORE_FORMAT_FEATURE_BLIT_SRC_BIT };
37 
ExplicitBarrierUndefinedImageToTransferDst(IRenderCommandList & cmdList,const RenderHandle handle)38 void ExplicitBarrierUndefinedImageToTransferDst(IRenderCommandList& cmdList, const RenderHandle handle)
39 {
40     const ImageResourceBarrier src { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
41         PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
42         ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED }; // NOTE: undefined, because we do not care the previous data
43     const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
44         PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT, ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
45     const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
46         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
47     cmdList.CustomImageBarrier(handle, src, dst, imageSubresourceRange);
48     cmdList.AddCustomBarrierPoint();
49 }
50 
ExplicitBarrierTransferDstImageToTransferSrc(IRenderCommandList & cmdList,const RenderHandle handle)51 void ExplicitBarrierTransferDstImageToTransferSrc(IRenderCommandList& cmdList, const RenderHandle handle)
52 {
53     const ImageResourceBarrier src { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
54         PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT, ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
55     const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
56         PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT, ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL };
57     const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
58         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
59     cmdList.CustomImageBarrier(handle, src, dst, imageSubresourceRange);
60     cmdList.AddCustomBarrierPoint();
61 }
62 
BlitScalingImage(IRenderCommandList & cmdList,const BufferImageCopy & copy,const RenderHandle srcHandle,const RenderHandle dstHandle,const GpuImageDesc & dstImageDesc)63 void BlitScalingImage(IRenderCommandList& cmdList, const BufferImageCopy& copy, const RenderHandle srcHandle,
64     const RenderHandle dstHandle, const GpuImageDesc& dstImageDesc)
65 {
66     const ImageBlit imageBlit {
67         {
68             ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT,
69             0,
70             0,
71             1,
72         },
73         {
74             { 0, 0, 0 },
75             { copy.imageExtent.width, copy.imageExtent.height, 1 },
76         },
77         {
78             ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT,
79             0,
80             0,
81             1,
82         },
83         {
84             { 0, 0, 0 },
85             { dstImageDesc.width, dstImageDesc.height, 1 },
86         },
87     };
88     constexpr Filter filter = Filter::CORE_FILTER_LINEAR;
89     cmdList.BlitImage(srcHandle, dstHandle, imageBlit, filter);
90 }
91 
GetMipLevelSize(uint32_t originalSize,uint32_t mipLevel)92 uint32_t GetMipLevelSize(uint32_t originalSize, uint32_t mipLevel)
93 {
94     const uint32_t mipSize = originalSize >> mipLevel;
95     return mipSize >= 1u ? mipSize : 1u;
96 }
97 
GenerateMipmaps(IRenderCommandList & cmdList,const GpuImageDesc & imageDesc,const RenderHandle mipImageHandle,const uint32_t currentMipLevel)98 void GenerateMipmaps(IRenderCommandList& cmdList, const GpuImageDesc& imageDesc, const RenderHandle mipImageHandle,
99     const uint32_t currentMipLevel)
100 {
101     constexpr Filter filter = Filter::CORE_FILTER_LINEAR;
102     const uint32_t mipCount = imageDesc.mipCount;
103     const uint32_t layerCount = imageDesc.layerCount;
104 
105     const uint32_t iw = imageDesc.width;
106     const uint32_t ih = imageDesc.height;
107     for (uint32_t mipIdx = currentMipLevel + 1; mipIdx < mipCount; ++mipIdx) {
108         const uint32_t dstMipLevel = mipIdx;
109         const uint32_t srcMipLevel = dstMipLevel - 1;
110         // explicit transition for src mip
111         {
112             const ImageResourceBarrier src { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
113                 PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
114                 ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
115             const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
116                 PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
117                 ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL };
118             const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT,
119                 srcMipLevel, 1, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
120             cmdList.CustomImageBarrier(mipImageHandle, src, dst, imageSubresourceRange);
121             cmdList.AddCustomBarrierPoint();
122         }
123         {
124             const ImageBlit imageBlit {
125                 {
126                     ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT,
127                     srcMipLevel,
128                     0,
129                     layerCount,
130                 },
131                 {
132                     { 0, 0, 0 },
133                     { GetMipLevelSize(iw, srcMipLevel), GetMipLevelSize(ih, srcMipLevel), 1 },
134                 },
135                 {
136                     ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT,
137                     dstMipLevel,
138                     0,
139                     layerCount,
140                 },
141                 {
142                     { 0, 0, 0 },
143                     { GetMipLevelSize(iw, dstMipLevel), GetMipLevelSize(ih, dstMipLevel), 1 },
144                 },
145             };
146             cmdList.BlitImage(mipImageHandle, mipImageHandle, imageBlit, filter);
147 
148             // explicit "out" transition for src mip to dst to enable easy all mip transition in the end
149             {
150                 const ImageResourceBarrier src { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
151                     PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
152                     ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL };
153                 const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
154                     PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
155                     ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
156                 const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT,
157                     srcMipLevel, 1, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
158                 cmdList.CustomImageBarrier(mipImageHandle, src, dst, imageSubresourceRange);
159                 cmdList.AddCustomBarrierPoint();
160             }
161         }
162     }
163 }
164 
CopyBuffersToImages(const IRenderNodeGpuResourceManager & gpuResourceMgr,IRenderCommandList & cmdList,const vector<StagingCopyStruct> & bufferToImage,const vector<BufferImageCopy> & bufferImageCopies,const ScalingImageDataStruct & scalingImageData)165 void CopyBuffersToImages(const IRenderNodeGpuResourceManager& gpuResourceMgr, IRenderCommandList& cmdList,
166     const vector<StagingCopyStruct>& bufferToImage, const vector<BufferImageCopy>& bufferImageCopies,
167     const ScalingImageDataStruct& scalingImageData)
168 {
169     for (const auto& ref : bufferToImage) {
170         if (ref.invalidOperation) {
171             continue;
172         }
173         const uint32_t beginIndex = ref.beginIndex;
174         const uint32_t count = ref.count;
175         for (uint32_t idx = 0; idx < count; ++idx) {
176             const BufferImageCopy& copyRef = bufferImageCopies[beginIndex + idx];
177             // barriers are only done for dynamic resources automatically (e.g. when copying to same image multiple
178             // times)
179             // NOTE: add desc to data (so we do not need to lock gpu resource manager)
180             const GpuImageDesc imageDesc = gpuResourceMgr.GetImageDescriptor(ref.dstHandle.GetHandle());
181             RenderHandle bufferToImageDst = ref.dstHandle.GetHandle();
182             bool useScaling = false;
183             if (ref.format != Format::BASE_FORMAT_UNDEFINED) {
184                 if (const auto iter = scalingImageData.formatToScalingImages.find(ref.format);
185                     iter != scalingImageData.formatToScalingImages.cend()) {
186                     PLUGIN_ASSERT(iter->second < scalingImageData.scalingImages.size());
187                     bufferToImageDst = scalingImageData.scalingImages[iter->second].handle.GetHandle();
188                     ExplicitBarrierUndefinedImageToTransferDst(cmdList, bufferToImageDst);
189                     useScaling = true;
190                 }
191             }
192             cmdList.CopyBufferToImage(ref.srcHandle.GetHandle(), bufferToImageDst, copyRef);
193             if (useScaling) {
194                 ExplicitBarrierTransferDstImageToTransferSrc(cmdList, bufferToImageDst);
195                 BlitScalingImage(cmdList, copyRef, bufferToImageDst, ref.dstHandle.GetHandle(), imageDesc);
196             }
197 
198             // generate mips
199             if (imageDesc.engineCreationFlags & EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_GENERATE_MIPS) {
200                 const FormatProperties formatProperties = gpuResourceMgr.GetFormatProperties(imageDesc.format);
201                 if ((formatProperties.optimalTilingFeatures & MIP_MAP_TILING_FEATURES) == MIP_MAP_TILING_FEATURES) {
202                     const uint32_t mipCount = imageDesc.mipCount;
203                     const uint32_t availableMipCount = ref.count;
204                     const uint32_t currentMipLevel = copyRef.imageSubresource.mipLevel;
205 
206                     const bool isLastAvailableMipLevel = (currentMipLevel + 1) == availableMipCount;
207                     const bool isMissingMipLevels = availableMipCount < mipCount;
208 
209                     if (isMissingMipLevels && isLastAvailableMipLevel) {
210                         GenerateMipmaps(
211                             cmdList, imageDesc, ref.dstHandle.GetHandle(), copyRef.imageSubresource.mipLevel);
212                     }
213                 }
214 #if (RENDER_VALIDATION_ENABLED == 1)
215                 if ((formatProperties.optimalTilingFeatures & MIP_MAP_TILING_FEATURES) != MIP_MAP_TILING_FEATURES) {
216                     PLUGIN_LOG_ONCE_W("core_validation_auto_mipmapping",
217                         "RENDER_VALIDATION: requested automatic mip mapping not done for format: %u", imageDesc.format);
218                 }
219 #endif
220             }
221         }
222     }
223 }
224 
CopyImagesToBuffersImpl(const IRenderNodeGpuResourceManager & gpuResourceMgr,IRenderCommandList & cmdList,const vector<StagingCopyStruct> & imageToBuffer,const vector<BufferImageCopy> & bufferImageCopies)225 void CopyImagesToBuffersImpl(const IRenderNodeGpuResourceManager& gpuResourceMgr, IRenderCommandList& cmdList,
226     const vector<StagingCopyStruct>& imageToBuffer, const vector<BufferImageCopy>& bufferImageCopies)
227 {
228     for (const auto& ref : imageToBuffer) {
229         if (ref.invalidOperation) {
230             continue;
231         }
232         const uint32_t beginIndex = ref.beginIndex;
233         const uint32_t count = ref.count;
234         for (uint32_t idx = 0; idx < count; ++idx) {
235             const BufferImageCopy& copyRef = bufferImageCopies[beginIndex + idx];
236             cmdList.CopyImageToBuffer(ref.srcHandle.GetHandle(), ref.dstHandle.GetHandle(), copyRef);
237         }
238     }
239 }
240 
CopyImagesToImagesImpl(const IRenderNodeGpuResourceManager & gpuResourceMgr,IRenderCommandList & cmdList,const vector<StagingCopyStruct> & imageToImage,const vector<ImageCopy> & imageCopies)241 void CopyImagesToImagesImpl(const IRenderNodeGpuResourceManager& gpuResourceMgr, IRenderCommandList& cmdList,
242     const vector<StagingCopyStruct>& imageToImage, const vector<ImageCopy>& imageCopies)
243 {
244     for (const auto& ref : imageToImage) {
245         if (ref.invalidOperation) {
246             continue;
247         }
248         const uint32_t beginIndex = ref.beginIndex;
249         const uint32_t count = ref.count;
250         for (uint32_t idx = 0; idx < count; ++idx) {
251             const ImageCopy& copyRef = imageCopies[beginIndex + idx];
252             cmdList.CopyImageToImage(ref.srcHandle.GetHandle(), ref.dstHandle.GetHandle(), copyRef);
253         }
254     }
255 }
256 
CopyHostDirectlyToBuffer(const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingConsumeStruct & stagingConsumeStruct)257 void CopyHostDirectlyToBuffer(
258     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingConsumeStruct& stagingConsumeStruct)
259 {
260     for (const auto& ref : stagingConsumeStruct.cpuToBuffer) {
261         if (ref.invalidOperation) {
262             continue;
263         }
264         uint8_t* baseDstDataBegin = static_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ref.dstHandle.GetHandle()));
265         if (!baseDstDataBegin) {
266             PLUGIN_LOG_E("staging: direct dstHandle %" PRIu64, ref.dstHandle.GetHandle().id);
267             return;
268         }
269         auto const& bufferDesc = gpuResourceMgr.GetBufferDescriptor(ref.dstHandle.GetHandle());
270         const uint8_t* baseDstDataEnd = baseDstDataBegin + bufferDesc.byteSize;
271 
272         const uint8_t* baseSrcDataBegin = static_cast<const uint8_t*>(ref.stagingData.data());
273         const uint32_t bufferBeginIndex = ref.beginIndex;
274         const uint32_t bufferEndIndex = bufferBeginIndex + ref.count;
275         for (uint32_t bufferIdx = bufferBeginIndex; bufferIdx < bufferEndIndex; ++bufferIdx) {
276             PLUGIN_ASSERT(bufferIdx < stagingConsumeStruct.bufferCopies.size());
277             const BufferCopy& currBufferCopy = stagingConsumeStruct.bufferCopies[bufferIdx];
278             uint8_t* dstData = baseDstDataBegin + currBufferCopy.dstOffset;
279             const uint8_t* srcPtr = nullptr;
280             size_t srcSize = 0;
281             if (ref.dataType == StagingCopyStruct::DataType::DATA_TYPE_VECTOR) {
282                 srcPtr = baseSrcDataBegin + currBufferCopy.srcOffset;
283                 srcSize = currBufferCopy.size;
284             }
285             if ((srcPtr) && (srcSize > 0)) {
286                 PLUGIN_ASSERT(bufferDesc.byteSize >= srcSize);
287                 if (!CloneData(dstData, size_t(baseDstDataEnd - dstData), srcPtr, srcSize)) {
288                     PLUGIN_LOG_E("Copying of CPU data directly failed");
289                 }
290             }
291         }
292         gpuResourceMgr.UnmapBuffer(ref.dstHandle.GetHandle());
293     }
294 }
295 
CopyHostDirectlyToBuffer(const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingDirectDataCopyConsumeStruct & stagingData)296 void CopyHostDirectlyToBuffer(
297     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingDirectDataCopyConsumeStruct& stagingData)
298 {
299     for (const auto& ref : stagingData.dataCopies) {
300         uint8_t* data = static_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ref.dstHandle.GetHandle()));
301         if (!data) {
302             PLUGIN_LOG_E("staging: dstHandle %" PRIu64, ref.dstHandle.GetHandle().id);
303             return;
304         }
305         const size_t dstOffset = ref.bufferCopy.dstOffset;
306         data += dstOffset;
307         auto const& bufferDesc = gpuResourceMgr.GetBufferDescriptor(ref.dstHandle.GetHandle());
308         const uint8_t* srcPtr = ref.data.data() + ref.bufferCopy.srcOffset;
309         const size_t copySize =
310             std::min(ref.data.size() - size_t(ref.bufferCopy.srcOffset), size_t(ref.bufferCopy.size));
311         if ((srcPtr) && (copySize > 0)) {
312             PLUGIN_ASSERT((size_t(bufferDesc.byteSize) - dstOffset) >= copySize);
313             if (!CloneData(data, bufferDesc.byteSize - dstOffset, srcPtr, copySize)) {
314                 PLUGIN_LOG_E("Copying of staging data failed");
315             }
316         }
317         gpuResourceMgr.UnmapBuffer(ref.dstHandle.GetHandle());
318     }
319 }
320 } // namespace
321 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)322 void RenderNodeStaging::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
323 {
324     renderNodeContextMgr_ = &renderNodeContextMgr;
325 
326     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
327     dataStoreNameStaging_ = renderNodeGraphData.renderNodeGraphName + "RenderDataStoreDefaultStaging";
328 }
329 
PreExecuteFrame()330 void RenderNodeStaging::PreExecuteFrame()
331 {
332     // re-create needed gpu resources
333 }
334 
ExecuteFrame(IRenderCommandList & cmdList)335 void RenderNodeStaging::ExecuteFrame(IRenderCommandList& cmdList)
336 {
337     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
338     auto& gpuResourceMgrImpl =
339         static_cast<RenderNodeGpuResourceManager&>(renderNodeContextMgr_->GetGpuResourceManager());
340     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
341     bool hasData = gpuResourceMgrImpl.HasStagingData();
342 
343     StagingConsumeStruct renderDataStoreStaging;
344     StagingDirectDataCopyConsumeStruct renderDataStoreStagingDirectCopy;
345     if (RenderDataStoreDefaultStaging* dataStoreDefaultStaging =
346             static_cast<RenderDataStoreDefaultStaging*>(renderDataStoreMgr.GetRenderDataStore(dataStoreNameStaging_));
347         dataStoreDefaultStaging) {
348         hasData = hasData || dataStoreDefaultStaging->HasStagingData();
349         renderDataStoreStaging = dataStoreDefaultStaging->ConsumeStagingData();
350         renderDataStoreStagingDirectCopy = dataStoreDefaultStaging->ConsumeStagingDirectDataCopy();
351     }
352 
353     // early out, no data
354     if (!hasData) {
355         return;
356     }
357 
358     // memcpy to staging
359     const StagingConsumeStruct staging = gpuResourceMgrImpl.ConsumeStagingData();
360     CopyHostToStaging(gpuResourceMgr, staging);
361     CopyHostToStaging(gpuResourceMgr, renderDataStoreStaging);
362     // direct memcpy
363     CopyHostDirectlyToBuffer(gpuResourceMgr, staging);
364     CopyHostDirectlyToBuffer(gpuResourceMgr, renderDataStoreStagingDirectCopy);
365 
366     // images
367     CopyStagingToImages(cmdList, gpuResourceMgr, staging, renderDataStoreStaging);
368     CopyImagesToBuffers(cmdList, gpuResourceMgr, staging, renderDataStoreStaging);
369     CopyImagesToImages(cmdList, gpuResourceMgr, staging, renderDataStoreStaging);
370 
371     // buffers
372     CopyStagingToBuffers(cmdList, staging, renderDataStoreStaging);
373 }
374 
CopyHostToStaging(const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingConsumeStruct & stagingData)375 void RenderNodeStaging::CopyHostToStaging(
376     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingConsumeStruct& stagingData)
377 {
378     auto const copyUserDataToStagingBuffer = [](auto& gpuResourceMgr, auto const& ref) {
379         uint8_t* data = static_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ref.srcHandle.GetHandle()));
380         if (!data) {
381             PLUGIN_LOG_E("staging: srcHandle %" PRIu64 " dstHandle %" PRIu64, ref.srcHandle.GetHandle().id,
382                 ref.dstHandle.GetHandle().id);
383             return;
384         }
385         auto const& bufferDesc = gpuResourceMgr.GetBufferDescriptor(ref.srcHandle.GetHandle());
386         const void* srcPtr = nullptr;
387         size_t srcSize = 0;
388         // should be removed already
389         PLUGIN_ASSERT(ref.dataType != StagingCopyStruct::DataType::DATA_TYPE_DIRECT_SRC_COPY);
390         if (ref.dataType == StagingCopyStruct::DataType::DATA_TYPE_VECTOR) {
391             srcPtr = ref.stagingData.data();
392             srcSize = ref.stagingData.size();
393         } else if (ref.dataType == StagingCopyStruct::DataType::DATA_TYPE_IMAGE_CONTAINER) {
394             PLUGIN_ASSERT(ref.imageContainerPtr);
395             if (ref.imageContainerPtr) {
396                 srcPtr = ref.imageContainerPtr->GetData().data();
397                 srcSize = ref.imageContainerPtr->GetData().size_bytes();
398             }
399         }
400         if ((srcPtr) && (srcSize > 0)) {
401             PLUGIN_ASSERT(bufferDesc.byteSize >= srcSize);
402             if (!CloneData(data, bufferDesc.byteSize, srcPtr, srcSize)) {
403                 PLUGIN_LOG_E("Copying of staging data failed");
404             }
405         }
406         gpuResourceMgr.UnmapBuffer(ref.srcHandle.GetHandle());
407     };
408 
409     for (const auto& ref : stagingData.bufferToImage) {
410         if ((!ref.invalidOperation) && (ref.dataType != StagingCopyStruct::DataType::DATA_TYPE_DIRECT_SRC_COPY)) {
411             copyUserDataToStagingBuffer(gpuResourceMgr, ref);
412         }
413     }
414     for (const auto& ref : stagingData.bufferToBuffer) {
415         if ((!ref.invalidOperation) && (ref.dataType != StagingCopyStruct::DataType::DATA_TYPE_DIRECT_SRC_COPY)) {
416             copyUserDataToStagingBuffer(gpuResourceMgr, ref);
417         }
418     }
419 }
420 
CopyStagingToImages(IRenderCommandList & cmdList,const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingConsumeStruct & stagingData,const StagingConsumeStruct & renderDataStoreStagingData)421 void RenderNodeStaging::CopyStagingToImages(IRenderCommandList& cmdList,
422     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingConsumeStruct& stagingData,
423     const StagingConsumeStruct& renderDataStoreStagingData)
424 {
425     // explicit input barriers
426     cmdList.BeginDisableAutomaticBarrierPoints();
427     {
428         ImageResourceBarrier src { 0, PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT };
429         const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
430             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
431             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
432         const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0,
433             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
434 
435         for (const auto& ref : stagingData.bufferToImage) {
436             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.dstHandle.GetHandle()))) {
437                 cmdList.CustomImageBarrier(ref.dstHandle.GetHandle(), src, dst, imageSubresourceRange);
438             }
439         }
440         for (const auto& ref : renderDataStoreStagingData.bufferToImage) {
441             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.dstHandle.GetHandle()))) {
442                 cmdList.CustomImageBarrier(ref.dstHandle.GetHandle(), src, dst, imageSubresourceRange);
443             }
444         }
445     }
446     cmdList.EndDisableAutomaticBarrierPoints();
447     cmdList.AddCustomBarrierPoint();
448 
449     CopyBuffersToImages(gpuResourceMgr, cmdList, stagingData.bufferToImage, stagingData.bufferImageCopies,
450         stagingData.scalingImageData);
451     CopyBuffersToImages(gpuResourceMgr, cmdList, renderDataStoreStagingData.bufferToImage,
452         renderDataStoreStagingData.bufferImageCopies, {}); // scaling from render data store not supported ATM
453 
454     // explicit output barriers
455     cmdList.BeginDisableAutomaticBarrierPoints();
456     {
457         const ImageResourceBarrier src {
458             AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT, PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
459             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL // we expect all mips to be transferred to dst
460         };
461         const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_SHADER_READ_BIT,
462             PipelineStageFlagBits::CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // some shader stage
463             ImageLayout::CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
464         const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0,
465             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
466 
467         for (const auto& ref : stagingData.bufferToImage) {
468             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.dstHandle.GetHandle()))) {
469                 cmdList.CustomImageBarrier(ref.dstHandle.GetHandle(), src, dst, imageSubresourceRange);
470             }
471         }
472         for (const auto& ref : renderDataStoreStagingData.bufferToImage) {
473             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.dstHandle.GetHandle()))) {
474                 cmdList.CustomImageBarrier(ref.dstHandle.GetHandle(), src, dst, imageSubresourceRange);
475             }
476         }
477     }
478     cmdList.EndDisableAutomaticBarrierPoints();
479     cmdList.AddCustomBarrierPoint();
480 }
481 
CopyImagesToBuffers(IRenderCommandList & cmdList,const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingConsumeStruct & stagingData,const StagingConsumeStruct & renderDataStoreStagingData)482 void RenderNodeStaging::CopyImagesToBuffers(IRenderCommandList& cmdList,
483     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingConsumeStruct& stagingData,
484     const StagingConsumeStruct& renderDataStoreStagingData)
485 {
486     // explicit input barriers
487     cmdList.BeginDisableAutomaticBarrierPoints();
488     {
489         // we transfer all mip levels, but we only copy the one
490         ImageResourceBarrier src { 0, PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT };
491         const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
492             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
493             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL };
494         const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0,
495             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
496 
497         for (const auto& ref : renderDataStoreStagingData.imageToBuffer) {
498             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.srcHandle.GetHandle()))) {
499                 cmdList.CustomImageBarrier(ref.srcHandle.GetHandle(), src, dst, imageSubresourceRange);
500             }
501         }
502     }
503     cmdList.EndDisableAutomaticBarrierPoints();
504     cmdList.AddCustomBarrierPoint();
505 
506     // Not supported through gpu resource manager staging
507     PLUGIN_ASSERT(stagingData.imageToBuffer.empty());
508     CopyImagesToBuffersImpl(gpuResourceMgr, cmdList, renderDataStoreStagingData.imageToBuffer,
509         renderDataStoreStagingData.bufferImageCopies);
510 
511     // explicit output barriers
512     cmdList.BeginDisableAutomaticBarrierPoints();
513     {
514         const ImageResourceBarrier src {
515             AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT, PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
516             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // we expect all mips to be transferred to dst
517         };
518         // NOTE: should fetch usage flags
519         const ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_SHADER_READ_BIT,
520             PipelineStageFlagBits::CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // some shader stage
521             ImageLayout::CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
522         const ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0,
523             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
524 
525         for (const auto& ref : renderDataStoreStagingData.imageToBuffer) {
526             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.srcHandle.GetHandle()))) {
527                 cmdList.CustomImageBarrier(ref.srcHandle.GetHandle(), src, dst, imageSubresourceRange);
528             }
529         }
530     }
531     cmdList.EndDisableAutomaticBarrierPoints();
532     cmdList.AddCustomBarrierPoint();
533 }
534 
CopyImagesToImages(IRenderCommandList & cmdList,const IRenderNodeGpuResourceManager & gpuResourceMgr,const StagingConsumeStruct & stagingData,const StagingConsumeStruct & renderDataStoreStagingData)535 void RenderNodeStaging::CopyImagesToImages(IRenderCommandList& cmdList,
536     const IRenderNodeGpuResourceManager& gpuResourceMgr, const StagingConsumeStruct& stagingData,
537     const StagingConsumeStruct& renderDataStoreStagingData)
538 {
539     // explicit input barriers
540     cmdList.BeginDisableAutomaticBarrierPoints();
541     {
542         // we transfer all mip levels, but we only copy the one
543         constexpr ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0,
544             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
545 
546         constexpr ImageResourceBarrier src { 0, PipelineStageFlagBits::CORE_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT };
547         constexpr ImageResourceBarrier srcDst { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
548             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
549             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL };
550 
551         constexpr ImageResourceBarrier dstDst { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
552             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
553             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
554 
555         for (const auto& ref : renderDataStoreStagingData.imageToImage) {
556             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.srcHandle.GetHandle()))) {
557                 cmdList.CustomImageBarrier(ref.srcHandle.GetHandle(), src, srcDst, imageSubresourceRange);
558             }
559             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.dstHandle.GetHandle()))) {
560                 cmdList.CustomImageBarrier(ref.dstHandle.GetHandle(), src, dstDst, imageSubresourceRange);
561             }
562         }
563     }
564     cmdList.EndDisableAutomaticBarrierPoints();
565     cmdList.AddCustomBarrierPoint();
566 
567     // Not supported through gpu resource manager staging
568     PLUGIN_ASSERT(stagingData.imageToImage.empty());
569     CopyImagesToImagesImpl(
570         gpuResourceMgr, cmdList, renderDataStoreStagingData.imageToImage, renderDataStoreStagingData.imageCopies);
571 
572     // explicit output barriers
573     cmdList.BeginDisableAutomaticBarrierPoints();
574     {
575         constexpr ImageResourceBarrier srcSrc { AccessFlagBits::CORE_ACCESS_TRANSFER_READ_BIT,
576             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
577             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL };
578         constexpr ImageResourceBarrier dstSrc { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
579             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT,
580             ImageLayout::CORE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
581         // NOTE: should fetch usage flags
582         constexpr ImageResourceBarrier dst { AccessFlagBits::CORE_ACCESS_SHADER_READ_BIT,
583             PipelineStageFlagBits::CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // some shader stage
584             ImageLayout::CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
585         constexpr ImageSubresourceRange imageSubresourceRange { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0,
586             PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
587 
588         for (const auto& ref : renderDataStoreStagingData.imageToImage) {
589             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.srcHandle.GetHandle()))) {
590                 cmdList.CustomImageBarrier(ref.srcHandle.GetHandle(), srcSrc, dst, imageSubresourceRange);
591             }
592             if ((!ref.invalidOperation) && (!RenderHandleUtil::IsDynamicResource(ref.dstHandle.GetHandle()))) {
593                 cmdList.CustomImageBarrier(ref.dstHandle.GetHandle(), dstSrc, dst, imageSubresourceRange);
594             }
595         }
596     }
597     cmdList.EndDisableAutomaticBarrierPoints();
598     cmdList.AddCustomBarrierPoint();
599 }
600 
CopyStagingToBuffers(IRenderCommandList & cmdList,const StagingConsumeStruct & stagingData,const StagingConsumeStruct & renderDataStoreStagingData)601 void RenderNodeStaging::CopyStagingToBuffers(IRenderCommandList& cmdList, const StagingConsumeStruct& stagingData,
602     const StagingConsumeStruct& renderDataStoreStagingData)
603 {
604     const auto copyBuffersToBuffers = [](IRenderCommandList& cmdList, const vector<StagingCopyStruct>& bufferToBuffer,
605                                           const vector<BufferCopy>& bufferCopies) {
606         for (const auto& ref : bufferToBuffer) {
607             if (ref.invalidOperation) {
608                 continue;
609             }
610             const auto copies = array_view(bufferCopies.data() + ref.beginIndex, ref.count);
611             for (const BufferCopy& copyRef : copies) {
612                 cmdList.CopyBufferToBuffer(ref.srcHandle.GetHandle(), ref.dstHandle.GetHandle(), copyRef);
613             }
614         }
615     };
616 
617     // dynamic resources can create barriers if needed
618     copyBuffersToBuffers(cmdList, stagingData.bufferToBuffer, stagingData.bufferCopies);
619     copyBuffersToBuffers(cmdList, renderDataStoreStagingData.bufferToBuffer, renderDataStoreStagingData.bufferCopies);
620 
621     // explict output barriers
622     cmdList.BeginDisableAutomaticBarrierPoints();
623     {
624         const BufferResourceBarrier src { AccessFlagBits::CORE_ACCESS_TRANSFER_WRITE_BIT,
625             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TRANSFER_BIT };
626         const BufferResourceBarrier dst { 0, // access flags are not currently known
627             PipelineStageFlagBits::CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT };
628 
629         for (const auto& ref : stagingData.bufferToBuffer) {
630             if (!ref.invalidOperation) {
631                 cmdList.CustomBufferBarrier(
632                     ref.dstHandle.GetHandle(), src, dst, 0, PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE);
633             }
634         }
635         for (const auto& ref : renderDataStoreStagingData.bufferToBuffer) {
636             if (!ref.invalidOperation) {
637                 cmdList.CustomBufferBarrier(
638                     ref.dstHandle.GetHandle(), src, dst, 0, PipelineStateConstants::GPU_BUFFER_WHOLE_SIZE);
639             }
640         }
641     }
642     cmdList.EndDisableAutomaticBarrierPoints();
643     cmdList.AddCustomBarrierPoint();
644 }
645 
646 // for plugin / factory interface
Create()647 IRenderNode* RenderNodeStaging::Create()
648 {
649     return new RenderNodeStaging();
650 }
651 
Destroy(IRenderNode * instance)652 void RenderNodeStaging::Destroy(IRenderNode* instance)
653 {
654     delete static_cast<RenderNodeStaging*>(instance);
655 }
656 RENDER_END_NAMESPACE()
657