Add draft of general documentation chapter about memory budget

Work in progress...
This commit is contained in:
Adam Sawicki 2019-10-31 16:03:25 +01:00
parent 5f573f588a
commit bc95d25c7f

View File

@ -29,9 +29,9 @@ extern "C" {
/** \mainpage Vulkan Memory Allocator
<b>Version 2.3.0-development</b> (2019-07-02)
<b>Version 2.3.0-development</b> (2019-10-31)
Copyright (c) 2017-2018 Advanced Micro Devices, Inc. All rights reserved. \n
Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT
Documentation of all members: vk_mem_alloc.h
@ -54,6 +54,9 @@ Documentation of all members: vk_mem_alloc.h
- [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory)
- [Cache control](@ref memory_mapping_cache_control)
- [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable)
- \subpage staying_within_budget
- [Querying for budget](@ref staying_within_budget_querying_for_budget)
- [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage)
- \subpage custom_memory_pools
- [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex)
- [Linear allocation algorithm](@ref linear_algorithm)
@ -523,6 +526,78 @@ else
\endcode
\page staying_within_budget Staying within budget
When developing a graphics-intensive game or program, it is important to avoid allocating
more GPU memory than it's physically available. When the memory is over-committed,
various bad things can happen, depending on the specific GPU, graphics driver, and
operating system:
- It may just work without any problems.
- The application may slow down because some memory blocks are moved to system RAM
and the GPU has to access them through PCI Express bus.
- A new allocation may take very long time to complete, even few seconds, and possibly
freeze entire system.
- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST`
returned somewhere later.
\section staying_within_budget_querying_for_budget Querying for budget
To query for current memory usage and available budget, use function vmaGetBudget().
Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap.
Please note that this function returns different information and works faster than
vmaCalculateStats(). vmaGetBudget() can be called every frame or even before every
allocation, while vmaCalculateStats() is intended to be used rarely,
only to obtain statistical information, e.g. for debugging purposes.
It is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information
about the budget from Vulkan device. VMA is able to use this extension automatically.
When not enabled, the allocator behaves same way, but then it estimates current usage
and available budget based on its internal information and Vulkan memory heap sizes,
which may be less precise. In order to use this extension:
1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2
required by it are available and enable them. Please note that the first is a device
extension and the second is instance extension!
2. Use flag #VMA_ALLOCATOR_CREATE_ ?? when creating #VmaAllocator object.
3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from
Vulkan inside of it to avoid overhead of querying it with every allocation.
\section staying_within_budget_controlling_memory_usage Controlling memory usage
There are many ways in which you can try to stay within the budget.
First, when making new allocation requires allocating a new memory block, the library
tries not to exceed the budget automatically. If a block with default recommended size
(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even
dedicated memory for just this resource.
If the size of the requested resource plus current memory usage is more than the
budget, by default the library still tries to create it, leaving it to the Vulkan
implementation whether the allocation succeeds or fails. You can change this behavior
by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
not made if it would exceed the budget or if the budget is already exceeded.
Some other allocations become lost instead to make room for it, if the mechanism of
[lost allocations](@ref lost_allocations) is used.
If that is not possible, the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
when creating resources that are not essential for the application (e.g. the texture
of a specific object) and not to pass it when creating critically important resources
(e.g. render targets).
Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure
a new allocation is created only when it fits inside one of the existing memory blocks.
If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
This also ensures that the function call is very fast because it never goes to Vulkan
to obtain a new block.
Please note that creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount
set to more than 0 will try to allocate memory blocks without checking whether they
fit within budget.
\page custom_memory_pools Custom memory pools
A memory pool contains a number of `VkDeviceMemory` blocks.
@ -2070,13 +2145,7 @@ typedef struct VmaBudget
It might be different (most probably smaller) than `VkMemoryHeap::size[i]` due to factors
external to the program, like other programs also consuming system resources.
Exceeding the budget may result, depending on operating system and graphics driver:
- Allocation failing with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
- Allocation taking very long time, even few seconds.
- Overall system slowdown.
- Even GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST` returned somewhere later.
Exceeding the budget may result in various problems.
*/
VkDeviceSize budget[VK_MAX_MEMORY_HEAPS];
} VmaBudget;