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