Memory Allocation
Vulkan memory is broken up into two categories, host memory and device memory.
Host Memory
Host memory is memory needed by the Vulkan implementation for non-device-visible storage.
This memory may be used to store the implementation’s representation and state of Vulkan objects.
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.
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, pfnInternalAllocation
will be
called.
Upon freeing executable memory, pfnInternalFree
will be called.
An implementation will only call an informational callback for executable
memory allocations and frees.
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 a
VkAllocationCallbacks
structure between the time a vkCreate*
command returns and the time a corresponding vkDestroy*
command
begins, that implementation must save a copy of the allocator before the
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 vkCreate*
command, a compatible
allocator must be provided to the corresponding vkDestroy*
command.
Two VkAllocationCallbacks
structures are compatible if memory
allocated with pfnAllocation
or pfnReallocation
in each can be
freed with pfnReallocation
or pfnFree
in the other.
An allocator must not be provided to a vkDestroy*
command if an
allocator was not provided to the corresponding vkCreate*
command.
If a non-NULL
allocator is used, the pfnAllocation
,
pfnReallocation
and 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 pfnInternalAllocation
and pfnInternalFree
to NULL
.
pfnInternalAllocation
and pfnInternalFree
must either both be
NULL
or both be non-NULL
.
If pfnAllocation
or pfnReallocation
fail, the implementation
may fail object creation and/or generate a
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.
pfnAllocation
or pfnReallocation
may be called in the following
situations:
- Allocations scoped to a
VkDevice
orVkInstance
may be allocated from any API command. - Allocations scoped to a command may be allocated from any API command.
- Allocations scoped to a
VkPipelineCache
may only be allocated from:vkCreatePipelineCache
vkMergePipelineCaches
fordstCache
vkCreateGraphicsPipelines
forpipelineCache
vkCreateComputePipelines
forpipelineCache
- Allocations scoped to a
VkValidationCacheEXT
may only be allocated from:vkCreateValidationCacheEXT
vkMergeValidationCachesEXT
fordstCache
vkCreateShaderModule
forvalidationCache
in VkShaderModuleValidationCacheCreateInfoEXT
- Allocations scoped to a
VkDescriptorPool
may only be allocated from:- any command that takes the pool as a direct argument
vkAllocateDescriptorSets
for thedescriptorPool
member of itspAllocateInfo
parametervkCreateDescriptorPool
- Allocations scoped to a
VkCommandPool
may only be allocated from:- any command that takes the pool as a direct argument
vkCreateCommandPool
vkAllocateCommandBuffers
for thecommandPool
member of itspAllocateInfo
parameter- any
vkCmd*
command whosecommandBuffer
was allocated from thatVkCommandPool
- Allocations scoped to any other object may only be allocated in that
object’s
vkCreate*
command.
pfnFree
, or pfnReallocation
with zero size
, may be called
in the following situations:
- Allocations scoped to a
VkDevice
orVkInstance
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
VkPipelineCache
may be freed fromvkDestroyPipelineCache
. - Allocations scoped to a
VkValidationCacheEXT
may be freed fromvkDestroyValidationCacheEXT
. - Allocations scoped to a
VkDescriptorPool
may be freed from- any command that takes the pool as a direct argument
- Allocations scoped to a
VkCommandPool
may be freed from:- any command that takes the pool as a direct argument
vkResetCommandBuffer
whosecommandBuffer
was allocated from thatVkCommandPool
- Allocations scoped to any other object may be freed in that object’s
vkDestroy*
command. - Any command that allocates host memory may also free host memory of the same scope.
Device Memory
Device memory is memory that is visible to the device — for example the contents of the image or buffer objects, which can be natively used by the device.
Device Memory Properties
Memory properties of a physical device describe the memory heaps and memory types available.
Device Memory Objects
Device Memory Allocation
When allocating memory that may be exported to another process or Vulkan
instance, add a VkExportMemoryAllocateInfoNV structure to the
pNext
chain of the VkMemoryAllocateInfo structure, specifying
the handle types that may be exported.
Win32 External Memory
Bits which can be set in handleType
are:
File Descriptor External Memory
Host External Memory
Android Hardware Buffer External Memory
Remote Device External Memory
Fuchsia External Memory
On Fuchsia, when allocating memory that may be imported from another
device, process or Vulkan instance, add a
VkImportMemoryZirconHandleInfoFUCHSIA structure to the pNext
chain of the VkMemoryAllocateInfo structure.
External memory on Fuchsia is imported and exported using VMO handles of
type zx_handle_t
.
VMO handles to external memory are canonically obtained from Fuchsia’s
Sysmem service or from syscalls such as zx_vmo_create
().
VMO handles for import can also be obtained by exporting them from another
Vulkan instance as described in exporting
fuchsia device memory.
Importing VMO handles to the Vulkan instance transfers ownership of the handle to the instance from the application. The application must not perform any operations on the handle after successful import.
Applications can import the same underlying memory into multiple instances
of Vulkan, into the same instance from which it was exported, and multiple
times into a given Vulkan instance.
In all cases, each import operation must create a distinct
VkDeviceMemory
object.
Importing Fuchsia External Memory
With pMemoryZirconHandleProperties
now successfully populated by
vkGetMemoryZirconHandlePropertiesFUCHSIA, assign the
VkMemoryAllocateInfo memoryTypeIndex field to a memory type which has
a bit set in the VkMemoryZirconHandlePropertiesFUCHSIA memoryTypeBits
field.
Exporting Fuchsia Device Memory
Similar to importing, exporting a VMO handle from Vulkan transfers ownership
of the handle from the Vulkan instance to the application.
The application is responsible for closing the handle with
zx_handle_close
() when it is no longer in use.
With the result pZirconHandle
now obtained, the memory properties for
the handle can be retrieved using
vkGetMemoryZirconHandlePropertiesFUCHSIA as documented above
substituting the dereferenced, retrieved pZirconHandle
in for the
zirconHandle
argument.
Metal Objects
A Vulkan implementation that is layered on top of Metal on Apple device platform, and implements the VK_EXT_metal_objects extension, supports the ability to import and export the underlying Metal objects associated with specific Vulkan objects.
The underlying Metal objects associated with certain Vulkan objects can be
exported from those Vulkan objects using the pNext
chain of the
VkExportMetalObjectsInfoEXT parameter of the
vkExportMetalObjectsEXT command.
An VkDeviceMemory object can be allocated on an existing
MTLBuffer
object, by including the MTLBuffer
object in a
VkImportMetalBufferInfoEXT structure in the pNext
chain of the
VkMemoryAllocateInfo structure in the vkAllocateMemory command.
A new VkImage object can be created on an existing IOSurface
object, or one or more existing Metal MTLTexture
objects, by including
those Metal objects in either VkImportMetalIOSurfaceInfoEXT or
VkImportMetalTextureInfoEXT structures in the pNext
chain of the
VkImageCreateInfo structure in the vkCreateImage command.
QNX Screen Buffer External Memory
Device Group Memory Allocations
Opaque Capture Address Allocation
Freeing Device Memory
Host Access to Device Memory Objects
Memory objects created with vkAllocateMemory are not directly host accessible.
Memory objects created with the memory property
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
are considered mappable.
Memory objects must be mappable in order to be successfully mapped on the
host.
Two commands are provided to enable applications to work with non-coherent
memory allocations: vkFlushMappedMemoryRanges
and
vkInvalidateMappedMemoryRanges
.
If the memory object was created with the
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
set,
vkFlushMappedMemoryRanges
and vkInvalidateMappedMemoryRanges
are
unnecessary and may have a performance cost.
However, availability
and visibility operations still need to be managed on the device.
See the description of host access
types for more information.
While memory objects imported from a handle type of
VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
or
VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT
are
inherently mapped to host address space, they are not considered to be host
mapped device memory unless they are explicitly host mapped using
vkMapMemory.
That means flushing or invalidating host caches with respect to host
accesses performed on such memory through the original host pointer
specified at import time is the responsibility of the application and must
be performed with appropriate synchronization primitives provided by the
platform which are outside the scope of Vulkan.
vkFlushMappedMemoryRanges
and vkInvalidateMappedMemoryRanges
,
however, can still be used on such memory objects to synchronize host
accesses performed through the host pointer of the host mapped device memory
range returned by vkMapMemory.
After a successful call to vkMapMemory
or vkMapMemory2KHR
the memory object memory
is considered to be currently host mapped.
Lazily Allocated Memory
If the memory object is allocated from a heap with the
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
VkImage
whose usage flags include
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
.
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.
External Memory Handle Types
Android Hardware Buffer
Android’s NDK defines AHardwareBuffer objects, which represent
device memory that is shareable across processes and that can be accessed
by a variety of media APIs and the hardware used to implement them.
These Android hardware buffer objects may be imported into
VkDeviceMemory objects for access via Vulkan, or exported from Vulkan.
An VkImage or VkBuffer can be bound to the imported or exported
VkDeviceMemory object if it is created with
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
.
The NDK format, usage, and size/dimensions of an AHardwareBuffer
object can be obtained with the AHardwareBuffer_describe
function.
While Android hardware buffers can be imported to or exported from Vulkan
without using that function, valid usage and implementation behavior is
defined in terms of the AHardwareBuffer_Desc
properties it returns.
Android hardware buffer objects are reference-counted using Android NDK
functions outside of the scope of this specification.
A VkDeviceMemory imported from an Android hardware buffer or that can
be exported to an Android hardware buffer must acquire a reference to its
AHardwareBuffer object, and must release this reference when the
device memory is freed.
During the host execution of a Vulkan command that has an Android hardware
buffer as a parameter (including indirect parameters via pNext
chains), the application must not decrement the Android hardware buffer’s
reference count to zero.
Android hardware buffers can be mapped and unmapped for CPU access using the NDK functions. These lock and unlock APIs are considered to acquire and release ownership of the Android hardware buffer, and applications must follow the rules described in External Resource Sharing to transfer ownership between the Vulkan instance and these native APIs.
Android hardware buffers can be shared with external APIs and Vulkan instances on the same device, and also with foreign devices. When transferring ownership of the Android hardware buffer, the external and foreign special queue families described in Queue Family Ownership Transfer are not identical. All APIs which produce or consume Android hardware buffers are considered to use foreign devices, except OpenGL ES contexts and Vulkan logical devices that have matching device and driver UUIDs. Implementations may treat a transfer to or from the foreign queue family as if it were a transfer to or from the external queue family when the Android hardware buffer’s usage only permits it to be used on the same physical device.
Android Hardware Buffer Optimal Usages
Vulkan buffer and image usage flags do not correspond exactly to Android
hardware buffer usage flags.
When allocating Android hardware buffers with non-Vulkan APIs, if any
AHARDWAREBUFFER_USAGE_GPU_*
usage bits are included, by default the
allocator must allocate the memory in such a way that it supports Vulkan
usages and creation flags in the
usage equivalence table
which do not have Android hardware buffer equivalents.
An VkAndroidHardwareBufferUsageANDROID structure can be included in
the pNext
chain of a VkImageFormatProperties2 structure passed
to vkGetPhysicalDeviceImageFormatProperties2 to obtain optimal Android
hardware buffer usage flags for specific Vulkan resource creation
parameters.
Some usage flags returned by these commands are required based on the input
parameters, but additional vendor-specific usage flags
(AHARDWAREBUFFER_USAGE_VENDOR_*
) may also be returned.
Any Android hardware buffer allocated with these vendor-specific usage flags
and imported to Vulkan must only be bound to resources created with
parameters that are a subset of the parameters used to obtain the Android
hardware buffer usage, since the memory may have been allocated in a way
incompatible with other parameters.
If an Android hardware buffer is successfully allocated with additional
non-vendor-specific usage flags in addition to the recommended usage, it
must support being used in the same ways as an Android hardware buffer
allocated with only the recommended usage, and also in ways indicated by the
additional usage.
Android Hardware Buffer External Formats
Android hardware buffers may represent images using implementation-specific formats, layouts, color models, etc., which do not have Vulkan equivalents. Such external formats are commonly used by external image sources such as video decoders or cameras. Vulkan can import Android hardware buffers that have external formats, but since the image contents are in a possibly proprietary representation, images with external formats must have optimal tiling, and their use is restricted. Images with external formats must only be sampled with a sampler that has Y′CBCR conversion enabled.
Images that will be backed by an Android hardware buffer can use an
external format by setting VkImageCreateInfo::format
to
VK_FORMAT_UNDEFINED
and including a VkExternalFormatANDROID
structure in the pNext
chain.
Images can be created with an external format even if the Android hardware
buffer has a format which has an
equivalent Vulkan format
to enable consistent handling of images from sources that might use either
category of format.
However, all images created with an external format are subject to the valid
usage requirements associated with external formats, even if the Android
hardware buffer’s format has a Vulkan equivalent.
The external format of an Android hardware buffer can be obtained by
passing a VkAndroidHardwareBufferFormatPropertiesANDROID structure to
vkGetAndroidHardwareBufferPropertiesANDROID.
Android Hardware Buffer Image Resources
Android hardware buffers have intrinsic width, height, format, and usage
properties, so Vulkan images bound to memory imported from an Android
hardware buffer must use dedicated allocations:
VkMemoryDedicatedRequirements
::requiresDedicatedAllocation
must
be VK_TRUE
for images created with
VkExternalMemoryImageCreateInfo::handleTypes
that includes
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
.
When creating an image that will be bound to an imported Android hardware
buffer, the image creation parameters must be equivalent to the
AHardwareBuffer properties as described by the valid usage of
VkMemoryAllocateInfo.
Similarly, device memory allocated for a dedicated image must not be
exported to an Android hardware buffer until it has been bound to that
image, and the implementation must return an Android hardware buffer with
properties derived from the image:
- The
width
andheight
members ofAHardwareBuffer_Desc
must be the same as thewidth
andheight
members of VkImageCreateInfo::extent
, respectively. - The
layers
member ofAHardwareBuffer_Desc
must be the same as thearrayLayers
member of VkImageCreateInfo. - The
format
member ofAHardwareBuffer_Desc
must be equivalent to VkImageCreateInfo::format
as defined by AHardwareBuffer Format Equivalence. - The
usage
member ofAHardwareBuffer_Desc
must include bits corresponding to bits included in VkImageCreateInfo::usage
and VkImageCreateInfo::flags
where such a correspondence exists according to AHardwareBuffer Usage Equivalence. It may also include additional usage bits, including vendor-specific usages. Presence of vendor usage bits may make the Android hardware buffer only usable in ways indicated by the image creation parameters, even when used outside Vulkan, in a similar way that allocating the Android hardware buffer with usage returned in VkAndroidHardwareBufferUsageANDROID does.
Implementations may support fewer combinations of image creation parameters
for images with Android hardware buffer external handle type than for
non-external images.
Support for a given set of parameters can be determined by passing
VkExternalImageFormatProperties to
vkGetPhysicalDeviceImageFormatProperties2 with handleType
set to
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
.
Any Android hardware buffer successfully allocated outside Vulkan with usage
that includes AHARDWAREBUFFER_USAGE_GPU_*
must be supported when using
equivalent Vulkan image parameters.
If a given choice of image parameters are supported for import, they can
also be used to create an image and memory that will be exported to an
Android hardware buffer.
AHardwareBuffer Format | Vulkan Format |
---|---|
AHardwareBuffer Usage | Vulkan Usage or Creation Flag |
---|---|
None | |
None | |
None | |
None | |
None | |
When using VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
with Android hardware
buffer images, applications should use VkImageFormatListCreateInfo to
inform the implementation which view formats will be used with the image.
For some common sets of format, this allows some implementations to provide
significantly better performance when accessing the image via Vulkan.
Android Hardware Buffer Resources
Android hardware buffers with a format of AHARDWAREBUFFER_FORMAT_BLOB
and usage that includes AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER
can be
used as the backing store for VkBuffer objects.
Such Android hardware buffers have a size in bytes specified by their
width
; height
and layers
are both 1
.
Unlike images, buffer resources backed by Android hardware buffers do not require dedicated allocations.
Exported AHardwareBuffer objects that do not have dedicated images
must have a format of AHARDWAREBUFFER_FORMAT_BLOB
, usage must include
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER
, width
must equal the
device memory allocation size, and height
and layers
must be 1
.
QNX Screen Buffer
The QNX SDP defines _screen_buffer
objects, which represent a buffer
that the QNX Screen graphics subsystem can use directly in its windowing
system APIs.
More specifically, a Screen buffer is an area of memory that stores pixel
data.
It can be attached to Screen windows, streams, or pixmaps.
These QNX Screen buffer objects may be imported into VkDeviceMemory
objects for access via Vulkan.
An VkImage or VkBuffer can be bound to the imported
VkDeviceMemory object if it is created with
VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX
.
struct
_screen_buffer
is strongly typed, so naming the handle type
is redundant.
The internal layout and therefore size of a struct
_screen_buffer
image may depend on native usage flags that do not have corresponding Vulkan
counterparts.
QNX Screen Buffer Validity
The design of Screen in the QNX SDP makes it difficult to determine the validity of objects from outside of Screen. Therefore, applications must ensure that QNX Screen buffer objects provided used in various Vulkan interfaces are ones created explicitly with QNX Screen APIs. See QNX SDP documentation for more information.
A VkDeviceMemory imported from a QNX Screen buffer has no way to
acquire a reference to its _screen_buffer
object.
Therefore, during the host execution of a Vulkan command that has a QNX
Screen buffer as a parameter (including indirect parameters via pNext
chains), the application must ensure that the QNX Screen buffer resource
remains valid.
Generally, for a _screen_buffer
object to be valid for use within a
Vulkan implementation, the buffer object should have a
_screen_buffer
::SCREEN_PROPERTY_USAGE
that includes at least one
of: SCREEN_USAGE_VULKAN
, SCREEN_USAGE_OPENGL_ES2
,
SCREEN_USAGE_OPENGL_ES3
, or SCREEN_USAGE_NATIVE
.
The exact Screen-native usage flags required depends on the Vulkan
implementation, and QNX Screen itself will not necessarily enforce these
requirements.
Note that Screen-native usage flags are in no way related to usage flags in
the Vulkan specification.
QNX Screen Buffer External Formats
QNX Screen buffers may represent images using implementation-specific formats, layouts, color models, etc., which do not have Vulkan equivalents. Such external formats are commonly used by external image sources such as video decoders or cameras. Vulkan can import QNX Screen buffers that have external formats, but since the image contents are in an undiscoverable and possibly proprietary representation, images with external formats must only be used as sampled images, must only be sampled with a sampler that has Y′CBCR conversion enabled, and must have optimal tiling.
Images that will be backed by a QNX Screen buffer can use an external
format by setting VkImageCreateInfo::format
to
VK_FORMAT_UNDEFINED
and including a VkExternalFormatQNX
structure in the pNext
chain.
Images can be created with an external format even if the QNX Screen buffer
has a format which has an
equivalent Vulkan format to
enable consistent handling of images from sources that might use either
category of format.
The external format of a QNX Screen buffer can be obtained by passing a
VkScreenBufferFormatPropertiesQNX structure to
vkGetScreenBufferPropertiesQNX.
QNX Screen Buffer Image Resources
QNX Screen buffers have intrinsic width, height, format, and usage
properties, so Vulkan images bound to memory imported from a QNX Screen
buffer must use dedicated allocations:
VkMemoryDedicatedRequirements
::requiresDedicatedAllocation
must
be VK_TRUE
for images created with
VkExternalMemoryImageCreateInfo::handleTypes
that includes
VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX
.
When creating an image that will be bound to an imported QNX Screen buffer,
the image creation parameters must be equivalent to the _screen_buffer
properties as described by the valid usage of VkMemoryAllocateInfo.
QNX Screen Format | Vulkan Format |
---|---|