diff --git a/docs/html/allocation_annotation.html b/docs/html/allocation_annotation.html index 5b0b8ce..4070853 100644 --- a/docs/html/allocation_annotation.html +++ b/docs/html/allocation_annotation.html @@ -72,44 +72,42 @@ $(function() {
You can annotate allocations with your own information, e.g. for debugging purposes. To do that, fill VmaAllocationCreateInfo::pUserData field when creating an allocation. It is an opaque void*
pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata.
The pointer may be later retrieved as VmaAllocationInfo::pUserData:
It can also be changed using function vmaSetAllocationUserData().
-Values of (non-zero) allocations' pUserData
are printed in JSON report created by vmaBuildStatsString(), in hexadecimal form.
Values of (non-zero) allocations' pUserData
are printed in JSON report created by vmaBuildStatsString() in hexadecimal form.
There is alternative mode available where pUserData
pointer is used to point to a null-terminated string, giving a name to the allocation. To use this mode, set VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags. Then pUserData
passed as VmaAllocationCreateInfo::pUserData or argument to vmaSetAllocationUserData() must be either null or pointer to a null-terminated string. The library creates internal copy of the string, so the pointer you pass doesn't need to be valid for whole lifetime of the allocation. You can free it after the call.
There is alternative mode available where pUserData
pointer is used to point to a null-terminated string, giving a name to the allocation. To use this mode, set VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags. Then pUserData
passed as VmaAllocationCreateInfo::pUserData or argument to vmaSetAllocationUserData() must be either null or a pointer to a null-terminated string. The library creates internal copy of the string, so the pointer you pass doesn't need to be valid for whole lifetime of the allocation. You can free it after the call.
The value of pUserData
pointer of the allocation will be different than the one you passed when setting allocation's name - pointing to a buffer managed internally that holds copy of the string.
Physical devices in Vulkan support various combinations of memory heaps and types. Help with choosing correct and optimal memory type for your specific resource is one of the key features of this library. You can use it by filling appropriate members of VmaAllocationCreateInfo structure, as described below. You can also combine multiple methods.
When using 3. or 4., the library internally queries Vulkan for memory types supported for that buffer or image (function vkGetBufferMemoryRequirements()
) and uses only one of these types.
If no memory type can be found that meets all the requirements, these functions return VK_ERROR_FEATURE_NOT_PRESENT
.
You can leave VmaAllocationCreateInfo structure completely filled with zeros. It means no requirements are specified for memory type. It is valid, although not very useful.
The easiest way to specify memory requirements is to fill member VmaAllocationCreateInfo::usage using one of the values of enum VmaMemoryUsage. It defines high level, common usage types. For more details, see description of this enum.
-For example, if you want to create a uniform buffer that will be filled using transfer only once or infrequently and used for rendering every frame, you can do it using following code:
+The easiest way to specify memory requirements is to fill member VmaAllocationCreateInfo::usage using one of the values of enum VmaMemoryUsage. It defines high level, common usage types. Since version 3 of the library, it is recommended to use VMA_MEMORY_USAGE_AUTO to let it select best memory type for your resource automatically.
+For example, if you want to create a uniform buffer that will be filled using transfer only once or infrequently and then used for rendering every frame as a uniform buffer, you can do it using following code. The buffer will most likely end up in a memory type with VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
to be fast to access by the GPU device.
If you have a preference for putting the resource in GPU (device) memory or CPU (host) memory on systems with discrete graphics card that have the memories separate, you can use VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or VMA_MEMORY_USAGE_AUTO_PREFER_HOST.
+When using VMA_MEMORY_USAGE_AUTO*
while you want to map the allocated memory, you also need to specify one of the host access flags: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT. This will help the library decide about preferred memory type to ensure it has VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
so you can map it.
For example, a staging buffer that will be filled via mapped pointer and then used as a source of transfer to the buffer decribed previously can be created like this. It will likely and up in a memory type that is HOST_VISIBLE
and HOST_COHERENT
but not HOST_CACHED
(meaning uncached, write-combined) and not DEVICE_LOCAL
(meaning system RAM).
For more examples of creating different kinds of resources, see chapter Recommended usage patterns.
+Usage values VMA_MEMORY_USAGE_AUTO*
are legal to use only when the library knows about the resource being created by having VkBufferCreateInfo
/ VkImageCreateInfo
passed, so they work with functions like: vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo() etc. If you allocate raw memory using function vmaAllocateMemory(), you have to use other means of selecting memory type, as decribed below.
VMA_MEMORY_USAGE_GPU_ONLY
, VMA_MEMORY_USAGE_CPU_ONLY
, VMA_MEMORY_USAGE_CPU_TO_GPU
, VMA_MEMORY_USAGE_GPU_TO_CPU
, VMA_MEMORY_USAGE_CPU_COPY
) are still available and work same way as in previous versions of the library for backward compatibility, but they are not recommended.You can specify more detailed requirements by filling members VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags with a combination of bits from enum VkMemoryPropertyFlags
. For example, if you want to create a buffer that will be persistently mapped on host (so it must be HOST_VISIBLE
) and preferably will also be HOST_COHERENT
and HOST_CACHED
, use following code:
A memory type is chosen that has all the required flags and as many preferred flags set as possible.
-If you use VmaAllocationCreateInfo::usage, it is just internally converted to a set of required and preferred flags.
+Value passed in VmaAllocationCreateInfo::usage is internally converted to a set of required and preferred flags, plus some extra "magic" (heuristics).
If you inspected memory types available on the physical device and you have a preference for memory types that you want to use, you can fill member VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set means that a memory type with that index is allowed to be used for the allocation. Special value 0, just like UINT32_MAX
, means there are no restrictions to memory type index.
If you allocate from custom memory pool, all the ways of specifying memory requirements described above are not applicable and the aforementioned members of VmaAllocationCreateInfo structure are ignored. Memory type is selected explicitly when creating the pool and then used to make all the allocations from that pool. For further details, see Custom memory pools.
diff --git a/docs/html/configuration.html b/docs/html/configuration.html index fe03f45..8ddf8ab 100644 --- a/docs/html/configuration.html +++ b/docs/html/configuration.html @@ -78,7 +78,7 @@ Pointers to Vulkan functionsIf you want to disable this feature, set configuration macro: #define VMA_STATIC_VULKAN_FUNCTIONS 0
.
Second, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions. You can fetch them e.g. using functions vkGetInstanceProcAddr
and vkGetDeviceProcAddr
or by using a helper library like volk.
Third, VMA tries to fetch remaining pointers that are still null by calling vkGetInstanceProcAddr
and vkGetDeviceProcAddr
on its own. If you want to disable this feature, set configuration macro: #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
.
Third, VMA tries to fetch remaining pointers that are still null by calling vkGetInstanceProcAddr
and vkGetDeviceProcAddr
on its own. You need to only fill in VmaVulkanFunctions::vkGetInstanceProcAddr and VmaVulkanFunctions::vkGetDeviceProcAddr. Other pointers will be fetched automatically. If you want to disable this feature, set configuration macro: #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
.
Finally, all the function pointers required by the library (considering selected Vulkan version and enabled extensions) are checked with VMA_ASSERT
if they are not null.
The library makes calls to vkAllocateMemory()
and vkFreeMemory()
internally. You can setup callbacks to be informed about these calls, e.g. for the purpose of gathering some statistics. To do it, fill optional member VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
When device memory of certain heap runs out of free space, new allocations may fail (returning error code) or they may succeed, silently pushing some existing memory blocks from GPU VRAM to system RAM (which degrades performance). This behavior is implementation-dependent - it depends on GPU vendor and graphics driver.
+When device memory of certain heap runs out of free space, new allocations may fail (returning error code) or they may succeed, silently pushing some existing_ memory blocks from GPU VRAM to system RAM (which degrades performance). This behavior is implementation-dependent - it depends on GPU vendor and graphics driver.
On AMD cards it can be controlled while creating Vulkan device object by using VK_AMD_memory_overallocation_behavior extension, if available.
Alternatively, if you want to test how your program behaves with limited amount of Vulkan device memory available without switching your graphics card to one that really has smaller VRAM, you can use a feature of this library intended for this purpose. To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
pNext
chain.To use custom memory pools:
You have to free all allocations made from this pool before destroying it.
New versions of this library support creating dedicated allocations in custom pools. It is supported only when VmaPoolCreateInfo::blockSize = 0. To use this feature, set VmaAllocationCreateInfo::pool to the pointer to your custom pool and VmaAllocationCreateInfo::flags to VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+When creating a pool, you must explicitly specify memory type index. To find the one suitable for your buffers or images, you can use helper functions vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo(). You need to provide structures with example parameters of buffers or images that you are going to create in that pool.
When creating buffers/images allocated in that pool, provide following parameters:
VkBufferCreateInfo
: Prefer to pass same parameters as above. Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior. Using different VK_BUFFER_USAGE_
flags may work, but you shouldn't create images in a pool intended for buffers or the other way around.Setting VmaDefragmentationInfo2::pAllocationsChanged is optional. This output array tells whether particular allocation in VmaDefragmentationInfo2::pAllocations at the same index has been modified during defragmentation. You can pass null, but you then need to query every allocation passed to defragmentation for new parameters using vmaGetAllocationInfo() if you might need to recreate and rebind a buffer or image associated with it.
If you use Custom memory pools, you can fill VmaDefragmentationInfo2::poolCount and VmaDefragmentationInfo2::pPools instead of VmaDefragmentationInfo2::allocationCount and VmaDefragmentationInfo2::pAllocations to defragment all allocations in given pools. You cannot use VmaDefragmentationInfo2::pAllocationsChanged in that case. You can also combine both methods.
You can combine these two methods by specifying non-zero maxGpu*
as well as maxCpu*
parameters. The library automatically chooses best method to defragment each memory pool.
You may try not to block your entire program to wait until defragmentation finishes, but do it in the background, as long as you carefully fullfill requirements described in function vmaDefragmentationBegin().
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, prefers VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, prefers VK_MEMORY_PROPERTY_HOST_CACHED_BIT
. Device extension VK_KHR_buffer_device_address allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code. It is promoted to core Vulkan 1.2.
+Device extension VK_KHR_buffer_device_address allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code. It has been promoted to core Vulkan 1.2.
If you want to use this feature in connection with VMA, follow these steps:
VkDeviceMemory
, with preferred block size.VkDeviceMemory
for this allocation, just like when you use VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.VK_ERROR_OUT_OF_DEVICE_MEMORY
.Features deliberately excluded from the scope of this library:
-VkBufferCreateInfo
, VkImageCreateInfo
are not stored in VmaAllocation object.VkCommandBuffer
. It just allocates memory.VkBufferCreateInfo
, VkImageCreateInfo
are not stored in VmaAllocation object.Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.
It is valid to use this flag for allocation made from memory type that is not HOST_VISIBLE
. This flag is then ignored and memory is not mapped. This is useful if you need an allocation that is efficient to use on GPU (DEVICE_LOCAL
) and still want to map it directly if possible on platforms that support it (e.g. Intel GPU).
Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a null-terminated string. Instead of copying pointer value, a local copy of the string is made and stored in allocation's pUserData
. The string is automatically freed together with the allocation. It is also used in vmaBuildStatsString().
Set this flag if the allocated memory will have aliasing resources.
Usage of this flag prevents supplying VkMemoryDedicatedAllocateInfoKHR
when VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified. Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
Requests possibility to map the allocation (using vmaMapMemory() or VMA_ALLOCATION_CREATE_MAPPED_BIT).
+VMA_MEMORY_USAGE_AUTO*
value, you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.HOST_VISIBLE
. This includes allocations created in Custom memory pools.Declares that mapped memory will only be written sequentially, e.g. using memcpy()
or a loop writing number-by-number, never read or accessed randomly, so a memory type can be selected that is uncached and write-combined.
pMappedData[i] += x;
Better prepare your data in a local variable and memcpy()
it to the mapped pointer all at once. Requests possibility to map the allocation (using vmaMapMemory() or VMA_ALLOCATION_CREATE_MAPPED_BIT).
+VMA_MEMORY_USAGE_AUTO*
value, you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.HOST_VISIBLE
. This includes allocations created in Custom memory pools.Declares that mapped memory can be read, written, and accessed in random order, so a HOST_CACHED
memory type is preferred.
Together with VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, it says that despite request for host access, a not-HOST_VISIBLE
memory type can be selected if it may improve performance.
By using this flag, you declare that you will check if the allocation ended up in a HOST_VISIBLE
memory type (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and issue an explicit transfer to write/read your data. To prepare for this possibility, don't forget to add appropriate flags like VK_BUFFER_USAGE_TRANSFER_DST_BIT
, VK_BUFFER_USAGE_TRANSFER_SRC_BIT
to the parameters of created buffer or image.
Allocation strategy that chooses smallest possible free range for the allocation to minimize memory usage and fragmentation, possibly at the expense of allocation time.
Allocation strategy that chooses first suitable free range for the allocation - not necessarily in terms of the smallest offset but the one that is easiest and fastest to find to minimize allocation time, possibly at the expense of allocation quality.
@@ -655,34 +681,32 @@ FunctionsEnumerator | |
---|---|
VMA_MEMORY_USAGE_UNKNOWN | No intended memory usage specified. Use other members of VmaAllocationCreateInfo to specify your requirements. |
VMA_MEMORY_USAGE_GPU_ONLY | Memory will be used on device only, so fast access from the device is preferred. It usually means device-local GPU (video) memory. No need to be mappable on host. It is roughly equivalent of Usage: -
Allocation may still end up in |
VMA_MEMORY_USAGE_GPU_ONLY |
|
VMA_MEMORY_USAGE_CPU_ONLY | Memory will be mappable on host. It usually means CPU (system) memory. Guarantees to be Usage: Staging copy of resources used as transfer source. + |
VMA_MEMORY_USAGE_CPU_ONLY |
|
VMA_MEMORY_USAGE_CPU_TO_GPU | Memory that is both mappable on host (guarantees to be Usage: Resources written frequently by host (dynamic), read by device. E.g. textures (with LINEAR layout), vertex buffers, uniform buffers updated every frame or every draw call. + |
VMA_MEMORY_USAGE_CPU_TO_GPU |
|
VMA_MEMORY_USAGE_GPU_TO_CPU | Memory mappable on host (guarantees to be Usage: -
|
VMA_MEMORY_USAGE_GPU_TO_CPU |
|
VMA_MEMORY_USAGE_CPU_COPY | CPU memory - memory that is preferably not Usage: Staging copy of resources moved from GPU memory to CPU memory as part of custom paging/residency mechanism, to be moved back to GPU memory when needed. + |
VMA_MEMORY_USAGE_CPU_COPY |
|
VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED | Lazily allocated GPU memory having Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with Allocations with this usage are always created as dedicated - it implies VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. |
VMA_MEMORY_USAGE_AUTO | Selects best memory type automatically. This flag is recommended for most common use cases. +When using this flag, if you want to map the allocation (using vmaMapMemory() or VMA_ALLOCATION_CREATE_MAPPED_BIT), you must pass one of the flags: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT in VmaAllocationCreateInfo::flags. +It can be used only with functions that let the library know |
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE | Selects best memory type automatically with preference for GPU (device) memory. +When using this flag, if you want to map the allocation (using vmaMapMemory() or VMA_ALLOCATION_CREATE_MAPPED_BIT), you must pass one of the flags: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT in VmaAllocationCreateInfo::flags. +It can be used only with functions that let the library know |
VMA_MEMORY_USAGE_AUTO_PREFER_HOST | Selects best memory type automatically with preference for CPU (host) memory. +When using this flag, if you want to map the allocation (using vmaMapMemory() or VMA_ALLOCATION_CREATE_MAPPED_BIT), you must pass one of the flags: VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT in VmaAllocationCreateInfo::flags. +It can be used only with functions that let the library know |
VMA_MEMORY_USAGE_MAX_ENUM |
Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.
-It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. It internally creates a temporary, dummy buffer that never has memory bound. It is just a convenience function, equivalent to calling:
-vkCreateBuffer
vkGetBufferMemoryRequirements
vmaFindMemoryTypeIndex
vkDestroyBuffer
It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. It internally creates a temporary, dummy buffer that never has memory bound.
Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.
-It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. It internally creates a temporary, dummy image that never has memory bound. It is just a convenience function, equivalent to calling:
-vkCreateImage
vkGetImageMemoryRequirements
vmaFindMemoryTypeIndex
vkDestroyImage
It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex. It internally creates a temporary, dummy image that never has memory bound.
To "map memory" in Vulkan means to obtain a CPU pointer to VkDeviceMemory
, to be able to read from it or write to it in CPU code. Mapping is possible only of memory allocated from a memory type that has VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
flag. Functions vkMapMemory()
, vkUnmapMemory()
are designed for this purpose. You can use them directly with memory allocated by this library, but it is not recommended because of following issue: Mapping the same VkDeviceMemory
block multiple times is illegal - only one mapping at a time is allowed. This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan. Because of this, Vulkan Memory Allocator provides following facilities:
VMA_MEMORY_USAGE_AUTO*
enum values. For other usage values they are ignored and every such allocation made in HOST_VISIBLE
memory type is mappable, but they can still be used for consistency.The library provides following functions for mapping of a specific VmaAllocation: vmaMapMemory(), vmaUnmapMemory(). They are safer and more convenient to use than standard Vulkan functions. You can map an allocation multiple times simultaneously - mapping is reference-counted internally. You can also map different allocations simultaneously regardless of whether they use the same VkDeviceMemory
block. The way it is implemented is that the library always maps entire memory block, not just region of the allocation. For further details, see description of vmaMapMemory() function. Example:
When mapping, you may see a warning from Vulkan validation layer similar to this one:
Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.
It happens because the library maps entire VkDeviceMemory
block, where different types of images and buffers may end up together, especially on GPUs with unified memory like Intel. You can safely ignore it if you are sure you access only memory of the intended object that you wanted to map.
There are some exceptions though, when you should consider mapping memory only for a short period of time:
-DEVICE_LOCAL + HOST_VISIBLE
memory (selected when you use VMA_MEMORY_USAGE_CPU_TO_GPU), then whenever a memory block allocated from this memory type stays mapped for the time of any call to vkQueueSubmit()
or vkQueuePresentKHR()
, this block is migrated by WDDM to system RAM, which degrades performance. It doesn't matter if that particular memory block is actually used by the command buffer being submitted.HOST_VISIBLE
, the allocation will be mapped on creation. For an example of how to make use of this fact, see section Advanced data uploading.Memory in Vulkan doesn't need to be unmapped before using it on GPU, but unless a memory types has VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
flag set, you need to manually invalidate cache before reading of mapped pointer and flush cache after writing to mapped pointer. Map/unmap operations don't do that automatically. Vulkan provides following functions for this purpose vkFlushMappedMemoryRanges()
, vkInvalidateMappedMemoryRanges()
, but this library provides more convenient functions that refer to given allocation object: vmaFlushAllocation(), vmaInvalidateAllocation(), or multiple objects at once: vmaFlushAllocations(), vmaInvalidateAllocations().
Regions of memory specified for flush/invalidate must be aligned to VkPhysicalDeviceLimits::nonCoherentAtomSize
. This is automatically ensured by the library. In any memory type that is HOST_VISIBLE
but not HOST_COHERENT
, all allocations within blocks are aligned to this value, so their offsets are always multiply of nonCoherentAtomSize
and two different allocations never share same "line" of this size.
Please note that memory allocated with VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be HOST_COHERENT
.
Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA) currently provide HOST_COHERENT
flag on all memory types that are HOST_VISIBLE
, so on this platform you may not need to bother.
It may happen that your allocation ends up in memory that is HOST_VISIBLE
(available for mapping) despite it wasn't explicitly requested. For example, application may work on integrated graphics with unified memory (like Intel) or allocation from video memory might have failed, so the library chose system memory as fallback.
You can detect this case and map such allocation to access its memory on CPU directly, instead of launching a transfer operation. In order to do that: call vmaGetAllocationMemoryProperties() and look for VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
flag.
You can even use VMA_ALLOCATION_CREATE_MAPPED_BIT flag while creating allocations that are not necessarily HOST_VISIBLE
(e.g. using VMA_MEMORY_USAGE_GPU_ONLY). If the allocation ends up in memory type that is HOST_VISIBLE
, it will be persistently mapped and you can use it directly. If not, the flag is just ignored. Example:
Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA) currently provide HOST_COHERENT
flag on all memory types that are HOST_VISIBLE
, so on PC you may not need to bother.
When you want to create a buffer or image:
@@ -147,15 +147,15 @@ Resource allocationDon't forget to destroy your objects when no longer needed:
Remember that using resources that alias in memory requires proper synchronization. You need to issue a memory barrier to make sure commands that use img1
and img2
don't overlap on GPU timeline. You also need to treat a resource after aliasing as uninitialized - containing garbage data. For example, if you use img1
and then want to use img2
, you need to issue an image memory barrier for img2
with oldLayout
= VK_IMAGE_LAYOUT_UNDEFINED
.
Additional considerations:
VK_IMAGE_CREATE_ALIAS_BIT
flag.memoryTypeBits
returned in memory requirements of each resource to make sure the bits overlap. Some GPUs may expose multiple memory types suitable e.g. only for buffers or images with COLOR_ATTACHMENT
usage, so the sets of memory types supported by your resources may be disjoint. Aliasing them is not possible in that case. Represents single memory allocation. More...
- -#include <vk_mem_alloc.h>
Represents single memory allocation.
It may be either dedicated block of VkDeviceMemory
or a specific region of a bigger block of this type plus unique offset.
#include <vk_mem_alloc.h>
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
Public Attributes |
#define VK_ERROR_UNKNOWN ((VkResult)-13) | -
After following steps described above, you can create VMA allocations and custom pools out of the special DEVICE_COHERENT
and DEVICE_UNCACHED
memory types on eligible devices. There are multiple ways to do it, for example:
VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD
to VmaAllocationCreateInfo::requiredFlags or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with other ways of Choosing memory type, like setting VmaAllocationCreateInfo::usage.VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
to VmaAllocationCreateInfo::requiredFlags or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with other ways of Choosing memory type, like setting VmaAllocationCreateInfo::usage.= 1u << index
.VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve performance on some GPUs. It augments Vulkan API with possibility to query driver whether it prefers particular buffer or image to have its own, dedicated allocation (separate VkDeviceMemory
block) for better efficiency - to be able to do some internal optimizations.
The extension is supported by this library. It will be used automatically when enabled. To enable it:
+VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve performance on some GPUs. It augments Vulkan API with possibility to query driver whether it prefers particular buffer or image to have its own, dedicated allocation (separate VkDeviceMemory
block) for better efficiency - to be able to do some internal optimizations. The extension is supported by this library. It will be used automatically when enabled.
It has been promoted to core Vulkan 1.1, so if you use eligible Vulkan version and inform VMA about it by setting VmaAllocatorCreateInfo::vulkanApiVersion, you are all set.
+Otherwise, if you want to use it as an extension:
1 . When creating Vulkan device, check if following 2 device extensions are supported (call vkEnumerateDeviceExtensionProperties()
). If yes, enable them (fill VkDeviceCreateInfo::ppEnabledExtensionNames
).
If you enabled these extensions:
-2 . Use VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating your VmaAllocator`to inform the library that you enabled required extensions and you want the library to use them.
+2 . Use VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating your VmaAllocator to inform the library that you enabled required extensions and you want the library to use them.
That is all. The extension will be automatically used whenever you create a buffer using vmaCreateBuffer() or image using vmaCreateImage().
-When using the extension together with Vulkan Validation Layer, you will receive warnings like this:
vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer. -
It is OK, you should just ignore it. It happens because you use function vkGetBufferMemoryRequirements2KHR()
instead of standard vkGetBufferMemoryRequirements()
, while the validation layer seems to be unaware of it.
When using the extension together with Vulkan Validation Layer, you will receive warnings like this:
+vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
+It is OK, you should just ignore it. It happens because you use function vkGetBufferMemoryRequirements2KHR()
instead of standard vkGetBufferMemoryRequirements()
, while the validation layer seems to be unaware of it.
To learn more about this extension, see: