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