blob: 1608f24432afeba8d68b6f7384f7722d8d42d2db [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.20"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Vulkan Memory Allocator: Staying within budget</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">Vulkan Memory Allocator
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.20 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li> </ul>
</div>
</div><!-- top -->
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Staying within budget </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>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:</p>
<ul>
<li>It may just work without any problems.</li>
<li>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.</li>
<li>A new allocation may take very long time to complete, even few seconds, and possibly freeze entire system.</li>
<li>The new allocation may fail with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>.</li>
<li>It may even result in GPU crash (TDR), observed as <code>VK_ERROR_DEVICE_LOST</code> returned somewhere later.</li>
</ul>
<h1><a class="anchor" id="staying_within_budget_querying_for_budget"></a>
Querying for budget</h1>
<p>To query for current memory usage and available budget, use function <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba" title="Retrieves information about current memory budget for all memory heaps.">vmaGetBudget()</a>. Returned structure <a class="el" href="struct_vma_budget.html" title="Statistics of current memory usage and available budget, in bytes, for specific memory heap.">VmaBudget</a> contains quantities expressed in bytes, per Vulkan memory heap.</p>
<p>Please note that this function returns different information and works faster than <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a>. <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba" title="Retrieves information about current memory budget for all memory heaps.">vmaGetBudget()</a> can be called every frame or even before every allocation, while <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a> is intended to be used rarely, only to obtain statistical information, e.g. for debugging purposes.</p>
<p>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:</p>
<ol type="1">
<li>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!</li>
<li>Use flag <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a> when creating <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object.</li>
<li>Make sure to call <a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236" title="Sets index of the current frame.">vmaSetCurrentFrameIndex()</a> every frame. Budget is queried from Vulkan inside of it to avoid overhead of querying it with every allocation.</li>
</ol>
<h1><a class="anchor" id="staying_within_budget_controlling_memory_usage"></a>
Controlling memory usage</h1>
<p>There are many ways in which you can try to stay within the budget.</p>
<p>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.</p>
<p>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 <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a> 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 <a class="el" href="lost_allocations.html">lost allocations</a> is used. If that is not possible, the allocation fails with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>. Example usage pattern may be to pass the <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a> 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).</p>
<p>Finally, you can also use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff" title="Set this flag to only try to allocate from existing VkDeviceMemory blocks and never create new such b...">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a> 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 <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>. This also ensures that the function call is very fast because it never goes to Vulkan to obtain a new block.</p>
<p>Please note that creating <a class="el" href="custom_memory_pools.html">Custom memory pools</a> with <a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae" title="Minimum number of blocks to be always allocated in this pool, even if they stay empty.">VmaPoolCreateInfo::minBlockCount</a> set to more than 0 will try to allocate memory blocks without checking whether they fit within budget. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="http://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.8.20
</small></address>
</body>
</html>