More documentation. Especially added new section "Finding out if memory is mappable".

This commit is contained in:
Adam Sawicki 2018-03-02 13:05:39 +01:00
parent a3e019d476
commit 0c11b12574
6 changed files with 190 additions and 131 deletions

View file

@ -353,17 +353,63 @@ Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA)
currently provide `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag on all memory types that are
`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, so on this platform you may not need to bother.
\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable
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.
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:
\code
VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufCreateInfo.size = sizeof(ConstantBuffer);
bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
VmaAllocationCreateInfo allocCreateInfo = {};
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
VkBuffer buf;
VmaAllocation alloc;
VmaAllocationInfo allocInfo;
vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
if(allocInfo.pUserData != nullptr)
{
// Allocation ended up in mappable memory.
// It's persistently mapped. You can access it directly.
memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
}
else
{
// Allocation ended up in non-mappable memory.
// You need to create CPU-side copy in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
}
\endcode
\page custom_memory_pools Custom memory pools
The library automatically creates and manages default memory pool for each
memory type available on the device. A pool contains a number of
`VkDeviceMemory` blocks. You can create custom pool and allocate memory out of
it. It can be useful if you want to:
A memory pool contains a number of `VkDeviceMemory` blocks.
The library automatically creates and manages default pool for each memory type available on the device.
Default memory pool automatically grows in size.
Size of allocated blocks is also variable and managed automatically.
You can create custom pool and allocate memory out of it.
It can be useful if you want to:
- Keep certain kind of allocations separate from others.
- Enforce particular size of Vulkan memory blocks.
- Enforce particular, fixed size of Vulkan memory blocks.
- Limit maximum amount of Vulkan memory allocated for that pool.
- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
To use custom memory pools:
@ -375,7 +421,7 @@ To use custom memory pools:
Example:
\code
// Create a pool that could have at most 2 blocks, 128 MiB each.
// Create a pool that can have at most 2 blocks, 128 MiB each.
VmaPoolCreateInfo poolCreateInfo = {};
poolCreateInfo.memoryTypeIndex = ...
poolCreateInfo.blockSize = 128ull * 1024 * 1024;
@ -1156,7 +1202,7 @@ typedef VkFlags VmaAllocationCreateFlags;
typedef struct VmaAllocationCreateInfo
{
/// Use VmaAllocationCreateFlagBits enum.
/// Use #VmaAllocationCreateFlagBits enum.
VmaAllocationCreateFlags flags;
/** \brief Intended usage of memory.
@ -1612,16 +1658,22 @@ for(size_t i = 0; i < allocations.size(); ++i)
}
\endcode
Warning! This function is not correct according to Vulkan specification. Use it
at your own risk. That's becuase Vulkan doesn't guarantee that memory
Note: Please don't expect memory to be fully compacted after this call.
Algorithms inside are based on some heuristics that try to maximize number of Vulkan
memory blocks to make totally empty to release them, as well as to maximimze continuous
empty space inside remaining blocks, while minimizing the number and size of data that
needs to be moved. Some fragmentation still remains after this call. This is normal.
Warning: This function is not 100% correct according to Vulkan specification. Use it
at your own risk. That's because Vulkan doesn't guarantee that memory
requirements (size and alignment) for a new buffer or image are consistent. They
may be different even for subsequent calls with the same parameters. It really
does happen on some platforms, especially with images.
This function may be time-consuming, so you shouldn't call it too often (like
every frame or after every resource creation/destruction), but rater you can
call it on special occasions (like when reloading a game level, when you just
destroyed a lot of objects).
Warning: This function may be time-consuming, so you shouldn't call it too often
(like every frame or after every resource creation/destruction).
You can call it on special occasions (like when reloading a game level or
when you just destroyed a lot of objects).
*/
VkResult vmaDefragment(
VmaAllocator allocator,