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 VULKAN_GPU_MEMORY_ALLOCATOR_VK_H
17 #define VULKAN_GPU_MEMORY_ALLOCATOR_VK_H
18 
19 // vulkan_core must be before vk_mem_alloc
20 // clang-format off
21 #include <vulkan/vulkan_core.h>
22 #ifdef __OHOS_PLATFORM__
23 #include "../../../../../../../third_party/skia/third_party/vulkanmemoryallocator/include/vk_mem_alloc.h"
24 #else
25 #include <VulkanMemoryAllocator/src/vk_mem_alloc.h>
26 #endif
27 // clang-format on
28 #include <cstddef>
29 #include <cstdint>
30 
31 #include <base/containers/string.h>
32 #include <base/containers/unordered_map.h>
33 #include <base/containers/vector.h>
34 #include <render/device/gpu_resource_desc.h>
35 #include <render/namespace.h>
36 
RENDER_BEGIN_NAMESPACE()37 RENDER_BEGIN_NAMESPACE()
38 /** Gpu memory allocator.
39  * Wrapper around Vulkan Memory Allocator (GPU Open) which is internally synchronized.
40  */
41 class PlatformGpuMemoryAllocator final {
42 public:
43     enum class MemoryAllocatorResourceType : uint8_t {
44         UNDEFINED = 0, // not supported ATM, needs to be buffer or image
45         GPU_BUFFER = 1,
46         GPU_IMAGE = 2,
47     };
48     struct GpuMemoryAllocatorCustomPool {
49         BASE_NS::string name;
50 
51         MemoryAllocatorResourceType resourceType { MemoryAllocatorResourceType::UNDEFINED };
52         uint32_t blockSize { 0 }; // zero fallbacks to default
53         bool linearAllocationAlgorithm { false };
54 
55         union GpuResourceDesc {
56             GpuBufferDesc buffer;
57             GpuImageDesc image;
58         };
59         GpuResourceDesc gpuResourceDesc;
60     };
61 
62     struct GpuMemoryAllocatorCreateInfo {
63         // set to zero for default (vma default 256 MB)
64         uint32_t preferredLargeHeapBlockSize { 32 * 1024 * 1024 };
65 
66         BASE_NS::vector<GpuMemoryAllocatorCustomPool> customPools;
67     };
68 
69     PlatformGpuMemoryAllocator(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
70         const GpuMemoryAllocatorCreateInfo& createInfo);
71     ~PlatformGpuMemoryAllocator();
72 
73     void CreateBuffer(const VkBufferCreateInfo& bufferCreateInfo, const VmaAllocationCreateInfo& allocationCreateInfo,
74         VkBuffer& buffer, VmaAllocation& allocation, VmaAllocationInfo& allocationInfo);
75     void DestroyBuffer(VkBuffer buffer, VmaAllocation allocation);
76 
77     void CreateImage(const VkImageCreateInfo& imageCreateInfo, const VmaAllocationCreateInfo& allocationCreateInfo,
78         VkImage& image, VmaAllocation& allocation, VmaAllocationInfo& allocationInfo);
79     void DestroyImage(VkImage image, VmaAllocation allocation);
80 
81     void* MapMemory(VmaAllocation allocation);
82     void UnmapMemory(VmaAllocation allocation);
83 
84     void FlushAllocation(const VmaAllocation& allocation, const VkDeviceSize offset, const VkDeviceSize byteSize);
85     void InvalidateAllocation(const VmaAllocation& allocation, const VkDeviceSize offset, const VkDeviceSize byteSize);
86     uint32_t GetMemoryTypeProperties(const uint32_t memoryType);
87 
88     VmaPool GetBufferPool(const GpuBufferDesc& desc) const;
89     VmaPool GetImagePool(const GpuImageDesc& desc) const;
90 
91 #if defined(RENDER_PERF_ENABLED) && (RENDER_PERF_ENABLED == 1)
92     BASE_NS::string GetBufferPoolDebugName(const GpuBufferDesc& desc) const;
93     BASE_NS::string GetImagePoolDebugName(const GpuImageDesc& desc) const;
94 #endif
95 
96 private:
97     void CreatePoolForBuffers(const GpuMemoryAllocatorCustomPool& customPool);
98     void CreatePoolForImages(const GpuMemoryAllocatorCustomPool& customPool);
99     VmaAllocator allocator_ {};
100 
101     BASE_NS::vector<VmaPool> customGpuBufferPools_;
102     BASE_NS::vector<VmaPool> customGpuImagePools_;
103 
104     BASE_NS::unordered_map<uint64_t, uint32_t> hashToGpuBufferPoolIndex_;
105     BASE_NS::unordered_map<uint64_t, uint32_t> hashToGpuImagePoolIndex_;
106 
107 #if defined(RENDER_PERF_ENABLED) && (RENDER_PERF_ENABLED == 1)
108     BASE_NS::vector<BASE_NS::string> customGpuBufferPoolNames_;
109     BASE_NS::vector<BASE_NS::string> customGpuImagePoolNames_;
110 
111     struct MemoryDebugStruct {
112         uint64_t buffer { 0 };
113         uint64_t image { 0 };
114     };
115     MemoryDebugStruct memoryDebugStruct_;
116 #endif
117 };
118 RENDER_END_NAMESPACE()
119 
120 #endif // VULKAN_GPU_MEMORY_ALLOCATOR_VK_H
121