• 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 "gpu_resource_manager.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #ifndef NDEBUG
21 #include <sstream>
22 #include <thread>
23 #endif
24 
25 #include <base/containers/fixed_string.h>
26 #include <base/math/mathf.h>
27 #include <render/namespace.h>
28 
29 #include "device/device.h"
30 #include "device/gpu_acceleration_structure.h"
31 #include "device/gpu_resource_desc_flag_validation.h"
32 #include "device/gpu_sampler.h"
33 #include "resource_handle_impl.h"
34 #include "util/log.h"
35 
36 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
37 #include "device/gpu_resource_util.h"
38 #endif
39 
40 using namespace BASE_NS;
41 using namespace CORE_NS;
42 
43 RENDER_BEGIN_NAMESPACE()
44 namespace {
45 static constexpr uint32_t INVALID_PENDING_INDEX { ~0u };
46 static constexpr uint32_t MAX_IMAGE_EXTENT { 32768u }; // should be fetched from the device
47 
48 static constexpr MemoryPropertyFlags NEEDED_DEVICE_MEMORY_PROPERTY_FLAGS_FOR_STAGING_MEM_OPT {
49     CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT
50 };
51 static constexpr MemoryPropertyFlags ADD_STAGING_MEM_OPT_FLAGS { CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
52                                                                  CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT };
53 
54 // make sure that generation is valid
55 static constexpr uint64_t INVALIDATE_GENERATION_SHIFT { 32 };
InvalidateWithGeneration(const EngineResourceHandle handle)56 EngineResourceHandle InvalidateWithGeneration(const EngineResourceHandle handle)
57 {
58     return { handle.id | ~RenderHandleUtil::RES_HANDLE_GENERATION_MASK };
59 }
60 
UnpackNewHandle(const EngineResourceHandle & handle,const RenderHandleType type,const uint32_t arrayIndex)61 EngineResourceHandle UnpackNewHandle(
62     const EngineResourceHandle& handle, const RenderHandleType type, const uint32_t arrayIndex)
63 {
64     // increments generation counter
65     if (RenderHandleUtil::IsValid(handle)) {
66         const uint32_t gpuGenIndex = RenderHandleUtil::GetGenerationIndexPart(handle) + 1;
67         return RenderHandleUtil::CreateEngineResourceHandle(type, arrayIndex, gpuGenIndex);
68     } else {
69         const uint32_t gpuGenIndex = uint32_t(handle.id >> INVALIDATE_GENERATION_SHIFT) + 1;
70         return RenderHandleUtil::CreateEngineResourceHandle(type, arrayIndex, gpuGenIndex);
71     }
72 }
73 
74 // we need to know if image is a depth format when binding to descriptor set as read only
GetAdditionalImageFlagsFromFormat(const Format format)75 constexpr RenderHandleInfoFlags GetAdditionalImageFlagsFromFormat(const Format format)
76 {
77     RenderHandleInfoFlags flags {};
78 
79     const bool isDepthFormat =
80         ((format == Format::BASE_FORMAT_D16_UNORM) || (format == Format::BASE_FORMAT_X8_D24_UNORM_PACK32) ||
81             (format == Format::BASE_FORMAT_D32_SFLOAT) || (format == Format::BASE_FORMAT_D24_UNORM_S8_UINT))
82             ? true
83             : false;
84     if (isDepthFormat) {
85         flags |= CORE_RESOURCE_HANDLE_DEPTH_IMAGE;
86     }
87 
88     return flags;
89 }
90 
ForceUpdateUnsupportedFormat(const Format format)91 Format ForceUpdateUnsupportedFormat(const Format format)
92 {
93     // NOTE: should do a linear list of formats with unsupported formats
94     // one could use simple r8_unorm related formats which are all supported
95     // NOTE: place this list to device where is FormatProperties as well
96 #if (RENDER_VALIDATION_ENABLED == 1)
97     PLUGIN_LOG_W("RENDER_VALIDATION: unsupported format: %u", format);
98 #endif
99     Format newFormat = format;
100     if (format == BASE_FORMAT_R8_SRGB) {
101         newFormat = BASE_FORMAT_R8_UNORM;
102     } else if (format == BASE_FORMAT_R8G8_SRGB) {
103         newFormat = BASE_FORMAT_R8G8_UNORM;
104     } else if (format == BASE_FORMAT_R8G8B8_SRGB) {
105         newFormat = BASE_FORMAT_R8G8B8_UNORM;
106     }
107     return newFormat;
108 }
109 
110 #if (RENDER_VALIDATION_ENABLED == 1)
ValidateGpuBufferDesc(const GpuBufferDesc & desc)111 void ValidateGpuBufferDesc(const GpuBufferDesc& desc)
112 {
113     if (desc.usageFlags == 0) {
114         PLUGIN_LOG_E("RENDER_VALIDATION: BufferUsageFlags must not be 0");
115     }
116     if ((desc.usageFlags & (~GpuResourceDescFlagValidation::ALL_GPU_BUFFER_USAGE_FLAGS)) != 0) {
117         PLUGIN_LOG_E("RENDER_VALIDATION: Invalid BufferUsageFlags (%u)", desc.usageFlags);
118     }
119     if (desc.memoryPropertyFlags == 0) {
120         PLUGIN_LOG_E("RENDER_VALIDATION: MemoryPropertyFlags must not be 0");
121     }
122     if ((desc.memoryPropertyFlags & (~GpuResourceDescFlagValidation::ALL_MEMORY_PROPERTY_FLAGS)) != 0) {
123         PLUGIN_LOG_E("RENDER_VALIDATION: Invalid MemoryPropertyFlags (%u)", desc.memoryPropertyFlags);
124     }
125 }
126 
ValidateGpuImageDesc(const GpuImageDesc & desc,const string_view name)127 void ValidateGpuImageDesc(const GpuImageDesc& desc, const string_view name)
128 {
129     bool valid = true;
130     if (desc.imageType > ImageType::CORE_IMAGE_TYPE_3D) {
131         PLUGIN_LOG_E("RENDER_VALIDATION: Unsupported image type");
132         valid = false;
133     }
134     if ((desc.imageViewType == ImageViewType::CORE_IMAGE_VIEW_TYPE_2D) && (desc.layerCount > 1u)) {
135         PLUGIN_LOG_E(
136             "RENDER_VALIDATION: Default image view is done for sampling / shader resource access and needs to be "
137             "CORE_IMAGE_VIEW_TYPE_2D_ARRAY with multiple layers");
138         valid = false;
139     }
140     if (desc.imageTiling > ImageTiling::CORE_IMAGE_TILING_LINEAR) {
141         PLUGIN_LOG_E("RENDER_VALIDATION: Unsupported image tiling mode (%u)", static_cast<uint32_t>(desc.imageTiling));
142         valid = false;
143     }
144     if (desc.usageFlags == 0) {
145         PLUGIN_LOG_E("RENDER_VALIDATION: ImageUsageFlags must not be 0");
146         valid = false;
147     }
148     if ((desc.usageFlags & (~GpuResourceDescFlagValidation::ALL_GPU_IMAGE_USAGE_FLAGS)) != 0) {
149         PLUGIN_LOG_E("RENDER_VALIDATION: Invalid ImageUsageFlags (%u)", desc.usageFlags);
150         valid = false;
151     }
152     if (desc.memoryPropertyFlags == 0) {
153         PLUGIN_LOG_E("RENDER_VALIDATION: MemoryPropertyFlags must not be 0");
154         valid = false;
155     }
156     if ((desc.memoryPropertyFlags & (~GpuResourceDescFlagValidation::ALL_MEMORY_PROPERTY_FLAGS)) != 0) {
157         PLUGIN_LOG_E("RENDER_VALIDATION: Invalid MemoryPropertyFlags (%u)", desc.memoryPropertyFlags);
158         valid = false;
159     }
160     if (desc.width == 0 || desc.height == 0 || desc.depth == 0) {
161         PLUGIN_LOG_E("RENDER_VALIDATION: Image extents must not be zero (x:%u, y:%u, z:%u)", desc.width, desc.height,
162             desc.depth);
163         valid = false;
164     }
165     if (desc.width > MAX_IMAGE_EXTENT || desc.height > MAX_IMAGE_EXTENT || desc.depth > MAX_IMAGE_EXTENT) {
166         PLUGIN_LOG_E("RENDER_VALIDATION: Image extents must not be bigger than (%u) (x:%u, y:%u, z:%u)",
167             MAX_IMAGE_EXTENT, desc.width, desc.height, desc.depth);
168         valid = false;
169     }
170     if (desc.mipCount == 0 || desc.layerCount == 0) {
171         PLUGIN_LOG_E("RENDER_VALIDATION: Image mip and layer count must be >=1 (mipCount:%u, layerCount:%u)",
172             desc.mipCount, desc.layerCount);
173         valid = false;
174     }
175     if ((desc.createFlags & (~GpuResourceDescFlagValidation::ALL_IMAGE_CREATE_FLAGS)) != 0) {
176         PLUGIN_LOG_E("RENDER_VALIDATION: Invalid ImageCreateFlags (%u)", desc.createFlags);
177         valid = false;
178     }
179     if ((desc.engineCreationFlags & CORE_ENGINE_IMAGE_CREATION_GENERATE_MIPS) &&
180         ((desc.usageFlags & CORE_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0)) {
181         PLUGIN_LOG_E(
182             "RENDER_VALIDATION: Must use usage flags CORE_IMAGE_USAGE_TRANSFER_SRC_BIT when generating mip maps");
183         valid = false;
184     }
185     if (desc.usageFlags & CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
186         const ImageUsageFlags usageFlags =
187             desc.usageFlags &
188             ~(CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | CORE_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
189                 CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
190         if (usageFlags != 0) {
191             PLUGIN_LOG_E(
192                 "RENDER_VALIDATION: If image usage flags contain CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, only "
193                 "DEPTH_STENCIL_ATTACHMENT_BIT, INPUT_ATTACHMENT_BIT, and COLOR_ATTACHMENT_BIT can be set.");
194             valid = false;
195         }
196     }
197 
198     if ((!valid) && (!name.empty())) {
199         PLUGIN_LOG_E("RENDER_VALIDATION: validation issue(s) with image (name: %s)", name.data());
200     }
201 }
202 
ValidateGpuImageCopy(const GpuImageDesc & desc,const BufferImageCopy & copy,const string_view name)203 void ValidateGpuImageCopy(const GpuImageDesc& desc, const BufferImageCopy& copy, const string_view name)
204 {
205     const uint32_t mip = copy.imageSubresource.mipLevel;
206     const Size3D imageSize { desc.width >> mip, desc.height >> mip, desc.depth };
207     if ((copy.imageOffset.width >= imageSize.width) || (copy.imageOffset.width >= imageSize.height) ||
208         (copy.imageOffset.depth >= imageSize.depth)) {
209         PLUGIN_LOG_E(
210             "RENDER_VALIDATION: BufferImageCopy offset exceeds GpuImageDesc. Mipsize: %u, %u, %u, offset: %u %u %u. "
211             "(name: %s)",
212             imageSize.width, imageSize.height, imageSize.depth, copy.imageOffset.width, copy.imageOffset.height,
213             copy.imageOffset.depth, name.data());
214     }
215 }
216 #endif
217 
GetValidGpuBufferDesc(const GpuBufferDesc & desc)218 GpuBufferDesc GetValidGpuBufferDesc(const GpuBufferDesc& desc)
219 {
220     return GpuBufferDesc {
221         desc.usageFlags & GpuResourceDescFlagValidation::ALL_GPU_BUFFER_USAGE_FLAGS,
222         desc.memoryPropertyFlags & GpuResourceDescFlagValidation::ALL_MEMORY_PROPERTY_FLAGS,
223         desc.engineCreationFlags,
224         desc.byteSize,
225     };
226 }
227 
CheckAndEnableMemoryOptimizations(const uint32_t gpuResourceMgrFlags,GpuBufferDesc & desc)228 void CheckAndEnableMemoryOptimizations(const uint32_t gpuResourceMgrFlags, GpuBufferDesc& desc)
229 {
230     if (gpuResourceMgrFlags & GpuResourceManager::GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY) {
231         if ((desc.memoryPropertyFlags == CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) &&
232             (desc.usageFlags & CORE_BUFFER_USAGE_TRANSFER_DST_BIT) &&
233             (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_ENABLE_MEMORY_OPTIMIZATIONS)) {
234             desc.memoryPropertyFlags |= ADD_STAGING_MEM_OPT_FLAGS;
235         }
236     }
237 }
238 
GetScalingImageNeed(const GpuImageDesc & desc,const array_view<const IImageContainer::SubImageDesc> & copies)239 bool GetScalingImageNeed(const GpuImageDesc& desc, const array_view<const IImageContainer::SubImageDesc>& copies)
240 {
241     bool scale = false;
242     if (desc.engineCreationFlags & EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_SCALE) {
243         // we only support single image (single buffer image copy) scaling
244         if (copies.size() == 1) {
245             scale = (copies[0].width != desc.width) || (copies[0].height != desc.height);
246         }
247     }
248     return scale;
249 }
250 
GetScalingImageNeed(const GpuImageDesc & desc,const array_view<const BufferImageCopy> & copies)251 bool GetScalingImageNeed(const GpuImageDesc& desc, const array_view<const BufferImageCopy>& copies)
252 {
253     bool scale = false;
254     if (desc.engineCreationFlags & EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_SCALE) {
255         // we only support single image (single buffer image copy) scaling
256         if (copies.size() == 1) {
257             scale = (copies[0].imageExtent.width != desc.width) || (copies[0].imageExtent.height != desc.height);
258         }
259     }
260     return scale;
261 }
262 
263 // staging needs to be locked when called with the input resources
UpdateStagingScaling(const Format format,const array_view<const IImageContainer::SubImageDesc> & copies,ScalingImageDataStruct & siData)264 void UpdateStagingScaling(
265     const Format format, const array_view<const IImageContainer::SubImageDesc>& copies, ScalingImageDataStruct& siData)
266 {
267     PLUGIN_ASSERT(copies.size() == 1);
268     if (auto iter = siData.formatToScalingImages.find(format); iter != siData.formatToScalingImages.end()) {
269         const size_t index = iter->second;
270         PLUGIN_ASSERT(index < siData.scalingImages.size());
271         auto& scaleImage = siData.scalingImages[index];
272         scaleImage.maxWidth = Math::max(scaleImage.maxWidth, copies[0].width);
273         scaleImage.maxHeight = Math::max(scaleImage.maxHeight, copies[0].height);
274     } else {
275         const size_t index = siData.scalingImages.size();
276         siData.scalingImages.push_back({ {}, format, copies[0].width, copies[0].height });
277         siData.formatToScalingImages[format] = index;
278     }
279 }
280 
UpdateStagingScaling(const Format format,const array_view<const BufferImageCopy> & copies,ScalingImageDataStruct & siData)281 void UpdateStagingScaling(
282     const Format format, const array_view<const BufferImageCopy>& copies, ScalingImageDataStruct& siData)
283 {
284     PLUGIN_ASSERT(copies.size() == 1);
285     const auto& extent = copies[0].imageExtent;
286     if (auto iter = siData.formatToScalingImages.find(format); iter != siData.formatToScalingImages.end()) {
287         const size_t index = iter->second;
288         PLUGIN_ASSERT(index < siData.scalingImages.size());
289         auto& scaleImage = siData.scalingImages[index];
290         scaleImage.maxWidth = Math::max(scaleImage.maxWidth, extent.width);
291         scaleImage.maxHeight = Math::max(scaleImage.maxHeight, extent.height);
292     } else {
293         const size_t index = siData.scalingImages.size();
294         siData.scalingImages.push_back({ {}, format, extent.width, extent.height });
295         siData.formatToScalingImages[format] = index;
296     }
297 }
298 
GetStagingScalingImageDesc(const Format format,const uint32_t width,const uint32_t height)299 GpuImageDesc GetStagingScalingImageDesc(const Format format, const uint32_t width, const uint32_t height)
300 {
301     return GpuImageDesc {
302         ImageType::CORE_IMAGE_TYPE_2D,
303         ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
304         format,
305         ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
306         // NOTE sampled is not needed, but image view should not be created
307         ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_SRC_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT |
308             ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT,
309         MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
310         0,
311         0, // No dynamic barrriers
312         width,
313         height,
314         1u,
315         1u,
316         1u,
317         1u,
318         {},
319     };
320 }
321 
ConvertCoreBufferImageCopy(const IImageContainer::SubImageDesc & bufferImageCopy)322 BufferImageCopy ConvertCoreBufferImageCopy(const IImageContainer::SubImageDesc& bufferImageCopy)
323 {
324     return BufferImageCopy {
325         /** Buffer offset */
326         bufferImageCopy.bufferOffset,
327         /** Buffer row length */
328         bufferImageCopy.bufferRowLength,
329         /** Buffer image height */
330         bufferImageCopy.bufferImageHeight,
331         /** Image subresource */
332         { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, bufferImageCopy.mipLevel, 0, bufferImageCopy.layerCount },
333         /** Image offset */
334         { 0, 0, 0 },
335         /** Image extent */
336         { bufferImageCopy.width, bufferImageCopy.height, bufferImageCopy.depth },
337     };
338 }
339 
340 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
LogGpuResource(const RenderHandle & gpuHandle,const EngineResourceHandle engineHandle)341 void LogGpuResource(const RenderHandle& gpuHandle, const EngineResourceHandle engineHandle)
342 {
343     constexpr string_view names[] = { "buffer", "image", "sampler" };
344     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(gpuHandle);
345     uint32_t idx = 0;
346     if (handleType == RenderHandleType::GPU_IMAGE) {
347         idx = 1u;
348     } else if (handleType == RenderHandleType::GPU_SAMPLER) {
349         idx = 2u;
350     }
351     PLUGIN_LOG_E("gpu %s > %" PRIx64 "=%" PRIx64 " generation: %u=%u", names[idx].data(), gpuHandle.id, engineHandle.id,
352         RenderHandleUtil::GetGenerationIndexPart(gpuHandle), RenderHandleUtil::GetGenerationIndexPart(engineHandle));
353 }
354 #endif
355 } // namespace
356 
GpuResourceManager(Device & device,const CreateInfo & createInfo)357 GpuResourceManager::GpuResourceManager(Device& device, const CreateInfo& createInfo)
358     : device_(device), gpuResourceMgrFlags_(createInfo.flags),
359       gpuBufferMgr_(make_unique<GpuResourceManagerTyped<GpuBuffer, GpuBufferDesc>>(device)),
360       gpuImageMgr_(make_unique<GpuResourceManagerTyped<GpuImage, GpuImageDesc>>(device)),
361       gpuSamplerMgr_(make_unique<GpuResourceManagerTyped<GpuSampler, GpuSamplerDesc>>(device)),
362       gpuAccelerationStructureMgr_(
363           make_unique<GpuResourceManagerTyped<GpuAccelerationStructure, GpuAccelerationStructureDesc>>(device))
364 {
365     bufferStore_.mgr = gpuBufferMgr_.get();
366     imageStore_.mgr = gpuImageMgr_.get();
367     samplerStore_.mgr = gpuSamplerMgr_.get();
368     accelStore_.mgr = gpuAccelerationStructureMgr_.get();
369 
370     const MemoryPropertyFlags deviceSharedMemoryPropertyFlags = device_.GetSharedMemoryPropertyFlags();
371     // remove create info flag if not really available
372     if (((gpuResourceMgrFlags_ & GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY) == 0) ||
373         !((deviceSharedMemoryPropertyFlags & NEEDED_DEVICE_MEMORY_PROPERTY_FLAGS_FOR_STAGING_MEM_OPT) ==
374             NEEDED_DEVICE_MEMORY_PROPERTY_FLAGS_FOR_STAGING_MEM_OPT)) {
375         gpuResourceMgrFlags_ = gpuResourceMgrFlags_ & ~GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY;
376     }
377 }
378 
~GpuResourceManager()379 GpuResourceManager::~GpuResourceManager()
380 {
381 #if (RENDER_VALIDATION_ENABLED == 1)
382     auto checkAndPrintValidation = [](const PerManagerStore& store, const string_view name) {
383         uint32_t aliveCounter = 0;
384         const auto clientLock = std::lock_guard(store.clientMutex);
385         for (const auto& ref : store.clientHandles) {
386             if (ref && (ref.GetRefCount() > 1)) {
387                 aliveCounter++;
388             }
389         }
390         if (aliveCounter > 0) {
391             PLUGIN_LOG_W(
392                 "RENDER_VALIDATION: Not all %s handle references released (count: %u)", name.data(), aliveCounter);
393         }
394     };
395     checkAndPrintValidation(bufferStore_, "GPU buffer");
396     checkAndPrintValidation(imageStore_, "GPU image");
397     checkAndPrintValidation(samplerStore_, "GPU sampler");
398     checkAndPrintValidation(accelStore_, "GPU acceleration structure");
399 #endif
400 }
401 
Get(const RenderHandle & handle) const402 RenderHandleReference GpuResourceManager::Get(const RenderHandle& handle) const
403 {
404     if (RenderHandleUtil::IsValid(handle)) {
405         const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
406         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
407         if (handleType == RenderHandleType::GPU_BUFFER) {
408             if (RenderHandleUtil::IsGpuAccelerationStructure(handle)) {
409                 auto& store = accelStore_;
410                 auto const clientLock = std::lock_guard(store.clientMutex);
411                 if (arrayIndex < static_cast<uint32_t>(store.clientHandles.size())) {
412                     return store.clientHandles[arrayIndex];
413                 }
414             } else {
415                 auto& store = bufferStore_;
416                 auto const clientLock = std::lock_guard(store.clientMutex);
417                 if (arrayIndex < static_cast<uint32_t>(store.clientHandles.size())) {
418                     return store.clientHandles[arrayIndex];
419                 }
420             }
421         } else if (handleType == RenderHandleType::GPU_IMAGE) {
422             auto& store = imageStore_;
423             auto const clientLock = std::lock_guard(store.clientMutex);
424             if (arrayIndex < static_cast<uint32_t>(store.clientHandles.size())) {
425                 return store.clientHandles[arrayIndex];
426             }
427         } else if (handleType == RenderHandleType::GPU_SAMPLER) {
428             auto& store = samplerStore_;
429             auto const clientLock = std::lock_guard(store.clientMutex);
430             if (arrayIndex < static_cast<uint32_t>(store.clientHandles.size())) {
431                 return store.clientHandles[arrayIndex];
432             }
433         }
434         PLUGIN_LOG_I(
435             "invalid gpu resource handle (id: %" PRIu64 ", type: %u)", handle.id, static_cast<uint32_t>(handleType));
436     }
437     return RenderHandleReference {};
438 }
439 
GetStagingBufferDesc(const uint32_t byteSize)440 GpuBufferDesc GpuResourceManager::GetStagingBufferDesc(const uint32_t byteSize)
441 {
442     return {
443         BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_SRC_BIT,
444         MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT |
445             MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
446         EngineBufferCreationFlagBits::CORE_ENGINE_BUFFER_CREATION_SINGLE_SHOT_STAGING,
447         byteSize,
448     };
449 }
450 
451 // call to evaluate if there's already pending resources which we will replace
452 // store.clientMutex needs to be locked
GetPendingOptionalResourceIndex(const PerManagerStore & store,const RenderHandle & handle,const string_view name)453 uint32_t GpuResourceManager::GetPendingOptionalResourceIndex(
454     const PerManagerStore& store, const RenderHandle& handle, const string_view name)
455 {
456     uint32_t optionalResourceIndex = ~0u;
457     uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
458     const bool hasReplaceHandle = (arrayIndex < static_cast<uint32_t>(store.clientHandles.size()));
459     if ((!hasReplaceHandle) && (!name.empty())) {
460         if (auto const iter = store.nameToClientIndex.find(name); iter != store.nameToClientIndex.cend()) {
461             arrayIndex = RenderHandleUtil::GetIndexPart(iter->second);
462         }
463     }
464     if (arrayIndex < static_cast<uint32_t>(store.clientHandles.size())) {
465         if (const uint32_t pendingArrIndex = store.additionalData[arrayIndex].indexToPendingData;
466             pendingArrIndex != INVALID_PENDING_INDEX) {
467             PLUGIN_ASSERT(pendingArrIndex < store.pendingData.allocations.size());
468             if (pendingArrIndex < static_cast<uint32_t>(store.pendingData.allocations.size())) {
469                 const auto& allocOp = store.pendingData.allocations[pendingArrIndex];
470                 optionalResourceIndex = allocOp.optionalResourceIndex;
471             }
472         }
473     }
474     return optionalResourceIndex;
475 }
476 
477 // needs to be locked when called
CreateStagingBuffer(const GpuBufferDesc & desc)478 RenderHandleReference GpuResourceManager::CreateStagingBuffer(const GpuBufferDesc& desc)
479 {
480     PerManagerStore& store = bufferStore_;
481     return StoreAllocation(store, {}, {}, RenderHandleType::GPU_BUFFER, ResourceDescriptor { desc }, ~0u, 0u).handle;
482 }
483 
484 // needs to be locked when called
CreateBuffer(const string_view name,const RenderHandle & replacedHandle,const GpuBufferDesc & desc)485 GpuResourceManager::StoreAllocationData GpuResourceManager::CreateBuffer(
486     const string_view name, const RenderHandle& replacedHandle, const GpuBufferDesc& desc)
487 {
488 #if (RENDER_VALIDATION_ENABLED == 1)
489     ValidateGpuBufferDesc(desc);
490 #endif
491 
492     PerManagerStore& store = bufferStore_;
493     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
494         // replace immediate created if still pending (i.e. not usable on the GPU)
495         // memory pointers on client become invalid
496         const uint32_t emplaceResourceIndex = static_cast<uint32_t>(store.pendingData.buffers.size());
497         const uint32_t optionalResourceIndex =
498             Math::min(emplaceResourceIndex, GetPendingOptionalResourceIndex(store, replacedHandle, name));
499 
500         unique_ptr<GpuBuffer> gpuBuffer = device_.CreateGpuBuffer(desc);
501         if (gpuBuffer) {
502             // safety checks
503             if ((optionalResourceIndex < emplaceResourceIndex) &&
504                 (optionalResourceIndex < store.pendingData.buffers.size())) {
505                 store.pendingData.buffers[optionalResourceIndex] = move(gpuBuffer);
506             } else {
507                 store.pendingData.buffers.emplace_back(move(gpuBuffer));
508             }
509         }
510 
511         const StoreAllocationData sad = StoreAllocation(store, name, replacedHandle, RenderHandleType::GPU_BUFFER,
512             ResourceDescriptor { desc }, optionalResourceIndex, 0u);
513         // additional data is increased in StoreAllocation
514         // there are as many additional data elements as clientHandle elements
515         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(sad.handle.GetHandle());
516         PLUGIN_ASSERT(arrayIndex < store.additionalData.size());
517         if (GpuBuffer* buffer = store.pendingData.buffers[optionalResourceIndex].get(); buffer) {
518             store.additionalData[arrayIndex].resourcePtr = reinterpret_cast<uintptr_t>(reinterpret_cast<void*>(buffer));
519         }
520         return sad;
521     } else {
522         return StoreAllocation(
523             store, name, replacedHandle, RenderHandleType::GPU_BUFFER, ResourceDescriptor { desc }, ~0u, 0u);
524     }
525 }
526 
Create(const string_view name,const GpuBufferDesc & desc)527 RenderHandleReference GpuResourceManager::Create(const string_view name, const GpuBufferDesc& desc)
528 {
529     RenderHandleReference handle;
530 
531     GpuBufferDesc validDesc = GetValidGpuBufferDesc(desc);
532     CheckAndEnableMemoryOptimizations(gpuResourceMgrFlags_, validDesc);
533 
534     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
535         device_.Activate();
536     }
537     PerManagerStore& store = bufferStore_;
538     {
539         const auto lock = std::lock_guard(store.clientMutex);
540 
541         handle = CreateBuffer(name, {}, validDesc).handle;
542     }
543     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
544         device_.Deactivate();
545     }
546     return handle;
547 }
548 
Create(const RenderHandleReference & replacedHandle,const GpuBufferDesc & desc)549 RenderHandleReference GpuResourceManager::Create(const RenderHandleReference& replacedHandle, const GpuBufferDesc& desc)
550 {
551     RenderHandleReference handle;
552 
553     const RenderHandle rawHandle = replacedHandle.GetHandle();
554 #if (RENDER_VALIDATION_ENABLED == 1)
555     const bool valid = RenderHandleUtil::IsValid(rawHandle);
556     const RenderHandleType type = RenderHandleUtil::GetHandleType(rawHandle);
557     if (valid && (type != RenderHandleType::GPU_BUFFER)) {
558         PLUGIN_LOG_E("RENDER_VALIDATION: trying to replace a non GPU buffer handle (type: %u) with GpuBufferDesc",
559             (uint32_t)type);
560     }
561 #endif
562     GpuBufferDesc validDesc = GetValidGpuBufferDesc(desc);
563     CheckAndEnableMemoryOptimizations(gpuResourceMgrFlags_, validDesc);
564 
565     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
566         device_.Activate();
567     }
568     {
569         PerManagerStore& store = bufferStore_;
570         const auto lock = std::lock_guard(store.clientMutex);
571 
572         handle = CreateBuffer({}, rawHandle, validDesc).handle;
573     }
574     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
575         device_.Deactivate();
576     }
577     return handle;
578 }
579 
Create(const string_view name,const GpuBufferDesc & desc,const array_view<const uint8_t> data)580 RenderHandleReference GpuResourceManager::Create(
581     const string_view name, const GpuBufferDesc& desc, const array_view<const uint8_t> data)
582 {
583     RenderHandleReference handle;
584 
585 #if (RENDER_VALIDATION_ENABLED == 1)
586     ValidateGpuBufferDesc(desc);
587 #endif
588 
589     GpuBufferDesc validDesc = GetValidGpuBufferDesc(desc);
590     CheckAndEnableMemoryOptimizations(gpuResourceMgrFlags_, validDesc);
591     PLUGIN_ASSERT(validDesc.byteSize == data.size_bytes());
592     const bool useStagingBuffer =
593         (validDesc.memoryPropertyFlags & CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ? false : true;
594 
595     auto& store = bufferStore_;
596     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
597         device_.Activate();
598     }
599     {
600         StoreAllocationData sad;
601         const auto lock = std::lock_guard(store.clientMutex);
602 
603         sad = CreateBuffer(name, {}, validDesc);
604         const uint32_t minByteSize = std::min(validDesc.byteSize, (uint32_t)data.size_bytes());
605 
606         auto const stagingLock = std::lock_guard(stagingMutex_);
607 
608         stagingOperations_.bufferCopies.emplace_back(BufferCopy { 0, 0, minByteSize });
609         const uint32_t beginIndex = (uint32_t)stagingOperations_.bufferCopies.size() - 1;
610         vector<uint8_t> copiedData(data.cbegin().ptr(), data.cend().ptr());
611 
612         // add staging vector index handle to resource handle in pending allocations
613         PLUGIN_ASSERT(sad.allocationIndex < store.pendingData.allocations.size());
614         auto& allocRef = store.pendingData.allocations[sad.allocationIndex];
615         allocRef.optionalStagingVectorIndex = static_cast<uint32_t>(stagingOperations_.bufferToBuffer.size());
616         allocRef.optionalStagingCopyType = useStagingBuffer ? StagingCopyStruct::CopyType::BUFFER_TO_BUFFER
617                                                             : StagingCopyStruct::CopyType::CPU_TO_BUFFER;
618 
619         if (useStagingBuffer) {
620             const uint32_t stagingBufferByteSize =
621                 useStagingBuffer ? static_cast<uint32_t>(copiedData.size_in_bytes()) : 0u;
622             stagingOperations_.bufferToBuffer.emplace_back(
623                 StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_VECTOR, {}, sad.handle, beginIndex, 1,
624                     move(copiedData), nullptr, Format::BASE_FORMAT_UNDEFINED, stagingBufferByteSize, false });
625         } else {
626             stagingOperations_.cpuToBuffer.emplace_back(
627                 StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_VECTOR, {}, sad.handle, beginIndex, 1,
628                     move(copiedData), nullptr, Format::BASE_FORMAT_UNDEFINED, 0u, false });
629         }
630         handle = move(sad.handle);
631     }
632     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
633         device_.Deactivate();
634     }
635     return handle;
636 }
637 
Create(const GpuBufferDesc & desc)638 RenderHandleReference GpuResourceManager::Create(const GpuBufferDesc& desc)
639 {
640     RenderHandleReference handle;
641     GpuBufferDesc validDesc = GetValidGpuBufferDesc(desc);
642     CheckAndEnableMemoryOptimizations(gpuResourceMgrFlags_, validDesc);
643     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
644         device_.Activate();
645     }
646     {
647         auto& store = bufferStore_;
648         const auto lock = std::lock_guard(store.clientMutex);
649 
650         handle = CreateBuffer({}, {}, validDesc).handle;
651     }
652     if (desc.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE) {
653         device_.Deactivate();
654     }
655     return handle;
656 }
657 
Create(const GpuBufferDesc & desc,const array_view<const uint8_t> data)658 RenderHandleReference GpuResourceManager::Create(const GpuBufferDesc& desc, const array_view<const uint8_t> data)
659 {
660     // this is a fwd-method, desc is validated inside the called method
661     return Create({}, desc, data);
662 }
663 
664 // needs to be locked when called
CreateImage(const string_view name,const RenderHandle & replacedHandle,const GpuImageDesc & desc)665 GpuResourceManager::StoreAllocationData GpuResourceManager::CreateImage(
666     const string_view name, const RenderHandle& replacedHandle, const GpuImageDesc& desc)
667 {
668 #if (RENDER_VALIDATION_ENABLED == 1)
669     ValidateGpuImageDesc(desc, name);
670 #endif
671 
672     PerManagerStore& store = imageStore_;
673     GpuImageDesc validatedDesc {
674         desc.imageType,
675         desc.imageViewType,
676         desc.format,
677         (desc.imageTiling > ImageTiling::CORE_IMAGE_TILING_LINEAR) ? ImageTiling::CORE_IMAGE_TILING_OPTIMAL
678                                                                    : desc.imageTiling,
679         desc.usageFlags & GpuResourceDescFlagValidation::ALL_GPU_IMAGE_USAGE_FLAGS,
680         ((desc.memoryPropertyFlags != 0) ? desc.memoryPropertyFlags
681                                          : MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) &
682             GpuResourceDescFlagValidation::ALL_MEMORY_PROPERTY_FLAGS,
683         desc.createFlags & GpuResourceDescFlagValidation::ALL_IMAGE_CREATE_FLAGS,
684         desc.engineCreationFlags,
685         Math::min(MAX_IMAGE_EXTENT, Math::max(1u, desc.width)),
686         Math::min(MAX_IMAGE_EXTENT, Math::max(1u, desc.height)),
687         Math::min(MAX_IMAGE_EXTENT, Math::max(1u, desc.depth)),
688         Math::max(
689             1u, Math::min(desc.mipCount,
690                     static_cast<uint32_t>(std::log2f(static_cast<float>(Math::max(desc.width, desc.height)))) + 1u)),
691         Math::max(1u, desc.layerCount),
692         Math::max(1u, desc.sampleCountFlags),
693         desc.componentMapping,
694     };
695     const FormatProperties formatProperties = device_.GetFormatProperties(desc.format);
696     if (((desc.imageTiling == CORE_IMAGE_TILING_OPTIMAL) && (formatProperties.optimalTilingFeatures == 0)) ||
697         ((desc.imageTiling == CORE_IMAGE_TILING_LINEAR) && (formatProperties.linearTilingFeatures == 0))) {
698         validatedDesc.format = ForceUpdateUnsupportedFormat(validatedDesc.format);
699     }
700     return StoreAllocation(store, name, replacedHandle, RenderHandleType::GPU_IMAGE,
701         ResourceDescriptor { std::move(validatedDesc) }, ~0u, 0u);
702 }
703 
Create(const RenderHandleReference & replacedHandle,const GpuImageDesc & desc)704 RenderHandleReference GpuResourceManager::Create(const RenderHandleReference& replacedHandle, const GpuImageDesc& desc)
705 {
706     const RenderHandle rawHandle = replacedHandle.GetHandle();
707 #if (RENDER_VALIDATION_ENABLED == 1)
708     const bool valid = RenderHandleUtil::IsValid(rawHandle);
709     const RenderHandleType type = RenderHandleUtil::GetHandleType(rawHandle);
710     if (valid && (type != RenderHandleType::GPU_IMAGE)) {
711         PLUGIN_LOG_E(
712             "RENDER_VALIDATION: trying to replace a non GPU image handle (type: %u) with GpuImageDesc", (uint32_t)type);
713     }
714 #endif
715     PerManagerStore& store = imageStore_;
716     const auto lock = std::lock_guard(store.clientMutex);
717 
718     return CreateImage({}, rawHandle, desc).handle;
719 }
720 
Create(const string_view name,const GpuImageDesc & desc)721 RenderHandleReference GpuResourceManager::Create(const string_view name, const GpuImageDesc& desc)
722 {
723     PerManagerStore& store = imageStore_;
724     const auto lock = std::lock_guard(store.clientMutex);
725 
726     return CreateImage(name, {}, desc).handle;
727 }
728 
Create(const GpuImageDesc & desc)729 RenderHandleReference GpuResourceManager::Create(const GpuImageDesc& desc)
730 {
731     PerManagerStore& store = imageStore_;
732     const auto lock = std::lock_guard(store.clientMutex);
733 
734     return CreateImage({}, {}, desc).handle;
735 }
736 
RemapGpuImageHandle(const RenderHandle & clientHandle,const RenderHandle & clientHandleGpuResource)737 void GpuResourceManager::RemapGpuImageHandle(
738     const RenderHandle& clientHandle, const RenderHandle& clientHandleGpuResource)
739 {
740     bool validClientHandles = (RenderHandleUtil::GetHandleType(clientHandle) == RenderHandleType::GPU_IMAGE) ||
741                               (RenderHandleUtil::GetHandleType(clientHandleGpuResource) == RenderHandleType::GPU_IMAGE);
742     if (validClientHandles) {
743         PerManagerStore& store = imageStore_;
744         auto const lock = std::lock_guard(store.clientMutex);
745 
746         const uint32_t clientArrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
747         const uint32_t clientResourceArrayIndex = RenderHandleUtil::GetIndexPart(clientHandleGpuResource);
748         validClientHandles =
749             validClientHandles && ((clientArrayIndex < (uint32_t)store.clientHandles.size()) &&
750                                       (clientResourceArrayIndex < (uint32_t)store.clientHandles.size()));
751         if (validClientHandles) {
752             store.descriptions[clientArrayIndex] = store.descriptions[clientResourceArrayIndex];
753             store.pendingData.remaps.emplace_back(RemapDescription { clientHandle, clientHandleGpuResource });
754         }
755     }
756 
757     if (!validClientHandles) {
758         PLUGIN_LOG_E("invalid client handles given to RemapGpuImageHandle()");
759     }
760 }
761 
Create(const string_view name,const GpuImageDesc & desc,IImageContainer::Ptr image)762 RenderHandleReference GpuResourceManager::Create(
763     const string_view name, const GpuImageDesc& desc, IImageContainer::Ptr image)
764 {
765     StoreAllocationData sad;
766     if (image) {
767         PerManagerStore& store = imageStore_;
768         auto const lockImg = std::lock_guard(store.clientMutex);
769 
770         sad = CreateImage(name, {}, desc);
771         if (IsGpuImage(sad.handle)) {
772             auto const lockStag = std::lock_guard(stagingMutex_);
773 
774             const auto& copies = image->GetBufferImageCopies();
775             const bool scaleImage = GetScalingImageNeed(desc, copies);
776 
777             Format format = Format::BASE_FORMAT_UNDEFINED;
778             if (scaleImage) { // needs to be locked
779                 UpdateStagingScaling(desc.format, copies, stagingOperations_.scalingImageData);
780                 format = desc.format;
781             }
782             for (const auto& copyRef : copies) {
783                 stagingOperations_.bufferImageCopies.emplace_back(ConvertCoreBufferImageCopy(copyRef));
784             }
785 
786             // add staging handle to resource handle in pending allocations
787             PLUGIN_ASSERT(sad.allocationIndex < store.pendingData.allocations.size());
788             auto& allocRef = store.pendingData.allocations[sad.allocationIndex];
789             allocRef.optionalStagingVectorIndex = static_cast<uint32_t>(stagingOperations_.bufferToImage.size());
790             allocRef.optionalStagingCopyType = StagingCopyStruct::CopyType::BUFFER_TO_IMAGE;
791 
792             const uint32_t stagingBufferByteSize = static_cast<uint32_t>(image->GetData().size_bytes());
793             const uint32_t count = static_cast<uint32_t>(copies.size());
794             const uint32_t beginIndex = static_cast<uint32_t>(stagingOperations_.bufferImageCopies.size()) - count;
795             stagingOperations_.bufferToImage.emplace_back(
796                 StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_IMAGE_CONTAINER, {}, sad.handle, beginIndex,
797                     count, {}, move(image), format, stagingBufferByteSize, false });
798         }
799     } else {
800         PLUGIN_LOG_E("invalid image pointer to Create GPU image");
801     }
802     return sad.handle;
803 }
804 
Create(const string_view name,const GpuImageDesc & desc,const array_view<const uint8_t> data,const array_view<const BufferImageCopy> bufferImageCopies)805 RenderHandleReference GpuResourceManager::Create(const string_view name, const GpuImageDesc& desc,
806     const array_view<const uint8_t> data, const array_view<const BufferImageCopy> bufferImageCopies)
807 {
808     StoreAllocationData sad;
809     {
810         PerManagerStore& store = imageStore_;
811         auto const lockImg = std::lock_guard(store.clientMutex);
812 
813         sad = CreateImage(name, {}, desc);
814         if (IsGpuImage(sad.handle)) {
815             auto const lockStag = std::lock_guard(stagingMutex_);
816 
817             Format format = Format::BASE_FORMAT_UNDEFINED;
818             if (GetScalingImageNeed(desc, bufferImageCopies)) { // needs to be locked
819                 UpdateStagingScaling(desc.format, bufferImageCopies, stagingOperations_.scalingImageData);
820                 format = desc.format;
821             }
822             for (const auto& copyRef : bufferImageCopies) {
823 #if (RENDER_VALIDATION_ENABLED == 1)
824                 ValidateGpuImageCopy(desc, copyRef, name);
825 #endif
826                 stagingOperations_.bufferImageCopies.emplace_back(copyRef);
827             }
828             // add staging vector index to resource alloc in pending allocations
829             PLUGIN_ASSERT(sad.allocationIndex < store.pendingData.allocations.size());
830             auto& allocRef = store.pendingData.allocations[sad.allocationIndex];
831             allocRef.optionalStagingVectorIndex = static_cast<uint32_t>(stagingOperations_.bufferToImage.size());
832             allocRef.optionalStagingCopyType = StagingCopyStruct::CopyType::BUFFER_TO_IMAGE;
833 
834             const uint32_t stagingBufferByteSize = static_cast<uint32_t>(data.size_bytes());
835             const uint32_t count = (uint32_t)bufferImageCopies.size();
836             const uint32_t beginIndex = (uint32_t)stagingOperations_.bufferImageCopies.size() - count;
837 
838             vector<uint8_t> copiedData(data.cbegin().ptr(), data.cend().ptr());
839             stagingOperations_.bufferToImage.emplace_back(
840                 StagingCopyStruct { StagingCopyStruct::DataType::DATA_TYPE_VECTOR, {}, sad.handle, beginIndex, count,
841                     move(copiedData), nullptr, format, stagingBufferByteSize, false });
842         }
843     }
844     return sad.handle;
845 }
846 
Create(const string_view name,const GpuImageDesc & desc,const array_view<const uint8_t> data)847 RenderHandleReference GpuResourceManager::Create(
848     const string_view name, const GpuImageDesc& desc, const array_view<const uint8_t> data)
849 {
850     BufferImageCopy bufferImageCopy {
851         0,
852         desc.width,
853         desc.height,
854         { ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0, 0, desc.layerCount },
855         { 0, 0, 0 },
856         { desc.width, desc.height, desc.depth },
857     };
858 
859     const array_view<const BufferImageCopy> av(&bufferImageCopy, 1);
860     return Create(name, desc, data, av);
861 }
862 
CreateView(const string_view name,const GpuImageDesc & desc,const GpuImagePlatformData & gpuImagePlatformData)863 RenderHandleReference GpuResourceManager::CreateView(
864     const string_view name, const GpuImageDesc& desc, const GpuImagePlatformData& gpuImagePlatformData)
865 {
866     device_.Activate();
867     PerManagerStore& store = imageStore_;
868     const auto lock = std::lock_guard(store.clientMutex);
869 
870     // replace immediate created if still pending (i.e. not usable on the GPU)
871     const uint32_t emplaceResourceIndex = static_cast<uint32_t>(store.pendingData.images.size());
872     const uint32_t optionalResourceIndex =
873         Math::min(emplaceResourceIndex, GetPendingOptionalResourceIndex(store, {}, name));
874 
875     unique_ptr<GpuImage> gpuImage = device_.CreateGpuImageView(desc, gpuImagePlatformData);
876     if (gpuImage) {
877         // safety checks
878         if ((optionalResourceIndex < emplaceResourceIndex) &&
879             (optionalResourceIndex < store.pendingData.images.size())) {
880             store.pendingData.images[optionalResourceIndex] = move(gpuImage);
881         } else {
882             store.pendingData.images.emplace_back(move(gpuImage));
883         }
884     }
885     device_.Deactivate();
886 
887     return StoreAllocation(
888         store, name, {}, RenderHandleType::GPU_IMAGE, ResourceDescriptor { desc }, optionalResourceIndex, 0u)
889         .handle;
890 }
891 
CreateView(const string_view name,const GpuImageDesc & desc,const BackendSpecificImageDesc & backendSpecificData)892 RenderHandleReference GpuResourceManager::CreateView(
893     const string_view name, const GpuImageDesc& desc, const BackendSpecificImageDesc& backendSpecificData)
894 {
895     device_.Activate();
896     PerManagerStore& store = imageStore_;
897     const auto lock = std::lock_guard(store.clientMutex);
898 
899     // replace immediate created if still pending (i.e. not usable on the GPU)
900     const uint32_t emplaceResourceIndex = static_cast<uint32_t>(store.pendingData.images.size());
901     const uint32_t optionalResourceIndex =
902         Math::min(emplaceResourceIndex, GetPendingOptionalResourceIndex(store, {}, name));
903 
904     // additional handle flags provide information if platform conversion is needed
905     uint32_t additionalHandleFlags = 0u;
906     unique_ptr<GpuImage> gpuImage = device_.CreateGpuImageView(desc, backendSpecificData);
907     if (gpuImage) {
908         const auto additionalImageFlags = gpuImage->GetAdditionalFlags();
909         additionalHandleFlags =
910             (additionalImageFlags & GpuImage::AdditionalFlagBits::ADDITIONAL_PLATFORM_CONVERSION_BIT)
911                 ? CORE_RESOURCE_HANDLE_PLATFORM_CONVERSION
912                 : 0u;
913         // safety checks
914         if ((optionalResourceIndex < emplaceResourceIndex) &&
915             (optionalResourceIndex < store.pendingData.images.size())) {
916             store.pendingData.images[optionalResourceIndex] = move(gpuImage);
917         } else {
918             store.pendingData.images.emplace_back(move(gpuImage));
919         }
920     }
921     device_.Deactivate();
922 
923     const auto handle = StoreAllocation(store, name, {}, RenderHandleType::GPU_IMAGE, ResourceDescriptor { desc },
924         optionalResourceIndex, additionalHandleFlags)
925                             .handle;
926 #if (RENDER_VALIDATION_ENABLED == 1)
927     if ((additionalHandleFlags & CORE_RESOURCE_HANDLE_PLATFORM_CONVERSION) &&
928         !RenderHandleUtil::IsPlatformConversionResource(handle.GetHandle())) {
929         PLUGIN_LOG_ONCE_W("core_validation_create_view_plat_conversion",
930             "RENDER_VALIDATION: platform conversion needing resource cannot replace existing resource handle (name: "
931             "%s)",
932             name.data());
933     }
934 #endif
935     return handle;
936 }
937 
Create(const GpuImageDesc & desc,const array_view<const uint8_t> data,const array_view<const BufferImageCopy> bufferImageCopies)938 RenderHandleReference GpuResourceManager::Create(const GpuImageDesc& desc, const array_view<const uint8_t> data,
939     const array_view<const BufferImageCopy> bufferImageCopies)
940 {
941     return Create({}, desc, data, bufferImageCopies);
942 }
943 
Create(const GpuImageDesc & desc,const array_view<const uint8_t> data)944 RenderHandleReference GpuResourceManager::Create(const GpuImageDesc& desc, const array_view<const uint8_t> data)
945 {
946     return Create({}, desc, data);
947 }
948 
Create(const GpuImageDesc & desc,IImageContainer::Ptr image)949 RenderHandleReference GpuResourceManager::Create(const GpuImageDesc& desc, IImageContainer::Ptr image)
950 {
951     return Create({}, desc, move(image));
952 }
953 
Create(const string_view name,const GpuSamplerDesc & desc)954 RenderHandleReference GpuResourceManager::Create(const string_view name, const GpuSamplerDesc& desc)
955 {
956     PerManagerStore& store = samplerStore_;
957     const auto lock = std::lock_guard(store.clientMutex);
958 
959     return StoreAllocation(store, name, {}, RenderHandleType::GPU_SAMPLER, ResourceDescriptor { desc }, ~0u, 0u).handle;
960 }
961 
Create(const RenderHandleReference & replacedHandle,const GpuSamplerDesc & desc)962 RenderHandleReference GpuResourceManager::Create(
963     const RenderHandleReference& replacedHandle, const GpuSamplerDesc& desc)
964 {
965     const RenderHandle rawHandle = replacedHandle.GetHandle();
966 #if (RENDER_VALIDATION_ENABLED == 1)
967     const bool valid = RenderHandleUtil::IsValid(rawHandle);
968     const RenderHandleType type = RenderHandleUtil::GetHandleType(rawHandle);
969     if (valid && (type != RenderHandleType::GPU_SAMPLER)) {
970         PLUGIN_LOG_E("RENDER_VALIDATION: trying to replace a non GPU sampler handle (type: %u) with GpuSamplerDesc",
971             (uint32_t)type);
972     }
973 #endif
974     PerManagerStore& store = samplerStore_;
975     const auto lock = std::lock_guard(store.clientMutex);
976 
977     return StoreAllocation(store, {}, rawHandle, RenderHandleType::GPU_SAMPLER, ResourceDescriptor { desc }, ~0u, 0u)
978         .handle;
979 }
980 
Create(const GpuSamplerDesc & desc)981 RenderHandleReference GpuResourceManager::Create(const GpuSamplerDesc& desc)
982 {
983     return Create("", desc);
984 }
985 
CreateAccelerationStructure(const BASE_NS::string_view name,const RenderHandle & replacedHandle,const GpuAccelerationStructureDesc & desc)986 GpuResourceManager::StoreAllocationData GpuResourceManager::CreateAccelerationStructure(
987     const BASE_NS::string_view name, const RenderHandle& replacedHandle, const GpuAccelerationStructureDesc& desc)
988 {
989     PerManagerStore& store = accelStore_;
990     constexpr auto additionalBufferFlags = CORE_RESOURCE_HANDLE_ACCELERATION_STRUCTURE;
991     return StoreAllocation(store, name, replacedHandle, RenderHandleType::GPU_BUFFER, ResourceDescriptor { desc }, ~0u,
992         additionalBufferFlags);
993 }
994 
Create(const GpuAccelerationStructureDesc & desc)995 RenderHandleReference GpuResourceManager::Create(const GpuAccelerationStructureDesc& desc)
996 {
997     PerManagerStore& store = accelStore_;
998     const auto lock = std::lock_guard(store.clientMutex);
999 
1000     return CreateAccelerationStructure("", {}, desc).handle;
1001 }
1002 
Create(const string_view name,const GpuAccelerationStructureDesc & desc)1003 RenderHandleReference GpuResourceManager::Create(const string_view name, const GpuAccelerationStructureDesc& desc)
1004 {
1005     PerManagerStore& store = accelStore_;
1006     const auto lock = std::lock_guard(store.clientMutex);
1007 
1008     return CreateAccelerationStructure(name, {}, desc).handle;
1009 }
1010 
Create(const RenderHandleReference & replacedHandle,const GpuAccelerationStructureDesc & desc)1011 RenderHandleReference GpuResourceManager::Create(
1012     const RenderHandleReference& replacedHandle, const GpuAccelerationStructureDesc& desc)
1013 {
1014     const RenderHandle rawHandle = replacedHandle.GetHandle();
1015 #if (RENDER_VALIDATION_ENABLED == 1)
1016     const bool valid = RenderHandleUtil::IsValid(rawHandle);
1017     const RenderHandleType type = RenderHandleUtil::GetHandleType(rawHandle);
1018     if (valid && (type != RenderHandleType::GPU_BUFFER) && (RenderHandleUtil::IsGpuAccelerationStructure(rawHandle))) {
1019         PLUGIN_LOG_E("RENDER_VALIDATION: trying to replace a non GPU acceleration structure handle (type: %u) with "
1020                      "GpuAccelerationStructureDesc",
1021             (uint32_t)type);
1022     }
1023 #endif
1024     PerManagerStore& store = accelStore_;
1025     const auto lock = std::lock_guard(store.clientMutex);
1026 
1027     return CreateAccelerationStructure("", rawHandle, desc).handle;
1028 }
1029 
1030 // has staging lock and possible gpu buffer lock inside
RemoveStagingOperations(const OperationDescription & destroyAlloc)1031 void GpuResourceManager::RemoveStagingOperations(const OperationDescription& destroyAlloc)
1032 {
1033     // remove possible stagings
1034     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(destroyAlloc.handle);
1035     if (((handleType == RenderHandleType::GPU_BUFFER) || (handleType == RenderHandleType::GPU_IMAGE)) &&
1036         (destroyAlloc.optionalStagingCopyType != StagingCopyStruct::CopyType::UNDEFINED)) {
1037         auto const lockStaging = std::lock_guard(stagingMutex_);
1038 
1039         auto invalidateStagingCopy = [](const OperationDescription& alloc, vector<StagingCopyStruct>& vecRef) {
1040             PLUGIN_ASSERT(alloc.optionalStagingVectorIndex < vecRef.size());
1041             vecRef[alloc.optionalStagingVectorIndex].srcHandle = {};
1042             vecRef[alloc.optionalStagingVectorIndex].dstHandle = {};
1043             vecRef[alloc.optionalStagingVectorIndex].invalidOperation = true;
1044         };
1045 
1046         if (destroyAlloc.optionalStagingCopyType == StagingCopyStruct::CopyType::BUFFER_TO_BUFFER) {
1047             invalidateStagingCopy(destroyAlloc, stagingOperations_.bufferToBuffer);
1048         } else if (destroyAlloc.optionalStagingCopyType == StagingCopyStruct::CopyType::BUFFER_TO_IMAGE) {
1049             invalidateStagingCopy(destroyAlloc, stagingOperations_.bufferToImage);
1050         } else if (destroyAlloc.optionalStagingCopyType == StagingCopyStruct::CopyType::IMAGE_TO_BUFFER) {
1051             invalidateStagingCopy(destroyAlloc, stagingOperations_.imageToBuffer);
1052         } else if (destroyAlloc.optionalStagingCopyType == StagingCopyStruct::CopyType::IMAGE_TO_IMAGE) {
1053             invalidateStagingCopy(destroyAlloc, stagingOperations_.imageToImage);
1054         } else if (destroyAlloc.optionalStagingCopyType == StagingCopyStruct::CopyType::CPU_TO_BUFFER) {
1055             invalidateStagingCopy(destroyAlloc, stagingOperations_.cpuToBuffer);
1056         } else {
1057             PLUGIN_ASSERT(false);
1058         }
1059     }
1060 
1061     // NOTE: we do not clean-up/invalidate copy operations stagingOperations_.cpuToBuffer ATM
1062     // it is user's responsibility do not use handle that you've destroyed
1063 }
1064 
1065 // needs to be locked from outside
1066 // staging cannot be locked when called
Destroy(PerManagerStore & store,const RenderHandle & handle)1067 void GpuResourceManager::Destroy(PerManagerStore& store, const RenderHandle& handle)
1068 {
1069 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
1070     PLUGIN_LOG_E("gpu resource deallocation %" PRIx64, handle.id);
1071 #endif
1072 
1073     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1074     if (arrayIndex < store.clientHandles.size()) {
1075         if (!(store.clientHandles[arrayIndex])) {
1076             return; // early out if re-destroying the same handle
1077         }
1078 #if (RENDER_VALIDATION_ENABLED == 1)
1079         const uint32_t currGeneration =
1080             RenderHandleUtil::GetGenerationIndexPart(store.clientHandles[arrayIndex].GetHandle());
1081         const uint32_t destroyHandleGeneration = RenderHandleUtil::GetGenerationIndexPart(handle);
1082         if (currGeneration != destroyHandleGeneration) {
1083             PLUGIN_LOG_W("RENDER_VALIDATION: destroy handle is not the current generation (destroy:%u != current:%u)",
1084                 currGeneration, destroyHandleGeneration);
1085         }
1086 #endif
1087         const uint32_t hasNameId = RenderHandleUtil::GetHasNamePart(handle);
1088         if (hasNameId != 0) {
1089             // remove name if present
1090             if (auto const pos = std::find_if(store.nameToClientIndex.begin(), store.nameToClientIndex.end(),
1091                     [arrayIndex](auto const& nameToHandle) { return nameToHandle.second == arrayIndex; });
1092                 pos != store.nameToClientIndex.end()) {
1093                 store.nameToClientIndex.erase(pos);
1094             }
1095         }
1096 
1097         // we do not set default values to GpuXDesc (we leave the old data, it won't be used)
1098         // old code: store.descriptions[arrayIndex] = {};
1099         // invalidate handle, noticed when trying to re-destroy (early-out in the beginning of the if)
1100         store.clientHandles[arrayIndex] = {};
1101 
1102         // if the handle is already found and it's an alloc we do not want to allocate and then deallocate
1103         if (const uint32_t pendingArrIndex = store.additionalData[arrayIndex].indexToPendingData;
1104             pendingArrIndex != INVALID_PENDING_INDEX) {
1105             // NOTE: check valid assert here (if called before resources are created)
1106             if (pendingArrIndex < store.pendingData.allocations.size()) {
1107                 auto& ref = store.pendingData.allocations[pendingArrIndex];
1108                 if (ref.allocType == AllocType::ALLOC) {
1109                     ref.allocType = AllocType::REMOVED;
1110                     RemoveStagingOperations(ref);
1111                 }
1112             }
1113         } else {
1114             PLUGIN_ASSERT(store.additionalData[arrayIndex].indexToPendingData == INVALID_PENDING_INDEX);
1115             store.additionalData[arrayIndex] = { 0, static_cast<uint32_t>(store.pendingData.allocations.size()) };
1116             store.pendingData.allocations.emplace_back(
1117                 handle, ResourceDescriptor { GpuBufferDesc {} }, AllocType::DEALLOC, static_cast<uint32_t>(~0u));
1118             // there cannot be staging operations because pendingData was not found
1119             // all other operations to destroyable handle are user's responsibility
1120         }
1121     }
1122 }
1123 
1124 // needs to be locked when called
DestroyImmediate(PerManagerStore & store,const RenderHandle & handle)1125 void GpuResourceManager::DestroyImmediate(PerManagerStore& store, const RenderHandle& handle)
1126 {
1127     if (RenderHandleUtil::IsValid(handle)) { // found, Destroy immediate
1128         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1129         if (arrayIndex < (uint32_t)store.gpuHandles.size()) {
1130             store.mgr->DestroyImmediate(arrayIndex);
1131             store.clientHandles[arrayIndex] = {};
1132             store.additionalData[arrayIndex] = {};
1133             store.gpuHandles[arrayIndex] = InvalidateWithGeneration(store.gpuHandles[arrayIndex]);
1134         }
1135     }
1136 }
1137 
Destroy(const RenderHandle & handle)1138 void GpuResourceManager::Destroy(const RenderHandle& handle)
1139 {
1140     if (RenderHandleUtil::IsValid(handle)) {
1141         const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1142         if (handleType == RenderHandleType::GPU_BUFFER) {
1143             if (RenderHandleUtil::IsGpuAccelerationStructure(handle)) {
1144                 const auto clientLock = std::lock_guard(accelStore_.clientMutex);
1145                 Destroy(accelStore_, handle);
1146             } else {
1147                 const auto clientLock = std::lock_guard(bufferStore_.clientMutex);
1148                 Destroy(bufferStore_, handle);
1149             }
1150         } else if (handleType == RenderHandleType::GPU_IMAGE) {
1151             const auto clientLock = std::lock_guard(imageStore_.clientMutex);
1152             Destroy(imageStore_, handle);
1153         } else if (handleType == RenderHandleType::GPU_SAMPLER) {
1154             const auto clientLock = std::lock_guard(samplerStore_.clientMutex);
1155             Destroy(samplerStore_, handle);
1156         } else {
1157             PLUGIN_LOG_I("invalid gpu resource handle : %" PRIu64, handle.id);
1158         }
1159     }
1160 }
1161 
GetHandle(const PerManagerStore & store,const string_view name) const1162 RenderHandleReference GpuResourceManager::GetHandle(const PerManagerStore& store, const string_view name) const
1163 {
1164     if (name.empty()) { // early out before lock
1165         return RenderHandleReference {};
1166     }
1167 
1168     auto const clientLock = std::lock_guard(store.clientMutex);
1169     if (auto const pos = store.nameToClientIndex.find(name); pos != store.nameToClientIndex.end()) {
1170         PLUGIN_ASSERT(pos->second < static_cast<uint32_t>(store.clientHandles.size()));
1171         return store.clientHandles[pos->second];
1172     }
1173     // NOTE: This is used in some places to check if the GPU resource is found
1174     // therefore no error prints here
1175     return RenderHandleReference {};
1176 }
1177 
GetRawHandle(const PerManagerStore & store,const string_view name) const1178 RenderHandle GpuResourceManager::GetRawHandle(const PerManagerStore& store, const string_view name) const
1179 {
1180     if (name.empty()) { // early out before lock
1181         return RenderHandle {};
1182     }
1183 
1184     auto const clientLock = std::lock_guard(store.clientMutex);
1185     if (auto const pos = store.nameToClientIndex.find(name); pos != store.nameToClientIndex.end()) {
1186         PLUGIN_ASSERT(pos->second < static_cast<uint32_t>(store.clientHandles.size()));
1187         return store.clientHandles[pos->second].GetHandle();
1188     }
1189     // NOTE: This is used in some places to check if the GPU resource is found
1190     // therefore no error prints here
1191     return RenderHandle {};
1192 }
1193 
GetBufferHandle(const string_view name) const1194 RenderHandleReference GpuResourceManager::GetBufferHandle(const string_view name) const
1195 {
1196     return GetHandle(bufferStore_, name);
1197 }
1198 
GetImageHandle(const string_view name) const1199 RenderHandleReference GpuResourceManager::GetImageHandle(const string_view name) const
1200 {
1201     return GetHandle(imageStore_, name);
1202 }
1203 
GetSamplerHandle(const string_view name) const1204 RenderHandleReference GpuResourceManager::GetSamplerHandle(const string_view name) const
1205 {
1206     return GetHandle(samplerStore_, name);
1207 }
1208 
GetAccelerationStructureHandle(const string_view name) const1209 RenderHandleReference GpuResourceManager::GetAccelerationStructureHandle(const string_view name) const
1210 {
1211     return GetHandle(accelStore_, name);
1212 }
1213 
GetBufferRawHandle(const string_view name) const1214 RenderHandle GpuResourceManager::GetBufferRawHandle(const string_view name) const
1215 {
1216     return GetRawHandle(bufferStore_, name);
1217 }
1218 
GetImageRawHandle(const string_view name) const1219 RenderHandle GpuResourceManager::GetImageRawHandle(const string_view name) const
1220 {
1221     return GetRawHandle(imageStore_, name);
1222 }
1223 
GetSamplerRawHandle(const string_view name) const1224 RenderHandle GpuResourceManager::GetSamplerRawHandle(const string_view name) const
1225 {
1226     return GetRawHandle(samplerStore_, name);
1227 }
1228 
GetAccelerationStructureRawHandle(const BASE_NS::string_view name) const1229 RenderHandle GpuResourceManager::GetAccelerationStructureRawHandle(const BASE_NS::string_view name) const
1230 {
1231     return GetRawHandle(accelStore_, name);
1232 }
1233 
GetBufferDescriptor(const RenderHandle & handle) const1234 GpuBufferDesc GpuResourceManager::GetBufferDescriptor(const RenderHandle& handle) const
1235 {
1236     if (!IsGpuBuffer(handle)) {
1237         return GpuBufferDesc {};
1238     }
1239     {
1240         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1241         const PerManagerStore& store = bufferStore_;
1242         auto const clientLock = std::lock_guard(store.clientMutex);
1243         if (arrayIndex < (uint32_t)store.descriptions.size()) {
1244 #if (RENDER_VALIDATION_ENABLED == 1)
1245             if (RenderHandleUtil::GetGenerationIndexPart(store.clientHandles[arrayIndex].GetHandle()) !=
1246                 RenderHandleUtil::GetGenerationIndexPart(handle)) {
1247                 const auto name = GetName(handle);
1248                 PLUGIN_LOG_E(
1249                     "RENDER_VALIDATION: buffer client handle is not current generation (name:%s)", name.c_str());
1250             }
1251 #endif
1252             return store.descriptions[arrayIndex].bufferDescriptor;
1253         }
1254     }
1255     return GpuBufferDesc {};
1256 }
1257 
GetBufferDescriptor(const RenderHandleReference & handle) const1258 GpuBufferDesc GpuResourceManager::GetBufferDescriptor(const RenderHandleReference& handle) const
1259 {
1260     return GetBufferDescriptor(handle.GetHandle());
1261 }
1262 
GetImageDescriptor(const RenderHandle & handle) const1263 GpuImageDesc GpuResourceManager::GetImageDescriptor(const RenderHandle& handle) const
1264 {
1265     if (!IsGpuImage(handle)) {
1266         return GpuImageDesc {};
1267     }
1268     {
1269         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1270         const PerManagerStore& store = imageStore_;
1271         auto const clientLock = std::lock_guard(store.clientMutex);
1272         if (arrayIndex < (uint32_t)store.descriptions.size()) {
1273 #if (RENDER_VALIDATION_ENABLED == 1)
1274             if (RenderHandleUtil::GetGenerationIndexPart(store.clientHandles[arrayIndex].GetHandle()) !=
1275                 RenderHandleUtil::GetGenerationIndexPart(handle)) {
1276                 const auto name = GetName(handle);
1277                 PLUGIN_LOG_E(
1278                     "RENDER_VALIDATION: image client handle is not current generation (name:%s)", name.c_str());
1279             }
1280 #endif
1281             return store.descriptions[arrayIndex].imageDescriptor;
1282         }
1283     }
1284     return GpuImageDesc {};
1285 }
1286 
GetImageDescriptor(const RenderHandleReference & handle) const1287 GpuImageDesc GpuResourceManager::GetImageDescriptor(const RenderHandleReference& handle) const
1288 {
1289     return GetImageDescriptor(handle.GetHandle());
1290 }
1291 
GetSamplerDescriptor(const RenderHandle & handle) const1292 GpuSamplerDesc GpuResourceManager::GetSamplerDescriptor(const RenderHandle& handle) const
1293 {
1294     if (!IsGpuSampler(handle)) {
1295         return GpuSamplerDesc {};
1296     }
1297     {
1298         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1299         const PerManagerStore& store = samplerStore_;
1300         auto const clientLock = std::lock_guard(store.clientMutex);
1301         if (arrayIndex < (uint32_t)store.descriptions.size()) {
1302 #if (RENDER_VALIDATION_ENABLED == 1)
1303             if (RenderHandleUtil::GetGenerationIndexPart(store.clientHandles[arrayIndex].GetHandle()) !=
1304                 RenderHandleUtil::GetGenerationIndexPart(handle)) {
1305                 const auto name = GetName(handle);
1306                 PLUGIN_LOG_E(
1307                     "RENDER_VALIDATION: sampler client handle is not current generation (name:%s)", name.c_str());
1308             }
1309 #endif
1310             return store.descriptions[arrayIndex].samplerDescriptor;
1311         }
1312     }
1313     return GpuSamplerDesc {};
1314 }
1315 
GetSamplerDescriptor(const RenderHandleReference & handle) const1316 GpuSamplerDesc GpuResourceManager::GetSamplerDescriptor(const RenderHandleReference& handle) const
1317 {
1318     return GetSamplerDescriptor(handle.GetHandle());
1319 }
1320 
GetAccelerationStructureDescriptor(const RenderHandle & handle) const1321 GpuAccelerationStructureDesc GpuResourceManager::GetAccelerationStructureDescriptor(const RenderHandle& handle) const
1322 {
1323     if (!IsGpuAccelerationStructure(handle)) {
1324         return GpuAccelerationStructureDesc {};
1325     }
1326     {
1327         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1328         const PerManagerStore& store = accelStore_;
1329         auto const clientLock = std::lock_guard(store.clientMutex);
1330         if (arrayIndex < (uint32_t)store.descriptions.size()) {
1331 #if (RENDER_VALIDATION_ENABLED == 1)
1332             if (RenderHandleUtil::GetGenerationIndexPart(store.clientHandles[arrayIndex].GetHandle()) !=
1333                 RenderHandleUtil::GetGenerationIndexPart(handle)) {
1334                 const auto name = GetName(handle);
1335                 PLUGIN_LOG_E(
1336                     "RENDER_VALIDATION: acceleration structure client handle is not current generation (name:%s)",
1337                     name.c_str());
1338             }
1339 #endif
1340             return store.descriptions[arrayIndex].accelerationDescriptor;
1341         }
1342     }
1343     return GpuAccelerationStructureDesc {};
1344 }
1345 
GetAccelerationStructureDescriptor(const RenderHandleReference & handle) const1346 GpuAccelerationStructureDesc GpuResourceManager::GetAccelerationStructureDescriptor(
1347     const RenderHandleReference& handle) const
1348 {
1349     return GetAccelerationStructureDescriptor(handle.GetHandle());
1350 }
1351 
GetName(const RenderHandle & handle) const1352 string GpuResourceManager::GetName(const RenderHandle& handle) const
1353 {
1354     if (RenderHandleUtil::GetHasNamePart(handle) != 0) {
1355         const PerManagerStore* store = nullptr;
1356         const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1357         if (handleType == RenderHandleType::GPU_BUFFER) {
1358             if (RenderHandleUtil::IsGpuAccelerationStructure(handle)) {
1359                 store = &accelStore_;
1360             } else {
1361                 store = &bufferStore_;
1362             }
1363         } else if (handleType == RenderHandleType::GPU_IMAGE) {
1364             store = &imageStore_;
1365         } else if (handleType == RenderHandleType::GPU_SAMPLER) {
1366             store = &samplerStore_;
1367         }
1368         if (store) {
1369             const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1370             for (const auto& iter : store->nameToClientIndex) {
1371                 if (arrayIndex == iter.second) {
1372                     return iter.first;
1373                 }
1374             }
1375         }
1376     }
1377     return {};
1378 }
1379 
GetName(const RenderHandleReference & handle) const1380 string GpuResourceManager::GetName(const RenderHandleReference& handle) const
1381 {
1382     return GetName(handle.GetHandle());
1383 }
1384 
CreateGpuResource(const OperationDescription & op,const uint32_t arrayIndex,const RenderHandleType resourceType,const uintptr_t preCreatedResVec)1385 void GpuResourceManager::CreateGpuResource(const OperationDescription& op, const uint32_t arrayIndex,
1386     const RenderHandleType resourceType, const uintptr_t preCreatedResVec)
1387 {
1388     if (resourceType == RenderHandleType::GPU_BUFFER) {
1389         PLUGIN_ASSERT(preCreatedResVec);
1390         if (RenderHandleUtil::IsGpuAccelerationStructure(op.handle)) {
1391             PLUGIN_ASSERT(op.optionalResourceIndex == ~0u);
1392             gpuAccelerationStructureMgr_->Create(arrayIndex, op.descriptor.accelerationDescriptor, {});
1393         } else {
1394             if (op.optionalResourceIndex != ~0u) {
1395                 BufferVector& res = *(reinterpret_cast<BufferVector*>(reinterpret_cast<void*>(preCreatedResVec)));
1396                 gpuBufferMgr_->Create(arrayIndex, op.descriptor.bufferDescriptor, move(res[op.optionalResourceIndex]));
1397             } else {
1398                 gpuBufferMgr_->Create(arrayIndex, op.descriptor.bufferDescriptor, {});
1399             }
1400         }
1401     } else if (resourceType == RenderHandleType::GPU_IMAGE) {
1402         PLUGIN_ASSERT(preCreatedResVec);
1403         if (op.optionalResourceIndex != ~0u) {
1404             ImageVector& images = *(reinterpret_cast<ImageVector*>(reinterpret_cast<void*>(preCreatedResVec)));
1405             gpuImageMgr_->Create(arrayIndex, op.descriptor.imageDescriptor, move(images[op.optionalResourceIndex]));
1406         } else {
1407             gpuImageMgr_->Create(arrayIndex, op.descriptor.imageDescriptor, {});
1408         }
1409     } else if (resourceType == RenderHandleType::GPU_SAMPLER) {
1410         PLUGIN_ASSERT(preCreatedResVec == 0);
1411         PLUGIN_ASSERT(op.optionalResourceIndex == ~0u);
1412         gpuSamplerMgr_->Create(arrayIndex, op.descriptor.samplerDescriptor, {});
1413     }
1414 }
1415 
1416 // needs to be locked when called, and call only for valid gpu handles
DestroyGpuResource(const OperationDescription & operation,const uint32_t arrayIndex,const RenderHandleType resourceType,PerManagerStore & store)1417 void GpuResourceManager::DestroyGpuResource(const OperationDescription& operation, const uint32_t arrayIndex,
1418     const RenderHandleType resourceType, PerManagerStore& store)
1419 {
1420     store.mgr->Destroy(arrayIndex);
1421     PLUGIN_ASSERT(arrayIndex < static_cast<uint32_t>(store.gpuHandles.size()));
1422     store.clientHandles[arrayIndex] = {};
1423     store.additionalData[arrayIndex] = {};
1424     store.gpuHandles[arrayIndex] = InvalidateWithGeneration(store.gpuHandles[arrayIndex]);
1425 }
1426 
HandlePendingRemappings(const vector<RemapDescription> & pendingShallowRemappings,vector<EngineResourceHandle> & gpuHandles)1427 void GpuResourceManager::HandlePendingRemappings(
1428     const vector<RemapDescription>& pendingShallowRemappings, vector<EngineResourceHandle>& gpuHandles)
1429 {
1430     for (auto const& shallowRemap : pendingShallowRemappings) {
1431         // find the gpu handle where the client handle wants to point to
1432         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(shallowRemap.resourceClientHandle);
1433         if (arrayIndex < gpuHandles.size()) {
1434             const EngineResourceHandle gpuHandle = gpuHandles[arrayIndex];
1435 
1436             const bool validGpuHandle = RenderHandleUtil::IsValid(gpuHandle);
1437             const uint32_t remapArrayIndex = RenderHandleUtil::GetIndexPart(shallowRemap.shallowClientHandle);
1438             if (validGpuHandle && (remapArrayIndex < (uint32_t)gpuHandles.size())) {
1439                 gpuHandles[remapArrayIndex] = gpuHandle;
1440             } else {
1441                 PLUGIN_LOG_E("gpuimage handle remapping failed; client handle not found");
1442             }
1443         }
1444     }
1445 }
1446 
HandlePendingAllocationsImpl(const bool isFrameEnd)1447 void GpuResourceManager::HandlePendingAllocationsImpl(const bool isFrameEnd)
1448 {
1449     auto handleStorePendingAllocations = [this](PerManagerStore& store, bool isFrameEnd) {
1450         store.clientMutex.lock();
1451 
1452         // check for handle destructions
1453         for (const auto& handleRef : store.clientHandles) {
1454             if (handleRef && (handleRef.GetRefCount() <= 1)) {
1455                 Destroy(store, handleRef.GetHandle());
1456             }
1457         }
1458 
1459         const auto pendingAllocations = move(store.pendingData.allocations);
1460         auto pendingBuffers = move(store.pendingData.buffers);
1461         auto pendingImages = move(store.pendingData.images);
1462         auto pendingRemaps = move(store.pendingData.remaps);
1463         uintptr_t pendingRes = 0; // ptr to pending resource vector
1464         if (store.handleType == RenderHandleType::GPU_BUFFER) {
1465             pendingRes = reinterpret_cast<uintptr_t>(static_cast<void*>(&pendingBuffers));
1466         } else if (store.handleType == RenderHandleType::GPU_IMAGE) {
1467             pendingRes = reinterpret_cast<uintptr_t>(static_cast<void*>(&pendingImages));
1468         }
1469 
1470         // increase the gpu handle vector sizes if needed
1471         if (store.clientHandles.size() > store.gpuHandles.size()) {
1472             store.gpuHandles.resize(store.clientHandles.size());
1473             store.mgr->Resize(store.clientHandles.size());
1474         }
1475 
1476         for (auto const& allocation : pendingAllocations) {
1477             const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(allocation.handle);
1478             // NOTE: needs to be cleared here
1479             store.additionalData[arrayIndex].indexToPendingData = ~0u;
1480             // NOTE: immediately created resource replacing should be prevented (ptr might be present still)
1481             if (allocation.allocType == AllocType::REMOVED) {
1482                 PLUGIN_ASSERT(arrayIndex < static_cast<uint32_t>(store.clientHandles.size()));
1483                 store.availableHandleIds.emplace_back(allocation.handle.id);
1484                 store.clientHandles[arrayIndex] = {};
1485                 store.additionalData[arrayIndex] = {};
1486                 continue;
1487             }
1488 
1489             PLUGIN_ASSERT(arrayIndex < (uint32_t)store.gpuHandles.size());
1490             // first allocation, then dealloc, with dealloc we need to check for deferred destruction
1491             if (allocation.allocType == AllocType::ALLOC) {
1492                 // NOTE: this is essential to get correct, this maps render pass etc. hashing
1493                 // if the generation counter is old there might vulkan image layout issues etc.
1494                 const EngineResourceHandle gpuHandle =
1495                     UnpackNewHandle(store.gpuHandles[arrayIndex], store.handleType, arrayIndex);
1496 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
1497                 LogGpuResource(allocation.handle, gpuHandle);
1498 #endif
1499                 CreateGpuResource(allocation, arrayIndex, store.handleType, pendingRes);
1500                 store.gpuHandles[arrayIndex] = gpuHandle;
1501 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
1502                 store.debugTagAllocations.emplace_back(allocation.handle);
1503 #endif
1504             } else if (isFrameEnd || (!RenderHandleUtil::IsDeferredDestroy(allocation.handle))) {
1505                 PLUGIN_ASSERT(allocation.allocType == AllocType::DEALLOC);
1506                 store.availableHandleIds.emplace_back(allocation.handle.id);
1507                 DestroyGpuResource(allocation, arrayIndex, store.handleType, store);
1508             }
1509             // render graph frame state reset for trackable and not auto reset frame states
1510             // with alloc there might be a replace which needs this as well as with dealloc
1511             if (RenderHandleUtil::IsDynamicResource(allocation.handle) &&
1512                 (!RenderHandleUtil::IsResetOnFrameBorders(allocation.handle))) {
1513                 PLUGIN_ASSERT((store.handleType == RenderHandleType::GPU_BUFFER) ||
1514                               (store.handleType == RenderHandleType::GPU_IMAGE));
1515                 clientHandleStateDestroy_.resources.emplace_back(allocation.handle);
1516             }
1517         }
1518         // although the pendingData was moved and doesn't need locks anymore, other parts of the store are modified
1519         // as well so we need to hold the lock until here.
1520         store.clientMutex.unlock();
1521 
1522         if (store.handleType == RenderHandleType::GPU_IMAGE) {
1523             // no lock needed for gpuHandles access
1524             HandlePendingRemappings(pendingRemaps, store.gpuHandles);
1525         }
1526     };
1527 
1528     handleStorePendingAllocations(bufferStore_, isFrameEnd);
1529     handleStorePendingAllocations(imageStore_, isFrameEnd);
1530     handleStorePendingAllocations(samplerStore_, isFrameEnd);
1531     handleStorePendingAllocations(accelStore_, isFrameEnd);
1532 
1533 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
1534     ProcessDebugTags();
1535 #endif
1536 
1537     gpuBufferMgr_->HandlePendingDeallocations();
1538     gpuImageMgr_->HandlePendingDeallocations();
1539     gpuSamplerMgr_->HandlePendingDeallocations();
1540     gpuAccelerationStructureMgr_->HandlePendingDeallocations();
1541 }
1542 
HandlePendingAllocations()1543 void GpuResourceManager::HandlePendingAllocations()
1544 {
1545     HandlePendingAllocationsImpl(false);
1546 }
1547 
EndFrame()1548 void GpuResourceManager::EndFrame()
1549 {
1550     DestroyFrameStaging();
1551     HandlePendingAllocationsImpl(true);
1552 }
1553 
RenderBackendImmediateRemapGpuImageHandle(const RenderHandle & clientHandle,const RenderHandle & clientHandleGpuResource)1554 void GpuResourceManager::RenderBackendImmediateRemapGpuImageHandle(
1555     const RenderHandle& clientHandle, const RenderHandle& clientHandleGpuResource)
1556 {
1557     const uint32_t clientArrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
1558     const uint32_t clientResourceArrayIndex = RenderHandleUtil::GetIndexPart(clientHandleGpuResource);
1559     const bool areGpuImages = (RenderHandleUtil::GetHandleType(clientHandle) == RenderHandleType::GPU_IMAGE) &&
1560                               (RenderHandleUtil::GetHandleType(clientHandleGpuResource) == RenderHandleType::GPU_IMAGE);
1561     if (areGpuImages) {
1562         PerManagerStore& store = imageStore_;
1563         auto const clientLock = std::lock_guard(store.clientMutex);
1564 
1565         if ((clientArrayIndex < store.gpuHandles.size()) && (clientResourceArrayIndex < store.gpuHandles.size())) {
1566             // NOTE: old owned gpu resource should be destroyed
1567             PLUGIN_ASSERT(RenderHandleUtil::IsValid(store.gpuHandles[clientResourceArrayIndex]));
1568 
1569             store.gpuHandles[clientArrayIndex] = store.gpuHandles[clientResourceArrayIndex];
1570             store.descriptions[clientArrayIndex] = store.descriptions[clientResourceArrayIndex];
1571         } else {
1572             PLUGIN_LOG_E("invalid backend gpu image remapping indices");
1573         }
1574     } else {
1575         PLUGIN_LOG_E("invalid backend gpu image remapping handles");
1576     }
1577 }
1578 
LockFrameStagingData()1579 void GpuResourceManager::LockFrameStagingData()
1580 {
1581     {
1582         std::lock_guard lock(stagingMutex_);
1583         perFrameStagingData_ = move(stagingOperations_);
1584     }
1585 
1586     // create frame staging buffers and set handles for staging
1587     perFrameStagingBuffers_.reserve(
1588         perFrameStagingData_.bufferToBuffer.size() + perFrameStagingData_.bufferToImage.size());
1589     for (auto& ref : perFrameStagingData_.bufferToBuffer) {
1590         if ((!ref.invalidOperation) && (ref.stagingBufferByteSize > 0)) {
1591             perFrameStagingBuffers_.emplace_back(CreateStagingBuffer(GetStagingBufferDesc(ref.stagingBufferByteSize)));
1592             ref.srcHandle = perFrameStagingBuffers_.back();
1593         }
1594     }
1595     for (auto& ref : perFrameStagingData_.bufferToImage) {
1596         if ((!ref.invalidOperation) && (ref.stagingBufferByteSize > 0)) {
1597             perFrameStagingBuffers_.emplace_back(CreateStagingBuffer(GetStagingBufferDesc(ref.stagingBufferByteSize)));
1598             ref.srcHandle = perFrameStagingBuffers_.back();
1599         }
1600     }
1601 
1602     // create image scaling targets and set handles
1603     perFrameStagingScalingImages_.resize(perFrameStagingData_.scalingImageData.scalingImages.size());
1604     for (size_t idx = 0; idx < perFrameStagingData_.scalingImageData.scalingImages.size(); ++idx) {
1605         auto& scalingImageRef = perFrameStagingData_.scalingImageData.scalingImages[idx];
1606         perFrameStagingScalingImages_[idx] = Create(
1607             GetStagingScalingImageDesc(scalingImageRef.format, scalingImageRef.maxWidth, scalingImageRef.maxHeight));
1608         scalingImageRef.handle = perFrameStagingScalingImages_[idx];
1609     }
1610 }
1611 
DestroyFrameStaging()1612 void GpuResourceManager::DestroyFrameStaging()
1613 {
1614     // explicit destruction of staging resources
1615     {
1616         PerManagerStore& store = bufferStore_;
1617         auto const clientLock = std::lock_guard(store.clientMutex);
1618         for (const auto& handleRef : perFrameStagingBuffers_) {
1619             Destroy(store, handleRef.GetHandle());
1620         }
1621         perFrameStagingBuffers_.clear();
1622     }
1623     {
1624         PerManagerStore& store = imageStore_;
1625         auto const clientLock = std::lock_guard(store.clientMutex);
1626         for (const auto& handleRef : perFrameStagingScalingImages_) {
1627             Destroy(store, handleRef.GetHandle());
1628         }
1629         perFrameStagingScalingImages_.clear();
1630     }
1631 }
1632 
HasStagingData() const1633 bool GpuResourceManager::HasStagingData() const
1634 {
1635     if (perFrameStagingData_.bufferToBuffer.empty() && perFrameStagingData_.bufferToImage.empty() &&
1636         perFrameStagingData_.imageToBuffer.empty() && perFrameStagingData_.imageToImage.empty() &&
1637         perFrameStagingData_.cpuToBuffer.empty() && perFrameStagingData_.bufferCopies.empty() &&
1638         perFrameStagingData_.bufferImageCopies.empty() && perFrameStagingData_.imageCopies.empty()) {
1639         return false;
1640     } else {
1641         return true;
1642     }
1643 }
1644 
ConsumeStagingData()1645 StagingConsumeStruct GpuResourceManager::ConsumeStagingData()
1646 {
1647     StagingConsumeStruct staging = move(perFrameStagingData_);
1648     return staging;
1649 }
1650 
ConsumeStateDestroyData()1651 GpuResourceManager::StateDestroyConsumeStruct GpuResourceManager::ConsumeStateDestroyData()
1652 {
1653     StateDestroyConsumeStruct srcs = move(clientHandleStateDestroy_);
1654     return srcs;
1655 }
1656 
MapBuffer(const RenderHandle & handle) const1657 void* GpuResourceManager::MapBuffer(const RenderHandle& handle) const
1658 {
1659     if (GpuBuffer* buffer = GetBuffer(handle); buffer) {
1660         return buffer->Map();
1661     } else {
1662         return nullptr;
1663     }
1664 }
1665 
MapBuffer(const RenderHandleReference & handle) const1666 void* GpuResourceManager::MapBuffer(const RenderHandleReference& handle) const
1667 {
1668     return MapBuffer(handle.GetHandle());
1669 }
1670 
MapBufferMemory(const RenderHandle & handle) const1671 void* GpuResourceManager::MapBufferMemory(const RenderHandle& handle) const
1672 {
1673     const bool isOutsideRendererMappable = RenderHandleUtil::IsMappableOutsideRenderer(handle);
1674     void* data = nullptr;
1675     if (isOutsideRendererMappable) {
1676         const bool isCreatedImmediate = RenderHandleUtil::IsImmediatelyCreated(handle);
1677         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1678         const auto clientLock = std::lock_guard(bufferStore_.clientMutex);
1679         if (isCreatedImmediate && (arrayIndex < static_cast<uint32_t>(bufferStore_.clientHandles.size()))) {
1680 #if (RENDER_VALIDATION_ENABLED == 1)
1681             if (RenderHandleUtil::GetGenerationIndexPart(bufferStore_.clientHandles[arrayIndex].GetHandle()) !=
1682                 RenderHandleUtil::GetGenerationIndexPart(handle)) {
1683                 const string name = GetName(bufferStore_.clientHandles[arrayIndex].GetHandle());
1684                 PLUGIN_LOG_E("RENDER_VALIDATION: client handle is not current generation (name%s)", name.c_str());
1685             }
1686             if (!bufferStore_.additionalData[arrayIndex].resourcePtr) {
1687                 PLUGIN_LOG_E("RENDER_VALIDATION: invalid pointer with mappable GPU buffer MapBufferMemory");
1688             }
1689 #endif
1690             if (bufferStore_.additionalData[arrayIndex].resourcePtr) {
1691                 data = (reinterpret_cast<GpuBuffer*>(bufferStore_.additionalData[arrayIndex].resourcePtr))->MapMemory();
1692             }
1693         }
1694     } else if (GpuBuffer* buffer = GetBuffer(handle); buffer) {
1695         data = buffer->MapMemory();
1696     }
1697     return data;
1698 }
1699 
MapBufferMemory(const RenderHandleReference & handle) const1700 void* GpuResourceManager::MapBufferMemory(const RenderHandleReference& handle) const
1701 {
1702     return MapBufferMemory(handle.GetHandle());
1703 }
1704 
UnmapBuffer(const RenderHandle & handle) const1705 void GpuResourceManager::UnmapBuffer(const RenderHandle& handle) const
1706 {
1707     const bool isOutsideRendererMappable = RenderHandleUtil::IsMappableOutsideRenderer(handle);
1708     if (isOutsideRendererMappable) {
1709         const bool isCreatedImmediate = RenderHandleUtil::IsImmediatelyCreated(handle);
1710         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1711         const auto clientLock = std::lock_guard(bufferStore_.clientMutex);
1712         if (isCreatedImmediate && (arrayIndex < static_cast<uint32_t>(bufferStore_.clientHandles.size()))) {
1713 #if (RENDER_VALIDATION_ENABLED == 1)
1714             if (RenderHandleUtil::GetGenerationIndexPart(bufferStore_.clientHandles[arrayIndex].GetHandle()) !=
1715                 RenderHandleUtil::GetGenerationIndexPart(handle)) {
1716                 const string name = GetName(bufferStore_.clientHandles[arrayIndex].GetHandle());
1717                 PLUGIN_LOG_E("RENDER_VALIDATION: client handle is not current generation (name%s)", name.c_str());
1718             }
1719             if (bufferStore_.additionalData[arrayIndex].resourcePtr) {
1720                 (reinterpret_cast<GpuBuffer*>(bufferStore_.additionalData[arrayIndex].resourcePtr))->Unmap();
1721             } else {
1722                 PLUGIN_LOG_E("RENDER_VALIDATION: invalid pointer with mappable GPU buffer UnmapBuffer");
1723             }
1724 #endif
1725         }
1726     } else if (const GpuBuffer* buffer = GetBuffer(handle); buffer) {
1727         buffer->Unmap();
1728     }
1729 }
1730 
UnmapBuffer(const RenderHandleReference & handle) const1731 void GpuResourceManager::UnmapBuffer(const RenderHandleReference& handle) const
1732 {
1733     return UnmapBuffer(handle.GetHandle());
1734 }
1735 
1736 // must be locked when called
CommitPendingData(PerManagerStore & store)1737 GpuResourceManager::PendingData GpuResourceManager::CommitPendingData(PerManagerStore& store)
1738 {
1739     return { move(store.pendingData.allocations), move(store.pendingData.buffers), move(store.pendingData.images),
1740         move(store.pendingData.remaps) };
1741 }
1742 
DebugPrintValidCounts()1743 void GpuResourceManager::DebugPrintValidCounts()
1744 {
1745 #if (RENDER_VALIDATION_ENABLED == 1)
1746     PLUGIN_LOG_D("GPU buffer count: %u", static_cast<uint32_t>(gpuBufferMgr_->GetValidResourceCount()));
1747     PLUGIN_LOG_D("GPU image count: %u", static_cast<uint32_t>(gpuImageMgr_->GetValidResourceCount()));
1748     PLUGIN_LOG_D("GPU sampler count: %u", static_cast<uint32_t>(gpuSamplerMgr_->GetValidResourceCount()));
1749     PLUGIN_LOG_D("GPU acceleration structure count: %u",
1750         static_cast<uint32_t>(gpuAccelerationStructureMgr_->GetValidResourceCount()));
1751 #endif
1752 }
1753 
WaitForIdleAndDestroyGpuResources()1754 void GpuResourceManager::WaitForIdleAndDestroyGpuResources()
1755 {
1756 #ifndef NDEBUG
1757     PLUGIN_LOG_D("WFIADGR thread id: %" PRIu64, (uint64_t)std::hash<std::thread::id> {}(std::this_thread::get_id()));
1758 #endif
1759     device_.Activate();
1760     device_.WaitForIdle();
1761 
1762     // 1. immediate Destroy all the handles that are to be destroyed
1763     // 2. throw away everything else that's pending
1764     auto DestroyPendingData = [this](PerManagerStore& store) {
1765         const auto lock = std::lock_guard(store.clientMutex);
1766 
1767         auto pd = CommitPendingData(store);
1768         if (store.clientHandles.size() > store.gpuHandles.size()) {
1769             store.gpuHandles.resize(store.clientHandles.size());
1770             store.mgr->Resize(store.clientHandles.size());
1771         }
1772 
1773 #if (RENDER_VALIDATION_ENABLED == 1)
1774         uint32_t dc = 0;
1775 #endif
1776         for (const auto& ref : pd.allocations) {
1777             if (ref.allocType == AllocType::DEALLOC) {
1778                 store.availableHandleIds.emplace_back(ref.handle.id);
1779                 DestroyImmediate(store, ref.handle);
1780                 // render graph frame state reset for trackable and not auto reset frame states
1781                 if (RenderHandleUtil::IsDynamicResource(ref.handle) &&
1782                     (!RenderHandleUtil::IsResetOnFrameBorders(ref.handle))) {
1783                     PLUGIN_ASSERT((store.handleType == RenderHandleType::GPU_BUFFER) ||
1784                                   (store.handleType == RenderHandleType::GPU_IMAGE));
1785                     clientHandleStateDestroy_.resources.emplace_back(ref.handle);
1786                 }
1787 #if (RENDER_VALIDATION_ENABLED == 1)
1788                 dc++;
1789             } else if (ref.allocType == AllocType::REMOVED) {
1790                 dc++;
1791 #endif
1792             }
1793         }
1794 #if (RENDER_VALIDATION_ENABLED == 1)
1795         PLUGIN_LOG_D("WFIADGR: d: %u r (type:%u)", dc, uint32_t(store.handleType));
1796         PLUGIN_LOG_D("WFIADGR: pa cl: %u (t:%u)", (uint32_t)pd.allocations.size() - dc, uint32_t(store.handleType));
1797 #endif
1798     };
1799 
1800     DestroyPendingData(bufferStore_);
1801     DestroyPendingData(imageStore_);
1802     DestroyPendingData(samplerStore_);
1803     DestroyPendingData(accelStore_);
1804 
1805     // make sure that all staging resources are forcefully destroyed
1806     LockFrameStagingData();
1807     ConsumeStagingData(); // consume cpu data
1808     DestroyFrameStaging();
1809 
1810     gpuBufferMgr_->HandlePendingDeallocationsImmediate();
1811     gpuImageMgr_->HandlePendingDeallocationsImmediate();
1812     gpuSamplerMgr_->HandlePendingDeallocationsImmediate();
1813     gpuAccelerationStructureMgr_->HandlePendingDeallocationsImmediate();
1814 
1815     DebugPrintValidCounts();
1816 
1817     device_.Deactivate();
1818 }
1819 
GetGpuHandle(const PerManagerStore & store,const RenderHandle & clientHandle) const1820 EngineResourceHandle GpuResourceManager::GetGpuHandle(
1821     const PerManagerStore& store, const RenderHandle& clientHandle) const
1822 {
1823     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
1824     if (arrayIndex < (uint32_t)store.gpuHandles.size()) {
1825 #if (RENDER_VALIDATION_ENABLED == 1)
1826         if (RenderHandleUtil::GetGenerationIndexPart(store.clientHandles[arrayIndex].GetHandle()) !=
1827             RenderHandleUtil::GetGenerationIndexPart(clientHandle)) {
1828             const string name = GetName(store.clientHandles[arrayIndex].GetHandle());
1829             PLUGIN_LOG_E("RENDER_VALIDATION: client handle is not current generation (name%s)", name.c_str());
1830         }
1831         if (!RenderHandleUtil::IsValid(store.gpuHandles[arrayIndex])) {
1832             PLUGIN_LOG_E("RENDER_VALIDATION : invalid gpu handle %" PRIx64, clientHandle.id);
1833         }
1834 #endif
1835         return store.gpuHandles[arrayIndex];
1836     } else {
1837         PLUGIN_LOG_E("No gpu resource handle for client handle : %" PRIx64, clientHandle.id);
1838         return EngineResourceHandle {};
1839     }
1840 }
1841 
GetGpuHandle(const RenderHandle & clientHandle) const1842 EngineResourceHandle GpuResourceManager::GetGpuHandle(const RenderHandle& clientHandle) const
1843 {
1844     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(clientHandle);
1845     if (handleType == RenderHandleType::GPU_BUFFER) {
1846         if (RenderHandleUtil::IsGpuAccelerationStructure(clientHandle)) {
1847             return GetGpuHandle(accelStore_, clientHandle);
1848         } else {
1849             return GetGpuHandle(bufferStore_, clientHandle);
1850         }
1851     } else if (handleType == RenderHandleType::GPU_IMAGE) {
1852         return GetGpuHandle(imageStore_, clientHandle);
1853     } else if (handleType == RenderHandleType::GPU_SAMPLER) {
1854         return GetGpuHandle(samplerStore_, clientHandle);
1855     } else {
1856         PLUGIN_LOG_E("invalid gpu resource handle : %" PRIx64, clientHandle.id);
1857         return {};
1858     }
1859 }
1860 
GetBuffer(const RenderHandle & handle) const1861 GpuBuffer* GpuResourceManager::GetBuffer(const RenderHandle& handle) const
1862 {
1863     const EngineResourceHandle resHandle = GetGpuHandle(bufferStore_, handle);
1864     return gpuBufferMgr_->Get(RenderHandleUtil::GetIndexPart(resHandle));
1865 }
1866 
GetImage(const RenderHandle & handle) const1867 GpuImage* GpuResourceManager::GetImage(const RenderHandle& handle) const
1868 {
1869     const EngineResourceHandle resHandle = GetGpuHandle(imageStore_, handle);
1870     return gpuImageMgr_->Get(RenderHandleUtil::GetIndexPart(resHandle));
1871 }
1872 
GetSampler(const RenderHandle & handle) const1873 GpuSampler* GpuResourceManager::GetSampler(const RenderHandle& handle) const
1874 {
1875     const EngineResourceHandle resHandle = GetGpuHandle(samplerStore_, handle);
1876     return gpuSamplerMgr_->Get(RenderHandleUtil::GetIndexPart(resHandle));
1877 }
1878 
GetAccelerationStructure(const RenderHandle & handle) const1879 GpuAccelerationStructure* GpuResourceManager::GetAccelerationStructure(const RenderHandle& handle) const
1880 {
1881     const EngineResourceHandle resHandle = GetGpuHandle(accelStore_, handle);
1882     return gpuAccelerationStructureMgr_->Get(RenderHandleUtil::GetIndexPart(resHandle));
1883 }
1884 
GetBufferHandleCount() const1885 uint32_t GpuResourceManager::GetBufferHandleCount() const
1886 {
1887     return static_cast<uint32_t>(bufferStore_.gpuHandles.size());
1888 }
1889 
GetImageHandleCount() const1890 uint32_t GpuResourceManager::GetImageHandleCount() const
1891 {
1892     return static_cast<uint32_t>(imageStore_.gpuHandles.size());
1893 }
1894 
CreateClientHandle(const RenderHandleType type,const ResourceDescriptor & resourceDescriptor,const uint64_t handleId,const uint32_t hasNameId,const uint32_t additionalInfoFlags)1895 RenderHandle GpuResourceManager::CreateClientHandle(const RenderHandleType type,
1896     const ResourceDescriptor& resourceDescriptor, const uint64_t handleId, const uint32_t hasNameId,
1897     const uint32_t additionalInfoFlags)
1898 {
1899     RenderHandle handle;
1900 
1901     const uint32_t index = RenderHandleUtil::GetIndexPart(handleId);
1902     const uint32_t generationIndex = RenderHandleUtil::GetGenerationIndexPart(handleId) + 1; // next gen
1903     if (type == RenderHandleType::GPU_BUFFER) {
1904         const auto& rd = resourceDescriptor.bufferDescriptor;
1905         RenderHandleInfoFlags infoFlags = (rd.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_DYNAMIC_BARRIERS)
1906                                               ? CORE_RESOURCE_HANDLE_DYNAMIC_TRACK
1907                                               : 0u;
1908         infoFlags |= (rd.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_CREATE_IMMEDIATE)
1909                          ? CORE_RESOURCE_HANDLE_IMMEDIATELY_CREATED
1910                          : 0;
1911         infoFlags |= (rd.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_DEFERRED_DESTROY)
1912                          ? CORE_RESOURCE_HANDLE_DEFERRED_DESTROY
1913                          : 0;
1914         infoFlags |= (rd.engineCreationFlags & CORE_ENGINE_BUFFER_CREATION_MAP_OUTSIDE_RENDERER)
1915                          ? CORE_RESOURCE_HANDLE_MAP_OUTSIDE_RENDERER
1916                          : 0;
1917         infoFlags |= additionalInfoFlags;
1918         handle = RenderHandleUtil::CreateGpuResourceHandle(type, infoFlags, index, generationIndex, hasNameId);
1919     } else if (type == RenderHandleType::GPU_IMAGE) {
1920         const auto& rd = resourceDescriptor.imageDescriptor;
1921         RenderHandleInfoFlags infoFlags {};
1922         infoFlags |= (rd.engineCreationFlags & CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS)
1923                          ? CORE_RESOURCE_HANDLE_DYNAMIC_TRACK
1924                          : 0u;
1925         infoFlags |= (rd.engineCreationFlags & CORE_ENGINE_IMAGE_CREATION_DEFERRED_DESTROY)
1926                          ? CORE_RESOURCE_HANDLE_DEFERRED_DESTROY
1927                          : 0;
1928         // force transient attachments to be state reset on frame borders
1929         infoFlags |= ((rd.engineCreationFlags & CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS) ||
1930                          (rd.usageFlags & CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT))
1931                          ? CORE_RESOURCE_HANDLE_RESET_ON_FRAME_BORDERS
1932                          : 0u;
1933         infoFlags |= GetAdditionalImageFlagsFromFormat(rd.format);
1934         infoFlags |= additionalInfoFlags;
1935         handle = RenderHandleUtil::CreateGpuResourceHandle(type, infoFlags, index, generationIndex, hasNameId);
1936     } else if (type == RenderHandleType::GPU_SAMPLER) {
1937         handle = RenderHandleUtil::CreateGpuResourceHandle(type, 0, index, generationIndex, hasNameId);
1938     }
1939     return handle;
1940 }
1941 
1942 // needs to be locked when called
GetNextAvailableHandleId(PerManagerStore & store)1943 uint64_t GpuResourceManager::GetNextAvailableHandleId(PerManagerStore& store)
1944 {
1945     uint64_t handleId = INVALID_RESOURCE_HANDLE;
1946     auto& availableHandleIds = store.availableHandleIds;
1947     if (!availableHandleIds.empty()) {
1948         handleId = availableHandleIds.back();
1949         availableHandleIds.pop_back();
1950     } else {
1951         handleId = static_cast<uint32_t>(store.clientHandles.size())
1952                    << RenderHandleUtil::RES_HANDLE_ID_SHIFT; // next idx
1953     }
1954     return handleId;
1955 }
1956 
1957 // needs to be locked when called
1958 // staging cannot be locked when called
StoreAllocation(PerManagerStore & store,const string_view name,const RenderHandle & replacedHandle,RenderHandleType handleType,const ResourceDescriptor & descriptor,uint32_t optionalResourceIndex,uint32_t additionalHandleFlags)1959 GpuResourceManager::StoreAllocationData GpuResourceManager::StoreAllocation(PerManagerStore& store,
1960     const string_view name, const RenderHandle& replacedHandle, RenderHandleType handleType,
1961     const ResourceDescriptor& descriptor, uint32_t optionalResourceIndex, uint32_t additionalHandleFlags)
1962 {
1963     // NOTE: PerManagerStore gpu handles cannot be touched here
1964     StoreAllocationData data;
1965 
1966     // there cannot be both (valid name and a valid replaced handle)
1967     const uint32_t replaceArrayIndex = RenderHandleUtil::GetIndexPart(replacedHandle);
1968     bool hasReplaceHandle = (replaceArrayIndex < (uint32_t)store.clientHandles.size());
1969     const uint32_t hasNameId = (!name.empty()) ? 1u : 0u;
1970     if (hasNameId != 0u) {
1971         if (auto const iter = store.nameToClientIndex.find(name); iter != store.nameToClientIndex.cend()) {
1972             PLUGIN_ASSERT(iter->second < static_cast<uint32_t>(store.clientHandles.size()));
1973             data.handle = store.clientHandles[iter->second];
1974             PLUGIN_ASSERT_MSG(!RenderHandleUtil::IsDeferredDestroy(data.handle.GetHandle()),
1975                 "deferred desctruction resources cannot be replaced");
1976         } else {
1977             const uint64_t handleId = GetNextAvailableHandleId(store);
1978             data.handle = RenderHandleReference(
1979                 CreateClientHandle(handleType, descriptor, handleId, hasNameId, additionalHandleFlags),
1980                 IRenderReferenceCounter::Ptr(new RenderReferenceCounter()));
1981             store.nameToClientIndex[name] = RenderHandleUtil::GetIndexPart(data.handle.GetHandle());
1982         }
1983     } else if (hasReplaceHandle) {
1984         data.handle = store.clientHandles[replaceArrayIndex];
1985         // NOTE: should be documented better, and prevented
1986         PLUGIN_ASSERT_MSG(!RenderHandleUtil::IsDeferredDestroy(data.handle.GetHandle()),
1987             "deferred desctruction resources cannot be replaced");
1988         if (!RenderHandleUtil::IsValid(data.handle.GetHandle())) {
1989 #if (RENDER_VALIDATION_ENABLED == 1)
1990             PLUGIN_LOG_E("RENDER_VALIDATION: invalid replaced handle given to GPU resource manager, creating new");
1991 #endif
1992             const uint64_t handleId = GetNextAvailableHandleId(store);
1993             data.handle = RenderHandleReference(
1994                 CreateClientHandle(handleType, descriptor, handleId, hasNameId, additionalHandleFlags),
1995                 IRenderReferenceCounter::Ptr(new RenderReferenceCounter()));
1996             hasReplaceHandle = false;
1997         }
1998     } else {
1999         const uint64_t handleId = GetNextAvailableHandleId(store);
2000         data.handle = RenderHandleReference(
2001             CreateClientHandle(handleType, descriptor, handleId, hasNameId, additionalHandleFlags),
2002             IRenderReferenceCounter::Ptr(new RenderReferenceCounter()));
2003     }
2004 
2005     PLUGIN_ASSERT(data.handle);
2006     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(data.handle.GetHandle());
2007     PLUGIN_ASSERT(store.clientHandles.size() == store.descriptions.size());
2008     PLUGIN_ASSERT(store.clientHandles.size() == store.additionalData.size());
2009     if (arrayIndex >= (uint32_t)store.clientHandles.size()) {
2010         store.clientHandles.emplace_back(data.handle);
2011         store.additionalData.push_back({});
2012         store.descriptions.emplace_back(descriptor);
2013     } else {
2014         store.clientHandles[arrayIndex] = data.handle;
2015         // store.additionalData[arrayIndex] cannot be cleared here (staging cleaned based on this)
2016         store.descriptions[arrayIndex] = descriptor;
2017     }
2018 
2019 #if (RENDER_DEBUG_GPU_RESOURCE_IDS == 1)
2020     PLUGIN_LOG_E("gpu resource allocation %" PRIx64 " (name: %s)", data.handle.GetHandle().id, name.data());
2021 #endif
2022 
2023     // store allocation for GPU allocation
2024 
2025     // needs to find the allocation and replace
2026     if (hasReplaceHandle || (hasNameId != 0)) {
2027         if (const uint32_t pendingArrIndex = store.additionalData[arrayIndex].indexToPendingData;
2028             pendingArrIndex != INVALID_PENDING_INDEX) {
2029             PLUGIN_ASSERT(pendingArrIndex < store.pendingData.allocations.size());
2030             data.allocationIndex = pendingArrIndex;
2031         }
2032     }
2033     if (data.allocationIndex == ~0u) {
2034         data.allocationIndex = store.pendingData.allocations.size();
2035         store.additionalData[arrayIndex].indexToPendingData = static_cast<uint32_t>(data.allocationIndex);
2036         store.pendingData.allocations.emplace_back(
2037             data.handle.GetHandle(), descriptor, AllocType::ALLOC, optionalResourceIndex);
2038     } else { // quite rare case and slow path
2039         // replace this frame's allocation
2040         auto& allocOp = store.pendingData.allocations[data.allocationIndex];
2041         // invalid flag should be only needed and all the allocations would be done later
2042         // i.e. create staging buffers and fetch based on index in render node staging
2043         RemoveStagingOperations(allocOp);
2044         store.pendingData.allocations[data.allocationIndex] = { data.handle.GetHandle(), descriptor, AllocType::ALLOC,
2045             optionalResourceIndex };
2046     }
2047 
2048     return data;
2049 }
2050 
IsGpuBuffer(const RenderHandleReference & handle) const2051 bool GpuResourceManager::IsGpuBuffer(const RenderHandleReference& handle) const
2052 {
2053     return IsGpuBuffer(handle.GetHandle());
2054 }
2055 
IsGpuImage(const RenderHandleReference & handle) const2056 bool GpuResourceManager::IsGpuImage(const RenderHandleReference& handle) const
2057 {
2058     return IsGpuImage(handle.GetHandle());
2059 }
2060 
IsGpuSampler(const RenderHandleReference & handle) const2061 bool GpuResourceManager::IsGpuSampler(const RenderHandleReference& handle) const
2062 {
2063     return IsGpuSampler(handle.GetHandle());
2064 }
2065 
IsGpuAccelerationStructure(const RenderHandleReference & handle) const2066 bool GpuResourceManager::IsGpuAccelerationStructure(const RenderHandleReference& handle) const
2067 {
2068     return IsGpuAccelerationStructure(handle.GetHandle());
2069 }
2070 
IsMappableOutsideRender(const RenderHandleReference & handle) const2071 bool GpuResourceManager::IsMappableOutsideRender(const RenderHandleReference& handle) const
2072 {
2073     return RenderHandleUtil::IsMappableOutsideRenderer(handle.GetHandle());
2074 }
2075 
IsGpuBuffer(const RenderHandle & handle) const2076 bool GpuResourceManager::IsGpuBuffer(const RenderHandle& handle) const
2077 {
2078     return RenderHandleUtil::IsGpuBuffer(handle);
2079 }
2080 
IsGpuImage(const RenderHandle & handle) const2081 bool GpuResourceManager::IsGpuImage(const RenderHandle& handle) const
2082 {
2083     return RenderHandleUtil::IsGpuImage(handle);
2084 }
2085 
IsGpuSampler(const RenderHandle & handle) const2086 bool GpuResourceManager::IsGpuSampler(const RenderHandle& handle) const
2087 {
2088     return RenderHandleUtil::IsGpuSampler(handle);
2089 }
2090 
IsGpuAccelerationStructure(const RenderHandle & handle) const2091 bool GpuResourceManager::IsGpuAccelerationStructure(const RenderHandle& handle) const
2092 {
2093     return RenderHandleUtil::IsGpuAccelerationStructure(handle);
2094 }
2095 
IsValid(const RenderHandle & handle) const2096 bool GpuResourceManager::IsValid(const RenderHandle& handle) const
2097 {
2098     return RenderHandleUtil::IsValid(handle);
2099 }
2100 
GetFormatProperties(const RenderHandle & handle) const2101 FormatProperties GpuResourceManager::GetFormatProperties(const RenderHandle& handle) const
2102 {
2103     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
2104     Format format = Format::BASE_FORMAT_UNDEFINED;
2105     if (type == RenderHandleType::GPU_BUFFER) {
2106         const GpuBufferDesc desc = GetBufferDescriptor(handle);
2107         format = desc.format;
2108     } else if (type == RenderHandleType::GPU_IMAGE) {
2109         const GpuImageDesc desc = GetImageDescriptor(handle);
2110         format = desc.format;
2111     }
2112     return device_.GetFormatProperties(format);
2113 }
2114 
GetFormatProperties(const RenderHandleReference & handle) const2115 FormatProperties GpuResourceManager::GetFormatProperties(const RenderHandleReference& handle) const
2116 {
2117     return GetFormatProperties(handle.GetHandle());
2118 }
2119 
GetFormatProperties(const Format & format) const2120 FormatProperties GpuResourceManager::GetFormatProperties(const Format& format) const
2121 {
2122     return device_.GetFormatProperties(format);
2123 }
2124 
CreateGpuImageDesc(const CORE_NS::IImageContainer::ImageDesc & desc) const2125 GpuImageDesc GpuResourceManager::CreateGpuImageDesc(const CORE_NS::IImageContainer::ImageDesc& desc) const
2126 {
2127     GpuImageDesc gpuImageDesc;
2128     // default values for loaded images
2129     gpuImageDesc.imageTiling = CORE_IMAGE_TILING_OPTIMAL;
2130     gpuImageDesc.usageFlags |= CORE_IMAGE_USAGE_SAMPLED_BIT | CORE_IMAGE_USAGE_TRANSFER_DST_BIT;
2131     gpuImageDesc.memoryPropertyFlags = CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
2132 
2133     if (desc.imageFlags & IImageContainer::ImageFlags::FLAGS_CUBEMAP_BIT) {
2134         gpuImageDesc.createFlags |= ImageCreateFlagBits::CORE_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
2135     }
2136     if ((desc.imageFlags & IImageContainer::ImageFlags::FLAGS_REQUESTING_MIPMAPS_BIT) && (desc.mipCount > 1)) {
2137         gpuImageDesc.engineCreationFlags |= EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_GENERATE_MIPS;
2138         gpuImageDesc.usageFlags |= CORE_IMAGE_USAGE_TRANSFER_SRC_BIT;
2139     }
2140     gpuImageDesc.imageType = static_cast<RENDER_NS::ImageType>(desc.imageType);
2141     gpuImageDesc.imageViewType = static_cast<RENDER_NS::ImageViewType>(desc.imageViewType);
2142     gpuImageDesc.format = desc.format;
2143     gpuImageDesc.width = desc.width;
2144     gpuImageDesc.height = desc.height;
2145     gpuImageDesc.depth = desc.depth;
2146     gpuImageDesc.mipCount = desc.mipCount;
2147     gpuImageDesc.layerCount = desc.layerCount;
2148     return gpuImageDesc;
2149 }
2150 
2151 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
ProcessDebugTags()2152 void GpuResourceManager::ProcessDebugTags()
2153 {
2154     // NOTE: there's a minor possibility that client data has changed before these are locked
2155     // but the GPU resource is the correct one
2156     // define CORE_EXTENT_DEBUG_GPU_RESOURCE_MGR_NAMES for more precise debugging
2157 #if defined(CORE_EXTENT_DEBUG_GPU_RESOURCE_MGR_NAMES)
2158     const auto frameIdx = to_string(device_.GetFrameCount());
2159 #endif
2160     auto AddDebugTags = [&](PerManagerStore& store, const RenderHandleType handleType) {
2161         const auto lock = std::lock_guard(store.clientMutex);
2162         vector<RenderHandle> allocs = move(store.debugTagAllocations);
2163         for (const auto& handle : allocs) {
2164             if (RenderHandleUtil::GetHasNamePart(handle) == 0) {
2165                 continue;
2166             }
2167             const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
2168             string name = GetName(store.clientHandles[arrayIndex].GetHandle());
2169 #if defined(CORE_EXTENT_DEBUG_GPU_RESOURCE_MGR_NAMES)
2170             const auto extentName =
2171                 "_chandle:" + to_string(handle.id) + "_idx:" + to_string(arrayIndex) + "_fr:" + frameIdx;
2172             name += extentName;
2173 #endif
2174             if (handleType == RenderHandleType::GPU_BUFFER) {
2175                 GpuResourceUtil::DebugBufferName(device_, *gpuBufferMgr_->Get(arrayIndex), name);
2176             } else if (handleType == RenderHandleType::GPU_IMAGE) {
2177                 GpuResourceUtil::DebugImageName(device_, *gpuImageMgr_->Get(arrayIndex), name);
2178             } else if (handleType == RenderHandleType::GPU_SAMPLER) {
2179                 GpuResourceUtil::DebugSamplerName(device_, *gpuSamplerMgr_->Get(arrayIndex), name);
2180             }
2181         }
2182     };
2183     AddDebugTags(bufferStore_, RenderHandleType::GPU_BUFFER);
2184     AddDebugTags(imageStore_, RenderHandleType::GPU_IMAGE);
2185     AddDebugTags(samplerStore_, RenderHandleType::GPU_SAMPLER);
2186 }
2187 #endif
2188 
RenderNodeGpuResourceManager(GpuResourceManager & gpuResourceManager)2189 RenderNodeGpuResourceManager::RenderNodeGpuResourceManager(GpuResourceManager& gpuResourceManager)
2190     : gpuResourceMgr_(gpuResourceManager)
2191 {}
2192 
~RenderNodeGpuResourceManager()2193 RenderNodeGpuResourceManager::~RenderNodeGpuResourceManager() {}
2194 
Get(const RenderHandle & handle) const2195 RenderHandleReference RenderNodeGpuResourceManager::Get(const RenderHandle& handle) const
2196 {
2197     return gpuResourceMgr_.Get(handle);
2198 }
2199 
Create(const GpuBufferDesc & desc)2200 RenderHandleReference RenderNodeGpuResourceManager::Create(const GpuBufferDesc& desc)
2201 {
2202     return gpuResourceMgr_.Create(desc);
2203 }
2204 
Create(const string_view name,const GpuBufferDesc & desc)2205 RenderHandleReference RenderNodeGpuResourceManager::Create(const string_view name, const GpuBufferDesc& desc)
2206 {
2207     return gpuResourceMgr_.Create(name, desc);
2208 }
2209 
Create(const RenderHandleReference & handle,const GpuBufferDesc & desc)2210 RenderHandleReference RenderNodeGpuResourceManager::Create(
2211     const RenderHandleReference& handle, const GpuBufferDesc& desc)
2212 {
2213     return gpuResourceMgr_.Create(handle, desc);
2214 }
2215 
Create(const string_view name,const GpuBufferDesc & desc,const array_view<const uint8_t> data)2216 RenderHandleReference RenderNodeGpuResourceManager::Create(
2217     const string_view name, const GpuBufferDesc& desc, const array_view<const uint8_t> data)
2218 {
2219     return gpuResourceMgr_.Create(name, desc, data);
2220 }
2221 
Create(const GpuImageDesc & desc)2222 RenderHandleReference RenderNodeGpuResourceManager::Create(const GpuImageDesc& desc)
2223 {
2224     return gpuResourceMgr_.Create(desc);
2225 }
2226 
Create(const string_view name,const GpuImageDesc & desc)2227 RenderHandleReference RenderNodeGpuResourceManager::Create(const string_view name, const GpuImageDesc& desc)
2228 {
2229     return gpuResourceMgr_.Create(name, desc);
2230 }
2231 
Create(const RenderHandleReference & handle,const GpuImageDesc & desc)2232 RenderHandleReference RenderNodeGpuResourceManager::Create(
2233     const RenderHandleReference& handle, const GpuImageDesc& desc)
2234 {
2235     return gpuResourceMgr_.Create(handle, desc);
2236 }
2237 
Create(const string_view name,const GpuImageDesc & desc,const array_view<const uint8_t> data)2238 RenderHandleReference RenderNodeGpuResourceManager::Create(
2239     const string_view name, const GpuImageDesc& desc, const array_view<const uint8_t> data)
2240 {
2241     return gpuResourceMgr_.Create(name, desc, data);
2242 }
2243 
Create(const string_view name,const GpuSamplerDesc & desc)2244 RenderHandleReference RenderNodeGpuResourceManager::Create(const string_view name, const GpuSamplerDesc& desc)
2245 {
2246     return gpuResourceMgr_.Create(name, desc);
2247 }
2248 
Create(const RenderHandleReference & handle,const GpuSamplerDesc & desc)2249 RenderHandleReference RenderNodeGpuResourceManager::Create(
2250     const RenderHandleReference& handle, const GpuSamplerDesc& desc)
2251 {
2252     return gpuResourceMgr_.Create(handle, desc);
2253 }
2254 
Create(const GpuSamplerDesc & desc)2255 RenderHandleReference RenderNodeGpuResourceManager::Create(const GpuSamplerDesc& desc)
2256 {
2257     return gpuResourceMgr_.Create(desc);
2258 }
2259 
Create(const string_view name,const GpuAccelerationStructureDesc & desc)2260 RenderHandleReference RenderNodeGpuResourceManager::Create(
2261     const string_view name, const GpuAccelerationStructureDesc& desc)
2262 {
2263     return gpuResourceMgr_.Create(name, desc);
2264 }
2265 
Create(const RenderHandleReference & handle,const GpuAccelerationStructureDesc & desc)2266 RenderHandleReference RenderNodeGpuResourceManager::Create(
2267     const RenderHandleReference& handle, const GpuAccelerationStructureDesc& desc)
2268 {
2269     return gpuResourceMgr_.Create(handle, desc);
2270 }
2271 
Create(const GpuAccelerationStructureDesc & desc)2272 RenderHandleReference RenderNodeGpuResourceManager::Create(const GpuAccelerationStructureDesc& desc)
2273 {
2274     return gpuResourceMgr_.Create(desc);
2275 }
2276 
GetBufferHandle(const string_view name) const2277 RenderHandle RenderNodeGpuResourceManager::GetBufferHandle(const string_view name) const
2278 {
2279     return gpuResourceMgr_.GetBufferRawHandle(name);
2280 }
2281 
GetImageHandle(const string_view name) const2282 RenderHandle RenderNodeGpuResourceManager::GetImageHandle(const string_view name) const
2283 {
2284     return gpuResourceMgr_.GetImageRawHandle(name);
2285 }
2286 
GetSamplerHandle(const string_view name) const2287 RenderHandle RenderNodeGpuResourceManager::GetSamplerHandle(const string_view name) const
2288 {
2289     return gpuResourceMgr_.GetSamplerRawHandle(name);
2290 }
2291 
GetAccelerationStructureHandle(const string_view name) const2292 RenderHandle RenderNodeGpuResourceManager::GetAccelerationStructureHandle(const string_view name) const
2293 {
2294     return gpuResourceMgr_.GetAccelerationStructureRawHandle(name);
2295 }
2296 
GetBufferDescriptor(const RenderHandle & handle) const2297 GpuBufferDesc RenderNodeGpuResourceManager::GetBufferDescriptor(const RenderHandle& handle) const
2298 {
2299     return gpuResourceMgr_.GetBufferDescriptor(handle);
2300 }
2301 
GetImageDescriptor(const RenderHandle & handle) const2302 GpuImageDesc RenderNodeGpuResourceManager::GetImageDescriptor(const RenderHandle& handle) const
2303 {
2304     return gpuResourceMgr_.GetImageDescriptor(handle);
2305 }
2306 
GetSamplerDescriptor(const RenderHandle & handle) const2307 GpuSamplerDesc RenderNodeGpuResourceManager::GetSamplerDescriptor(const RenderHandle& handle) const
2308 {
2309     return gpuResourceMgr_.GetSamplerDescriptor(handle);
2310 }
2311 
GetAccelerationStructureDescriptor(const RenderHandle & handle) const2312 GpuAccelerationStructureDesc RenderNodeGpuResourceManager::GetAccelerationStructureDescriptor(
2313     const RenderHandle& handle) const
2314 {
2315     return gpuResourceMgr_.GetAccelerationStructureDescriptor(handle);
2316 }
2317 
HasStagingData() const2318 bool RenderNodeGpuResourceManager::HasStagingData() const
2319 {
2320     return gpuResourceMgr_.HasStagingData();
2321 }
2322 
ConsumeStagingData()2323 StagingConsumeStruct RenderNodeGpuResourceManager::ConsumeStagingData()
2324 {
2325     return gpuResourceMgr_.ConsumeStagingData();
2326 }
2327 
MapBuffer(const RenderHandle & handle) const2328 void* RenderNodeGpuResourceManager::MapBuffer(const RenderHandle& handle) const
2329 {
2330     return gpuResourceMgr_.MapBuffer(handle);
2331 }
2332 
MapBufferMemory(const RenderHandle & handle) const2333 void* RenderNodeGpuResourceManager::MapBufferMemory(const RenderHandle& handle) const
2334 {
2335     return gpuResourceMgr_.MapBufferMemory(handle);
2336 }
2337 
UnmapBuffer(const RenderHandle & handle) const2338 void RenderNodeGpuResourceManager::UnmapBuffer(const RenderHandle& handle) const
2339 {
2340     gpuResourceMgr_.UnmapBuffer(handle);
2341 }
2342 
GetGpuResourceManager()2343 GpuResourceManager& RenderNodeGpuResourceManager::GetGpuResourceManager()
2344 {
2345     return gpuResourceMgr_;
2346 }
2347 
IsValid(const RenderHandle & handle) const2348 bool RenderNodeGpuResourceManager::IsValid(const RenderHandle& handle) const
2349 {
2350     return RenderHandleUtil::IsValid(handle);
2351 }
2352 
IsGpuBuffer(const RenderHandle & handle) const2353 bool RenderNodeGpuResourceManager::IsGpuBuffer(const RenderHandle& handle) const
2354 {
2355     return RenderHandleUtil::IsGpuBuffer(handle);
2356 }
2357 
IsGpuImage(const RenderHandle & handle) const2358 bool RenderNodeGpuResourceManager::IsGpuImage(const RenderHandle& handle) const
2359 {
2360     return RenderHandleUtil::IsGpuImage(handle);
2361 }
2362 
IsGpuSampler(const RenderHandle & handle) const2363 bool RenderNodeGpuResourceManager::IsGpuSampler(const RenderHandle& handle) const
2364 {
2365     return RenderHandleUtil::IsGpuSampler(handle);
2366 }
2367 
GetFormatProperties(const RenderHandle & handle) const2368 FormatProperties RenderNodeGpuResourceManager::GetFormatProperties(const RenderHandle& handle) const
2369 {
2370     return gpuResourceMgr_.GetFormatProperties(handle);
2371 }
2372 
GetFormatProperties(const Format format) const2373 FormatProperties RenderNodeGpuResourceManager::GetFormatProperties(const Format format) const
2374 {
2375     return gpuResourceMgr_.GetFormatProperties(format);
2376 }
2377 
GetName(const RenderHandle & handle) const2378 string RenderNodeGpuResourceManager::GetName(const RenderHandle& handle) const
2379 {
2380     return gpuResourceMgr_.GetName(handle);
2381 }
2382 
2383 RENDER_END_NAMESPACE()
2384