1 /*
2  * Copyright (c) 2024 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 #ifndef DEVICE_GPU_RESOURCE_MANAGER_H
17 #define DEVICE_GPU_RESOURCE_MANAGER_H
18 
19 #include <mutex>
20 #include <shared_mutex>
21 
22 #include <base/containers/array_view.h>
23 #include <base/containers/string.h>
24 #include <base/containers/unique_ptr.h>
25 #include <base/containers/unordered_map.h>
26 #include <base/containers/vector.h>
27 #include <render/device/gpu_resource_desc.h>
28 #include <render/device/intf_gpu_resource_manager.h>
29 #include <render/namespace.h>
30 #include <render/resource_handle.h>
31 
32 #include "device/gpu_buffer.h"
33 #include "device/gpu_image.h"
34 #include "device/gpu_resource_handle_util.h" // for EngineResourceHandle
35 
36 RENDER_BEGIN_NAMESPACE()
37 class Device;
38 class GpuAccelerationStructure;
39 class GpuBufferManager;
40 class GpuImageManager;
41 class GpuSampler;
42 class GpuSamplerManager;
43 class GpuResourceCache;
44 class GpuResourceManagerBase;
45 template<typename ResourceType, typename CreateInfoType>
46 class GpuResourceManagerTyped;
47 struct GpuImagePlatformData;
48 
49 /** Staging Gpu resource copy struct */
50 struct StagingCopyStruct {
51     /** Data type enumeration */
52     enum class DataType : uint8_t {
53         /** Vector */
54         DATA_TYPE_VECTOR = 0,
55         /** Image container */
56         DATA_TYPE_IMAGE_CONTAINER = 1,
57         /** Direct copy from src, no CPU data with stagingData or imageContainerPtr */
58         DATA_TYPE_DIRECT_SRC_COPY = 2,
59         /** Resource to resource copy with graphics commands */
60         DATA_TYPE_SRC_TO_DST_COPY = 2,
61     };
62     /** Copy type enumeration */
63     enum class CopyType : uint8_t {
64         /** Undefined */
65         UNDEFINED = 0,
66         /** Buffer to buffer */
67         BUFFER_TO_BUFFER,
68         /** Buffer to image */
69         BUFFER_TO_IMAGE,
70         /** Image to buffer */
71         IMAGE_TO_BUFFER,
72         /** Image to image */
73         IMAGE_TO_IMAGE,
74         /** Cpu to buffer */
75         CPU_TO_BUFFER,
76     };
77 
78     /** Data type, default vector */
79     DataType dataType { DataType::DATA_TYPE_VECTOR };
80 
81     /** Source handle */
82     RenderHandleReference srcHandle;
83     /** Destination handle */
84     RenderHandleReference dstHandle;
85 
86     /** Begin index */
87     uint32_t beginIndex { 0 };
88     /** Count */
89     uint32_t count { 0 };
90 
91     /** Staging data */
92     BASE_NS::vector<uint8_t> stagingData;
93     /** Image container pointer */
94     CORE_NS::IImageContainer::Ptr imageContainerPtr;
95 
96     /** Optional format for scaling */
97     BASE_NS::Format format { BASE_NS::Format::BASE_FORMAT_UNDEFINED };
98 
99     /** Staging buffer bytesize. */
100     uint32_t stagingBufferByteSize { 0u };
101 
102     /** Invalid operation which should be ignored. Might be a copy that has been removed during processing. */
103     bool invalidOperation { false };
104 };
105 
106 /** Staging image scaling info struct. Uses the same scaling image for all with the format */
107 struct StagingImageScalingStruct {
108     /** Handle to the resource which is created just before staging */
109     RenderHandleReference handle;
110     /** Format of the scaling image */
111     BASE_NS::Format format { BASE_NS::Format::BASE_FORMAT_UNDEFINED };
112     /** Maximum width of the scaling image */
113     uint32_t maxWidth { 0u };
114     /** Maximum height of the scaling image */
115     uint32_t maxHeight { 0u };
116 };
117 
118 /** All staging scaling image data */
119 struct ScalingImageDataStruct {
120     /** Scaling resource infos (used for fast iteration) */
121     BASE_NS::vector<StagingImageScalingStruct> scalingImages;
122     /** Map with format to image scaling struct index */
123     BASE_NS::unordered_map<uint32_t, size_t> formatToScalingImages;
124 };
125 
126 /** Staging Gpu resource consume struct, this contains all staged resources for this frame */
127 struct StagingConsumeStruct {
128     /** Buffer to buffer */
129     BASE_NS::vector<StagingCopyStruct> bufferToBuffer;
130     /** Buffer to image */
131     BASE_NS::vector<StagingCopyStruct> bufferToImage;
132     /** Image to buffer */
133     BASE_NS::vector<StagingCopyStruct> imageToBuffer;
134     /** Image to image */
135     BASE_NS::vector<StagingCopyStruct> imageToImage;
136     /** Direct CPU copy to buffer */
137     BASE_NS::vector<StagingCopyStruct> cpuToBuffer;
138 
139     /** Buffer copies */
140     BASE_NS::vector<BufferCopy> bufferCopies;
141     /** Buffer image copies */
142     BASE_NS::vector<BufferImageCopy> bufferImageCopies;
143     /** Image copies */
144     BASE_NS::vector<ImageCopy> imageCopies;
145 
146     /** Scaling image data */
147     ScalingImageDataStruct scalingImageData;
148 };
149 
150 /** Per frame work loop:
151  *
152  * 1. renderer.cpp calls HandlePendingAllocations() before any RenderNode-method calls
153  * 2. renderer.cpp calls LockFrameStagingData() before RenderNode::ExecuteFrame call
154  * 3. renderer.cpp calls HandlePendingAllocations() before RenderNode::ExecuteFrame call
155  * 4. RenderBackendXX.cpp calls renderBackendHandleRemapping() before going through render command lists
156  *
157  * NOTE:
158  *    - There are no allocations or deallocations after RenderNode::ExecuteFrame()
159  *
160  * Creation process:
161  *
162  * 1. Create-method is called. It will call StoreAllocation-method.
163  * 2. StoreAllocation-method checks:
164  *     - if replacing old resource with new (when creating with a same name)
165  *     - if there exists handles (array slots) for recycle/reuse
166  *     - if needs to Create new handle (push_backs several vectors)
167  *     - push into pending allocation list
168  *     - quite a lot of processing due to replacing handles and removing old staging ops etc.
169  * 3. handlePendingAllocation is called from Render.cpp
170  *     - allocates the actual new gpu resources
171  *
172  * Destruction process:
173  *
174  * 1. Destroy-method is called
175  *     - invalidates nameToClientHandle
176  *     - push into pending deallocation list
177  * 2. handlePendingAllocation is called from Render.cpp
178  *     - deallocates the actual gpu resources
179  *     - sends the array index (handle array index) for recycling
180  *
181  * NOTE: It is safe to Destroy in RenderNode::ExecuteFrame()
182  * The client handle has been added to render command list
183  * and it is not invalidated in this particular frame.
184  *
185  * NOTE: Simplification would come from not able to replace handles with staging
186  */
187 class GpuResourceManager final : public IGpuResourceManager {
188 public:
189     static GpuBufferDesc GetStagingBufferDesc(const uint32_t byteSize);
190 
191     enum GpuResourceManagerFlagBits : uint32_t {
192         /** Use direct copy with integrated GPUs were device memory is always host visible.
193          * If this flag is set. Device is checked for availability.
194          **/
195         GPU_RESOURCE_MANAGER_OPTIMIZE_STAGING_MEMORY = (1 << 0),
196     };
197     using GpuResourceManagerFlags = uint32_t;
198 
199     struct CreateInfo {
200         GpuResourceManagerFlags flags { 0 };
201     };
202 
203     GpuResourceManager(Device& device, const CreateInfo& createInfo);
204     ~GpuResourceManager() override;
205 
206     GpuResourceManager(const GpuResourceManager&) = delete;
207     GpuResourceManager& operator=(const GpuResourceManager&) = delete;
208 
209     RenderHandleReference Get(const RenderHandle& handle) const override;
210 
211     RenderHandleReference Create(const BASE_NS::string_view name, const GpuBufferDesc& desc) override;
212     RenderHandleReference Create(const BASE_NS::string_view name, const GpuBufferDesc& desc,
213         const BASE_NS::array_view<const uint8_t> data) override;
214 
215     RenderHandleReference Create(const GpuBufferDesc& desc, const BASE_NS::array_view<const uint8_t> data) override;
216     RenderHandleReference Create(const RenderHandleReference& replacedHandle, const GpuBufferDesc& desc) override;
217     RenderHandleReference Create(const GpuBufferDesc& desc) override;
218 
219     RenderHandleReference Create(const BASE_NS::string_view name, const GpuImageDesc& desc) override;
220     RenderHandleReference Create(const BASE_NS::string_view name, const GpuImageDesc& desc,
221         const BASE_NS::array_view<const uint8_t> data) override;
222     RenderHandleReference Create(const RenderHandleReference& replacedHandle, const GpuImageDesc& desc) override;
223     RenderHandleReference Create(
224         const BASE_NS::string_view name, const GpuImageDesc& desc, CORE_NS::IImageContainer::Ptr image) override;
225     RenderHandleReference Create(const BASE_NS::string_view name, const GpuImageDesc& desc,
226         const BASE_NS::array_view<const uint8_t> data,
227         const BASE_NS::array_view<const BufferImageCopy> bufferImageCopies) override;
228 
229     /* Create a GpuImage with unique image name from external texture. Immediate resource creation not deferred. */
230     RenderHandleReference CreateView(const BASE_NS::string_view name, const GpuImageDesc& desc,
231         const BackendSpecificImageDesc& backendSpecificData) override;
232     /* Create gpu image view for platform resource. Immediate creation not deferred. */
233     RenderHandleReference CreateView(
234         const BASE_NS::string_view name, const GpuImageDesc& desc, const GpuImagePlatformData& gpuImagePlatformData);
235 
236     RenderHandleReference Create(const GpuImageDesc& desc) override;
237     RenderHandleReference Create(const GpuImageDesc& desc, const BASE_NS::array_view<const uint8_t> data) override;
238     RenderHandleReference Create(const GpuImageDesc& desc, const BASE_NS::array_view<const uint8_t> data,
239         const BASE_NS::array_view<const BufferImageCopy> bufferImageCopies) override;
240     RenderHandleReference Create(const GpuImageDesc& desc, CORE_NS::IImageContainer::Ptr image) override;
241 
242     RenderHandleReference Create(const GpuAccelerationStructureDesc& desc) override;
243     RenderHandleReference Create(const BASE_NS::string_view name, const GpuAccelerationStructureDesc& desc) override;
244     RenderHandleReference Create(
245         const RenderHandleReference& replacedHandle, const GpuAccelerationStructureDesc& desc) override;
246 
247     /** Remap gpu image handle to some valid gpu image handle. Resources are not destroyed.
248     @param clientHandle A valid client image handle.
249     @param clientHandleGpuResource A valid gpu image handle with a valid gpu resource.
250     clientHandle resource need to be created with CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS
251     */
252     void RemapGpuImageHandle(const RenderHandle& clientHandle, const RenderHandle& clientHandleGpuResource);
253 
254     RenderHandleReference Create(const BASE_NS::string_view name, const GpuSamplerDesc& desc) override;
255     RenderHandleReference Create(const RenderHandleReference& replacedHandle, const GpuSamplerDesc& desc) override;
256     RenderHandleReference Create(const GpuSamplerDesc& desc) override;
257 
258     RenderHandleReference CreateSwapchainImage(
259         const RenderHandleReference& replacedHandle, const BASE_NS::string_view name, const GpuImageDesc& desc);
260 
261     /** Does not have GPU backed data. Will be remapped to other handle */
262     RenderHandleReference CreateShallowHandle(const GpuImageDesc& desc);
263 
264     RenderHandleReference GetBufferHandle(const BASE_NS::string_view name) const override;
265     RenderHandleReference GetImageHandle(const BASE_NS::string_view name) const override;
266     RenderHandleReference GetSamplerHandle(const BASE_NS::string_view name) const override;
267 
268     RenderHandle GetBufferRawHandle(const BASE_NS::string_view name) const;
269     RenderHandle GetImageRawHandle(const BASE_NS::string_view name) const;
270     RenderHandle GetSamplerRawHandle(const BASE_NS::string_view name) const;
271 
272     GpuBufferDesc GetBufferDescriptor(const RenderHandleReference& handle) const override;
273     GpuImageDesc GetImageDescriptor(const RenderHandleReference& handle) const override;
274     GpuSamplerDesc GetSamplerDescriptor(const RenderHandleReference& handle) const override;
275     GpuAccelerationStructureDesc GetAccelerationStructureDescriptor(const RenderHandleReference& handle) const override;
276 
277     GpuBufferDesc GetBufferDescriptor(const RenderHandle& handle) const;
278     GpuImageDesc GetImageDescriptor(const RenderHandle& handle) const;
279     GpuSamplerDesc GetSamplerDescriptor(const RenderHandle& handle) const;
280     GpuAccelerationStructureDesc GetAccelerationStructureDescriptor(const RenderHandle& handle) const;
281 
282     /** Forward allocation/deallocation requests to actual resource managers. Not thread safe.
283     Called only from Renderer. */
284     void HandlePendingAllocations();
285     /** Called from the Renderer after the frame has been rendered with the backend. */
286     void EndFrame();
287 
288     /** Special un-safe call from render backends, to re-map swapchain.
289     This method is un-safe and should only be called from specific location(s). */
290     void RenderBackendImmediateRemapGpuImageHandle(
291         const RenderHandle& clientHandle, const RenderHandle& clientHandleGpuResource);
292 
293     /** The staging data is locked for this frame consumable sets. */
294     void LockFrameStagingData();
295 
296     bool HasStagingData() const;
297     StagingConsumeStruct ConsumeStagingData();
298 
299     struct StateDestroyConsumeStruct {
300         // gpu image or gpu buffers
301         BASE_NS::vector<RenderHandle> resources;
302     };
303     StateDestroyConsumeStruct ConsumeStateDestroyData();
304 
305     void* MapBuffer(const RenderHandleReference& handle) const;
306     void* MapBufferMemory(const RenderHandleReference& handle) const override;
307     void UnmapBuffer(const RenderHandleReference& handle) const override;
308 
309     void* MapBuffer(const RenderHandle& handle) const;
310     void* MapBufferMemory(const RenderHandle& handle) const;
311     void UnmapBuffer(const RenderHandle& handle) const;
312 
313     void WaitForIdleAndDestroyGpuResources() override;
314 
315     EngineResourceHandle GetGpuHandle(const RenderHandle& clientHandle) const;
316 
317     GpuBuffer* GetBuffer(const RenderHandle& gpuHandle) const;
318     GpuImage* GetImage(const RenderHandle& gpuHandle) const;
319     GpuSampler* GetSampler(const RenderHandle& gpuHandle) const;
320 
321     template<typename T>
GetBuffer(const RenderHandle & handle)322     T* GetBuffer(const RenderHandle& handle) const
323     {
324         return static_cast<T*>(GetBuffer(handle));
325     }
326     template<typename T>
GetImage(const RenderHandle & handle)327     T* GetImage(const RenderHandle& handle) const
328     {
329         return static_cast<T*>(GetImage(handle));
330     }
331     template<typename T>
GetSampler(const RenderHandle & handle)332     T* GetSampler(const RenderHandle& handle) const
333     {
334         return static_cast<T*>(GetSampler(handle));
335     }
336 
337     // for render graph to resizing (non-locked access only valid in certain positions)
338     uint32_t GetBufferHandleCount() const;
339     uint32_t GetImageHandleCount() const;
340 
341     bool IsGpuBuffer(const RenderHandleReference& handle) const override;
342     bool IsGpuImage(const RenderHandleReference& handle) const override;
343     bool IsGpuSampler(const RenderHandleReference& handle) const override;
344     bool IsGpuAccelerationStructure(const RenderHandleReference& handle) const override;
345     bool IsSwapchain(const RenderHandleReference& handle) const override;
346     bool IsMappableOutsideRender(const RenderHandleReference& handle) const override;
347     bool IsGpuBuffer(const RenderHandle& handle) const;
348     bool IsGpuImage(const RenderHandle& handle) const;
349     bool IsGpuSampler(const RenderHandle& handle) const;
350     bool IsGpuAccelerationStructure(const RenderHandle& handle) const;
351     bool IsSwapchain(const RenderHandle& handle) const;
352     bool IsValid(const RenderHandle& handle) const;
353 
354     FormatProperties GetFormatProperties(const RenderHandleReference& handle) const override;
355     FormatProperties GetFormatProperties(const RenderHandle& handle) const;
356     FormatProperties GetFormatProperties(const BASE_NS::Format format) const override;
357 
358     GpuImageDesc CreateGpuImageDesc(const CORE_NS::IImageContainer::ImageDesc& desc) const override;
359 
360     BASE_NS::string GetName(const RenderHandle& handle) const;
361     BASE_NS::string GetName(const RenderHandleReference& handle) const override;
362 
363     BASE_NS::vector<RenderHandleReference> GetGpuBufferHandles() const override;
364     BASE_NS::vector<RenderHandleReference> GetGpuImageHandles() const override;
365     BASE_NS::vector<RenderHandleReference> GetGpuSamplerHandles() const override;
366 
367     void SetDefaultGpuBufferCreationFlags(const BufferUsageFlags usageFlags) override;
368     void SetDefaultGpuImageCreationFlags(const ImageUsageFlags usageFlags) override;
369 
370     IGpuResourceCache& GetGpuResourceCache() const override;
371 
372     ImageAspectFlags GetImageAspectFlags(const RenderHandle& handle) const;
373     ImageAspectFlags GetImageAspectFlags(const RenderHandleReference& handle) const override;
374     ImageAspectFlags GetImageAspectFlags(const BASE_NS::Format format) const override;
375 
376 private:
377     Device& device_;
378 
379     GpuResourceManagerFlags gpuResourceMgrFlags_ { 0 };
380 
381     BASE_NS::unique_ptr<GpuResourceManagerTyped<GpuBuffer, GpuBufferDesc>> gpuBufferMgr_;
382     BASE_NS::unique_ptr<GpuResourceManagerTyped<GpuImage, GpuImageDesc>> gpuImageMgr_;
383     BASE_NS::unique_ptr<GpuResourceManagerTyped<GpuSampler, GpuSamplerDesc>> gpuSamplerMgr_;
384 
385     BASE_NS::unique_ptr<GpuResourceCache> gpuResourceCache_;
386 
387     union ResourceDescriptor {
ResourceDescriptor(const GpuBufferDesc & descriptor)388         explicit ResourceDescriptor(const GpuBufferDesc& descriptor) : combinedBufDescriptor { {}, descriptor } {}
ResourceDescriptor(const GpuImageDesc & descriptor)389         explicit ResourceDescriptor(const GpuImageDesc& descriptor) : imageDescriptor(descriptor) {}
ResourceDescriptor(const GpuSamplerDesc & descriptor)390         explicit ResourceDescriptor(const GpuSamplerDesc& descriptor) : samplerDescriptor(descriptor) {}
ResourceDescriptor(const GpuAccelerationStructureDesc & descriptor)391         explicit ResourceDescriptor(const GpuAccelerationStructureDesc& descriptor) : combinedBufDescriptor(descriptor)
392         {}
393         // used for GpuBufferDesc as well
394         GpuAccelerationStructureDesc combinedBufDescriptor;
395         GpuImageDesc imageDescriptor;
396         GpuSamplerDesc samplerDescriptor;
397     };
398 
399     // combine alloc and de-alloc
400     // removed is a handle that is removed before pending allocation is called (i.e. destroyed)
401     enum class AllocType : uint8_t {
402         UNDEFINED = 0,
403         ALLOC = 1,
404         DEALLOC = 2,
405         REMOVED = 3,
406     };
407 
408     struct OperationDescription {
OperationDescriptionOperationDescription409         OperationDescription(
410             RenderHandle handle, const ResourceDescriptor& descriptor, AllocType allocType, uint32_t optResourceIndex)
411             : handle(handle), descriptor(descriptor), allocType(allocType), optionalResourceIndex(optResourceIndex),
412               optionalStagingVectorIndex(~0u), optionalStagingCopyType(StagingCopyStruct::CopyType::UNDEFINED)
413         {}
414 
415         RenderHandle handle;
416         ResourceDescriptor descriptor;
417         AllocType allocType { AllocType::UNDEFINED };
418         uint32_t optionalResourceIndex { ~0u };
419         uint32_t optionalStagingVectorIndex { ~0u };
420         StagingCopyStruct::CopyType optionalStagingCopyType { StagingCopyStruct::CopyType::UNDEFINED };
421     };
422     struct RemapDescription {
423         RenderHandle shallowClientHandle;
424         RenderHandle resourceClientHandle;
425     };
426     using BufferVector = BASE_NS::vector<BASE_NS::unique_ptr<GpuBuffer>>;
427     using ImageVector = BASE_NS::vector<BASE_NS::unique_ptr<GpuImage>>;
428 
429     struct PendingData {
430         BASE_NS::vector<OperationDescription> allocations;
431         // optional
432         BASE_NS::vector<BASE_NS::unique_ptr<GpuBuffer>> buffers; // pre-created
433         BASE_NS::vector<BASE_NS::unique_ptr<GpuImage>> images;   // pre-created
434         BASE_NS::vector<RemapDescription> remaps;
435     };
436 
437     mutable std::mutex allocationMutex_;
438     struct AdditionalData {
439         uintptr_t resourcePtr { 0 };
440         uint32_t indexToPendingData { ~0u }; // cleared to default when processed
441     };
442 
443     struct PerManagerStore {
444         const RenderHandleType handleType { RenderHandleType::UNDEFINED };
445         GpuResourceManagerBase* mgr { nullptr };
446 
447         // client access lock
448         mutable std::shared_mutex clientMutex {};
449 
450         // the following needs be locked with clientMutex
451         BASE_NS::unordered_map<BASE_NS::string, uint32_t> nameToClientIndex {};
452         // resource descriptions, accessed with RenderHandle array index
453         BASE_NS::vector<ResourceDescriptor> descriptions {};
454 
455         // handles might be invalid (when invalid generation is stored in high-bits, i.e. the handle is invalid)
456         BASE_NS::vector<RenderHandleReference> clientHandles {};
457 
458         // index to pending data, ptr to possible gpu buffer mapped data
459         BASE_NS::vector<AdditionalData> additionalData {};
460 
461         // handle ids which can be re-used
462         BASE_NS::vector<uint64_t> availableHandleIds {};
463 
464         PendingData pendingData {};
465 
466         // the following are not locked (ever)
467 
468         // handles might be invalid (when invalid generation is stored in high - bits, i.e.the handle is invalid)
469         BASE_NS::vector<EngineResourceHandle> gpuHandles {};
470         // ogl object name tagging not supported ATM
471 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
472         BASE_NS::vector<RenderHandle> debugTagAllocations {};
473 #endif
474     };
475     PerManagerStore bufferStore_ { RenderHandleType::GPU_BUFFER };
476     PerManagerStore imageStore_ { RenderHandleType::GPU_IMAGE };
477     PerManagerStore samplerStore_ { RenderHandleType::GPU_SAMPLER };
478 
479     // needs to be locked when called
480     static uint64_t GetNextAvailableHandleId(PerManagerStore& mgrStore);
481 
482     struct StoreAllocationData {
483         RenderHandleReference handle;
484         size_t allocationIndex { ~0u };
485     };
486     struct StoreAllocationInfo {
487         ResourceDescriptor descriptor;
488         BASE_NS::string_view name;
489         RenderHandle replacedHandle {};
490         RenderHandleType type {};
491         uint32_t optResourceIndex { ~0u };
492         uint32_t addHandleFlags { 0u };
493         AllocType allocType { AllocType::ALLOC };
494     };
495 
496     void HandlePendingAllocationsImpl(const bool isEndFrame);
497     void Destroy(const RenderHandle& handle);
498     // Destroy staging buffers. Not thread safe. Called from gpu resource manager
499     void DestroyFrameStaging();
500 
501     // needs to be locked when called
502     StoreAllocationData CreateBuffer(
503         const BASE_NS::string_view name, const RenderHandle& replacedHandle, const GpuBufferDesc& desc);
504     // needs to be locked when called
505     StoreAllocationData CreateImage(
506         const BASE_NS::string_view name, const RenderHandle& replacedHandle, const GpuImageDesc& desc);
507     RenderHandleReference CreateStagingBuffer(const GpuBufferDesc& desc);
508     // needs to be locked when called
509     StoreAllocationData CreateAccelerationStructure(
510         const BASE_NS::string_view name, const RenderHandle& replacedHandle, const GpuAccelerationStructureDesc& desc);
511 
512     RenderHandle CreateClientHandle(const RenderHandleType type, const ResourceDescriptor& resourceDescriptor,
513         const uint64_t handleId, const uint32_t hasNameId, const uint32_t additionalInfoFlags);
514 
515     // needs to be locked when called
516     StoreAllocationData StoreAllocation(PerManagerStore& store, const StoreAllocationInfo& info);
517 
518     void CreateGpuResource(const OperationDescription& op, const uint32_t arrayIndex,
519         const RenderHandleType resourceType, const uintptr_t preCreateData);
520 
521     // needs to be locked when called
522     void DestroyGpuResource(const OperationDescription& operation, const uint32_t arrayIndex,
523         const RenderHandleType resourceType, PerManagerStore& store);
524 
525     RenderHandleReference GetHandle(const PerManagerStore& store, const BASE_NS::string_view name) const;
526     RenderHandle GetRawHandle(const PerManagerStore& store, const BASE_NS::string_view name) const;
527 
528     EngineResourceHandle GetGpuHandle(const PerManagerStore& store, const RenderHandle& clientHandle) const;
529 
530     // destroydHandle store needs to be locked, staging locked inside and bufferstore if not already locked
531     void RemoveStagingOperations(const OperationDescription& destroyAlloc);
532     // needs to be locked outside
533     void Destroy(PerManagerStore& store, const RenderHandle& handle);
534     // needs to be locked when called
535     void DestroyImmediate(PerManagerStore& store, const RenderHandle& handle);
536 
537     void HandlePendingRemappings(const BASE_NS::vector<RemapDescription>& pendingShallowRemappings,
538         BASE_NS::vector<EngineResourceHandle>& gpuHandles);
539 
540     PendingData CommitPendingData(PerManagerStore& store);
541 
542     // needs to be locked when called
543     uint32_t GetPendingOptionalResourceIndex(
544         const PerManagerStore& store, const RenderHandle& handle, const BASE_NS::string_view name);
545 
546     // locked inside
547     BASE_NS::vector<RenderHandleReference> GetHandles(const PerManagerStore& store) const;
548 
549     void DebugPrintValidCounts();
550 
551     // list of handles that state data should be destroyed
552     // (e.g. handle is replaced with a new resource or destroyed)
553     // information is passed to render graph
554     StateDestroyConsumeStruct clientHandleStateDestroy_;
555 
556     mutable std::mutex stagingMutex_;
557     StagingConsumeStruct stagingOperations_;   // needs to be locked
558     StagingConsumeStruct perFrameStagingData_; // per frame data after LockFrameStagingData()
559     BASE_NS::vector<RenderHandleReference> perFrameStagingBuffers_;
560     BASE_NS::vector<RenderHandleReference> perFrameStagingScalingImages_;
561 
562     // combined with bitwise OR buffer usage flags
563     BufferUsageFlags defaultBufferUsageFlags_ { 0u };
564     // combined with bitwise OR image usage flags
565     ImageUsageFlags defaultImageUsageFlags_ { 0u };
566 
567     // ogl object name tagging not supported ATM
568 #if (RENDER_VULKAN_VALIDATION_ENABLED == 1)
569     void ProcessDebugTags();
570 #endif
571 };
572 
573 class RenderNodeGpuResourceManager final : public IRenderNodeGpuResourceManager {
574 public:
575     explicit RenderNodeGpuResourceManager(GpuResourceManager& gpuResourceManager);
576     ~RenderNodeGpuResourceManager();
577 
578     RenderHandleReference Get(const RenderHandle& handle) const override;
579 
580     RenderHandleReference Create(const GpuBufferDesc& desc) override;
581     RenderHandleReference Create(const BASE_NS::string_view name, const GpuBufferDesc& desc) override;
582     RenderHandleReference Create(const RenderHandleReference& handle, const GpuBufferDesc& desc) override;
583     RenderHandleReference Create(const BASE_NS::string_view name, const GpuBufferDesc& desc,
584         const BASE_NS::array_view<const uint8_t> data) override;
585 
586     RenderHandleReference Create(const GpuImageDesc& desc) override;
587     RenderHandleReference Create(const BASE_NS::string_view name, const GpuImageDesc& desc) override;
588     RenderHandleReference Create(const RenderHandleReference& handle, const GpuImageDesc& desc) override;
589     RenderHandleReference Create(const BASE_NS::string_view name, const GpuImageDesc& desc,
590         const BASE_NS::array_view<const uint8_t> data) override;
591 
592     RenderHandleReference Create(const GpuSamplerDesc& desc) override;
593     RenderHandleReference Create(const BASE_NS::string_view name, const GpuSamplerDesc& desc) override;
594     RenderHandleReference Create(const RenderHandleReference& handle, const GpuSamplerDesc& desc) override;
595 
596     RenderHandleReference Create(const GpuAccelerationStructureDesc& desc) override;
597     RenderHandleReference Create(const BASE_NS::string_view name, const GpuAccelerationStructureDesc& desc) override;
598     RenderHandleReference Create(
599         const RenderHandleReference& handle, const GpuAccelerationStructureDesc& desc) override;
600 
601     RenderHandle GetBufferHandle(const BASE_NS::string_view name) const override;
602     RenderHandle GetImageHandle(const BASE_NS::string_view name) const override;
603     RenderHandle GetSamplerHandle(const BASE_NS::string_view name) const override;
604 
605     GpuBufferDesc GetBufferDescriptor(const RenderHandle& handle) const override;
606     GpuImageDesc GetImageDescriptor(const RenderHandle& handle) const override;
607     GpuSamplerDesc GetSamplerDescriptor(const RenderHandle& handle) const override;
608     GpuAccelerationStructureDesc GetAccelerationStructureDescriptor(const RenderHandle& handle) const override;
609 
610     bool HasStagingData() const;
611     StagingConsumeStruct ConsumeStagingData();
612 
613     void* MapBuffer(const RenderHandle& handle) const override;
614     void* MapBufferMemory(const RenderHandle& handle) const override;
615     void UnmapBuffer(const RenderHandle& handle) const override;
616 
617     GpuResourceManager& GetGpuResourceManager();
618 
619     bool IsValid(const RenderHandle& handle) const override;
620     bool IsGpuBuffer(const RenderHandle& handle) const override;
621     bool IsGpuImage(const RenderHandle& handle) const override;
622     bool IsGpuSampler(const RenderHandle& handle) const override;
623     bool IsGpuAccelerationStructure(const RenderHandle& handle) const override;
624     bool IsSwapchain(const RenderHandle& handle) const override;
625 
626     FormatProperties GetFormatProperties(const RenderHandle& handle) const override;
627     FormatProperties GetFormatProperties(const BASE_NS::Format format) const override;
628 
629     BASE_NS::string GetName(const RenderHandle& handle) const override;
630 
631     IGpuResourceCache& GetGpuResourceCache() const override;
632 
633     ImageAspectFlags GetImageAspectFlags(const RenderHandle& handle) const override;
634     ImageAspectFlags GetImageAspectFlags(const BASE_NS::Format format) const override;
635 
636 private:
637     GpuResourceManager& gpuResourceMgr_;
638 };
639 RENDER_END_NAMESPACE()
640 
641 #endif // DEVICE_GPU_RESOURCE_MANAGER_H
642