Vulkan-Docs/doc/specs/vulkan/chapters/memory.txt

1116 lines
46 KiB
Plaintext

// Copyright (c) 2015-2016 The Khronos Group Inc.
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
[[memory]]
= Memory Allocation
Vulkan memory is broken up into two categories, _host memory_ and _device
memory_.
[[memory-host]]
== Host Memory
Host memory is memory needed by the Vulkan implementation for
non-device-visible storage.
This storage may: be used for e.g. internal software structures.
[[memory-allocation]]
Vulkan provides applications the opportunity to perform host memory
allocations on behalf of the Vulkan implementation.
If this feature is not used, the implementation will perform its own memory
allocations.
Since most memory allocations are off the critical path, this is not meant
as a performance feature.
Rather, this can: be useful for certain embedded systems, for debugging
purposes (e.g. putting a guard page after all host allocations), or for
memory allocation logging.
// refBegin VkAllocationCallbacks Structure containing callback function pointers for memory allocation
Allocators are provided by the application as a pointer to a
sname:VkAllocationCallbacks structure:
include::../api/structs/VkAllocationCallbacks.txt[]
* pname:pUserData is a value to be interpreted by the implementation of
the callbacks.
When any of the callbacks in sname:VkAllocationCallbacks are called, the
Vulkan implementation will pass this value as the first parameter to the
callback.
This value can: vary each time an allocator is passed into a command,
even when the same object takes an allocator in multiple commands.
* pname:pfnAllocation is a pointer to an application-defined memory
allocation function of type tlink:PFN_vkAllocationFunction.
* pname:pfnReallocation is a pointer to an application-defined memory
reallocation function of type tlink:PFN_vkReallocationFunction.
* pname:pfnFree is a pointer to an application-defined memory free
function of type tlink:PFN_vkFreeFunction.
* pname:pfnInternalAllocation is a pointer to an application-defined
function that is called by the implementation when the implementation
makes internal allocations, and it is of type
tlink:PFN_vkInternalAllocationNotification.
* pname:pfnInternalFree is a pointer to an application-defined function
that is called by the implementation when the implementation frees
internal allocations, and it is of type
tlink:PFN_vkInternalFreeNotification.
.Valid Usage
****
* pname:pfnAllocation must: be a pointer to a valid user-defined
tlink:PFN_vkAllocationFunction
* pname:pfnReallocation must: be a pointer to a valid user-defined
tlink:PFN_vkReallocationFunction
* pname:pfnFree must: be a pointer to a valid user-defined
tlink:PFN_vkFreeFunction
* If either of pname:pfnInternalAllocation or pname:pfnInternalFree is not
`NULL`, both must: be valid callbacks
****
include::../validity/structs/VkAllocationCallbacks.txt[]
// refBegin PFN_vkAllocationFunction Application-defined memory allocation function
The type of pname:pfnAllocation is:
include::../api/funcpointers/PFN_vkAllocationFunction.txt[]
* pname:pUserData is the value specified for
slink:VkAllocationCallbacks::pname:pUserData in the allocator specified
by the application.
* pname:size is the size in bytes of the requested allocation.
* pname:alignment is the requested alignment of the allocation in bytes
and must: be a power of two.
* pname:allocationScope is a elink:VkSystemAllocationScope value
specifying the allocation scope of the lifetime of the allocation, as
described <<memory-host-allocation-scope,here>>.
[[vkAllocationFunction_return_rules]]
If pname:pfnAllocation is unable to allocate the requested memory, it must:
return `NULL`.
If the allocation was successful, it must: return a valid pointer to memory
allocation containing at least pname:size bytes, and with the pointer value
being a multiple of pname:alignment.
[NOTE]
.Note
====
Correct Vulkan operation cannot: be assumed if the application does not
follow these rules.
For example, pname:pfnAllocation (or pname:pfnReallocation) could cause
termination of running Vulkan instance(s) on a failed allocation for
debugging purposes, either directly or indirectly.
In these circumstances, it cannot: be assumed that any part of any affected
VkInstance objects are going to operate correctly (even
flink:vkDestroyInstance), and the application must: ensure it cleans up
properly via other means (e.g. process termination).
====
If pname:pfnAllocation returns `NULL`, and if the implementation is unable
to continue correct processing of the current command without the requested
allocation, it must: treat this as a run-time error, and generate
ename:VK_ERROR_OUT_OF_HOST_MEMORY at the appropriate time for the command in
which the condition was detected, as described in <<fundamentals-errorcodes,
Return Codes>>.
If the implementation is able to continue correct processing of the current
command without the requested allocation, then it may: do so, and must: not
generate ename:VK_ERROR_OUT_OF_HOST_MEMORY as a result of this failed
allocation.
// refEnd PFN_vkAllocationFunction VkAllocationCallbacks
// refBegin PFN_vkReallocationFunction Application-defined memory reallocation function
The type of pname:pfnReallocation is:
include::../api/funcpointers/PFN_vkReallocationFunction.txt[]
* pname:pUserData is the value specified for
slink:VkAllocationCallbacks::pname:pUserData in the allocator specified
by the application.
* pname:pOriginal must: be either `NULL` or a pointer previously returned
by pname:pfnReallocation or pname:pfnAllocation of the same allocator.
* pname:size is the size in bytes of the requested allocation.
* pname:alignment is the requested alignment of the allocation in bytes
and must: be a power of two.
* pname:allocationScope is a elink:VkSystemAllocationScope value
specifying the allocation scope of the lifetime of the allocation, as
described <<memory-host-allocation-scope,here>>.
pname:pfnReallocation must: return an allocation with enough space for
pname:size bytes, and the contents of the original allocation from bytes
zero to [eq]#min(original size, new size) - 1# must: be preserved in the
returned allocation.
If pname:size is larger than the old size, the contents of the additional
space are undefined.
If satisfying these requirements involves creating a new allocation, then
the old allocation should: be freed.
If pname:pOriginal is `NULL`, then pname:pfnReallocation must: behave
equivalently to a call to tlink:PFN_vkAllocationFunction with the same
parameter values (without pname:pOriginal).
If pname:size is zero, then pname:pfnReallocation must: behave equivalently
to a call to tlink:PFN_vkFreeFunction with the same pname:pUserData
parameter value, and pname:pMemory equal to pname:pOriginal.
If pname:pOriginal is non-`NULL`, the implementation must: ensure that
pname:alignment is equal to the pname:alignment used to originally allocate
pname:pOriginal.
If this function fails and pname:pOriginal is non-`NULL` the application
must: not free the old allocation.
pname:pfnReallocation must: follow the same
<<vkAllocationFunction_return_rules, rules for return values as
tname:PFN_vkAllocationFunction>>.
// refEnd PFN_vkReallocationFunction VkAllocationCallbacks
// refBegin PFN_vkFreeFunction Application-defined memory free function
The type of pname:pfnFree is:
include::../api/funcpointers/PFN_vkFreeFunction.txt[]
* pname:pUserData is the value specified for
slink:VkAllocationCallbacks::pname:pUserData in the allocator specified
by the application.
* pname:pMemory is the allocation to be freed.
pname:pMemory may: be `NULL`, which the callback must: handle safely.
If pname:pMemory is non-`NULL`, it must: be a pointer previously allocated
by pname:pfnAllocation or pname:pfnReallocation.
The application should: free this memory.
// refEnd PFN_vkFreeFunction VkAllocationCallbacks
// refBegin PFN_vkInternalAllocationNotification Application-defined memory allocation notification function
The type of pname:pfnInternalAllocation is:
include::../api/funcpointers/PFN_vkInternalAllocationNotification.txt[]
* pname:pUserData is the value specified for
slink:VkAllocationCallbacks::pname:pUserData in the allocator specified
by the application.
* pname:size is the requested size of an allocation.
* pname:allocationType is the requested type of an allocation.
* pname:allocationScope is a elink:VkSystemAllocationScope value
specifying the allocation scope of the lifetime of the allocation, as
described <<memory-host-allocation-scope,here>>.
This is a purely informational callback.
// refEnd PFN_vkInternalAllocationNotification VkAllocationCallbacks
// refBegin PFN_vkInternalFreeNotification Application-defined memory free notification function
The type of pname:pfnInternalFree is:
include::../api/funcpointers/PFN_vkInternalFreeNotification.txt[]
* pname:pUserData is the value specified for
slink:VkAllocationCallbacks::pname:pUserData in the allocator specified
by the application.
* pname:size is the requested size of an allocation.
* pname:allocationType is the requested type of an allocation.
* pname:allocationScope is a elink:VkSystemAllocationScope value
specifying the allocation scope of the lifetime of the allocation, as
described <<memory-host-allocation-scope,here>>.
// refEnd PFN_vkInternalFreeNotification VkAllocationCallbacks
// refBegin VkSystemAllocationScope Allocation scope
[[memory-host-allocation-scope]]
Each allocation has an _allocation scope_ which defines its lifetime and
which object it is associated with.
The allocation scope is provided in the pname:allocationScope parameter
passed to callbacks defined in slink:VkAllocationCallbacks.
Possible values for this parameter are defined by
elink:VkSystemAllocationScope:
include::../api/enums/VkSystemAllocationScope.txt[]
* ename:VK_SYSTEM_ALLOCATION_SCOPE_COMMAND - The allocation is scoped to
the duration of the Vulkan command.
* ename:VK_SYSTEM_ALLOCATION_SCOPE_OBJECT - The allocation is scoped to
the lifetime of the Vulkan object that is being created or used.
* ename:VK_SYSTEM_ALLOCATION_SCOPE_CACHE - The allocation is scoped to the
lifetime of a sname:VkPipelineCache object.
* ename:VK_SYSTEM_ALLOCATION_SCOPE_DEVICE - The allocation is scoped to
the lifetime of the Vulkan device.
* ename:VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - The allocation is scoped to
the lifetime of the Vulkan instance.
Most Vulkan commands operate on a single object, or there is a sole object
that is being created or manipulated.
When an allocation uses an allocation scope of
ename:VK_SYSTEM_ALLOCATION_SCOPE_OBJECT or
ename:VK_SYSTEM_ALLOCATION_SCOPE_CACHE, the allocation is scoped to the
object being created or manipulated.
When an implementation requires host memory, it will make callbacks to the
application using the most specific allocator and allocation scope
available:
* If an allocation is scoped to the duration of a command, the allocator
will use the ename:VK_SYSTEM_ALLOCATION_SCOPE_COMMAND allocation scope.
The most specific allocator available is used: if the object being
created or manipulated has an allocator, that object's allocator will be
used, else if the parent sname:VkDevice has an allocator it will be
used, else if the parent sname:VkInstance has an allocator it will be
used.
Else,
* If an allocation is associated with an object of type
sname:VkPipelineCache, the allocator will use the
ename:VK_SYSTEM_ALLOCATION_SCOPE_CACHE allocation scope.
The most specific allocator available is used (pipeline cache, else
device, else instance).
Else,
* If an allocation is scoped to the lifetime of an object, that object is
being created or manipulated by the command, and that object's type is
not sname:VkDevice or sname:VkInstance, the allocator will use an
allocation scope of ename:VK_SYSTEM_ALLOCATION_SCOPE_OBJECT.
The most specific allocator available is used (object, else device, else
instance).
Else,
* If an allocation is scoped to the lifetime of a device, the allocator
will use an allocation scope of ename VK_SYSTEM_ALLOCATION_SCOPE_DEVICE.
The most specific allocator available is used (device, else instance).
Else,
* If the allocation is scoped to the lifetime of an instance and the
instance has an allocator, its allocator will be used with an allocation
scope of ename:VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE.
* Otherwise an implementation will allocate memory through an alternative
mechanism that is unspecified.
// refEnd VkSystemAllocationScope VkAllocationCallbacks
Objects that are allocated from pools do not specify their own allocator.
When an implementation requires host memory for such an object, that memory
is sourced from the object's parent pool's allocator.
The application is not expected to handle allocating memory that is intended
for execution by the host due to the complexities of differing security
implementations across multiple platforms.
The implementation will allocate such memory internally and invoke an
application provided informational callback when these _internal
allocations_ are allocated and freed.
Upon allocation of executable memory, pname:pfnInternalAllocation will be
called.
Upon freeing executable memory, pname:pfnInternalFree will be called.
An implementation will only call an informational callback for executable
memory allocations and frees.
// refBegin VkInternalAllocationType Allocation type
The pname:allocationType parameter to the pname:pfnInternalAllocation and
pname:pfnInternalFree functions may: be one of the following values:
include::../api/enums/VkInternalAllocationType.txt[]
* ename:VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - The allocation is
intended for execution by the host.
// refEnd VkInternalAllocationType PFN_vkInternalAllocationNotification PFN_vkInternalFreeNotification
An implementation must: only make calls into an application-provided
allocator during the execution of an API command.
An implementation must: only make calls into an application-provided
allocator from the same thread that called the provoking API command.
The implementation should: not synchronize calls to any of the callbacks.
If synchronization is needed, the callbacks must: provide it themselves.
The informational callbacks are subject to the same restrictions as the
allocation callbacks.
If an implementation intends to make calls through an
sname:VkAllocationCallbacks structure between the time a ftext:vkCreate*
command returns and the time a corresponding ftext:vkDestroy* command
begins, that implementation must: save a copy of the allocator before the
ftext:vkCreate* command returns.
The callback functions and any data structures they rely upon must: remain
valid for the lifetime of the object they are associated with.
If an allocator is provided to a ftext:vkCreate* command, a _compatible_
allocator must: be provided to the corresponding ftext:vkDestroy* command.
Two sname:VkAllocationCallbacks structures are compatible if memory
allocated with pname:pfnAllocation or pname:pfnReallocation in each can: be
freed with pname:pfnReallocation or pname:pfnFree in the other.
An allocator must: not be provided to a ftext:vkDestroy* command if an
allocator was not provided to the corresponding ftext:vkCreate* command.
If a non-`NULL` allocator is used, the pname:pfnAllocation,
pname:pfnReallocation and pname:pfnFree members must: be non-`NULL` and
point to valid implementations of the callbacks.
An application can: choose to not provide informational callbacks by setting
both pname:pfnInternalAllocation and pname:pfnInternalFree to `NULL`.
pname:pfnInternalAllocation and pname:pfnInternalFree must: either both be
`NULL` or both be non-`NULL`.
If pname:pfnAllocation or pname:pfnReallocation fail, the implementation
may: fail object creation and/or generate an
ename:VK_ERROR_OUT_OF_HOST_MEMORY error, as appropriate.
Allocation callbacks must: not call any Vulkan commands.
The following sets of rules define when an implementation is permitted to
call the allocator callbacks.
pname:pfnAllocation or pname:pfnReallocation may: be called in the following
situations:
* Allocations scoped to a sname:VkDevice or sname:VkInstance may: be
allocated from any API command.
* Allocations scoped to a command may: be allocated from any API command.
* Allocations scoped to a sname:VkPipelineCache may: only be allocated
from:
** fname:vkCreatePipelineCache
** fname:vkMergePipelineCaches for pname:dstCache
** fname:vkCreateGraphicsPipelines for pname:pPipelineCache
** fname:vkCreateComputePipelines for pname:pPipelineCache
* Allocations scoped to a sname:VkDescriptorPool may: only be allocated
from:
** any command that takes the pool as a direct argument
** fname:vkAllocateDescriptorSets for the pname:descriptorPool member of
its pname:pAllocateInfo parameter
** fname:vkCreateDescriptorPool
* Allocations scoped to a sname:VkCommandPool may: only be allocated from:
** any command that takes the pool as a direct argument
** fname:vkCreateCommandPool
** fname:vkAllocateCommandBuffers for the pname:commandPool member of its
pname:pAllocateInfo parameter
** any ftext:vkCmd* command whose pname:commandBuffer was allocated from
that sname:VkCommandPool
* Allocations scoped to any other object may: only be allocated in that
object's ftext:vkCreate* command.
pname:pfnFree may: be called in the following situations:
* Allocations scoped to a sname:VkDevice or sname:VkInstance may: be freed
from any API command.
* Allocations scoped to a command must: be freed by any API command which
allocates such memory.
* Allocations scoped to a sname:VkPipelineCache may: be freed from
fname:vkDestroyPipelineCache.
* Allocations scoped to a sname:VkDescriptorPool may: be freed from
** any command that takes the pool as a direct argument
* Allocations scoped to a sname:VkCommandPool may: be freed from:
** any command that takes the pool as a direct argument
** fname:vkResetCommandBuffer whose pname:commandBuffer was allocated from
that sname:VkCommandPool
* Allocations scoped to any other object may: be freed in that object's
ftext:vkDestroy* command.
* Any command that allocates host memory may: also free host memory of the
same scope.
[[memory-device]]
== Device Memory
Device memory is memory that is visible to the device, for example the
contents of opaque images that can: be natively used by the device, or
uniform buffer objects that reside in on-device memory.
Memory properties of a physical device describe the memory heaps and memory
types available.
// refBegin vkGetPhysicalDeviceMemoryProperties Reports memory information for the specified physical device
To query memory properties, call:
include::../api/protos/vkGetPhysicalDeviceMemoryProperties.txt[]
* pname:physicalDevice is the handle to the device to query.
* pname:pMemoryProperties points to an instance of
sname:VkPhysicalDeviceMemoryProperties structure in which the properties
are returned.
include::../validity/protos/vkGetPhysicalDeviceMemoryProperties.txt[]
// refBegin VkPhysicalDeviceMemoryProperties Structure specifying physical device memory properties
The sname:VkPhysicalDeviceMemoryProperties structure is defined as:
include::../api/structs/VkPhysicalDeviceMemoryProperties.txt[]
* pname:memoryTypeCount is the number of valid elements in the
pname:memoryTypes array.
* pname:memoryTypes is an array of slink:VkMemoryType structures
describing the _memory types_ that can: be used to access memory
allocated from the heaps specified by pname:memoryHeaps.
* pname:memoryHeapCount is the number of valid elements in the
pname:memoryHeaps array.
* pname:memoryHeaps is an array of slink:VkMemoryHeap structures
describing the _memory heaps_ from which memory can: be allocated.
The sname:VkPhysicalDeviceMemoryProperties structure describes a number of
_memory heaps_ as well as a number of _memory types_ that can: be used to
access memory allocated in those heaps.
Each heap describes a memory resource of a particular size, and each memory
type describes a set of memory properties (e.g. host cached vs uncached)
that can: be used with a given memory heap.
Allocations using a particular memory type will consume resources from the
heap indicated by that memory type's heap index.
More than one memory type may: share each heap, and the heaps and memory
types provide a mechanism to advertise an accurate size of the physical
memory resources while allowing the memory to be used with a variety of
different properties.
The number of memory heaps is given by pname:memoryHeapCount and is less
than or equal to ename:VK_MAX_MEMORY_HEAPS.
Each heap is described by an element of the pname:memoryHeaps array, as a
sname:VkMemoryHeap structure.
The number of memory types available across all memory heaps is given by
pname:memoryTypeCount and is less than or equal to
ename:VK_MAX_MEMORY_TYPES.
Each memory type is described by an element of the pname:memoryTypes array,
as a sname:VkMemoryType structure.
At least one heap must: include ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT in
slink:VkMemoryHeap::pname:flags.
If there are multiple heaps that all have similar performance
characteristics, they may: all include
ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT.
In a unified memory architecture (UMA) system, there is often only a single
memory heap which is considered to be equally ``local'' to the host and to
the device, and such an implementation must: advertise the heap as
device-local.
Each memory type returned by flink:vkGetPhysicalDeviceMemoryProperties must:
have its pname:propertyFlags set to one of the following values:
* 0
* ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
* ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT
* ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
* ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
* ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
* ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT
* ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
* ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
There must: be at least one memory type with both the
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bits set in its
pname:propertyFlags.
There must: be at least one memory type with the
ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT bit set in its
pname:propertyFlags.
The memory types are sorted according to a preorder which serves to aid in
easily selecting an appropriate memory type.
Given two memory types X and Y, the preorder defines [eq]#X {leq} Y# if:
* the memory property bits set for X are a strict subset of the memory
property bits set for Y.
Or,
* the memory property bits set for X are the same as the memory property
bits set for Y, and X uses a memory heap with greater or equal
performance (as determined in an implementation-specific manner).
Memory types are ordered in the list such that X is assigned a lesser
pname:memoryTypeIndex than Y if [eq]#(X {leq} Y) {land} {lnot} (Y {leq} X)#
according to the preorder.
Note that the list of all allowed memory property flag combinations above
satisfies this preorder, but other orders would as well.
The goal of this ordering is to enable applications to use a simple search
loop in selecting the proper memory type, along the lines of:
[source,{basebackend@docbook:c++:cpp}]
---------------------------------------------------
// Find a memory type in "memoryTypeBits" that includes all of "properties"
int32_t FindProperties(uint32_t memoryTypeBits, VkMemoryPropertyFlags properties)
{
for (int32_t i = 0; i < memoryTypeCount; ++i)
{
if ((memoryTypeBits & (1 << i)) &&
((memoryTypes[i].propertyFlags & properties) == properties))
return i;
}
return -1;
}
// Try to find an optimal memory type, or if it does not exist
// find any compatible memory type
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(device, image, &memoryRequirements);
int32_t memoryType = FindProperties(memoryRequirements.memoryTypeBits, optimalProperties);
if (memoryType == -1)
memoryType = FindProperties(memoryRequirements.memoryTypeBits, requiredProperties);
---------------------------------------------------
The loop will find the first supported memory type that has all bits
requested in code:properties set.
If there is no exact match, it will find a closest match (i.e. a memory type
with the fewest additional bits set), which has some additional bits set but
which are not detrimental to the behaviors requested by code:properties.
The application can: first search for the optimal properties, e.g. a memory
type that is device-local or supports coherent cached accesses, as
appropriate for the intended usage, and if such a memory type is not present
can: fallback to searching for a less optimal but guaranteed set of
properties such as "0" or "host-visible and coherent".
include::../validity/structs/VkPhysicalDeviceMemoryProperties.txt[]
// refBegin VkMemoryHeap Structure specifying a memory heap
The sname:VkMemoryHeap structure is defined as:
include::../api/structs/VkMemoryHeap.txt[]
* pname:size is the total memory size in bytes in the heap.
* pname:flags is a bitmask of attribute flags for the heap.
The bits specified in pname:flags are:
+
--
// refBegin VkMemoryHeapFlagBits Bitmask specifying attribute flags for a heap
include::../api/enums/VkMemoryHeapFlagBits.txt[]
--
** if pname:flags contains ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, it means
the heap corresponds to device local memory.
Device local memory may: have different performance characteristics
than host local memory, and may: support different memory property
flags.
include::../validity/structs/VkMemoryHeap.txt[]
// refBegin VkMemoryType Structure specifying memory type
The sname:VkMemoryType structure is defined as:
include::../api/structs/VkMemoryType.txt[]
* pname:heapIndex describes which memory heap this memory type corresponds
to, and must: be less than pname:memoryHeapCount from the
sname:VkPhysicalDeviceMemoryProperties structure.
* pname:propertyFlags is a bitmask of properties for this memory type.
The bits specified in pname:propertyFlags are:
+
--
// refBegin VkMemoryPropertyFlagBits Bitmask specifying properties for a memory type
include::../api/enums/VkMemoryPropertyFlagBits.txt[]
--
** if pname:propertyFlags has the
ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT bit set, memory allocated
with this type is the most efficient for device access.
This property will only be set for memory types belonging to heaps with
the ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT set.
** if pname:propertyFlags has the
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit set, memory allocated
with this type can: be mapped for host access using flink:vkMapMemory.
** if pname:propertyFlags has the
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set, host cache
management commands fname:vkFlushMappedMemoryRanges and
fname:vkInvalidateMappedMemoryRanges are not needed to make host writes
visible to the device or device writes visible to the host,
respectively.
** if pname:propertyFlags has the ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT
bit set, memory allocated with this type is cached on the host.
Host memory accesses to uncached memory are slower than to cached
memory, however uncached memory is always host coherent.
** if pname:propertyFlags has the
ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT bit set, the memory type
only allows device access to the memory.
Memory types must: not have both
ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT and
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set.
Additionally, the object's backing memory may: be provided by the
implementation lazily as specified in <<memory-device-lazy_allocation,
Lazily Allocated Memory>>.
include::../validity/structs/VkMemoryType.txt[]
// refBegin VkDeviceMemory Opaque handle to a device memory object
A Vulkan device operates on data in device memory via memory objects that
are represented in the API by a sname:VkDeviceMemory handle.
Memory objects are represented by sname:VkDeviceMemory handles:
include::../api/handles/VkDeviceMemory.txt[]
// refEnd VkDeviceMemory
// refBegin vkAllocateMemory Allocate GPU memory
To allocate memory objects, call:
include::../api/protos/vkAllocateMemory.txt[]
* pname:device is the logical device that owns the memory.
* pname:pAllocateInfo is a pointer to an instance of the
slink:VkMemoryAllocateInfo structure describing parameters of the
allocation.
A successful returned allocation must: use the requested parameters --
no substitution is permitted by the implementation.
* pname:pAllocator controls host memory allocation as described in the
<<memory-allocation, Memory Allocation>> chapter.
* pname:pMemory is a pointer to a sname:VkDeviceMemory handle in which
information about the allocated memory is returned.
Allocations returned by fname:vkAllocateMemory are guaranteed to meet any
alignment requirement by the implementation.
For example, if an implementation requires 128 byte alignment for images and
64 byte alignment for buffers, the device memory returned through this
mechanism would be 128-byte aligned.
This ensures that applications can: correctly suballocate objects of
different types (with potentially different alignment requirements) in the
same memory object.
When memory is allocated, its contents are undefined.
There is an implementation-dependent maximum number of memory allocations
which can: be simultaneously created on a device.
This is specified by the
<<features-limits-maxMemoryAllocationCount,pname:maxMemoryAllocationCount>>
member of the sname:VkPhysicalDeviceLimits structure.
If pname:maxMemoryAllocationCount is exceeded, fname:vkAllocateMemory will
return ename:VK_ERROR_TOO_MANY_OBJECTS.
[NOTE]
.Note
====
Some platforms may: have a limit on the maximum size of a single allocation.
For example, certain systems may: fail to create allocations with a size
greater than or equal to 4GB.
Such a limit is implementation-dependent, and if such a failure occurs then
the error ename:VK_ERROR_OUT_OF_DEVICE_MEMORY should: be returned.
====
.Valid Usage
****
* The number of currently valid memory objects, allocated from
pname:device, must: be less than
sname:VkPhysicalDeviceLimits::pname:maxMemoryAllocationCount
****
include::../validity/protos/vkAllocateMemory.txt[]
// refBegin VkMemoryAllocateInfo Structure containing parameters of a memory allocation
The sname:VkMemoryAllocateInfo structure is defined as:
include::../api/structs/VkMemoryAllocateInfo.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:allocationSize is the size of the allocation in bytes
* pname:memoryTypeIndex is the memory type index, which selects the
properties of the memory to be allocated, as well as the heap the memory
will come from.
.Valid Usage
****
* pname:allocationSize must: be less than or equal to the amount of memory
available to the sname:VkMemoryHeap specified by pname:memoryTypeIndex
and the calling command's sname:VkDevice
* pname:allocationSize must: be greater than `0`
****
include::../validity/structs/VkMemoryAllocateInfo.txt[]
ifdef::VK_NV_dedicated_allocation[]
// refBegin VkDedicatedAllocationMemoryAllocateInfoNV Specify a dedicated memory allocation resource
If the pname:pNext list includes a
sname:VkDedicatedAllocationMemoryAllocateInfoNV structure, then that
structure includes a handle of the sole buffer or image resource that the
memory can: be bound to.
The sname:VkDedicatedAllocationMemoryAllocateInfoNV structure is defined as:
include::../api/structs/VkDedicatedAllocationMemoryAllocateInfoNV.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:image is sname:VK_NULL_HANDLE or a handle of an image which this
memory will be bound to.
* pname:buffer is sname:VK_NULL_HANDLE or a handle of a buffer which this
memory will be bound to.
.Valid Usage
****
* At least one of pname:image and pname:buffer must: be
sname:VK_NULL_HANDLE
* If pname:image is not sname:VK_NULL_HANDLE, the image must: have been
created with
sname:VkDedicatedAllocationImageCreateInfoNV::pname:dedicatedAllocation
equal to ename:VK_TRUE
* If pname:buffer is not sname:VK_NULL_HANDLE, the buffer must: have been
created with
sname:VkDedicatedAllocationBufferCreateInfoNV::pname:dedicatedAllocation
equal to ename:VK_TRUE
* If pname:image is not sname:VK_NULL_HANDLE,
sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
sname:VkMemoryRequirements::pname:size of the image
* If pname:buffer is not sname:VK_NULL_HANDLE,
sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
sname:VkMemoryRequirements::pname:size of the buffer
****
include::../validity/structs/VkDedicatedAllocationMemoryAllocateInfoNV.txt[]
endif::VK_NV_dedicated_allocation[]
ifdef::VK_NV_external_memory[]
include::VK_NV_external_memory/allocate_memory.txt[]
endif::VK_NV_external_memory[]
ifdef::VK_NV_external_memory_win32[]
include::VK_NV_external_memory_win32/handle_permissions.txt[]
include::VK_NV_external_memory_win32/import_memory_win32.txt[]
include::VK_NV_external_memory_win32/get_handle_win32.txt[]
endif::VK_NV_external_memory_win32[]
// refBegin vkFreeMemory Free GPU memory
To free a memory object, call:
include::../api/protos/vkFreeMemory.txt[]
* pname:device is the logical device that owns the memory.
* pname:memory is the sname:VkDeviceMemory object to be freed.
* pname:pAllocator controls host memory allocation as described in the
<<memory-allocation, Memory Allocation>> chapter.
Before freeing a memory object, an application must: ensure the memory
object is no longer in use by the device--for example by command buffers
queued for execution.
The memory can: remain bound to images or buffers at the time the memory
object is freed, but any further use of them (on host or device) for
anything other than destroying those objects will result in undefined
behavior.
If there are still any bound images or buffers, the memory may: not be
immediately released by the implementation, but must: be released by the
time all bound images and buffers have been destroyed.
Once memory is released, it is returned to the heap from which it was
allocated.
How memory objects are bound to Images and Buffers is described in detail in
the <<resources-association, Resource Memory Association>> section.
If a memory object is mapped at the time it is freed, it is implicitly
unmapped.
.Valid Usage
****
* All submitted commands that refer to pname:memory (via images or
buffers) must: have completed execution
****
include::../validity/protos/vkFreeMemory.txt[]
[[memory-device-hostaccess]]
=== Host Access to Device Memory Objects
Memory objects created with fname:vkAllocateMemory are not directly host
accessible.
Memory objects created with the memory property
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT are considered _mappable_.
Memory objects must: be mappable in order to be successfully mapped on the
host.
// refBegin vkMapMemory Map a memory object into application address space
To retrieve a host virtual address pointer to a region of a mappable memory
object, call:
include::../api/protos/vkMapMemory.txt[]
* pname:device is the logical device that owns the memory.
* pname:memory is the sname:VkDeviceMemory object to be mapped.
* pname:offset is a zero-based byte offset from the beginning of the
memory object.
* pname:size is the size of the memory range to map, or
ename:VK_WHOLE_SIZE to map from pname:offset to the end of the
allocation.
* pname:flags is reserved for future use.
* pname:ppData points to a pointer in which is returned a host-accessible
pointer to the beginning of the mapped range.
This pointer minus pname:offset must: be aligned to at least
sname:VkPhysicalDeviceLimits::pname:minMemoryMapAlignment.
It is an application error to call fname:vkMapMemory on a memory object that
is already mapped.
[NOTE]
.Note
====
fname:vkMapMemory will fail if the implementation is unable to allocate an
appropriately sized contiguous virtual address range, e.g. due to virtual
address space fragmentation or platform limits.
In such cases, fname:vkMapMemory must: return VK_ERROR_MEMORY_MAP_FAILED.
The application can: improve the likelihood of success by reducing the size
of the mapped range and/or removing unneeded mappings using
fname:VkUnmapMemory.
====
[[memory-device-hostaccess-hazards]]
fname:vkMapMemory does not check whether the device memory is currently in
use before returning the host-accessible pointer.
The application must: guarantee that any previously submitted command that
writes to this range has completed before the host reads from or writes to
that range, and that any previously submitted command that reads from that
range has completed before the host writes to that region (see
<<synchronization-submission-host-writes, here>> for details on fulfilling
such a guarantee).
If the device memory was allocated without the
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set, these guarantees must: be
made for an extended range: the application must: round down the start of
the range to the nearest multiple of
sname:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize, and round the end
of the range up to the nearest multiple of
sname:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize.
While a range of device memory is mapped for host access, the application is
responsible for synchronizing both device and host access to that memory
range.
[NOTE]
.Note
====
It is important for the application developer to become meticulously
familiar with all of the mechanisms described in the chapter on
<<synchronization, Synchronization and Cache Control>> as they are crucial
to maintaining memory access ordering.
====
.Valid Usage
****
* pname:memory must: not currently be mapped
* pname:offset must: be less than the size of pname:memory
* If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be
greater than `0`
* If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be
less than or equal to the size of the pname:memory minus pname:offset
* pname:memory must: have been created with a memory type that reports
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
****
include::../validity/protos/vkMapMemory.txt[]
Two commands are provided to enable applications to work with non-coherent
memory allocations: fname:vkFlushMappedMemoryRanges and
fname:vkInvalidateMappedMemoryRanges.
[NOTE]
.Note
====
If the memory object was created with the
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set,
fname:vkFlushMappedMemoryRanges and fname:vkInvalidateMappedMemoryRanges are
unnecessary and may: have performance cost.
====
// refBegin vkFlushMappedMemoryRanges Flush mapped memory ranges
To flush ranges of non-coherent memory from the host caches, call:
include::../api/protos/vkFlushMappedMemoryRanges.txt[]
* pname:device is the logical device that owns the memory ranges.
* pname:memoryRangeCount is the length of the pname:pMemoryRanges array.
* pname:pMemoryRanges is a pointer to an array of
slink:VkMappedMemoryRange structures describing the memory ranges to
flush.
fname:vkFlushMappedMemoryRanges must: be used to guarantee that host writes
to non-coherent memory are visible to the device.
It must: be called after the host writes to non-coherent memory have
completed and before command buffers that will read or write any of those
memory locations are submitted to a queue.
[NOTE]
.Note
====
Unmapping non-coherent memory does not implicitly flush the mapped memory,
and host writes that have not been flushed may: not ever be visible to the
device.
====
include::../validity/protos/vkFlushMappedMemoryRanges.txt[]
// refBegin vkInvalidateMappedMemoryRanges Invalidate ranges of mapped memory objects
To invalidate ranges of non-coherent memory from the host caches, call:
include::../api/protos/vkInvalidateMappedMemoryRanges.txt[]
* pname:device is the logical device that owns the memory ranges.
* pname:memoryRangeCount is the length of the pname:pMemoryRanges array.
* pname:pMemoryRanges is a pointer to an array of
slink:VkMappedMemoryRange structures describing the memory ranges to
invalidate.
fname:vkInvalidateMappedMemoryRanges must: be used to guarantee that device
writes to non-coherent memory are visible to the host.
It must: be called after command buffers that execute and flush (via memory
barriers) the device writes have completed, and before the host will read or
write any of those locations.
If a range of non-coherent memory is written by the host and then
invalidated without first being flushed, its contents are undefined.
[NOTE]
.Note
====
Mapping non-coherent memory does not implicitly invalidate the mapped
memory, and device writes that have not been invalidated must: be made
visible before the host reads or overwrites them.
====
include::../validity/protos/vkInvalidateMappedMemoryRanges.txt[]
// refBegin VkMappedMemoryRange Structure specifying a mapped memory range
The sname:VkMappedMemoryRange structure is defined as:
include::../api/structs/VkMappedMemoryRange.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:memory is the memory object to which this range belongs.
* pname:offset is the zero-based byte offset from the beginning of the
memory object.
* pname:size is either the size of range, or ename:VK_WHOLE_SIZE to affect
the range from pname:offset to the end of the current mapping of the
allocation.
.Valid Usage
****
* pname:memory must: currently be mapped
* If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:offset and
pname:size must: specify a range contained within the currently mapped
range of pname:memory
* If pname:size is equal to ename:VK_WHOLE_SIZE, pname:offset must: be
within the currently mapped range of pname:memory
* pname:offset must: be a multiple of
sname:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize
* If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be a
multiple of sname:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize
****
include::../validity/structs/VkMappedMemoryRange.txt[]
ifdef::editing-notes[]
[NOTE]
.editing-note
====
TODO (Tobias) - There's a circular section reference between this next
section and the <<synchronization-fences-waiting,synchronization section>>.
The information is all covered by both places, but it seems a bit weird to
have them reference each other.
Not sure how to resolve it.
====
endif::editing-notes[]
Host-visible memory types that advertise the
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT property still require
<<synchronization-pipeline-barriers,memory barriers>> between host and
device in order to be coherent, but do not require additional cache
management operations to achieve coherency.
For host writes to be seen by subsequent command buffer operations, a
pipeline barrier from a source of ename:VK_ACCESS_HOST_WRITE_BIT and
ename:VK_PIPELINE_STAGE_HOST_BIT to a destination of the relevant device
<<synchronization-pipeline-stages, pipeline stages>> and
<<synchronization-access-types, access types>> must: be performed.
Note that such a barrier is performed
<<synchronization-submission-host-writes,implicitly>> upon each command
buffer submission, so an explicit barrier is only rarely needed (e.g. if a
command buffer waits upon an event signaled by the host, where the host
wrote some data after submission).
A pipeline barrier is required: to make writes visible to subsequent reads
on the host.
// refBegin vkUnmapMemory Unmap a previously mapped memory object
To unmap a memory object once host access to it is no longer needed by the
application, call:
include::../api/protos/vkUnmapMemory.txt[]
* pname:device is the logical device that owns the memory.
* pname:memory is the memory object to be unmapped.
.Valid Usage
****
* pname:memory must: currently be mapped
****
include::../validity/protos/vkUnmapMemory.txt[]
[[memory-device-lazy_allocation]]
=== Lazily Allocated Memory
If the memory object is allocated from a heap with the
ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT bit set, that object's backing
memory may: be provided by the implementation lazily.
The actual committed size of the memory may: initially be as small as zero
(or as large as the requested size), and monotonically increases as
additional memory is needed.
A memory type with this flag set is only allowed to be bound to a
sname:VkImage whose usage flags include
ename:VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT.
[NOTE]
.Note
====
Using lazily allocated memory objects for framebuffer attachments that are
not needed once a render pass instance has completed may: allow some
implementations to never allocate memory for such attachments.
====
// refBegin vkGetDeviceMemoryCommitment Query the current commitment for a VkDeviceMemory
To determine the amount of lazily-allocated memory that is currently
committed for a memory object, call:
include::../api/protos/vkGetDeviceMemoryCommitment.txt[]
* pname:device is the logical device that owns the memory.
* pname:memory is the memory object being queried.
* pname:pCommittedMemoryInBytes is a pointer to a basetype:VkDeviceSize
value in which the number of bytes currently committed is returned, on
success.
The implementation may: update the commitment at any time, and the value
returned by this query may: be out of date.
The implementation guarantees to allocate any committed memory from the
heapIndex indicated by the memory type that the memory object was created
with.
.Valid Usage
****
* pname:memory must: have been created with a memory type that reports
ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
****
include::../validity/protos/vkGetDeviceMemoryCommitment.txt[]