HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VE_Memory.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: VE_Memory.h ( VE Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __VE_MEMORY_H__
12 #define __VE_MEMORY_H__
13 
14 #include "VE_API.h"
15 #include "VE_Result.h"
16 #include "VE_Instance.h"
17 
18 #include <vk_mem_alloc.h>
19 
20 #include <SYS/SYS_Handle.h>
21 #include <UT/UT_NonCopyable.h>
22 
23 class VE_Ext;
24 
26 {
32 };
33 
35  FLAG_COHERENT = 1 << 0,
36  FLAG_DEDICATED = 1 << 1,
37 };
38 
39 using VE_MemFlags = uint32_t;
40 
42 {
43 public:
44  const VmaAllocationInfo &info() const { return myInfo; }
45 
46  bool isValid() const { return myAllocation != nullptr; }
47 
48  void free(VmaAllocator allocator);
49 
50 
51 protected:
52  friend class VE_VmaMemoryAllocator;
53 
54  VmaAllocation myAllocation = VK_NULL_HANDLE;
55  VmaAllocationInfo myInfo;
56 };
57 
59 {
60 protected:
61  VE_Result<void *> map(VmaAllocator allocator);
62  void unmap(VmaAllocator allocator);
63 };
64 
66 {
67 public:
69  VkInstance,
70  VkPhysicalDevice,
71  VkDevice,
72  uint32_t req_ver,
73  VmaAllocatorCreateFlags flags);
74 
75  void destroy();
76 
77  template <typename R>
78  struct Allocation {
81  };
82 
83  template <typename R>
87  };
88 
93 
94  VE_Result<VE_VmaAllocation> allocateMemory(const VkMemoryRequirements&, const VmaAllocationCreateInfo &info);
95  VE_Result<ImageAllocation> allocateImage(const VkImageCreateInfo&, const VmaAllocationCreateInfo &info);
96  VE_Result<BufferAllocation> allocateBuffer(const VkBufferCreateInfo&, const VmaAllocationCreateInfo &info);
97 
98  VE_Result<VE_VmaMappableAllocation> allocateMappableMemory(const VkMemoryRequirements&, const VmaAllocationCreateInfo &info);
99  VE_Result<MappableBufferAllocation> allocateMappableBuffer(const VkBufferCreateInfo&, const VmaAllocationCreateInfo &info, exint alignment = 0);
100  VE_Result<MappableImageAllocation> allocateMappableImage(const VkImageCreateInfo&, const VmaAllocationCreateInfo &info);
101 
102 protected:
103  VE_VoidResult init(
104  VkInstance,
105  VkPhysicalDevice,
106  VkDevice,
107  uint32_t req_ver,
108  VmaAllocatorCreateFlags flags);
109 
110  VmaAllocator myAllocator = VK_NULL_HANDLE;
111 };
112 
113 /// A block of memory as allocated by VE_MemoryAllocator. Will free itself when
114 /// it goes out of scope.
115 /// It represents a block of bytes, and should in general be used to as a
116 /// backing member in some higher level, resource-like class, such as a Buffer
117 /// or Image class.
119 {
120 public:
121  VkDeviceMemory getVkMem() const { return allocInfo().deviceMemory; }
122  VkDeviceSize getOffset() const { return allocInfo().offset; }
123  VkDeviceSize getSize() const { return allocInfo().size; }
124 
125  const VmaAllocationInfo &allocInfo() const { return info(); }
126 
127  // Copying a block of memory should be done with an explicit copy method,
128  // and that method should exist at the resource level instead of here.
130 
131  VE_MemType getType() const { return myData.type; }
132 
133  void *mapMemory();
134  void unmapMemory();
135 
136  void *mappedPointer() { return myData.mappedPtr; }
137  const void *mappedPointer() const { return myData.mappedPtr; }
138 
139  bool isCoherent() const { return myData.flags & FLAG_COHERENT; }
140  bool isDedicated() const { return myData.flags & FLAG_DEDICATED; }
141 
142  VE_Memory(VE_Memory &&other) noexcept
143  {
144  *this = std::move(other);
145  }
146 
147  VE_Memory &operator=(VE_Memory &&other) noexcept
148  {
149  std::swap(myAllocation, other.myAllocation);
150  std::swap(myInfo, other.myInfo);
151  std::swap(myAllocator, other.myAllocator);
152  std::swap(myData, other.myData);
153  std::swap(myExternalHandle, other.myExternalHandle);
154  return *this;
155  }
156 
157  /// On linux, the returned handle is owned by the caller, and the caller is
158  /// fully responsible for it. No operations are allowed on the file
159  /// descriptor after a successful import into OpenCL (section 5.5.2.1 of the
160  /// OpenCL spec). Likewise, performing any operation on the file descriptor
161  /// after an import into OpenGL results in undefined behaviour (documented
162  /// in description of the EXT_external_objects_fd extension). As a result,
163  /// different callers will potentially get different handles.
164  /// On windows, the returned handle is NOT owned by the caller! The caller
165  /// can use the handle to import the Vulkan memory, but should not close it.
166  /// See section 5.5.2.2 of the OpenCL spec and documentation for extension
167  /// EXT_external_objects_win32 for more information. Every caller of this
168  /// function thus shares the same handle.
169  /// On mac, this function returns extension_unavailable error.
170  VE_Result<SYS_Handle> getExternalHandle(VkDevice device, const VE_Ext* ext);
171 
172  virtual ~VE_Memory();
173 
174 private:
175  VE_Memory(
176  VmaAllocator allocator,
180  : VE_VmaMappableAllocation(block)
181  , myAllocator(allocator)
182  {
183  myData.type = type;
184  myData.flags = flags;
185  myData.mappedPtr = nullptr;
186  }
187 
188  friend class VE_MemoryAllocator;
189 
190  VmaAllocator myAllocator;
191 
192  // External handle for sharing this memory object with other APIs. Only used
193  // on windows.
194  SYS_Handle myExternalHandle;
195 
196  struct
197  {
199  void *mappedPtr;
201  } myData;
202 };
203 
204 /// General purpose allocator for vulkan backed memory blocks that tries to
205 /// balance convenience, safety, and performance.
206 ///
207 /// The main convenience offered is that memory blocks allocated from this
208 /// object will free themselves when they go out of scope. The caller does not
209 /// need to explicity free them. This makes this class well suited for
210 /// allocating lots of resources that would be difficult to keep track of
211 /// manually.
212 ///
213 /// However, the memory blocks do this by maintaining references to the
214 /// underlying VmaAllocator object handle, which is owned by and cleaned up by
215 /// this class. Therefore, care must be taken to ensure this object's life time
216 /// extends beyond its allocated blocks. If the memory blocks and this allocator
217 /// are kept as members of a larger structure, ensure proper member ordering so
218 /// that the blocks are destroyed before the allocator.
219 ///
220 /// Thread safety:
221 /// This allocator contains no locks and attempts no cross thread
222 /// synchronization. If you need memory allocations in different threads, you
223 /// should give those threads their own allocator.
225 {
226 public:
228  VkInstance,
229  VkPhysicalDevice,
230  VkDevice,
231  uint32_t req_ver,
232  VmaAllocationCreateFlags flags);
234  const VE_Instance &,
235  VkPhysicalDevice,
236  VkDevice,
237  VmaAllocationCreateFlags flags);
238 
239  static VkExternalMemoryHandleTypeFlags getExternMemHandleType();
240 
242  const
243  {
244  return myMemoryProperties;
245  };
246 
247  UT_Array<VmaBudget> heapInfos() const;
248 
249  // prints memory heap info and usage statistics
250  void printMemoryInfo() const;
251  void printMemoryInfo(std::ostream* out = nullptr) const;
252 
253  // get simplified memory usage statistics
254  void getMemoryUsage(exint* out_device_vma_alloc_size,
255  exint* out_device_vk_alloc_size,
256  exint* out_device_total_size,
257  exint* out_shared_vma_alloc_size,
258  exint* out_shared_vk_alloc_size,
259  exint* out_shared_total_size) const;
260 
263  const VkImageCreateInfo &img_info,
264  VkImage &vk_img);
267  const VkBufferCreateInfo &buf_info,
268  VkBuffer &vk_buf,
269  exint alignment = 0);
272  const VkMemoryRequirements &info);
273 
274  VE_MemoryAllocator() = default;
276 
278 
280  {
281  *this = std::move(other);
282  }
283 
285  {
286  std::swap(myAllocator, other.myAllocator);
287  std::swap(myMemoryProperties, other.myMemoryProperties);
288  std::swap(myGLExportPool, other.myGLExportPool);
289  std::swap(myGLSharedExportPool, other.myGLSharedExportPool);
290  return *this;
291  }
292 
293 private:
294  void createGLExportPool(VkDevice);
295 
296  VE_MemFlags memoryFlags(const VmaAllocationInfo &vma_info, VE_MemType type) const;
297 
298  VkPhysicalDeviceMemoryProperties myMemoryProperties;
299  VmaPool myGLExportPool = VK_NULL_HANDLE;
300  VmaPool myGLSharedExportPool = VK_NULL_HANDLE;
301 };
302 
303 /// This is a low level function to create a raw VmaAllocator object, in case the
304 /// caller wants direct access to the Vma API.
305 /// It is recommended to use VE_MemoryAllocator unless you have good reason not
306 /// to.
307 VE_API
309  VkInstance,
310  VkPhysicalDevice,
311  VkDevice,
312  uint32_t req_ver,
313  VmaAllocatorCreateFlags flags);
314 
315 VE_API
316 void VEdestroyVmaAllocator(VmaAllocator);
317 
318 /// Returns the platform specific external memory handle type
321 
322 #endif
type
Definition: core.h:556
GLbitfield flags
Definition: glcorearb.h:1596
const VmaAllocationInfo & info() const
Definition: VE_Memory.h:44
VkDeviceMemory getVkMem() const
Definition: VE_Memory.h:121
#define VK_NULL_HANDLE
Definition: vulkan_core.h:45
VE_VmaMappableAllocation allocation
Definition: VE_Memory.h:86
VE_MemoryAllocator & operator=(VE_MemoryAllocator &&other) noexcept
Definition: VE_Memory.h:284
VkFlags VkExternalMemoryHandleTypeFlags
Definition: vulkan_core.h:4970
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1699
const void * mappedPointer() const
Definition: VE_Memory.h:137
int64 exint
Definition: SYS_Types.h:125
uint32_t VE_MemFlags
Definition: VE_Memory.h:39
VE_MemType
Definition: VE_Memory.h:25
VE_MemFlagBits
Definition: VE_Memory.h:34
bool isDedicated() const
Definition: VE_Memory.h:140
VE_Memory & operator=(VE_Memory &&other) noexcept
Definition: VE_Memory.h:147
VkDeviceSize getOffset() const
Definition: VE_Memory.h:122
void * mappedPointer()
Definition: VE_Memory.h:136
Definition: VE_Ext.h:24
VE_Memory(VE_Memory &&other) noexcept
Definition: VE_Memory.h:142
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
#define VE_API
Definition: VE_API.h:20
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
VE_API VkExternalMemoryHandleTypeFlags VEgetExternalMemoryHandleType()
Returns the platform specific external memory handle type.
const VmaAllocationInfo & allocInfo() const
Definition: VE_Memory.h:125
VE_Result< ImageAllocation > allocateImage(const VkImageCreateInfo &, const VmaAllocationCreateInfo &info)
const VkPhysicalDeviceMemoryProperties & physicalDeviceMemoryProperties() const
Definition: VE_Memory.h:241
VE_MemType type
Definition: VE_Memory.h:198
VkDeviceSize getSize() const
Definition: VE_Memory.h:123
VE_API VE_Result< VmaAllocator > VEcreateVmaAllocator(VkInstance, VkPhysicalDevice, VkDevice, uint32_t req_ver, VmaAllocatorCreateFlags flags)
VE_Result< VE_VmaAllocation > allocateMemory(const VkMemoryRequirements &, const VmaAllocationCreateInfo &info)
VE_MemoryAllocator(VE_MemoryAllocator &&other) noexcept
Definition: VE_Memory.h:279
VmaAllocationInfo myInfo
Definition: VE_Memory.h:55
VE_MemFlags flags
Definition: VE_Memory.h:200
bool isValid() const
Definition: VE_Memory.h:46
VE_MemType getType() const
Definition: VE_Memory.h:131
static VE_Result< VE_VmaMemoryAllocator > create(VkInstance, VkPhysicalDevice, VkDevice, uint32_t req_ver, VmaAllocatorCreateFlags flags)
void * mappedPtr
Definition: VE_Memory.h:199
uint64_t VkDeviceSize
Definition: vulkan_core.h:95
bool isCoherent() const
Definition: VE_Memory.h:139
VE_Result< BufferAllocation > allocateBuffer(const VkBufferCreateInfo &, const VmaAllocationCreateInfo &info)
VE_API void VEdestroyVmaAllocator(VmaAllocator)
VmaAllocator myAllocator
Definition: VE_Memory.h:110