VulkanMemoryAllocator/docs/html/resource_aliasing.html

162 lines
13 KiB
HTML
Raw Normal View History

<!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=11"/>
<meta name="generator" content="Doxygen 1.9.2"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Vulkan Memory Allocator: Resource aliasing (overlap)</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.9.2 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @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:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(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><div class="header">
<div class="headertitle"><div class="title">Resource aliasing (overlap) </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p >New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory management, give an opportunity to alias (overlap) multiple resources in the same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL). It can be useful to save video memory, but it must be used with caution.</p>
<p >For example, if you know the flow of your whole render frame in advance, you are going to use some intermediate textures or buffers only during a small range of render passes, and you know these ranges don't overlap in time, you can bind these resources to the same place in memory, even if they have completely different parameters (width, height, format etc.).</p>
<p ><img src="../gfx/Aliasing.png" alt="Resource aliasing (overlap)" class="inline"/></p>
<p >Such scenario is possible using VMA, but you need to create your images manually. Then you need to calculate parameters of an allocation to be made using formula:</p>
<ul>
<li>allocation size = max(size of each image)</li>
<li>allocation alignment = max(alignment of each image)</li>
<li>allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image)</li>
</ul>
<p >Following example shows two different images bound to the same place in memory, allocated to fit largest of them.</p>
<div class="fragment"><div class="line"><span class="comment">// A 512x512 texture to be sampled.</span></div>
<div class="line">VkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };</div>
<div class="line">img1CreateInfo.imageType = VK_IMAGE_TYPE_2D;</div>
<div class="line">img1CreateInfo.extent.width = 512;</div>
<div class="line">img1CreateInfo.extent.height = 512;</div>
<div class="line">img1CreateInfo.extent.depth = 1;</div>
<div class="line">img1CreateInfo.mipLevels = 10;</div>
<div class="line">img1CreateInfo.arrayLayers = 1;</div>
<div class="line">img1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;</div>
<div class="line">img1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;</div>
<div class="line">img1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;</div>
<div class="line">img1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;</div>
<div class="line">img1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;</div>
<div class="line"> </div>
<div class="line"><span class="comment">// A full screen texture to be used as color attachment.</span></div>
<div class="line">VkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };</div>
<div class="line">img2CreateInfo.imageType = VK_IMAGE_TYPE_2D;</div>
<div class="line">img2CreateInfo.extent.width = 1920;</div>
<div class="line">img2CreateInfo.extent.height = 1080;</div>
<div class="line">img2CreateInfo.extent.depth = 1;</div>
<div class="line">img2CreateInfo.mipLevels = 1;</div>
<div class="line">img2CreateInfo.arrayLayers = 1;</div>
<div class="line">img2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;</div>
<div class="line">img2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;</div>
<div class="line">img2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;</div>
<div class="line">img2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;</div>
<div class="line">img2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;</div>
<div class="line"> </div>
<div class="line">VkImage img1;</div>
<div class="line">res = vkCreateImage(device, &amp;img1CreateInfo, <span class="keyword">nullptr</span>, &amp;img1);</div>
<div class="line">VkImage img2;</div>
<div class="line">res = vkCreateImage(device, &amp;img2CreateInfo, <span class="keyword">nullptr</span>, &amp;img2);</div>
<div class="line"> </div>
<div class="line">VkMemoryRequirements img1MemReq;</div>
<div class="line">vkGetImageMemoryRequirements(device, img1, &amp;img1MemReq);</div>
<div class="line">VkMemoryRequirements img2MemReq;</div>
<div class="line">vkGetImageMemoryRequirements(device, img2, &amp;img2MemReq);</div>
<div class="line"> </div>
<div class="line">VkMemoryRequirements finalMemReq = {};</div>
<div class="line">finalMemReq.size = std::max(img1MemReq.size, img2MemReq.size);</div>
<div class="line">finalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment);</div>
<div class="line">finalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits &amp; img2MemReq.memoryTypeBits;</div>
<div class="line"><span class="comment">// Validate if(finalMemReq.memoryTypeBits != 0)</span></div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
<div class="line">allocCreateInfo.<a class="code hl_variable" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code hl_enumvalue" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
<div class="line"> </div>
<div class="line"><a class="code hl_struct" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div>
<div class="line">res = <a class="code hl_function" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vmaAllocateMemory</a>(allocator, &amp;finalMemReq, &amp;allocCreateInfo, &amp;alloc, <span class="keyword">nullptr</span>);</div>
<div class="line"> </div>
<div class="line">res = <a class="code hl_function" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a>(allocator, alloc, img1);</div>
<div class="line">res = <a class="code hl_function" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a>(allocator, alloc, img2);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// You can use img1, img2 here, but not at the same time!</span></div>
<div class="line"> </div>
<div class="line"><a class="code hl_function" href="vk__mem__alloc_8h.html#a5fea5518972ae9094b1526cbcb19b05f">vmaFreeMemory</a>(allocator, alloc);</div>
<div class="line">vkDestroyImage(allocator, img2, <span class="keyword">nullptr</span>);</div>
<div class="line">vkDestroyImage(allocator, img1, <span class="keyword">nullptr</span>);</div>
<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1003</div></div>
<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1011</div></div>
<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
<div class="ttc" id="avk__mem__alloc_8h_html_a3d3ca45799923aa5d138e9e5f9eb2da5"><div class="ttname"><a href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a></div><div class="ttdeci">VkResult vmaBindImageMemory(VmaAllocator allocator, VmaAllocation allocation, VkImage image)</div><div class="ttdoc">Binds image to allocation.</div></div>
<div class="ttc" id="avk__mem__alloc_8h_html_a5fea5518972ae9094b1526cbcb19b05f"><div class="ttname"><a href="vk__mem__alloc_8h.html#a5fea5518972ae9094b1526cbcb19b05f">vmaFreeMemory</a></div><div class="ttdeci">void vmaFreeMemory(VmaAllocator allocator, const VmaAllocation allocation)</div><div class="ttdoc">Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...</div></div>
<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:845</div></div>
<div class="ttc" id="avk__mem__alloc_8h_html_abf28077dbf82d0908b8acbe8ee8dd9b8"><div class="ttname"><a href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vmaAllocateMemory</a></div><div class="ttdeci">VkResult vmaAllocateMemory(VmaAllocator allocator, const VkMemoryRequirements *pVkMemoryRequirements, const VmaAllocationCreateInfo *pCreateInfo, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">General purpose memory allocation.</div></div>
</div><!-- fragment --><p >Remember that using resources that alias in memory requires proper synchronization. You need to issue a memory barrier to make sure commands that use <code>img1</code> and <code>img2</code> 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 <code>img1</code> and then want to use <code>img2</code>, you need to issue an image memory barrier for <code>img2</code> with <code>oldLayout</code> = <code>VK_IMAGE_LAYOUT_UNDEFINED</code>.</p>
<p >Additional considerations:</p>
<ul>
<li>Vulkan also allows to interpret contents of memory between aliasing resources consistently in some cases. See chapter 11.8. "Memory Aliasing" of Vulkan specification or <code>VK_IMAGE_CREATE_ALIAS_BIT</code> flag.</li>
<li>You can create more complex layout where different images and buffers are bound at different offsets inside one large allocation. For example, one can imagine a big texture used in some render passes, aliasing with a set of many small buffers used between in some further passes. To bind a resource at non-zero offset of an allocation, use <a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a" title="Binds buffer to allocation with additional parameters.">vmaBindBufferMemory2()</a> / <a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc" title="Binds image to allocation with additional parameters.">vmaBindImageMemory2()</a>.</li>
<li>Before allocating memory for the resources you want to alias, check <code>memoryTypeBits</code> 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 <code>COLOR_ATTACHMENT</code> usage, so the sets of memory types supported by your resources may be disjoint. Aliasing them is not possible in that case. </li>
</ul>
</div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.2
</small></address>
</body>
</html>