// Copyright 2015-2022 The Khronos Group Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

[[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.

[NOTE]
.Note
====
This memory may: be used to store the implementation's representation and
state of Vulkan objects.
====

[[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.

[open,refpage='VkAllocationCallbacks',desc='Structure containing callback function pointers for memory allocation',type='structs']
--
Allocators are provided by the application as a pointer to a
sname:VkAllocationCallbacks structure:

include::{generated}/api/structs/VkAllocationCallbacks.adoc[]

  * 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 tlink:PFN_vkAllocationFunction pointer to an
    application-defined memory allocation function.
  * pname:pfnReallocation is a tlink:PFN_vkReallocationFunction pointer to
    an application-defined memory reallocation function.
  * pname:pfnFree is a tlink:PFN_vkFreeFunction pointer to an
    application-defined memory free function.
  * pname:pfnInternalAllocation is a
    tlink:PFN_vkInternalAllocationNotification pointer to an
    application-defined function that is called by the implementation when
    the implementation makes internal allocations.
  * pname:pfnInternalFree is a tlink:PFN_vkInternalFreeNotification pointer
    to an application-defined function that is called by the implementation
    when the implementation frees internal allocations.

.Valid Usage
****
  * [[VUID-VkAllocationCallbacks-pfnAllocation-00632]]
    pname:pfnAllocation must: be a valid pointer to a valid user-defined
    tlink:PFN_vkAllocationFunction
  * [[VUID-VkAllocationCallbacks-pfnReallocation-00633]]
    pname:pfnReallocation must: be a valid pointer to a valid user-defined
    tlink:PFN_vkReallocationFunction
  * [[VUID-VkAllocationCallbacks-pfnFree-00634]]
    pname:pfnFree must: be a valid pointer to a valid user-defined
    tlink:PFN_vkFreeFunction
  * [[VUID-VkAllocationCallbacks-pfnInternalAllocation-00635]]
    If either of pname:pfnInternalAllocation or pname:pfnInternalFree is not
    `NULL`, both must: be valid callbacks
****

include::{generated}/validity/structs/VkAllocationCallbacks.adoc[]
--

[open,refpage='PFN_vkAllocationFunction',desc='Application-defined memory allocation function',type='funcpointers',xrefs='VkAllocationCallbacks']
--
The type of pname:pfnAllocation is:

include::{generated}/api/funcpointers/PFN_vkAllocationFunction.adoc[]

  * 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
slink: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 runtime 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.
--

[open,refpage='PFN_vkReallocationFunction',desc='Application-defined memory reallocation function',type='funcpointers',xrefs='VkAllocationCallbacks']
--
The type of pname:pfnReallocation is:

include::{generated}/api/funcpointers/PFN_vkReallocationFunction.adoc[]

  * 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 a compatible
    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>>.
--

[open,refpage='PFN_vkFreeFunction',desc='Application-defined memory free function',type='funcpointers',xrefs='VkAllocationCallbacks']
--
The type of pname:pfnFree is:

include::{generated}/api/funcpointers/PFN_vkFreeFunction.adoc[]

  * 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.
--

[open,refpage='PFN_vkInternalAllocationNotification',desc='Application-defined memory allocation notification function',type='funcpointers',xrefs='VkAllocationCallbacks']
--
The type of pname:pfnInternalAllocation is:

include::{generated}/api/funcpointers/PFN_vkInternalAllocationNotification.adoc[]

  * 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 a elink:VkInternalAllocationType value
    specifying 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.
--

[open,refpage='PFN_vkInternalFreeNotification',desc='Application-defined memory free notification function',type='funcpointers',xrefs='VkAllocationCallbacks']
--
The type of pname:pfnInternalFree is:

include::{generated}/api/funcpointers/PFN_vkInternalFreeNotification.adoc[]

  * 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 a elink:VkInternalAllocationType value
    specifying 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>>.
--

[open,refpage='VkSystemAllocationScope',desc='Allocation scope',type='enums',xrefs='VkAllocationCallbacks']
--
[[memory-host-allocation-scope]]
Each allocation has an _allocation scope_ defining its lifetime and which
object it is associated with.
Possible values passed to the pname:allocationScope parameter of the
callback functions specified by slink:VkAllocationCallbacks, indicating the
allocation scope, are:

include::{generated}/api/enums/VkSystemAllocationScope.adoc[]

  * ename:VK_SYSTEM_ALLOCATION_SCOPE_COMMAND specifies that the allocation
    is scoped to the duration of the Vulkan command.
  * ename:VK_SYSTEM_ALLOCATION_SCOPE_OBJECT specifies that the allocation is
    scoped to the lifetime of the Vulkan object that is being created or
    used.
  * ename:VK_SYSTEM_ALLOCATION_SCOPE_CACHE specifies that the allocation is
    scoped to the lifetime of a sname:VkPipelineCache
ifdef::VK_EXT_validation_cache[]
    or sname:VkValidationCacheEXT
endif::VK_EXT_validation_cache[]
    object.
  * ename:VK_SYSTEM_ALLOCATION_SCOPE_DEVICE specifies that the allocation is
    scoped to the lifetime of the Vulkan device.
  * ename:VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE specifies that 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 a
ifdef::VK_EXT_validation_cache[]
    sname:VkValidationCacheEXT or
endif::VK_EXT_validation_cache[]
    sname:VkPipelineCache object, the allocator will use the
    ename:VK_SYSTEM_ALLOCATION_SCOPE_CACHE allocation scope.
    The most specific allocator available is used (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.
--

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.

[open,refpage='VkInternalAllocationType',desc='Allocation type',type='enums',xrefs='PFN_vkInternalAllocationNotification PFN_vkInternalFreeNotification']
--
The pname:allocationType parameter to the pname:pfnInternalAllocation and
pname:pfnInternalFree functions may: be one of the following values:

include::{generated}/api/enums/VkInternalAllocationType.adoc[]

  * ename:VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE specifies that the
    allocation is intended for execution by the host.
--

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
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 a
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:pipelineCache
  ** fname:vkCreateComputePipelines for pname:pipelineCache
ifdef::VK_EXT_validation_cache[]
  * Allocations scoped to a sname:VkValidationCacheEXT may: only be
    allocated from:
  ** fname:vkCreateValidationCacheEXT
  ** fname:vkMergeValidationCachesEXT for pname:dstCache
  ** fname:vkCreateShaderModule for pname:validationCache in
     slink:VkShaderModuleValidationCacheCreateInfoEXT
endif::VK_EXT_validation_cache[]
  * 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, or pname:pfnReallocation with zero pname:size, 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.
ifdef::VK_EXT_validation_cache[]
  * Allocations scoped to a sname:VkValidationCacheEXT may: be freed from
    fname:vkDestroyValidationCacheEXT.
endif::VK_EXT_validation_cache[]
  * 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 the image or buffer objects, which can: be natively used by the
device.


[[memory-device-properties]]
=== Device Memory Properties

Memory properties of a physical device describe the memory heaps and memory
types available.

[open,refpage='vkGetPhysicalDeviceMemoryProperties',desc='Reports memory information for the specified physical device',type='protos']
--
To query memory properties, call:

include::{generated}/api/protos/vkGetPhysicalDeviceMemoryProperties.adoc[]

  * pname:physicalDevice is the handle to the device to query.
  * pname:pMemoryProperties is a pointer to a
    slink:VkPhysicalDeviceMemoryProperties structure in which the properties
    are returned.

include::{generated}/validity/protos/vkGetPhysicalDeviceMemoryProperties.adoc[]
--

[open,refpage='VkPhysicalDeviceMemoryProperties',desc='Structure specifying physical device memory properties',type='structs']
--
The sname:VkPhysicalDeviceMemoryProperties structure is defined as:

include::{generated}/api/structs/VkPhysicalDeviceMemoryProperties.adoc[]

  * pname:memoryTypeCount is the number of valid elements in the
    pname:memoryTypes array.
  * pname:memoryTypes is an array of ename:VK_MAX_MEMORY_TYPES
    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 ename:VK_MAX_MEMORY_HEAPS
    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
slink: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 slink: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.

[[memory-device-bitmask-list]]
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
ifdef::VK_VERSION_1_1[]
  * ename:VK_MEMORY_PROPERTY_PROTECTED_BIT
  * ename:VK_MEMORY_PROPERTY_PROTECTED_BIT |
    ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
endif::VK_VERSION_1_1[]
ifdef::VK_AMD_device_coherent_memory[]
  * ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | +
    ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | +
    ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD
  * 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_COHERENT_BIT_AMD
  * ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | +
    ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD
  * 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_COHERENT_BIT_AMD
  * 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_COHERENT_BIT_AMD
  * ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | +
    ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | +
    ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD | +
    ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
  * 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_COHERENT_BIT_AMD | +
    ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
  * ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | +
    ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD | +
    ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
  * 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_COHERENT_BIT_AMD | +
    ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
  * 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_COHERENT_BIT_AMD | +
    ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD
endif::VK_AMD_device_coherent_memory[]
ifdef::VK_NV_external_memory_rdma[]
  * ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | +
    ename:VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV
endif::VK_NV_external_memory_rdma[]

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.
ifdef::VK_AMD_device_coherent_memory[]
If the <<features-deviceCoherentMemory, pname:deviceCoherentMemory>> feature
is enabled, there must: be at least one memory type with the
ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD bit set in its
pname:propertyFlags.
endif::VK_AMD_device_coherent_memory[]

For each pair of elements *X* and *Y* returned in pname:memoryTypes, *X*
must: be placed at a lower index position than *Y* if:

  * the set of bit flags returned in the pname:propertyFlags member of *X*
    is a strict subset of the set of bit flags returned in the
    pname:propertyFlags member of *Y*; or
  * the pname:propertyFlags members of *X* and *Y* are equal, and *X*
    belongs to a memory heap with greater performance (as determined in an
    implementation-specific manner)
ifdef::VK_AMD_device_coherent_memory[]
    ; or
  * the pname:propertyFlags members of *Y* includes
    ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD or
    ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD and *X* does not
endif::VK_AMD_device_coherent_memory[]

[NOTE]
.Note
====
There is no ordering requirement between *X* and *Y* elements for the case
their pname:propertyFlags members are not in a subset relation.
That potentially allows more than one possible way to order the same set of
memory types.
Notice that the <<memory-device-bitmask-list,list of all allowed memory
property flag combinations>> is written in a valid order.
But if instead ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT was before
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, the list would still be in a
valid order.
ifdef::VK_AMD_device_coherent_memory[]

There may be a performance penalty for using device coherent or uncached
device memory types, and using these accidentally is undesirable.
In order to avoid this, memory types with these properties always appear at
the end of the list; but are subject to the same rules otherwise.
endif::VK_AMD_device_coherent_memory[]
====

This ordering requirement enables applications to use a simple search loop
to select the desired memory type along the lines of:

[source,c++]
~~~~
// Find a memory in `memoryTypeBitsRequirement` that includes all of `requiredProperties`
int32_t findProperties(const VkPhysicalDeviceMemoryProperties* pMemoryProperties,
                       uint32_t memoryTypeBitsRequirement,
                       VkMemoryPropertyFlags requiredProperties) {
    const uint32_t memoryCount = pMemoryProperties->memoryTypeCount;
    for (uint32_t memoryIndex = 0; memoryIndex < memoryCount; ++memoryIndex) {
        const uint32_t memoryTypeBits = (1 << memoryIndex);
        const bool isRequiredMemoryType = memoryTypeBitsRequirement & memoryTypeBits;

        const VkMemoryPropertyFlags properties =
            pMemoryProperties->memoryTypes[memoryIndex].propertyFlags;
        const bool hasRequiredProperties =
            (properties & requiredProperties) == requiredProperties;

        if (isRequiredMemoryType && hasRequiredProperties)
            return static_cast<int32_t>(memoryIndex);
    }

    // failed to find memory type
    return -1;
}

// Try to find an optimal memory type, or if it does not exist try fallback memory type
// `device` is the VkDevice
// `image` is the VkImage that requires memory to be bound
// `memoryProperties` properties as returned by vkGetPhysicalDeviceMemoryProperties
// `requiredProperties` are the property flags that must be present
// `optimalProperties` are the property flags that are preferred by the application
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(device, image, &memoryRequirements);
int32_t memoryType =
    findProperties(&memoryProperties, memoryRequirements.memoryTypeBits, optimalProperties);
if (memoryType == -1) // not found; try fallback properties
    memoryType =
        findProperties(&memoryProperties, memoryRequirements.memoryTypeBits, requiredProperties);
~~~~

include::{generated}/validity/structs/VkPhysicalDeviceMemoryProperties.adoc[]
--

[open,refpage='VK_MAX_MEMORY_TYPES',desc='Length of an array of memory types',type='consts']
--
ename:VK_MAX_MEMORY_TYPES is the length of an array of slink:VkMemoryType
structures describing memory types, as returned in
slink:VkPhysicalDeviceMemoryProperties::pname:memoryTypes.

include::{generated}/api/enums/VK_MAX_MEMORY_TYPES.adoc[]
--

[open,refpage='VK_MAX_MEMORY_HEAPS',desc='Length of an array of memory heaps',type='consts']
--
ename:VK_MAX_MEMORY_HEAPS is the length of an array of slink:VkMemoryHeap
structures describing memory heaps, as returned in
slink:VkPhysicalDeviceMemoryProperties::pname:memoryHeaps.

include::{generated}/api/enums/VK_MAX_MEMORY_HEAPS.adoc[]
--

ifdef::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
[open,refpage='vkGetPhysicalDeviceMemoryProperties2',desc='Reports memory information for the specified physical device',type='protos']
--
To query memory properties, call:

ifdef::VK_VERSION_1_1[]
include::{generated}/api/protos/vkGetPhysicalDeviceMemoryProperties2.adoc[]
endif::VK_VERSION_1_1[]

ifdef::VK_VERSION_1_1+VK_KHR_get_physical_device_properties2[or the equivalent command]

ifdef::VK_KHR_get_physical_device_properties2[]
include::{generated}/api/protos/vkGetPhysicalDeviceMemoryProperties2KHR.adoc[]
endif::VK_KHR_get_physical_device_properties2[]

  * pname:physicalDevice is the handle to the device to query.
  * pname:pMemoryProperties is a pointer to a
    slink:VkPhysicalDeviceMemoryProperties2 structure in which the
    properties are returned.

fname:vkGetPhysicalDeviceMemoryProperties2 behaves similarly to
flink:vkGetPhysicalDeviceMemoryProperties, with the ability to return
extended information in a pname:pNext chain of output structures.

include::{generated}/validity/protos/vkGetPhysicalDeviceMemoryProperties2.adoc[]
--

[open,refpage='VkPhysicalDeviceMemoryProperties2',desc='Structure specifying physical device memory properties',type='structs']
--
The sname:VkPhysicalDeviceMemoryProperties2 structure is defined as:

include::{generated}/api/structs/VkPhysicalDeviceMemoryProperties2.adoc[]

ifdef::VK_KHR_get_physical_device_properties2[]
or the equivalent

include::{generated}/api/structs/VkPhysicalDeviceMemoryProperties2KHR.adoc[]
endif::VK_KHR_get_physical_device_properties2[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memoryProperties is a slink:VkPhysicalDeviceMemoryProperties
    structure which is populated with the same values as in
    flink:vkGetPhysicalDeviceMemoryProperties.

include::{generated}/validity/structs/VkPhysicalDeviceMemoryProperties2.adoc[]
--
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]

[open,refpage='VkMemoryHeap',desc='Structure specifying a memory heap',type='structs']
--
The sname:VkMemoryHeap structure is defined as:

include::{generated}/api/structs/VkMemoryHeap.adoc[]

  * pname:size is the total memory size in bytes in the heap.
  * pname:flags is a bitmask of elink:VkMemoryHeapFlagBits specifying
    attribute flags for the heap.

include::{generated}/validity/structs/VkMemoryHeap.adoc[]
--

[open,refpage='VkMemoryHeapFlagBits',desc='Bitmask specifying attribute flags for a heap',type='enums']
--
Bits which may: be set in slink:VkMemoryHeap::pname:flags, indicating
attribute flags for the heap, are:

include::{generated}/api/enums/VkMemoryHeapFlagBits.adoc[]

  * ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT specifies that 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.
ifdef::VK_VERSION_1_1,VK_KHR_device_group_creation[]
  * ename:VK_MEMORY_HEAP_MULTI_INSTANCE_BIT specifies that in a logical
    device representing more than one physical device, there is a
    per-physical device instance of the heap memory.
    By default, an allocation from such a heap will be replicated to each
    physical device's instance of the heap.
endif::VK_VERSION_1_1,VK_KHR_device_group_creation[]
--

[open,refpage='VkMemoryHeapFlags',desc='Bitmask of VkMemoryHeapFlagBits',type='flags']
--
include::{generated}/api/flags/VkMemoryHeapFlags.adoc[]

tname:VkMemoryHeapFlags is a bitmask type for setting a mask of zero or more
elink:VkMemoryHeapFlagBits.
--

[open,refpage='VkMemoryType',desc='Structure specifying memory type',type='structs']
--
The sname:VkMemoryType structure is defined as:

include::{generated}/api/structs/VkMemoryType.adoc[]

  * pname:heapIndex describes which memory heap this memory type corresponds
    to, and must: be less than pname:memoryHeapCount from the
    slink:VkPhysicalDeviceMemoryProperties structure.
  * pname:propertyFlags is a bitmask of elink:VkMemoryPropertyFlagBits of
    properties for this memory type.

include::{generated}/validity/structs/VkMemoryType.adoc[]
--

[open,refpage='VkMemoryPropertyFlagBits',desc='Bitmask specifying properties for a memory type',type='enums']
--
Bits which may: be set in slink:VkMemoryType::pname:propertyFlags,
indicating properties of a memory type, are:

include::{generated}/api/enums/VkMemoryPropertyFlagBits.adoc[]

  * ename:VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT bit specifies that memory
    allocated with this type is the most efficient for device access.
    This property will be set if and only if the memory type belongs to a
    heap with the ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT set.
  * ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit specifies that memory
    allocated with this type can: be mapped for host access using
    flink:vkMapMemory.
  * ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host
    cache management commands flink:vkFlushMappedMemoryRanges and
    flink:vkInvalidateMappedMemoryRanges are not needed to flush host writes
    to the device or make device writes visible to the host, respectively.
  * ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT bit specifies that 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.
  * ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT bit specifies that 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>>.
ifdef::VK_VERSION_1_1[]
  * ename:VK_MEMORY_PROPERTY_PROTECTED_BIT bit specifies that the memory
    type only allows device access to the memory, and allows protected queue
    operations to access the memory.
    Memory types must: not have ename:VK_MEMORY_PROPERTY_PROTECTED_BIT set
    and any of ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set, or
    ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set, or
    ename:VK_MEMORY_PROPERTY_HOST_CACHED_BIT set.
endif::VK_VERSION_1_1[]
ifdef::VK_AMD_device_coherent_memory[]
  * ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD bit specifies that
    device accesses to allocations of this memory type are automatically
    made available and visible.
  * ename:VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD bit specifies that
    memory allocated with this type is not cached on the device.
    Uncached device memory is always device coherent.
endif::VK_AMD_device_coherent_memory[]
ifdef::VK_NV_external_memory_rdma[]
  * ename:VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV bit specifies that external
    devices can access this memory directly.
endif::VK_NV_external_memory_rdma[]

ifdef::VK_AMD_device_coherent_memory[]
For any memory allocated with both the
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT and the
ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD, host or device accesses
also perform automatic memory domain transfer operations, such that writes
are always automatically available and visible to both host and device
memory domains.

[NOTE]
.Note
====
Device coherence is a useful property for certain debugging use cases (e.g.
crash analysis, where performing separate coherence actions could mean
values are not reported correctly).
However, device coherent accesses may be slower than equivalent accesses
without device coherence, particularly if they are also device uncached.
For device uncached memory in particular, repeated accesses to the same or
neighbouring memory locations over a short time period (e.g. within a frame)
may be slower than it would be for the equivalent cached memory type.
As such, it is generally inadvisable to use device coherent or device
uncached memory except when really needed.
====
endif::VK_AMD_device_coherent_memory[]
--

[open,refpage='VkMemoryPropertyFlags',desc='Bitmask of VkMemoryPropertyFlagBits',type='flags']
--
include::{generated}/api/flags/VkMemoryPropertyFlags.adoc[]

tname:VkMemoryPropertyFlags is a bitmask type for setting a mask of zero or
more elink:VkMemoryPropertyFlagBits.
--

ifdef::VK_EXT_memory_budget[]
[open,refpage='VkPhysicalDeviceMemoryBudgetPropertiesEXT',desc='Structure specifying physical device memory budget and usage',type='structs']
--
If the sname:VkPhysicalDeviceMemoryBudgetPropertiesEXT structure is included
in the pname:pNext chain of slink:VkPhysicalDeviceMemoryProperties2, it is
filled with the current memory budgets and usages.

The sname:VkPhysicalDeviceMemoryBudgetPropertiesEXT structure is defined as:

include::{generated}/api/structs/VkPhysicalDeviceMemoryBudgetPropertiesEXT.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:heapBudget is an array of ename:VK_MAX_MEMORY_HEAPS
    basetype:VkDeviceSize values in which memory budgets are returned, with
    one element for each memory heap.
    A heap's budget is a rough estimate of how much memory the process can:
    allocate from that heap before allocations may: fail or cause
    performance degradation.
    The budget includes any currently allocated device memory.
  * pname:heapUsage is an array of ename:VK_MAX_MEMORY_HEAPS
    basetype:VkDeviceSize values in which memory usages are returned, with
    one element for each memory heap.
    A heap's usage is an estimate of how much memory the process is
    currently using in that heap.

The values returned in this structure are not invariant.
The pname:heapBudget and pname:heapUsage values must: be zero for array
elements greater than or equal to
slink:VkPhysicalDeviceMemoryProperties::pname:memoryHeapCount.
The pname:heapBudget value must: be non-zero for array elements less than
slink:VkPhysicalDeviceMemoryProperties::pname:memoryHeapCount.
The pname:heapBudget value must: be less than or equal to
slink:VkMemoryHeap::pname:size for each heap.

include::{generated}/validity/structs/VkPhysicalDeviceMemoryBudgetPropertiesEXT.adoc[]
--
endif::VK_EXT_memory_budget[]


[[memory-device-objects]]
=== Device Memory Objects

[open,refpage='VkDeviceMemory',desc='Opaque handle to a device memory object',type='handles']
--
A Vulkan device operates on data in device memory via memory objects that
are represented in the API by a sname:VkDeviceMemory handle:

include::{generated}/api/handles/VkDeviceMemory.adoc[]
--


=== Device Memory Allocation

[open,refpage='vkAllocateMemory',desc='Allocate device memory',type='protos']
--
To allocate memory objects, call:

include::{generated}/api/protos/vkAllocateMemory.adoc[]

  * pname:device is the logical device that owns the memory.
  * pname:pAllocateInfo is a pointer to a slink:VkMemoryAllocateInfo
    structure describing parameters of the allocation.
    A successfully 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 slink:VkDeviceMemory handle in which
    information about the allocated memory is returned.

Allocations returned by fname:vkAllocateMemory are guaranteed to meet any
alignment requirement of 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.

ifndef::VK_VERSION_1_1[]
When memory is allocated, its contents are undefined:.
endif::VK_VERSION_1_1[]
ifdef::VK_VERSION_1_1[]
When memory is allocated, its contents are undefined: with the following
constraint:

  * The contents of unprotected memory must: not be a function of the
    contents of data protected memory objects, even if those memory objects
    were previously freed.

[NOTE]
.Note
====
The contents of memory allocated by one application should: not be a
function of data from protected memory objects of another application, even
if those memory objects were previously freed.
====
endif::VK_VERSION_1_1[]

The maximum number of valid memory allocations that can: exist
simultaneously within a slink:VkDevice may: be restricted by implementation-
or platform-dependent limits.
The <<limits-maxMemoryAllocationCount, pname:maxMemoryAllocationCount>>
feature describes the number of allocations that can: exist simultaneously
before encountering these internal limits.

[NOTE]
.Note
====
For historical reasons, if pname:maxMemoryAllocationCount is exceeded, some
implementations may return ename:VK_ERROR_TOO_MANY_OBJECTS.
Exceeding this limit will result in undefined: behavior, and an application
should not rely on the use of the returned error code in order to identify
when the limit is reached.
====

[NOTE]
.Note
====
Many protected memory implementations involve complex hardware and system
software support, and often have additional and much lower limits on the
number of simultaneous protected memory allocations (from memory types with
the ename:VK_MEMORY_PROPERTY_PROTECTED_BIT property) than for non-protected
memory allocations.
These limits can be system-wide, and depend on a variety of factors outside
of the Vulkan implementation, so they cannot be queried in Vulkan.
Applications should: use as few allocations as possible from such memory
types by suballocating aggressively, and be prepared for allocation failure
even when there is apparently plenty of capacity remaining in the memory
heap.
As a guideline, the Vulkan conformance test suite requires that at least 80
minimum-size allocations can exist concurrently when no other uses of
protected memory are active in the system.
====

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 must: be returned.
ifdef::VK_KHR_maintenance3[]
This limit is advertised in
slink:VkPhysicalDeviceMaintenance3Properties::pname:maxMemoryAllocationSize.
endif::VK_KHR_maintenance3[]

ifdef::VK_AMD_memory_overallocation_behavior[]

The cumulative memory size allocated to a heap can: be limited by the size
of the specified heap.
In such cases, allocated memory is tracked on a per-device and per-heap
basis.
Some platforms allow overallocation into other heaps.
The overallocation behavior can: be specified through the
`apiext:VK_AMD_memory_overallocation_behavior` extension.

endif::VK_AMD_memory_overallocation_behavior[]

ifdef::VK_EXT_pageable_device_local_memory[]

If the
slink:VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT::pname:pageableDeviceLocalMemory
feature is enabled, memory allocations made from a heap that includes
ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT in slink:VkMemoryHeap::pname:flags
may: be transparently moved to host-local memory allowing multiple
applications to share device-local memory.
If there is no space left in device-local memory when this new allocation is
made, other allocations may: be moved out transparently to make room.
The operating system will determine which allocations to move to
device-local memory or host-local memory based on platform-specific
criteria.
To help the operating system make good choices, the application should: set
the appropriate memory priority with slink:VkMemoryPriorityAllocateInfoEXT
and adjust it as necessary with flink:vkSetDeviceMemoryPriorityEXT.
Higher priority allocations will moved to device-local memory first.

Memory allocations made on heaps without the
ename:VK_MEMORY_HEAP_DEVICE_LOCAL_BIT property will not be transparently
promoted to device-local memory by the operating system.

endif::VK_EXT_pageable_device_local_memory[]

.Valid Usage
****
  * [[VUID-vkAllocateMemory-pAllocateInfo-01713]]
    pname:pAllocateInfo->allocationSize must: be less than or equal to
    slink:VkPhysicalDeviceMemoryProperties::pname:memoryHeaps[`memindex`].pname:size
    where `memindex` =
    slink:VkPhysicalDeviceMemoryProperties::pname:memoryTypes[pname:pAllocateInfo->memoryTypeIndex].pname:heapIndex
    as returned by flink:vkGetPhysicalDeviceMemoryProperties for the
    slink:VkPhysicalDevice that pname:device was created from
  * [[VUID-vkAllocateMemory-pAllocateInfo-01714]]
    pname:pAllocateInfo->memoryTypeIndex must: be less than
    slink:VkPhysicalDeviceMemoryProperties::pname:memoryTypeCount as
    returned by flink:vkGetPhysicalDeviceMemoryProperties for the
    slink:VkPhysicalDevice that pname:device was created from
ifdef::VK_AMD_device_coherent_memory[]
  * [[VUID-vkAllocateMemory-deviceCoherentMemory-02790]]
    If the <<features-deviceCoherentMemory, pname:deviceCoherentMemory>>
    feature is not enabled, pname:pAllocateInfo->memoryTypeIndex must: not
    identify a memory type supporting
    ename:VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD
endif::VK_AMD_device_coherent_memory[]
  * [[VUID-vkAllocateMemory-maxMemoryAllocationCount-04101]]
    There must: be less than
    sname:VkPhysicalDeviceLimits::pname:maxMemoryAllocationCount device
    memory allocations currently allocated on the device
****

include::{generated}/validity/protos/vkAllocateMemory.adoc[]
--

[open,refpage='VkMemoryAllocateInfo',desc='Structure containing parameters of a memory allocation',type='structs']
--
The sname:VkMemoryAllocateInfo structure is defined as:

include::{generated}/api/structs/VkMemoryAllocateInfo.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:allocationSize is the size of the allocation in bytes.
  * pname:memoryTypeIndex is an index identifying a memory type from the
    pname:memoryTypes array of the slink:VkPhysicalDeviceMemoryProperties
    structure.

The internal data of an allocated device memory object must: include a
reference to implementation-specific resources, referred to as the memory
object's _payload_.
ifdef::VK_KHR_external_memory_win32,VK_KHR_external_memory_fd,VK_EXT_external_memory_host,VK_ANDROID_external_memory_android_hardware_buffer[]
Applications can: also import and export that internal data to and from
device memory objects to share data between Vulkan instances and other
compatible APIs.
A sname:VkMemoryAllocateInfo structure defines a memory import operation if
its pname:pNext chain includes one of the following structures:

[[memory-import-operation]]
ifdef::VK_KHR_external_memory_win32[]
  * slink:VkImportMemoryWin32HandleInfoKHR with a non-zero pname:handleType
    value
endif::VK_KHR_external_memory_win32[]
ifdef::VK_KHR_external_memory_fd[]
  * slink:VkImportMemoryFdInfoKHR with a non-zero pname:handleType value
endif::VK_KHR_external_memory_fd[]
ifdef::VK_EXT_external_memory_host[]
  * slink:VkImportMemoryHostPointerInfoEXT with a non-zero pname:handleType
    value
endif::VK_EXT_external_memory_host[]
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * slink:VkImportAndroidHardwareBufferInfoANDROID with a non-`NULL`
    pname:buffer value
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
ifdef::VK_FUCHSIA_external_memory[]
  * slink:VkImportMemoryZirconHandleInfoFUCHSIA with a non-zero
    pname:handleType value
endif::VK_FUCHSIA_external_memory[]
ifdef::VK_FUCHSIA_buffer_collection[]
  * slink:VkImportMemoryBufferCollectionFUCHSIA
endif::VK_FUCHSIA_buffer_collection[]

ifdef::VK_KHR_external_memory_win32[]
If the parameters define an import operation and the external handle type is
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, or
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT,
pname:allocationSize is ignored.
The implementation must: query the size of these allocations from the OS.
endif::VK_KHR_external_memory_win32[]

Whether device memory objects constructed via a memory import operation hold
a reference to their payload depends on the properties of the handle type
used to perform the import, as defined below for each valid handle type.
Importing memory must: not modify the content of the memory.
Implementations must: ensure that importing memory does not enable the
importing Vulkan instance to access any memory or resources in other Vulkan
instances other than that corresponding to the memory object imported.
Implementations must: also ensure accessing imported memory which has not
been initialized does not allow the importing Vulkan instance to obtain data
from the exporting Vulkan instance or vice-versa.

[NOTE]
.Note
====
How exported and imported memory is isolated is left to the implementation,
but applications should be aware that such isolation may: prevent
implementations from placing multiple exportable memory objects in the same
physical or virtual page.
Hence, applications should: avoid creating many small external memory
objects whenever possible.
====

Importing memory must: not increase overall heap usage within a system.
ifdef::VK_VERSION_1_1,VK_KHR_maintenance3,VK_EXT_memory_budget[]
However, it must: affect the following per-process values:

ifdef::VK_VERSION_1_1,VK_KHR_maintenance3[]
  * slink:VkPhysicalDeviceMaintenance3Properties::pname:maxMemoryAllocationCount
endif::VK_VERSION_1_1,VK_KHR_maintenance3[]
ifdef::VK_EXT_memory_budget[]
  * slink:VkPhysicalDeviceMemoryBudgetPropertiesEXT::pname:heapUsage
endif::VK_EXT_memory_budget[]
endif::VK_VERSION_1_1,VK_KHR_maintenance3,VK_EXT_memory_budget[]

When performing a memory import operation, it is the responsibility of the
application to ensure the external handles and their associated payloads
meet all valid usage requirements.
However, implementations must: perform sufficient validation of external
handles and payloads to ensure that the operation results in a valid memory
object which will not cause program termination, device loss, queue stalls,
or corruption of other resources when used as allowed according to its
allocation parameters.
If the external handle provided does not meet these requirements, the
implementation must: fail the memory import operation with the error code
ename:VK_ERROR_INVALID_EXTERNAL_HANDLE.
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
If the parameters define an export operation and the external handle type is
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
implementations should: not strictly follow pname:memoryTypeIndex.
Instead, they should: modify the allocation internally to use the required
memory type for the application's given usage.
This is because for an export operation, there is currently no way for the
client to know the memory type index before allocating.
endif::VK_ANDROID_external_memory_android_hardware_buffer[]

endif::VK_KHR_external_memory_win32,VK_KHR_external_memory_fd,VK_EXT_external_memory_host,VK_ANDROID_external_memory_android_hardware_buffer[]

.Valid Usage
****
  * [[VUID-VkMemoryAllocateInfo-None-06657]]
    The parameters must: not define more than one
    <<memory-import-operation,import operation>>
ifndef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryAllocateInfo-allocationSize-00638]]
    pname:allocationSize must: be greater than `0`
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
ifdef::VK_FUCHSIA_buffer_collection[]
  * [[VUID-VkMemoryAllocateInfo-buffer-06380]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA, and
    slink:VkMemoryDedicatedAllocateInfo::pname:buffer is present and
    non-NULL, slink:VkImportMemoryBufferCollectionFUCHSIA::pname:collection
    and slink:VkImportMemoryBufferCollectionFUCHSIA::pname:index must match
    slink:VkBufferCollectionBufferCreateInfoFUCHSIA::pname:collection and
    slink:VkBufferCollectionBufferCreateInfoFUCHSIA::pname:index,
    respectively, of the slink:VkBufferCollectionBufferCreateInfoFUCHSIA
    structure used to create the
    slink:VkMemoryDedicatedAllocateInfo::pname:buffer
  * [[VUID-VkMemoryAllocateInfo-image-06381]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA, and
    slink:VkMemoryDedicatedAllocateInfo::pname:image is present and
    non-NULL, slink:VkImportMemoryBufferCollectionFUCHSIA::pname:collection
    and slink:VkImportMemoryBufferCollectionFUCHSIA::pname:index must match
    slink:VkBufferCollectionImageCreateInfoFUCHSIA::pname:collection and
    slink:VkBufferCollectionImageCreateInfoFUCHSIA::pname:index,
    respectively, of the slink:VkBufferCollectionImageCreateInfoFUCHSIA
    structure used to create the
    slink:VkMemoryDedicatedAllocateInfo::pname:image
  * [[VUID-VkMemoryAllocateInfo-allocationSize-06382]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA, pname:allocationSize must: match
    slink:VkMemoryRequirements::pname:size value retrieved by
    flink:vkGetImageMemoryRequirements or
    flink:vkGetBufferMemoryRequirements for image-based or buffer-based
    collections respectively
  * [[VUID-VkMemoryAllocateInfo-pNext-06383]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA, the pname:pNext chain must: include a
    slink:VkMemoryDedicatedAllocateInfo structure with either its
    pname:image or pname:buffer field set to a value other than
    dlink:VK_NULL_HANDLE
  * [[VUID-VkMemoryAllocateInfo-image-06384]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA and
    slink:VkMemoryDedicatedAllocateInfo::pname:image is not
    dlink:VK_NULL_HANDLE, the pname:image must: be created with a
    slink:VkBufferCollectionImageCreateInfoFUCHSIA structure chained to its
    slink:VkImageCreateInfo::pname:pNext pointer
  * [[VUID-VkMemoryAllocateInfo-buffer-06385]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA and
    slink:VkMemoryDedicatedAllocateInfo::pname:buffer is not
    dlink:VK_NULL_HANDLE, the pname:buffer must: be created with a
    slink:VkBufferCollectionBufferCreateInfoFUCHSIA structure chained to its
    slink:VkBufferCreateInfo::pname:pNext pointer
  * [[VUID-VkMemoryAllocateInfo-memoryTypeIndex-06386]]
    If the parameters define an import operation from an
    slink:VkBufferCollectionFUCHSIA, pname:memoryTypeIndex must: be from
    slink:VkBufferCollectionPropertiesFUCHSIA as retrieved by
    flink:vkGetBufferCollectionPropertiesFUCHSIA
endif::VK_FUCHSIA_buffer_collection[]
ifdef::VK_KHR_external_memory[]
ifdef::VK_KHR_dedicated_allocation,VK_NV_dedicated_allocation[]
  * [[VUID-VkMemoryAllocateInfo-pNext-00639]]
    If the pname:pNext chain includes a sname:VkExportMemoryAllocateInfo
    structure, and any of the handle types specified in
    sname:VkExportMemoryAllocateInfo::pname:handleTypes require a dedicated
    allocation, as reported by
    flink:vkGetPhysicalDeviceImageFormatProperties2 in
    sname:VkExternalImageFormatProperties::pname:externalMemoryProperties.externalMemoryFeatures
    or
    sname:VkExternalBufferProperties::pname:externalMemoryProperties.externalMemoryFeatures,
    the pname:pNext chain must: include a
    sname:VkMemoryDedicatedAllocateInfo or
    sname:VkDedicatedAllocationMemoryAllocateInfoNV structure with either
    its pname:image or pname:buffer member set to a value other than
    dlink:VK_NULL_HANDLE
endif::VK_KHR_dedicated_allocation,VK_NV_dedicated_allocation[]
endif::VK_KHR_external_memory[]
ifdef::VK_KHR_external_memory[]
ifdef::VK_NV_external_memory[]
  * [[VUID-VkMemoryAllocateInfo-pNext-00640]]
    If the pname:pNext chain includes a slink:VkExportMemoryAllocateInfo
    structure, it must: not include a slink:VkExportMemoryAllocateInfoNV or
    slink:VkExportMemoryWin32HandleInfoNV structure
endif::VK_NV_external_memory[]
endif::VK_KHR_external_memory[]
ifdef::VK_KHR_external_memory_win32+VK_NV_external_memory_win32[]
  * [[VUID-VkMemoryAllocateInfo-pNext-00641]]
    If the pname:pNext chain includes a
    slink:VkImportMemoryWin32HandleInfoKHR structure, it must: not include a
    slink:VkImportMemoryWin32HandleInfoNV structure
endif::VK_KHR_external_memory_win32+VK_NV_external_memory_win32[]
ifdef::VK_KHR_external_memory_fd[]
  * [[VUID-VkMemoryAllocateInfo-allocationSize-01742]]
    If the parameters define an import operation, the external handle
    specified was created by the Vulkan API, and the external handle type is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, then the values of
    pname:allocationSize and pname:memoryTypeIndex must: match those
    specified when the payload being imported was created
endif::VK_KHR_external_memory_fd[]
ifdef::VK_KHR_external_memory+VK_KHR_device_group[]
  * [[VUID-VkMemoryAllocateInfo-None-00643]]
    If the parameters define an import operation and the external handle
    specified was created by the Vulkan API, the device mask specified by
    slink:VkMemoryAllocateFlagsInfo must: match the mask specified when the
    payload being imported was allocated
  * [[VUID-VkMemoryAllocateInfo-None-00644]]
    If the parameters define an import operation and the external handle
    specified was created by the Vulkan API, the list of physical devices
    that comprise the logical device passed to flink:vkAllocateMemory must:
    match the list of physical devices that comprise the logical device on
    which the payload was originally allocated
endif::VK_KHR_external_memory+VK_KHR_device_group[]
ifdef::VK_KHR_external_memory_win32[]
  * [[VUID-VkMemoryAllocateInfo-memoryTypeIndex-00645]]
    If the parameters define an import operation and the external handle is
    an NT handle or a global share handle created outside of the Vulkan API,
    the value of pname:memoryTypeIndex must: be one of those returned by
    flink:vkGetMemoryWin32HandlePropertiesKHR
  * [[VUID-VkMemoryAllocateInfo-allocationSize-01743]]
    If the parameters define an import operation, the external handle was
    created by the Vulkan API, and the external handle type is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, then the
    values of pname:allocationSize and pname:memoryTypeIndex must: match
    those specified when the payload being imported was created
  * [[VUID-VkMemoryAllocateInfo-allocationSize-00647]]
    If the parameters define an import operation and the external handle
    type is ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT,
    pname:allocationSize must: match the size specified when creating the
    Direct3D 12 heap from which the payload was extracted
endif::VK_KHR_external_memory_win32[]
ifdef::VK_KHR_external_memory_fd[]
  * [[VUID-VkMemoryAllocateInfo-memoryTypeIndex-00648]]
    If the parameters define an import operation and the external handle is
    a POSIX file descriptor created outside of the Vulkan API, the value of
    pname:memoryTypeIndex must: be one of those returned by
    flink:vkGetMemoryFdPropertiesKHR
endif::VK_KHR_external_memory_fd[]
ifdef::VK_VERSION_1_1[]
  * [[VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872]]
    If the <<features-protectedMemory, pname:protectedMemory>> feature is
    not enabled, the sname:VkMemoryAllocateInfo::pname:memoryTypeIndex must:
    not indicate a memory type that reports
    ename:VK_MEMORY_PROPERTY_PROTECTED_BIT
endif::VK_VERSION_1_1[]
ifdef::VK_EXT_external_memory_host[]
  * [[VUID-VkMemoryAllocateInfo-memoryTypeIndex-01744]]
    If the parameters define an import operation and the external handle is
    a host pointer, the value of pname:memoryTypeIndex must: be one of those
    returned by flink:vkGetMemoryHostPointerPropertiesEXT
  * [[VUID-VkMemoryAllocateInfo-allocationSize-01745]]
    If the parameters define an import operation and the external handle is
    a host pointer, pname:allocationSize must: be an integer multiple of
    sname:VkPhysicalDeviceExternalMemoryHostPropertiesEXT::pname:minImportedHostPointerAlignment
ifdef::VK_NV_dedicated_allocation[]
  * [[VUID-VkMemoryAllocateInfo-pNext-02805]]
    If the parameters define an import operation and the external handle is
    a host pointer, the pname:pNext chain must: not include a
    slink:VkDedicatedAllocationMemoryAllocateInfoNV structure with either
    its pname:image or pname:buffer field set to a value other than
    dlink:VK_NULL_HANDLE
endif::VK_NV_dedicated_allocation[]
ifdef::VK_KHR_dedicated_allocation[]
  * [[VUID-VkMemoryAllocateInfo-pNext-02806]]
    If the parameters define an import operation and the external handle is
    a host pointer, the pname:pNext chain must: not include a
    slink:VkMemoryDedicatedAllocateInfo structure with either its
    pname:image or pname:buffer field set to a value other than
    dlink:VK_NULL_HANDLE
endif::VK_KHR_dedicated_allocation[]
endif::VK_EXT_external_memory_host[]
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryAllocateInfo-allocationSize-02383]]
    If the parameters define an import operation and the external handle
    type is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
    pname:allocationSize must: be the size returned by
    flink:vkGetAndroidHardwareBufferPropertiesANDROID for the Android
    hardware buffer
  * [[VUID-VkMemoryAllocateInfo-pNext-02384]]
    If the parameters define an import operation and the external handle
    type is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
    and the pname:pNext chain does not include a
    slink:VkMemoryDedicatedAllocateInfo structure or
    slink:VkMemoryDedicatedAllocateInfo::pname:image is
    dlink:VK_NULL_HANDLE, the Android hardware buffer must: have a
    code:AHardwareBuffer_Desc::code:format of
    code:AHARDWAREBUFFER_FORMAT_BLOB and a
    code:AHardwareBuffer_Desc::code:usage that includes
    code:AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER
  * [[VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385]]
    If the parameters define an import operation and the external handle
    type is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
    pname:memoryTypeIndex must: be one of those returned by
    flink:vkGetAndroidHardwareBufferPropertiesANDROID for the Android
    hardware buffer
  * [[VUID-VkMemoryAllocateInfo-pNext-01874]]
    If the parameters do not define an import operation, and the pname:pNext
    chain includes a sname:VkExportMemoryAllocateInfo structure with
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
    included in its pname:handleTypes member, and the pname:pNext chain
    includes a slink:VkMemoryDedicatedAllocateInfo structure with
    pname:image not equal to dlink:VK_NULL_HANDLE, then pname:allocationSize
    must: be `0`, otherwise pname:allocationSize must: be greater than `0`
  * [[VUID-VkMemoryAllocateInfo-pNext-02386]]
    If the parameters define an import operation, the external handle is an
    Android hardware buffer, and the pname:pNext chain includes a
    slink:VkMemoryDedicatedAllocateInfo with pname:image that is not
    dlink:VK_NULL_HANDLE, the Android hardware buffer's
    basetype:AHardwareBuffer::code:usage must: include at least one of
    code:AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
    code:AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE or
    code:AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER
  * [[VUID-VkMemoryAllocateInfo-pNext-02387]]
    If the parameters define an import operation, the external handle is an
    Android hardware buffer, and the pname:pNext chain includes a
    slink:VkMemoryDedicatedAllocateInfo with pname:image that is not
    dlink:VK_NULL_HANDLE, the format of pname:image must: be
    ename:VK_FORMAT_UNDEFINED or the format returned by
    flink:vkGetAndroidHardwareBufferPropertiesANDROID in
    slink:VkAndroidHardwareBufferFormatPropertiesANDROID::pname:format for
    the Android hardware buffer
  * [[VUID-VkMemoryAllocateInfo-pNext-02388]]
    If the parameters define an import operation, the external handle is an
    Android hardware buffer, and the pname:pNext chain includes a
    slink:VkMemoryDedicatedAllocateInfo structure with pname:image that is
    not dlink:VK_NULL_HANDLE, the width, height, and array layer dimensions
    of pname:image and the Android hardware buffer's
    code:AHardwareBuffer_Desc must: be identical
  * [[VUID-VkMemoryAllocateInfo-pNext-02389]]
    If the parameters define an import operation, the external handle is an
    Android hardware buffer, and the pname:pNext chain includes a
    slink:VkMemoryDedicatedAllocateInfo structure with pname:image that is
    not dlink:VK_NULL_HANDLE, and the Android hardware buffer's
    basetype:AHardwareBuffer::code:usage includes
    code:AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE, the pname:image must:
    have a complete mipmap chain
  * [[VUID-VkMemoryAllocateInfo-pNext-02586]]
    If the parameters define an import operation, the external handle is an
    Android hardware buffer, and the pname:pNext chain includes a
    slink:VkMemoryDedicatedAllocateInfo structure with pname:image that is
    not dlink:VK_NULL_HANDLE, and the Android hardware buffer's
    basetype:AHardwareBuffer::code:usage does not include
    code:AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE, the pname:image must:
    have exactly one mipmap level
  * [[VUID-VkMemoryAllocateInfo-pNext-02390]]
    If the parameters define an import operation, the external handle is an
    Android hardware buffer, and the pname:pNext chain includes a
    slink:VkMemoryDedicatedAllocateInfo structure with pname:image that is
    not dlink:VK_NULL_HANDLE, each bit set in the usage of pname:image must:
    be listed in
    <<memory-external-android-hardware-buffer-usage,AHardwareBuffer Usage
    Equivalence>>, and if there is a corresponding
    code:AHARDWAREBUFFER_USAGE bit listed that bit must: be included in the
    Android hardware buffer's code:AHardwareBuffer_Desc::code:usage
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
ifdef::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
  * [[VUID-VkMemoryAllocateInfo-opaqueCaptureAddress-03329]]
    If
    slink:VkMemoryOpaqueCaptureAddressAllocateInfo::pname:opaqueCaptureAddress
    is not zero, sname:VkMemoryAllocateFlagsInfo::pname:flags must: include
    ename:VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT
  * [[VUID-VkMemoryAllocateInfo-flags-03330]]
    If sname:VkMemoryAllocateFlagsInfo::pname:flags includes
    ename:VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, the
    <<features-bufferDeviceAddressCaptureReplay,
    pname:bufferDeviceAddressCaptureReplay>> feature must: be enabled
  * [[VUID-VkMemoryAllocateInfo-flags-03331]]
    If sname:VkMemoryAllocateFlagsInfo::pname:flags includes
    ename:VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, the
    <<features-bufferDeviceAddress, pname:bufferDeviceAddress>> feature
    must: be enabled
ifdef::VK_EXT_external_memory_host[]
  * [[VUID-VkMemoryAllocateInfo-pNext-03332]]
    If the pname:pNext chain includes a
    sname:VkImportMemoryHostPointerInfoEXT structure,
    slink:VkMemoryOpaqueCaptureAddressAllocateInfo::pname:opaqueCaptureAddress
    must: be zero
endif::VK_EXT_external_memory_host[]
  * [[VUID-VkMemoryAllocateInfo-opaqueCaptureAddress-03333]]
    If the parameters define an import operation,
    slink:VkMemoryOpaqueCaptureAddressAllocateInfo::pname:opaqueCaptureAddress
    must: be zero
endif::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
ifdef::VK_FUCHSIA_external_memory[]
  * [[VUID-VkMemoryAllocateInfo-None-04749]]
    If the parameters define an import operation and the external handle
    type is ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA, the
    value of sname:memoryTypeIndex must: be an index identifying a memory
    type from the sname:memoryTypeBits field of the
    slink:VkMemoryZirconHandlePropertiesFUCHSIA structure populated by a
    call to flink:vkGetMemoryZirconHandlePropertiesFUCHSIA
  * [[VUID-VkMemoryAllocateInfo-allocationSize-04750]]
    If the parameters define an import operation and the external handle
    type is ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA, the
    value of pname:allocationSize must: be greater than `0` and must: be
    less than or equal to the size of the VMO as determined by
    code:zx_vmo_get_size(pname:handle) where pname:handle is the VMO handle
    to the imported external memory
endif::VK_FUCHSIA_external_memory[]
ifdef::VK_EXT_metal_objects[]
  * [[VUID-VkMemoryAllocateInfo-pNext-06780]]
    If the pname:pNext chain includes a
    slink:VkExportMetalObjectCreateInfoEXT structure, its
    pname:exportObjectType member must: be
    ename:VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT
endif::VK_EXT_metal_objects[]
****

include::{generated}/validity/structs/VkMemoryAllocateInfo.adoc[]
--

ifdef::VK_VERSION_1_1,VK_KHR_dedicated_allocation[]
[open,refpage='VkMemoryDedicatedAllocateInfo',desc='Specify a dedicated memory allocation resource',type='structs']
--
If the pname:pNext chain includes a sname:VkMemoryDedicatedAllocateInfo
structure, then that structure includes a handle of the sole buffer or image
resource that the memory can: be bound to.

The sname:VkMemoryDedicatedAllocateInfo structure is defined as:

include::{generated}/api/structs/VkMemoryDedicatedAllocateInfo.adoc[]

ifdef::VK_KHR_dedicated_allocation[]
or the equivalent

include::{generated}/api/structs/VkMemoryDedicatedAllocateInfoKHR.adoc[]
endif::VK_KHR_dedicated_allocation[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:image is dlink:VK_NULL_HANDLE or a handle of an image which this
    memory will be bound to.
  * pname:buffer is dlink:VK_NULL_HANDLE or a handle of a buffer which this
    memory will be bound to.

.Valid Usage
****
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-01432]]
    At least one of pname:image and pname:buffer must: be
    dlink:VK_NULL_HANDLE
ifndef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-01433]]
    If pname:image is not dlink:VK_NULL_HANDLE,
    sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
    sname:VkMemoryRequirements::pname:size of the image
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-02964]]
    If pname:image is not dlink:VK_NULL_HANDLE and the memory is not an
    imported Android Hardware Buffer,
    sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
    sname:VkMemoryRequirements::pname:size of the image
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-01434]]
    If pname:image is not dlink:VK_NULL_HANDLE, pname:image must: have been
    created without ename:VK_IMAGE_CREATE_SPARSE_BINDING_BIT set in
    slink:VkImageCreateInfo::pname:flags
ifndef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-buffer-01435]]
    If pname:buffer is not dlink:VK_NULL_HANDLE,
    sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
    sname:VkMemoryRequirements::pname:size of the buffer
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-buffer-02965]]
    If pname:buffer is not dlink:VK_NULL_HANDLE and the memory is not an
    imported Android Hardware Buffer,
    sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
    sname:VkMemoryRequirements::pname:size of the buffer
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-buffer-01436]]
    If pname:buffer is not dlink:VK_NULL_HANDLE, pname:buffer must: have
    been created without ename:VK_BUFFER_CREATE_SPARSE_BINDING_BIT set in
    slink:VkBufferCreateInfo::pname:flags
ifdef::VK_KHR_external_memory_win32[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-01876]]
    If pname:image is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation with handle
    type ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, and the
    external handle was created by the Vulkan API, then the memory being
    imported must: also be a dedicated image allocation and pname:image must
    be identical to the image associated with the imported memory
  * [[VUID-VkMemoryDedicatedAllocateInfo-buffer-01877]]
    If pname:buffer is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation with handle
    type ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, and the
    external handle was created by the Vulkan API, then the memory being
    imported must: also be a dedicated buffer allocation and pname:buffer
    must: be identical to the buffer associated with the imported memory
endif::VK_KHR_external_memory_win32[]
ifdef::VK_KHR_external_memory_fd[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-01878]]
    If pname:image is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation with handle
    type ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, the memory
    being imported must: also be a dedicated image allocation and
    pname:image must: be identical to the image associated with the imported
    memory
  * [[VUID-VkMemoryDedicatedAllocateInfo-buffer-01879]]
    If pname:buffer is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation with handle
    type ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, the memory
    being imported must: also be a dedicated buffer allocation and
    pname:buffer must: be identical to the buffer associated with the
    imported memory
endif::VK_KHR_external_memory_fd[]
ifdef::VK_KHR_sampler_ycbcr_conversion[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-01797]]
    If pname:image is not dlink:VK_NULL_HANDLE, pname:image must: not have
    been created with ename:VK_IMAGE_CREATE_DISJOINT_BIT set in
    slink:VkImageCreateInfo::pname:flags
endif::VK_KHR_sampler_ycbcr_conversion[]
ifdef::VK_FUCHSIA_external_memory[]
  * [[VUID-VkMemoryDedicatedAllocateInfo-image-04751]]
    If pname:image is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation with handle
    type ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA, the
    memory being imported must: also be a dedicated image allocation and
    pname:image must: be identical to the image associated with the imported
    memory
  * [[VUID-VkMemoryDedicatedAllocateInfo-buffer-04752]]
    If pname:buffer is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation with handle
    type ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA, the
    memory being imported must: also be a dedicated buffer allocation and
    pname:buffer must: be identical to the buffer associated with the
    imported memory
endif::VK_FUCHSIA_external_memory[]
****

include::{generated}/validity/structs/VkMemoryDedicatedAllocateInfo.adoc[]
--
endif::VK_VERSION_1_1,VK_KHR_dedicated_allocation[]

ifdef::VK_NV_dedicated_allocation[]
[open,refpage='VkDedicatedAllocationMemoryAllocateInfoNV',desc='Specify a dedicated memory allocation resource',type='structs']
--
If the pname:pNext chain 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::{generated}/api/structs/VkDedicatedAllocationMemoryAllocateInfoNV.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:image is dlink:VK_NULL_HANDLE or a handle of an image which this
    memory will be bound to.
  * pname:buffer is dlink:VK_NULL_HANDLE or a handle of a buffer which this
    memory will be bound to.

.Valid Usage
****
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00649]]
    At least one of pname:image and pname:buffer must: be
    dlink:VK_NULL_HANDLE
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00650]]
    If pname:image is not dlink:VK_NULL_HANDLE, the image must: have been
    created with
    slink:VkDedicatedAllocationImageCreateInfoNV::pname:dedicatedAllocation
    equal to ename:VK_TRUE
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00651]]
    If pname:buffer is not dlink:VK_NULL_HANDLE, the buffer must: have been
    created with
    slink:VkDedicatedAllocationBufferCreateInfoNV::pname:dedicatedAllocation
    equal to ename:VK_TRUE
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00652]]
    If pname:image is not dlink:VK_NULL_HANDLE,
    sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
    sname:VkMemoryRequirements::pname:size of the image
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00653]]
    If pname:buffer is not dlink:VK_NULL_HANDLE,
    sname:VkMemoryAllocateInfo::pname:allocationSize must: equal the
    sname:VkMemoryRequirements::pname:size of the buffer
ifdef::VK_KHR_external_memory_win32,VK_KHR_external_memory_fd[]
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00654]]
    If pname:image is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation, the memory
    being imported must: also be a dedicated image allocation and
    pname:image must: be identical to the image associated with the imported
    memory
  * [[VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00655]]
    If pname:buffer is not dlink:VK_NULL_HANDLE and
    slink:VkMemoryAllocateInfo defines a memory import operation, the memory
    being imported must: also be a dedicated buffer allocation and
    pname:buffer must: be identical to the buffer associated with the
    imported memory
endif::VK_KHR_external_memory_win32,VK_KHR_external_memory_fd[]
****

include::{generated}/validity/structs/VkDedicatedAllocationMemoryAllocateInfoNV.adoc[]
--
endif::VK_NV_dedicated_allocation[]

ifdef::VK_EXT_memory_priority[]
[open,refpage='VkMemoryPriorityAllocateInfoEXT',desc='Specify a memory allocation priority',type='structs']
--
If the pname:pNext chain includes a sname:VkMemoryPriorityAllocateInfoEXT
structure, then that structure includes a priority for the memory.

The sname:VkMemoryPriorityAllocateInfoEXT structure is defined as:

include::{generated}/api/structs/VkMemoryPriorityAllocateInfoEXT.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:priority is a floating-point value between `0` and `1`, indicating
    the priority of the allocation relative to other memory allocations.
    Larger values are higher priority.
    The granularity of the priorities is implementation-dependent.

Memory allocations with higher priority may: be more likely to stay in
device-local memory when the system is under memory pressure.

If this structure is not included, it is as if the pname:priority value were
`0.5`.

.Valid Usage
****
  * [[VUID-VkMemoryPriorityAllocateInfoEXT-priority-02602]]
    pname:priority must: be between `0` and `1`, inclusive
****

include::{generated}/validity/structs/VkMemoryPriorityAllocateInfoEXT.adoc[]
--
endif::VK_EXT_memory_priority[]

ifdef::VK_EXT_pageable_device_local_memory[]
[open,refpage='vkSetDeviceMemoryPriorityEXT',desc='Change a memory allocation priority',type='protos']
--
To modify the priority of an existing memory allocation, call:

include::{generated}/api/protos/vkSetDeviceMemoryPriorityEXT.adoc[]

  * pname:device is the logical device that owns the memory.
  * pname:memory is the slink:VkDeviceMemory object to which the new
    priority will be applied.
  * pname:priority is a floating-point value between `0` and `1`, indicating
    the priority of the allocation relative to other memory allocations.
    Larger values are higher priority.
    The granularity of the priorities is implementation-dependent.

Memory allocations with higher priority may: be more likely to stay in
device-local memory when the system is under memory pressure.

.Valid Usage
****
  * [[VUID-vkSetDeviceMemoryPriorityEXT-priority-06258]]
    pname:priority must: be between `0` and `1`, inclusive
****

include::{generated}/validity/protos/vkSetDeviceMemoryPriorityEXT.adoc[]
--
endif::VK_EXT_pageable_device_local_memory[]

ifdef::VK_VERSION_1_1,VK_KHR_external_memory[]
[open,refpage='VkExportMemoryAllocateInfo',desc='Specify exportable handle types for a device memory object',type='structs']
--
When allocating memory whose payload may: be exported to another process or
Vulkan instance, add a slink:VkExportMemoryAllocateInfo structure to the
pname:pNext chain of the slink:VkMemoryAllocateInfo structure, specifying
the handle types that may: be exported.

The slink:VkExportMemoryAllocateInfo structure is defined as:

include::{generated}/api/structs/VkExportMemoryAllocateInfo.adoc[]

ifdef::VK_KHR_external_memory[]
or the equivalent

include::{generated}/api/structs/VkExportMemoryAllocateInfoKHR.adoc[]
endif::VK_KHR_external_memory[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:handleTypes is zero or a bitmask of
    elink:VkExternalMemoryHandleTypeFlagBits specifying one or more memory
    handle types the application can: export from the resulting allocation.
    The application can: request multiple handle types for the same
    allocation.

.Valid Usage
****
  * [[VUID-VkExportMemoryAllocateInfo-handleTypes-00656]]
    The bits in pname:handleTypes must: be supported and compatible, as
    reported by slink:VkExternalImageFormatProperties or
    slink:VkExternalBufferProperties
****

include::{generated}/validity/structs/VkExportMemoryAllocateInfo.adoc[]
--
endif::VK_VERSION_1_1,VK_KHR_external_memory[]

ifdef::VK_NV_external_memory[]
include::{chapters}/VK_NV_external_memory/allocate_memory.adoc[]
endif::VK_NV_external_memory[]

ifdef::VK_KHR_external_memory_win32,VK_NV_external_memory_win32[]
=== Win32 External Memory
endif::VK_KHR_external_memory_win32,VK_NV_external_memory_win32[]

ifdef::VK_KHR_external_memory_win32[]
[open,refpage='VkExportMemoryWin32HandleInfoKHR',desc='Structure specifying additional attributes of Windows handles exported from a memory',type='structs']
--
To specify additional attributes of NT handles exported from a memory
object, add a slink:VkExportMemoryWin32HandleInfoKHR structure to the
pname:pNext chain of the slink:VkMemoryAllocateInfo structure.
The sname:VkExportMemoryWin32HandleInfoKHR structure is defined as:

include::{generated}/api/structs/VkExportMemoryWin32HandleInfoKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:pAttributes is a pointer to a Windows code:SECURITY_ATTRIBUTES
    structure specifying security attributes of the handle.
  * pname:dwAccess is a code:DWORD specifying access rights of the handle.
  * pname:name is a null-terminated UTF-16 string to associate with the
    payload referenced by NT handles exported from the created memory.

If slink:VkExportMemoryAllocateInfo is not included in the same pname:pNext
chain, this structure is ignored.

If slink:VkExportMemoryAllocateInfo is included in the pname:pNext chain of
slink:VkMemoryAllocateInfo with a Windows pname:handleType, but either
sname:VkExportMemoryWin32HandleInfoKHR is not included in the pname:pNext
chain, or if it is but pname:pAttributes is set to `NULL`, default security
descriptor values will be used, and child processes created by the
application will not inherit the handle, as described in the MSDN
documentation for "`Synchronization Object Security and Access Rights`"^1^.
Further, if the structure is not present, the access rights used depend on
the handle type.

For handles of the following types:

  * ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT

The implementation must: ensure the access rights allow read and write
access to the memory.

1::
    https://docs.microsoft.com/en-us/windows/win32/sync/synchronization-object-security-and-access-rights

.Valid Usage
****
  * [[VUID-VkExportMemoryWin32HandleInfoKHR-handleTypes-00657]]
    If slink:VkExportMemoryAllocateInfo::pname:handleTypes does not include
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, a
    sname:VkExportMemoryWin32HandleInfoKHR structure must: not be included
    in the pname:pNext chain of slink:VkMemoryAllocateInfo
****

include::{generated}/validity/structs/VkExportMemoryWin32HandleInfoKHR.adoc[]
--

[open,refpage='VkImportMemoryWin32HandleInfoKHR',desc='Import Win32 memory created on the same physical device',type='structs']
--
To import memory from a Windows handle, add a
slink:VkImportMemoryWin32HandleInfoKHR structure to the pname:pNext chain of
the slink:VkMemoryAllocateInfo structure.

The sname:VkImportMemoryWin32HandleInfoKHR structure is defined as:

include::{generated}/api/structs/VkImportMemoryWin32HandleInfoKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the type of pname:handle or pname:name.
  * pname:handle is `NULL` or the external handle to import.
  * pname:name is `NULL` or a null-terminated UTF-16 string naming the
    payload to import.

Importing memory object payloads from Windows handles does not transfer
ownership of the handle to the Vulkan implementation.
For handle types defined as NT handles, the application must: release handle
ownership using the code:CloseHandle system call when the handle is no
longer needed.
For handle types defined as NT handles, the imported memory object holds a
reference to its payload.

[NOTE]
.Note
====
Non-NT handle import operations do not add a reference to their associated
payload.
If the original object owning the payload is destroyed, all resources and
handles sharing that payload will become invalid.
====

Applications can: import the same payload 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
sname:VkDeviceMemory object.

.Valid Usage
****
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00658]]
    If pname:handleType is not `0`, it must: be supported for import, as
    reported by slink:VkExternalImageFormatProperties or
    slink:VkExternalBufferProperties
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handle-00659]]
    The memory from which pname:handle was exported, or the memory named by
    pname:name must: have been created on the same underlying physical
    device as pname:device
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660]]
    If pname:handleType is not `0`, it must: be defined as an NT handle or a
    global share handle
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handleType-01439]]
    If pname:handleType is not
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, pname:name
    must: be `NULL`
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handleType-01440]]
    If pname:handleType is not `0` and pname:handle is `NULL`, pname:name
    must: name a valid memory resource of the type specified by
    pname:handleType
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00661]]
    If pname:handleType is not `0` and pname:name is `NULL`, pname:handle
    must: be a valid handle of the type specified by pname:handleType
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handle-01441]]
    if pname:handle is not `NULL`, pname:name must: be `NULL`
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-handle-01518]]
    If pname:handle is not `NULL`, it must: obey any requirements listed for
    pname:handleType in
    <<external-memory-handle-types-compatibility,external memory handle
    types compatibility>>
  * [[VUID-VkImportMemoryWin32HandleInfoKHR-name-01519]]
    If pname:name is not `NULL`, it must: obey any requirements listed for
    pname:handleType in
    <<external-memory-handle-types-compatibility,external memory handle
    types compatibility>>
****

include::{generated}/validity/structs/VkImportMemoryWin32HandleInfoKHR.adoc[]
--

[open,refpage='vkGetMemoryWin32HandleKHR',desc='Get a Windows HANDLE for a memory object',type='protos']
--
To export a Windows handle representing the payload of a Vulkan device
memory object, call:

include::{generated}/api/protos/vkGetMemoryWin32HandleKHR.adoc[]

  * pname:device is the logical device that created the device memory being
    exported.
  * pname:pGetWin32HandleInfo is a pointer to a
    slink:VkMemoryGetWin32HandleInfoKHR structure containing parameters of
    the export operation.
  * pname:pHandle will return the Windows handle representing the payload of
    the device memory object.

For handle types defined as NT handles, the handles returned by
fname:vkGetMemoryWin32HandleKHR are owned by the application and hold a
reference to their payload.
To avoid leaking resources, the application must: release ownership of them
using the code:CloseHandle system call when they are no longer needed.

[NOTE]
.Note
====
Non-NT handle types do not add a reference to their associated payload.
If the original object owning the payload is destroyed, all resources and
handles sharing that payload will become invalid.
====

include::{generated}/validity/protos/vkGetMemoryWin32HandleKHR.adoc[]
--

[open,refpage='VkMemoryGetWin32HandleInfoKHR',desc='Structure describing a Win32 handle memory export operation',type='structs']
--
The sname:VkMemoryGetWin32HandleInfoKHR structure is defined as:

include::{generated}/api/structs/VkMemoryGetWin32HandleInfoKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memory is the memory object from which the handle will be
    exported.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the type of handle requested.

The properties of the handle returned depend on the value of
pname:handleType.
See elink:VkExternalMemoryHandleTypeFlagBits for a description of the
properties of the defined external memory handle types.

.Valid Usage
****
  * [[VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00662]]
    pname:handleType must: have been included in
    slink:VkExportMemoryAllocateInfo::pname:handleTypes when pname:memory
    was created
  * [[VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00663]]
    If pname:handleType is defined as an NT handle,
    flink:vkGetMemoryWin32HandleKHR must: be called no more than once for
    each valid unique combination of pname:memory and pname:handleType
  * [[VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00664]]
    pname:handleType must: be defined as an NT handle or a global share
    handle
****

include::{generated}/validity/structs/VkMemoryGetWin32HandleInfoKHR.adoc[]
--

[open,refpage='vkGetMemoryWin32HandlePropertiesKHR',desc='Get Properties of External Memory Win32 Handles',type='protos']
--
Windows memory handles compatible with Vulkan may: also be created by
non-Vulkan APIs using methods beyond the scope of this specification.
To determine the correct parameters to use when importing such handles,
call:

include::{generated}/api/protos/vkGetMemoryWin32HandlePropertiesKHR.adoc[]

  * pname:device is the logical device that will be importing pname:handle.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the type of the handle pname:handle.
  * pname:handle is the handle which will be imported.
  * pname:pMemoryWin32HandleProperties is a pointer to a
    slink:VkMemoryWin32HandlePropertiesKHR structure in which properties of
    pname:handle are returned.

.Valid Usage
****
  * [[VUID-vkGetMemoryWin32HandlePropertiesKHR-handle-00665]]
    pname:handle must: be an external memory handle created outside of the
    Vulkan API
  * [[VUID-vkGetMemoryWin32HandlePropertiesKHR-handleType-00666]]
    pname:handleType must: not be one of the handle types defined as opaque
****

include::{generated}/validity/protos/vkGetMemoryWin32HandlePropertiesKHR.adoc[]
--

[open,refpage='VkMemoryWin32HandlePropertiesKHR',desc='Properties of External Memory Windows Handles',type='structs']
--
The sname:VkMemoryWin32HandlePropertiesKHR structure returned is defined as:

include::{generated}/api/structs/VkMemoryWin32HandlePropertiesKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memoryTypeBits is a bitmask containing one bit set for every
    memory type which the specified windows handle can: be imported as.

include::{generated}/validity/structs/VkMemoryWin32HandlePropertiesKHR.adoc[]
--
endif::VK_KHR_external_memory_win32[]

ifdef::VK_NV_external_memory_win32[]
include::{chapters}/VK_NV_external_memory_win32/handle_permissions.adoc[]

include::{chapters}/VK_NV_external_memory_win32/import_memory_win32.adoc[]

include::{chapters}/VK_NV_external_memory_win32/get_handle_win32.adoc[]
endif::VK_NV_external_memory_win32[]

ifdef::VK_KHR_external_memory_fd[]
=== File Descriptor External Memory

[open,refpage='VkImportMemoryFdInfoKHR',desc='Import memory created on the same physical device from a file descriptor',type='structs']
--
To import memory from a POSIX file descriptor handle, add a
slink:VkImportMemoryFdInfoKHR structure to the pname:pNext chain of the
slink:VkMemoryAllocateInfo structure.
The sname:VkImportMemoryFdInfoKHR structure is defined as:

include::{generated}/api/structs/VkImportMemoryFdInfoKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the handle type of pname:fd.
  * pname:fd is the external handle to import.

Importing memory from a file descriptor transfers ownership of the file
descriptor from the application to the Vulkan implementation.
The application must: not perform any operations on the file descriptor
after a successful import.
The imported memory object holds a reference to its payload.

Applications can: import the same payload 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
sname:VkDeviceMemory object.

.Valid Usage
****
  * [[VUID-VkImportMemoryFdInfoKHR-handleType-00667]]
    If pname:handleType is not `0`, it must: be supported for import, as
    reported by slink:VkExternalImageFormatProperties or
    slink:VkExternalBufferProperties
  * [[VUID-VkImportMemoryFdInfoKHR-fd-00668]]
    The memory from which pname:fd was exported must: have been created on
    the same underlying physical device as pname:device
  * [[VUID-VkImportMemoryFdInfoKHR-handleType-00669]]
    If pname:handleType is not `0`, it must: be
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
  * [[VUID-VkImportMemoryFdInfoKHR-handleType-00670]]
    If pname:handleType is not `0`, pname:fd must: be a valid handle of the
    type specified by pname:handleType
  * [[VUID-VkImportMemoryFdInfoKHR-fd-01746]]
    The memory represented by pname:fd must: have been created from a
    physical device and driver that is compatible with pname:device and
    pname:handleType, as described in
    <<external-memory-handle-types-compatibility>>
  * [[VUID-VkImportMemoryFdInfoKHR-fd-01520]]
    pname:fd must: obey any requirements listed for pname:handleType in
    <<external-memory-handle-types-compatibility,external memory handle
    types compatibility>>
****

include::{generated}/validity/structs/VkImportMemoryFdInfoKHR.adoc[]
--

[open,refpage='vkGetMemoryFdKHR',desc='Get a POSIX file descriptor for a memory object',type='protos']
--
To export a POSIX file descriptor referencing the payload of a Vulkan device
memory object, call:

include::{generated}/api/protos/vkGetMemoryFdKHR.adoc[]

  * pname:device is the logical device that created the device memory being
    exported.
  * pname:pGetFdInfo is a pointer to a slink:VkMemoryGetFdInfoKHR structure
    containing parameters of the export operation.
  * pname:pFd will return a file descriptor referencing the payload of the
    device memory object.

Each call to fname:vkGetMemoryFdKHR must: create a new file descriptor
holding a reference to the memory object's payload and transfer ownership of
the file descriptor to the application.
To avoid leaking resources, the application must: release ownership of the
file descriptor using the code:close system call when it is no longer
needed, or by importing a Vulkan memory object from it.
Where supported by the operating system, the implementation must: set the
file descriptor to be closed automatically when an code:execve system call
is made.

include::{generated}/validity/protos/vkGetMemoryFdKHR.adoc[]
--

[open,refpage='VkMemoryGetFdInfoKHR',desc='Structure describing a POSIX FD memory export operation',type='structs']
--
The sname:VkMemoryGetFdInfoKHR structure is defined as:

include::{generated}/api/structs/VkMemoryGetFdInfoKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memory is the memory object from which the handle will be
    exported.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the type of handle requested.

The properties of the file descriptor exported depend on the value of
pname:handleType.
See elink:VkExternalMemoryHandleTypeFlagBits for a description of the
properties of the defined external memory handle types.

ifdef::VK_EXT_external_memory_dma_buf[]
[NOTE]
.Note
====
The size of the exported file may: be larger than the size requested by
slink:VkMemoryAllocateInfo::pname:allocationSize.
If pname:handleType is ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
then the application can: query the file's actual size with
link:https://man7.org/linux/man-pages/man2/lseek.2.html[`lseek`].
====
endif::VK_EXT_external_memory_dma_buf[]

.Valid Usage
****
  * [[VUID-VkMemoryGetFdInfoKHR-handleType-00671]]
    pname:handleType must: have been included in
    slink:VkExportMemoryAllocateInfo::pname:handleTypes when pname:memory
    was created
  * [[VUID-VkMemoryGetFdInfoKHR-handleType-00672]]
    pname:handleType must: be
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
****

include::{generated}/validity/structs/VkMemoryGetFdInfoKHR.adoc[]
--

[open,refpage='vkGetMemoryFdPropertiesKHR',desc='Get Properties of External Memory File Descriptors',type='protos']
--
POSIX file descriptor memory handles compatible with Vulkan may: also be
created by non-Vulkan APIs using methods beyond the scope of this
specification.
To determine the correct parameters to use when importing such handles,
call:

include::{generated}/api/protos/vkGetMemoryFdPropertiesKHR.adoc[]

  * pname:device is the logical device that will be importing pname:fd.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the type of the handle pname:fd.
  * pname:fd is the handle which will be imported.
  * pname:pMemoryFdProperties is a pointer to a
    slink:VkMemoryFdPropertiesKHR structure in which the properties of the
    handle pname:fd are returned.

.Valid Usage
****
  * [[VUID-vkGetMemoryFdPropertiesKHR-fd-00673]]
    pname:fd must: be an external memory handle created outside of the
    Vulkan API
  * [[VUID-vkGetMemoryFdPropertiesKHR-handleType-00674]]
    pname:handleType must: not be
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
****

include::{generated}/validity/protos/vkGetMemoryFdPropertiesKHR.adoc[]
--

[open,refpage='VkMemoryFdPropertiesKHR',desc='Properties of External Memory File Descriptors',type='structs']
--
The sname:VkMemoryFdPropertiesKHR structure returned is defined as:

include::{generated}/api/structs/VkMemoryFdPropertiesKHR.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memoryTypeBits is a bitmask containing one bit set for every
    memory type which the specified file descriptor can: be imported as.

include::{generated}/validity/structs/VkMemoryFdPropertiesKHR.adoc[]
--
endif::VK_KHR_external_memory_fd[]

ifdef::VK_EXT_external_memory_host[]
=== Host External Memory

[open,refpage='VkImportMemoryHostPointerInfoEXT',desc='Import memory from a host pointer',type='structs']
--
To import memory from a host pointer, add a
slink:VkImportMemoryHostPointerInfoEXT structure to the pname:pNext chain of
the slink:VkMemoryAllocateInfo structure.
The sname:VkImportMemoryHostPointerInfoEXT structure is defined as:

include::{generated}/api/structs/VkImportMemoryHostPointerInfoEXT.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the handle type.
  * pname:pHostPointer is the host pointer to import from.

Importing memory from a host pointer shares ownership of the memory between
the host and the Vulkan implementation.
The application can: continue to access the memory through the host pointer
but it is the application's responsibility to synchronize device and
non-device access to the payload as defined in
<<memory-device-hostaccess,Host Access to Device Memory Objects>>.

Applications can: import the same payload into multiple instances of Vulkan
and multiple times into a given Vulkan instance.
However, implementations may: fail to import the same payload multiple times
into a given physical device due to platform constraints.

Importing memory from a particular host pointer may: not be possible due to
additional platform-specific restrictions beyond the scope of this
specification in which case the implementation must: fail the memory import
operation with the error code ename:VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR.

Whether device memory objects imported from a host pointer hold a reference
to their payload is undefined:.
As such, the application must: ensure that the imported memory range remains
valid and accessible for the lifetime of the imported memory object.

.Valid Usage
****
  * [[VUID-VkImportMemoryHostPointerInfoEXT-handleType-01747]]
    If pname:handleType is not `0`, it must: be supported for import, as
    reported in slink:VkExternalMemoryProperties
  * [[VUID-VkImportMemoryHostPointerInfoEXT-handleType-01748]]
    If pname:handleType is not `0`, it must: be
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT
  * [[VUID-VkImportMemoryHostPointerInfoEXT-pHostPointer-01749]]
    pname:pHostPointer must: be a pointer aligned to an integer multiple of
    sname:VkPhysicalDeviceExternalMemoryHostPropertiesEXT::pname:minImportedHostPointerAlignment
  * [[VUID-VkImportMemoryHostPointerInfoEXT-handleType-01750]]
    If pname:handleType is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
    pname:pHostPointer must: be a pointer to pname:allocationSize number of
    bytes of host memory, where pname:allocationSize is the member of the
    sname:VkMemoryAllocateInfo structure this structure is chained to
  * [[VUID-VkImportMemoryHostPointerInfoEXT-handleType-01751]]
    If pname:handleType is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT,
    pname:pHostPointer must: be a pointer to pname:allocationSize number of
    bytes of host mapped foreign memory, where pname:allocationSize is the
    member of the sname:VkMemoryAllocateInfo structure this structure is
    chained to
****

include::{generated}/validity/structs/VkImportMemoryHostPointerInfoEXT.adoc[]
--

[open,refpage='vkGetMemoryHostPointerPropertiesEXT',desc='Get properties of external memory host pointer',type='protos']
--
To determine the correct parameters to use when importing host pointers,
call:

include::{generated}/api/protos/vkGetMemoryHostPointerPropertiesEXT.adoc[]

  * pname:device is the logical device that will be importing
    pname:pHostPointer.
  * pname:handleType is a elink:VkExternalMemoryHandleTypeFlagBits value
    specifying the type of the handle pname:pHostPointer.
  * pname:pHostPointer is the host pointer to import from.
  * pname:pMemoryHostPointerProperties is a pointer to a
    slink:VkMemoryHostPointerPropertiesEXT structure in which the host
    pointer properties are returned.

.Valid Usage
****
  * [[VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01752]]
    pname:handleType must: be
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT or
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT
  * [[VUID-vkGetMemoryHostPointerPropertiesEXT-pHostPointer-01753]]
    pname:pHostPointer must: be a pointer aligned to an integer multiple of
    sname:VkPhysicalDeviceExternalMemoryHostPropertiesEXT::pname:minImportedHostPointerAlignment
  * [[VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01754]]
    If pname:handleType is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
    pname:pHostPointer must: be a pointer to host memory
  * [[VUID-vkGetMemoryHostPointerPropertiesEXT-handleType-01755]]
    If pname:handleType is
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT,
    pname:pHostPointer must: be a pointer to host mapped foreign memory
****

include::{generated}/validity/protos/vkGetMemoryHostPointerPropertiesEXT.adoc[]
--

[open,refpage='VkMemoryHostPointerPropertiesEXT',desc='Properties of external memory host pointer',type='structs']
--
The sname:VkMemoryHostPointerPropertiesEXT structure is defined as:

include::{generated}/api/structs/VkMemoryHostPointerPropertiesEXT.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memoryTypeBits is a bitmask containing one bit set for every
    memory type which the specified host pointer can: be imported as.

The value returned by pname:memoryTypeBits must: only include bits that
identify memory types which are host visible.

include::{generated}/validity/structs/VkMemoryHostPointerPropertiesEXT.adoc[]
--

endif::VK_EXT_external_memory_host[]

ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
=== Android Hardware Buffer External Memory

[open,refpage='VkImportAndroidHardwareBufferInfoANDROID',desc='Import memory from an Android hardware buffer',type='structs']
--
To import memory created outside of the current Vulkan instance from an
Android hardware buffer, add a
sname:VkImportAndroidHardwareBufferInfoANDROID structure to the pname:pNext
chain of the slink:VkMemoryAllocateInfo structure.
The sname:VkImportAndroidHardwareBufferInfoANDROID structure is defined as:

include::{generated}/api/structs/VkImportAndroidHardwareBufferInfoANDROID.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:buffer is the Android hardware buffer to import.

If the flink:vkAllocateMemory command succeeds, the implementation must:
acquire a reference to the imported hardware buffer, which it must: release
when the device memory object is freed.
If the command fails, the implementation must: not retain a reference.

.Valid Usage
****
  * [[VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01880]]
    If pname:buffer is not `NULL`, Android hardware buffers must: be
    supported for import, as reported by
    slink:VkExternalImageFormatProperties or
    slink:VkExternalBufferProperties
  * [[VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881]]
    If pname:buffer is not `NULL`, it must: be a valid Android hardware
    buffer object with code:AHardwareBuffer_Desc::code:usage compatible with
    Vulkan as described in <<memory-external-android-hardware-buffer,Android
    Hardware Buffers>>
****

include::{generated}/validity/structs/VkImportAndroidHardwareBufferInfoANDROID.adoc[]
--

[open,refpage='vkGetMemoryAndroidHardwareBufferANDROID',desc='Get an Android hardware buffer for a memory object',type='protos']
--
To export an Android hardware buffer referencing the payload of a Vulkan
device memory object, call:

include::{generated}/api/protos/vkGetMemoryAndroidHardwareBufferANDROID.adoc[]

  * pname:device is the logical device that created the device memory being
    exported.
  * pname:pInfo is a pointer to a
    slink:VkMemoryGetAndroidHardwareBufferInfoANDROID structure containing
    parameters of the export operation.
  * pname:pBuffer will return an Android hardware buffer referencing the
    payload of the device memory object.

Each call to fname:vkGetMemoryAndroidHardwareBufferANDROID must: return an
Android hardware buffer with a new reference acquired in addition to the
reference held by the slink:VkDeviceMemory.
To avoid leaking resources, the application must: release the reference by
calling code:AHardwareBuffer_release when it is no longer needed.
When called with the same handle in
slink:VkMemoryGetAndroidHardwareBufferInfoANDROID::pname:memory,
fname:vkGetMemoryAndroidHardwareBufferANDROID must: return the same Android
hardware buffer object.
If the device memory was created by importing an Android hardware buffer,
fname:vkGetMemoryAndroidHardwareBufferANDROID must: return that same Android
hardware buffer object.

include::{generated}/validity/protos/vkGetMemoryAndroidHardwareBufferANDROID.adoc[]
--

[open,refpage='VkMemoryGetAndroidHardwareBufferInfoANDROID',desc='Structure describing an Android hardware buffer memory export operation',type='structs']
--
The sname:VkMemoryGetAndroidHardwareBufferInfoANDROID structure is defined
as:

include::{generated}/api/structs/VkMemoryGetAndroidHardwareBufferInfoANDROID.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memory is the memory object from which the Android hardware buffer
    will be exported.

.Valid Usage
****
  * [[VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-handleTypes-01882]]
    ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
    must: have been included in
    slink:VkExportMemoryAllocateInfo::pname:handleTypes when pname:memory
    was created
  * [[VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-pNext-01883]]
    If the pname:pNext chain of the slink:VkMemoryAllocateInfo used to
    allocate pname:memory included a slink:VkMemoryDedicatedAllocateInfo
    with non-`NULL` pname:image member, then that pname:image must: already
    be bound to pname:memory
****

include::{generated}/validity/structs/VkMemoryGetAndroidHardwareBufferInfoANDROID.adoc[]
--

[open,refpage='vkGetAndroidHardwareBufferPropertiesANDROID',desc='Get Properties of External Memory Android Hardware Buffers',type='protos']
--
To determine the memory parameters to use when importing an Android hardware
buffer, call:

include::{generated}/api/protos/vkGetAndroidHardwareBufferPropertiesANDROID.adoc[]

  * pname:device is the logical device that will be importing pname:buffer.
  * pname:buffer is the Android hardware buffer which will be imported.
  * pname:pProperties is a pointer to a
    slink:VkAndroidHardwareBufferPropertiesANDROID structure in which the
    properties of pname:buffer are returned.

.Valid Usage
****
  * [[VUID-vkGetAndroidHardwareBufferPropertiesANDROID-buffer-01884]]
    pname:buffer must: be a valid Android hardware buffer object with at
    least one of the code:AHARDWAREBUFFER_USAGE_GPU_* flags in its
    code:AHardwareBuffer_Desc::code:usage
****

include::{generated}/validity/protos/vkGetAndroidHardwareBufferPropertiesANDROID.adoc[]
--

[open,refpage='VkAndroidHardwareBufferPropertiesANDROID',desc='Properties of External Memory Android Hardware Buffers',type='structs']
--
The sname:VkAndroidHardwareBufferPropertiesANDROID structure returned is
defined as:

include::{generated}/api/structs/VkAndroidHardwareBufferPropertiesANDROID.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:allocationSize is the size of the external memory
  * pname:memoryTypeBits is a bitmask containing one bit set for every
    memory type which the specified Android hardware buffer can: be imported
    as.

include::{generated}/validity/structs/VkAndroidHardwareBufferPropertiesANDROID.adoc[]
--

[open,refpage='VkAndroidHardwareBufferFormatPropertiesANDROID',desc='Structure describing the image format properties of an Android hardware buffer',type='structs']
--
To obtain format properties of an Android hardware buffer, include a
sname:VkAndroidHardwareBufferFormatPropertiesANDROID structure in the
pname:pNext chain of the slink:VkAndroidHardwareBufferPropertiesANDROID
structure passed to flink:vkGetAndroidHardwareBufferPropertiesANDROID.
This structure is defined as:

include::{generated}/api/structs/VkAndroidHardwareBufferFormatPropertiesANDROID.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:format is the Vulkan format corresponding to the Android hardware
    buffer's format, or ename:VK_FORMAT_UNDEFINED if there is not an
    equivalent Vulkan format.
  * pname:externalFormat is an implementation-defined external format
    identifier for use with slink:VkExternalFormatANDROID.
    It must: not be zero.
  * pname:formatFeatures describes the capabilities of this external format
    when used with an image bound to memory imported from pname:buffer.
  * pname:samplerYcbcrConversionComponents is the component swizzle that
    should: be used in slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedYcbcrModel is a suggested color model to use in the
    slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedYcbcrRange is a suggested numerical value range to use in
    slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedXChromaOffset is a suggested X chroma offset to use in
    slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedYChromaOffset is a suggested Y chroma offset to use in
    slink:VkSamplerYcbcrConversionCreateInfo.

If the Android hardware buffer has one of the formats listed in the
<<memory-external-android-hardware-buffer-formats,Format Equivalence
table>>, then pname:format must: have the equivalent Vulkan format listed in
the table.
Otherwise, pname:format may: be ename:VK_FORMAT_UNDEFINED, indicating the
Android hardware buffer can: only be used with an external format.

The pname:formatFeatures member must: include
ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
ename:VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
ename:VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should: include
ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.

[NOTE]
.Note
====
The pname:formatFeatures member only indicates the features available when
using an
<<memory-external-android-hardware-buffer-external-formats,external-format
image>> created from the Android hardware buffer.
Images from Android hardware buffers with a format other than
ename:VK_FORMAT_UNDEFINED are subject to the format capabilities obtained
from flink:vkGetPhysicalDeviceFormatProperties2, and
flink:vkGetPhysicalDeviceImageFormatProperties2 with appropriate parameters.
These sets of features are independent of each other, e.g. the external
format will support sampler {YCbCr} conversion even if the non-external
format does not, and writing to non-external format images is possible but
writing to external format images is not.
====

Android hardware buffers with the same external format must: have the same
support for ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT,
ename:VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT,
ename:VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT,
ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT,
ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT,
and
ename:VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT.
in pname:formatFeatures.
Other format features may: differ between Android hardware buffers that have
the same external format.
This allows applications to use the same slink:VkSamplerYcbcrConversion
object (and samplers and pipelines created from them) for any Android
hardware buffers that have the same external format.

If pname:format is not ename:VK_FORMAT_UNDEFINED, then the value of
pname:samplerYcbcrConversionComponents must: be valid when used as the
pname:components member of slink:VkSamplerYcbcrConversionCreateInfo with
that format.
If pname:format is ename:VK_FORMAT_UNDEFINED, all members of
pname:samplerYcbcrConversionComponents must: be the
<<resources-image-views-identity-mappings,identity swizzle>>.

Implementations may: not always be able to determine the color model,
numerical range, or chroma offsets of the image contents, so the values in
sname:VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
Applications should: treat these values as sensible defaults to use in the
absence of more reliable information obtained through some other means.
If the underlying physical device is also usable via OpenGL ES with the
{GLregistry}/OES/OES_EGL_image_external.txt[`GL_OES_EGL_image_external`]
extension, the implementation should: suggest values that will produce
similar sampled values as would be obtained by sampling the same external
image via code:samplerExternalOES in OpenGL ES using equivalent sampler
parameters.

[NOTE]
.Note
====
Since
{GLregistry}/OES/OES_EGL_image_external.txt[`GL_OES_EGL_image_external`]
does not require the same sampling and conversion calculations as Vulkan
does, achieving identical results between APIs may: not be possible on some
implementations.
====

include::{generated}/validity/structs/VkAndroidHardwareBufferFormatPropertiesANDROID.adoc[]
--

ifdef::VK_VERSION_1_3,VK_KHR_format_feature_flags2[]
[open,refpage='VkAndroidHardwareBufferFormatProperties2ANDROID',desc='Structure describing the image format properties of an Android hardware buffer',type='structs']
--
The format properties of an Android hardware buffer can: be obtained by
including a sname:VkAndroidHardwareBufferFormatProperties2ANDROID structure
in the pname:pNext chain of the
slink:VkAndroidHardwareBufferPropertiesANDROID structure passed to
flink:vkGetAndroidHardwareBufferPropertiesANDROID.
This structure is defined as:

include::{generated}/api/structs/VkAndroidHardwareBufferFormatProperties2ANDROID.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:format is the Vulkan format corresponding to the Android hardware
    buffer's format, or ename:VK_FORMAT_UNDEFINED if there is not an
    equivalent Vulkan format.
  * pname:externalFormat is an implementation-defined external format
    identifier for use with slink:VkExternalFormatANDROID.
    It must: not be zero.
  * pname:formatFeatures describes the capabilities of this external format
    when used with an image bound to memory imported from pname:buffer.
  * pname:samplerYcbcrConversionComponents is the component swizzle that
    should: be used in slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedYcbcrModel is a suggested color model to use in the
    slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedYcbcrRange is a suggested numerical value range to use in
    slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedXChromaOffset is a suggested X chroma offset to use in
    slink:VkSamplerYcbcrConversionCreateInfo.
  * pname:suggestedYChromaOffset is a suggested Y chroma offset to use in
    slink:VkSamplerYcbcrConversionCreateInfo.

The bits reported in pname:formatFeatures must: include the bits reported in
the corresponding fields of
sname:VkAndroidHardwareBufferFormatPropertiesANDROID::pname:formatFeatures.

include::{generated}/validity/structs/VkAndroidHardwareBufferFormatProperties2ANDROID.adoc[]
--
endif::VK_VERSION_1_3,VK_KHR_format_feature_flags2[]
endif::VK_ANDROID_external_memory_android_hardware_buffer[]


ifdef::VK_NV_external_memory_rdma[]
=== Remote Device External Memory

[open,refpage='vkGetMemoryRemoteAddressNV',desc='Get an address for a memory object accessible by remote devices',type='protos']
--
To export an address representing the payload of a Vulkan device memory
object accessible by remote devices, call:

include::{generated}/api/protos/vkGetMemoryRemoteAddressNV.adoc[]

  * pname:device is the logical device that created the device memory being
    exported.
  * pname:pMemoryGetRemoteAddressInfo is a pointer to a
    slink:VkMemoryGetRemoteAddressInfoNV structure containing parameters of
    the export operation.
  * pname:pAddress is a pointer to a basetype:VkRemoteAddressNV value in
    which an address representing the payload of the device memory object is
    returned.

More communication may be required between the kernel-mode drivers of the
devices involved.
This information is out of scope of this documentation and should be
requested from the vendors of the devices.

include::{generated}/validity/protos/vkGetMemoryRemoteAddressNV.adoc[]
--

[open,refpage='VkMemoryGetRemoteAddressInfoNV',desc='Structure describing a remote accessible address export operation',type='structs']
--
The sname:VkMemoryGetRemoteAddressInfoNV structure is defined as:

include::{generated}/api/structs/VkMemoryGetRemoteAddressInfoNV.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memory is the memory object from which the remote accessible
    address will be exported.
  * pname:handleType is the type of handle requested.

.Valid Usage
****
  * [[VUID-VkMemoryGetRemoteAddressInfoNV-handleType-04966]]
    pname:handleType must: have been included in
    slink:VkExportMemoryAllocateInfo::pname:handleTypes when pname:memory
    was created
****

include::{generated}/validity/structs/VkMemoryGetRemoteAddressInfoNV.adoc[]
--

[open,refpage='VkRemoteAddressNV',desc='Remote device address type',type='basetypes']
--
basetype:VkRemoteAddressNV represents an address of a memory object
accessible by remote devices, as returned in
flink:vkGetMemoryRemoteAddressNV::pname:pAddress.

include::{generated}/api/basetypes/VkRemoteAddressNV.adoc[]
--
endif::VK_NV_external_memory_rdma[]

ifdef::VK_FUCHSIA_external_memory[]
include::{chapters}/VK_FUCHSIA_external_memory/device_memory.adoc[]
endif::VK_FUCHSIA_external_memory[]

ifdef::VK_EXT_metal_objects[]
include::{chapters}/VK_EXT_metal_objects/device_memory.adoc[]
endif::VK_EXT_metal_objects[]

ifdef::VK_VERSION_1_1,VK_KHR_device_group[]
=== Device Group Memory Allocations

[open,refpage='VkMemoryAllocateFlagsInfo',desc='Structure controlling how many instances of memory will be allocated',type='structs']
--
If the pname:pNext chain of slink:VkMemoryAllocateInfo includes a
sname:VkMemoryAllocateFlagsInfo structure, then that structure includes
flags and a device mask controlling how many instances of the memory will be
allocated.

The sname:VkMemoryAllocateFlagsInfo structure is defined as:

include::{generated}/api/structs/VkMemoryAllocateFlagsInfo.adoc[]

ifdef::VK_KHR_device_group[]
or the equivalent

include::{generated}/api/structs/VkMemoryAllocateFlagsInfoKHR.adoc[]
endif::VK_KHR_device_group[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:flags is a bitmask of elink:VkMemoryAllocateFlagBits controlling
    the allocation.
  * pname:deviceMask is a mask of physical devices in the logical device,
    indicating that memory must: be allocated on each device in the mask, if
    ename:VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set in pname:flags.

If ename:VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is not set, the number of
instances allocated depends on whether
ename:VK_MEMORY_HEAP_MULTI_INSTANCE_BIT is set in the memory heap.
If ename:VK_MEMORY_HEAP_MULTI_INSTANCE_BIT is set, then memory is allocated
for every physical device in the logical device (as if pname:deviceMask has
bits set for all device indices).
If ename:VK_MEMORY_HEAP_MULTI_INSTANCE_BIT is not set, then a single
instance of memory is allocated (as if pname:deviceMask is set to one).

On some implementations, allocations from a multi-instance heap may: consume
memory on all physical devices even if the pname:deviceMask excludes some
devices.
If slink:VkPhysicalDeviceGroupProperties::pname:subsetAllocation is
ename:VK_TRUE, then memory is only consumed for the devices in the device
mask.

[NOTE]
.Note
====
In practice, most allocations on a multi-instance heap will be allocated
across all physical devices.
Unicast allocation support is an optional optimization for a minority of
allocations.
====

.Valid Usage
****
  * [[VUID-VkMemoryAllocateFlagsInfo-deviceMask-00675]]
    If ename:VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set, pname:deviceMask
    must: be a valid device mask
  * [[VUID-VkMemoryAllocateFlagsInfo-deviceMask-00676]]
    If ename:VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set, pname:deviceMask
    must: not be zero
****

include::{generated}/validity/structs/VkMemoryAllocateFlagsInfo.adoc[]
--

[open,refpage='VkMemoryAllocateFlagBits',desc='Bitmask specifying flags for a device memory allocation',type='enums']
--
Bits which can: be set in slink:VkMemoryAllocateFlagsInfo::pname:flags,
controlling device memory allocation, are:

include::{generated}/api/enums/VkMemoryAllocateFlagBits.adoc[]

ifdef::VK_KHR_device_group[]
or the equivalent

include::{generated}/api/enums/VkMemoryAllocateFlagBitsKHR.adoc[]
endif::VK_KHR_device_group[]

  * ename:VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT specifies that memory will be
    allocated for the devices in
    slink:VkMemoryAllocateFlagsInfo::pname:deviceMask.
ifdef::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
  * ename:VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT specifies that the memory
    can: be attached to a buffer object created with the
    ename:VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT bit set in pname:usage,
    and that the memory handle can: be used to retrieve an opaque address
    via flink:vkGetDeviceMemoryOpaqueCaptureAddress.
  * ename:VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT specifies
    that the memory's address can: be saved and reused on a subsequent run
    (e.g. for trace capture and replay), see
    slink:VkBufferOpaqueCaptureAddressCreateInfo for more detail.
endif::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
--

[open,refpage='VkMemoryAllocateFlags',desc='Bitmask of VkMemoryAllocateFlagBits',type='flags']
--
include::{generated}/api/flags/VkMemoryAllocateFlags.adoc[]

ifdef::VK_KHR_device_group[]
or the equivalent

include::{generated}/api/flags/VkMemoryAllocateFlagsKHR.adoc[]
endif::VK_KHR_device_group[]

tname:VkMemoryAllocateFlags is a bitmask type for setting a mask of zero or
more elink:VkMemoryAllocateFlagBits.
--
endif::VK_VERSION_1_1,VK_KHR_device_group[]


ifdef::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
=== Opaque Capture Address Allocation

[open,refpage='VkMemoryOpaqueCaptureAddressAllocateInfo',desc='Request a specific address for a memory allocation',type='structs',alias='VkMemoryOpaqueCaptureAddressAllocateInfoKHR']
--
To request a specific device address for a memory allocation, add a
slink:VkMemoryOpaqueCaptureAddressAllocateInfo structure to the pname:pNext
chain of the slink:VkMemoryAllocateInfo structure.
The sname:VkMemoryOpaqueCaptureAddressAllocateInfo structure is defined as:

include::{generated}/api/structs/VkMemoryOpaqueCaptureAddressAllocateInfo.adoc[]

ifdef::VK_KHR_buffer_device_address[]
or the equivalent

include::{generated}/api/structs/VkMemoryOpaqueCaptureAddressAllocateInfoKHR.adoc[]
endif::VK_KHR_buffer_device_address[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:opaqueCaptureAddress is the opaque capture address requested for
    the memory allocation.

If pname:opaqueCaptureAddress is zero, no specific address is requested.

If pname:opaqueCaptureAddress is not zero, it should: be an address
retrieved from flink:vkGetDeviceMemoryOpaqueCaptureAddress on an identically
created memory allocation on the same implementation.

[NOTE]
.Note
====
In most cases, it is expected that a non-zero pname:opaqueAddress is an
address retrieved from flink:vkGetDeviceMemoryOpaqueCaptureAddress on an
identically created memory allocation.
If this is not the case, it is likely that
ename:VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS errors will occur.

This is, however, not a strict requirement because trace capture/replay
tools may need to adjust memory allocation parameters for imported memory.
====

If this structure is not present, it is as if pname:opaqueCaptureAddress is
zero.

include::{generated}/validity/structs/VkMemoryOpaqueCaptureAddressAllocateInfo.adoc[]
--

endif::VK_VERSION_1_2,VK_KHR_buffer_device_address[]


=== Freeing Device Memory

[open,refpage='vkFreeMemory',desc='Free device memory',type='protos']
--
To free a memory object, call:

include::{generated}/api/protos/vkFreeMemory.adoc[]

  * pname:device is the logical device that owns the memory.
  * pname:memory is the slink: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
in the _pending state_.
Memory can: be freed whilst still bound to resources, but those resources
must: not be used afterwards.
Freeing a memory object releases the reference it held, if any, to its
payload.
If there are still any bound images or buffers, the memory object's payload
may: not be immediately released by the implementation, but must: be
released by the time all bound images and buffers have been destroyed.
Once all references to a payload are 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.

[NOTE]
.Note
====
As described <<memory-device-unmap-does-not-flush, below>>, host writes are
not implicitly flushed when the memory object is unmapped, but the
implementation must: guarantee that writes that have not been flushed do not
affect any other memory.
====

.Valid Usage
****
  * [[VUID-vkFreeMemory-memory-00677]]
    All submitted commands that refer to pname:memory (via images or
    buffers) must: have completed execution
****

include::{generated}/validity/protos/vkFreeMemory.adoc[]
--


[[memory-device-hostaccess]]
=== Host Access to Device Memory Objects

Memory objects created with flink: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.

[open,refpage='vkMapMemory',desc='Map a memory object into application address space',type='protos']
--
To retrieve a host virtual address pointer to a region of a mappable memory
object, call:

include::{generated}/api/protos/vkMapMemory.adoc[]

  * pname:device is the logical device that owns the memory.
  * pname:memory is the slink: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 is a pointer to a code:void* variable in which a
    host-accessible pointer to the beginning of the mapped range is
    returned.
    This pointer minus pname:offset must: be aligned to at least
    slink:VkPhysicalDeviceLimits::pname:minMemoryMapAlignment.

After a successful call to fname:vkMapMemory the memory object pname:memory
is considered to be currently _host mapped_.

[NOTE]
.Note
====
It is an application error to call fname:vkMapMemory on a memory object that
is already _host 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
ename: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
flink: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
slink:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize, and round the end
of the range up to the nearest multiple of
slink:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize.

While a range of device memory is host mapped, 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
****
  * [[VUID-vkMapMemory-memory-00678]]
    pname:memory must: not be currently host mapped
  * [[VUID-vkMapMemory-offset-00679]]
    pname:offset must: be less than the size of pname:memory
  * [[VUID-vkMapMemory-size-00680]]
    If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be
    greater than `0`
  * [[VUID-vkMapMemory-size-00681]]
    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
  * [[VUID-vkMapMemory-memory-00682]]
    pname:memory must: have been created with a memory type that reports
    ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
ifdef::VK_KHR_device_group[]
  * [[VUID-vkMapMemory-memory-00683]]
    pname:memory must: not have been allocated with multiple instances
endif::VK_KHR_device_group[]
****

include::{generated}/validity/protos/vkMapMemory.adoc[]
--

[open,refpage='VkMemoryMapFlags',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkMemoryMapFlags.adoc[]

tname:VkMemoryMapFlags is a bitmask type for setting a mask, but is
currently reserved for future use.
--

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 a performance cost.
However, <<synchronization-dependencies-available-and-visible, availability
and visibility operations>> still need to be managed on the device.
See the description of <<synchronization-host-access-types, host access
types>> for more information.
====

ifdef::VK_EXT_external_memory_host[]
[NOTE]
.Note
====
While memory objects imported from a handle type of
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT or
ename: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
flink: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.
fname:vkFlushMappedMemoryRanges and fname: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 flink:vkMapMemory.
====
endif::VK_EXT_external_memory_host[]

[open,refpage='vkFlushMappedMemoryRanges',desc='Flush mapped memory ranges',type='protos']
--
To flush ranges of non-coherent memory from the host caches, call:

include::{generated}/api/protos/vkFlushMappedMemoryRanges.adoc[]

  * 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 guarantees that host writes to the memory
ranges described by pname:pMemoryRanges are made available to the host
memory domain, such that they can: be made available to the device memory
domain via <<synchronization-dependencies-available-and-visible, memory
domain operations>> using the ename:VK_ACCESS_HOST_WRITE_BIT
<<synchronization-access-types,access type>>.

Within each range described by pname:pMemoryRanges, each set of
pname:nonCoherentAtomSize bytes in that range is flushed if any byte in that
set has been written by the host since it was first host mapped, or the last
time it was flushed.
If pname:pMemoryRanges includes sets of pname:nonCoherentAtomSize bytes
where no bytes have been written by the host, those bytes must: not be
flushed.

[[memory-device-unmap-does-not-flush]]
Unmapping non-coherent memory does not implicitly flush the host mapped
memory, and host writes that have not been flushed may: not ever be visible
to the device.
However, implementations must: ensure that writes that have not been flushed
do not become visible to any other memory.

[NOTE]
.Note
====
The above guarantee avoids a potential memory corruption in scenarios where
host writes to a mapped memory object have not been flushed before the
memory is unmapped (or freed), and the virtual address range is subsequently
reused for a different mapping (or memory allocation).
====

include::{generated}/validity/protos/vkFlushMappedMemoryRanges.adoc[]
--

[open,refpage='vkInvalidateMappedMemoryRanges',desc='Invalidate ranges of mapped memory objects',type='protos']
--
To invalidate ranges of non-coherent memory from the host caches, call:

include::{generated}/api/protos/vkInvalidateMappedMemoryRanges.adoc[]

  * 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 guarantees that device writes to the
memory ranges described by pname:pMemoryRanges, which have been made
available to the host memory domain using the ename:VK_ACCESS_HOST_WRITE_BIT
and ename:VK_ACCESS_HOST_READ_BIT <<synchronization-access-types, access
types>>, are made visible to the host.
If a range of non-coherent memory is written by the host and then
invalidated without first being flushed, its contents are undefined:.

Within each range described by pname:pMemoryRanges, each set of
pname:nonCoherentAtomSize bytes in that range is invalidated if any byte in
that set has been written by the device since it was first host mapped, or
the last time it was invalidated.

[NOTE]
.Note
====
Mapping non-coherent memory does not implicitly invalidate that memory.
====

include::{generated}/validity/protos/vkInvalidateMappedMemoryRanges.adoc[]
--

[open,refpage='VkMappedMemoryRange',desc='Structure specifying a mapped memory range',type='structs']
--
The sname:VkMappedMemoryRange structure is defined as:

include::{generated}/api/structs/VkMappedMemoryRange.adoc[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    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
****
  * [[VUID-VkMappedMemoryRange-memory-00684]]
    pname:memory must: be currently host mapped
  * [[VUID-VkMappedMemoryRange-size-00685]]
    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
  * [[VUID-VkMappedMemoryRange-size-00686]]
    If pname:size is equal to ename:VK_WHOLE_SIZE, pname:offset must: be
    within the currently mapped range of pname:memory
  * [[VUID-VkMappedMemoryRange-offset-00687]]
    pname:offset must: be a multiple of
    slink:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize
  * [[VUID-VkMappedMemoryRange-size-01389]]
    If pname:size is equal to ename:VK_WHOLE_SIZE, the end of the current
    mapping of pname:memory must: either be a multiple of
    slink:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize bytes from the
    beginning of the memory object, or be equal to the end of the memory
    object
  * [[VUID-VkMappedMemoryRange-size-01390]]
    If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must:
    either be a multiple of
    slink:VkPhysicalDeviceLimits::pname:nonCoherentAtomSize, or pname:offset
    plus pname:size must: equal the size of pname:memory
****

include::{generated}/validity/structs/VkMappedMemoryRange.adoc[]
--


[open,refpage='vkUnmapMemory',desc='Unmap a previously mapped memory object',type='protos']
--
To unmap a memory object once host access to it is no longer needed by the
application, call:

include::{generated}/api/protos/vkUnmapMemory.adoc[]

  * pname:device is the logical device that owns the memory.
  * pname:memory is the memory object to be unmapped.

.Valid Usage
****
  * [[VUID-vkUnmapMemory-memory-00689]]
    pname:memory must: be currently host mapped
****

include::{generated}/validity/protos/vkUnmapMemory.adoc[]
--


[[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.
====

[open,refpage='vkGetDeviceMemoryCommitment',desc='Query the current commitment for a VkDeviceMemory',type='protos']
--
To determine the amount of lazily-allocated memory that is currently
committed for a memory object, call:

include::{generated}/api/protos/vkGetDeviceMemoryCommitment.adoc[]

  * 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
pname:heapIndex indicated by the memory type that the memory object was
created with.

.Valid Usage
****
  * [[VUID-vkGetDeviceMemoryCommitment-memory-00690]]
    pname:memory must: have been created with a memory type that reports
    ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
****

include::{generated}/validity/protos/vkGetDeviceMemoryCommitment.adoc[]
--


ifdef::VK_VERSION_1_1[]
[[memory-protected-memory]]
=== Protected Memory

_Protected memory_ divides device memory into protected device memory and
unprotected device memory.

Protected memory adds the following concepts:

  * Memory:
  ** Unprotected device memory, which can: be visible to the device and can:
     be visible to the host
  ** Protected device memory, which can: be visible to the device but must:
     not be visible to the host
  * Resources:
  ** Unprotected images and unprotected buffers, to which unprotected memory
     can: be bound
  ** Protected images and protected buffers, to which protected memory can:
     be bound
  * Command buffers:
  ** Unprotected command buffers, which can: be submitted to a device queue
     to execute unprotected queue operations
  ** Protected command buffers, which can: be submitted to a
     protected-capable device queue to execute protected queue operations
  * Device queues:
  ** Unprotected device queues, to which unprotected command buffers can: be
     submitted
  ** Protected-capable device queues, to which unprotected command buffers
     or protected command buffers can: be submitted
  * Queue submissions
  ** Unprotected queue submissions, through which unprotected command
     buffers can: be submitted
  ** Protected queue submissions, through which protected command buffers
     can: be submitted
  * Queue operations
  ** Unprotected queue operations
  ** Protected queue operations

ifdef::VK_EXT_pipeline_protected_access[]
[NOTE]
.Note
====
When the <<features-protectedMemory, pname:protectedMemory>> feature is
enabled, all pipelines may: be recorded in either protected or unprotected
command buffers (or both), which may incur an extra cost on some
implementations.
This can: be mitigated by enabling the <<features-pipelineProtectedAccess,
pname:pipelineProtectedAccess>> feature, in which case pipelines created
with ename:VK_PIPELINE_CREATE_PROTECTED_ACCESS_ONLY_BIT_EXT may only be
recorded in protected command buffers, and pipelines created with
ename:VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT may only be recorded in
unprotected command buffers.
====
endif::VK_EXT_pipeline_protected_access[]


[[memory-protected-access-rules]]
==== Protected Memory Access Rules

If slink:VkPhysicalDeviceProtectedMemoryProperties::pname:protectedNoFault
is ename:VK_FALSE, applications must: not perform any of the following
operations:

  * Write to unprotected memory within protected queue operations.
  * Access protected memory within protected queue operations other than in
    framebuffer-space pipeline stages, the compute shader stage, or the
    transfer stage.
  * Perform a query within protected queue operations.

If slink:VkPhysicalDeviceProtectedMemoryProperties::pname:protectedNoFault
is ename:VK_TRUE, these operations are valid, but reads will return
undefined: values, and writes will either be dropped or store undefined:
values.

Additionally, indirect operations must: not be performed within protected
queue operations.

Whether these operations are valid or not, or if any other invalid usage is
performed, the implementation must: guarantee that:

  * Protected device memory must: never be visible to the host.
  * Values written to unprotected device memory must: not be a function of
    values from protected memory.
endif::VK_VERSION_1_1[]


ifdef::VK_KHR_external_memory_capabilities+VK_ANDROID_external_memory_android_hardware_buffer[]
[[memory-external-handle-types]]
=== External Memory Handle Types


[[memory-external-android-hardware-buffer]]
==== Android Hardware Buffer

Android's NDK defines basetype: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
slink:VkDeviceMemory objects for access via Vulkan, or exported from Vulkan.
An slink:VkImage or slink:VkBuffer can: be bound to the imported or exported
slink:VkDeviceMemory object if it is created with
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID.

[open,refpage='AHardwareBuffer',desc='Android hardware buffer type',type='basetypes']
--
To remove an unnecessary compile-time dependency, an incomplete type
definition of basetype:AHardwareBuffer is provided in the Vulkan headers:

include::{generated}/api/basetypes/AHardwareBuffer.adoc[]

The actual basetype:AHardwareBuffer type is defined in Android NDK headers.
--

[NOTE]
.Note
====
The NDK format, usage, and size/dimensions of an basetype:AHardwareBuffer
object can be obtained with the code: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 code:AHardwareBuffer_Desc properties it returns.
====

Android hardware buffer objects are reference-counted using Android NDK
functions outside of the scope of this specification.
A slink:VkDeviceMemory imported from an Android hardware buffer or that can:
be exported to an Android hardware buffer must: acquire a reference to its
basetype: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 pname: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 <<resources-external-sharing,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
<<synchronization-queue-transfers>> 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.


[[memory-external-android-hardware-buffer-optimal-usages]]
===== 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
code: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
<<memory-external-android-hardware-buffer-usage, usage equivalence table>>
which do not have Android hardware buffer equivalents.

An slink:VkAndroidHardwareBufferUsageANDROID structure can: be included in
the pname:pNext chain of a slink:VkImageFormatProperties2 structure passed
to flink: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
(code: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.


[[memory-external-android-hardware-buffer-external-formats]]
===== 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 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 {YCbCr} conversion
enabled, and must: have optimal tiling.

Images that will be backed by an Android hardware buffer can: use an
external format by setting slink:VkImageCreateInfo::pname:format to
ename:VK_FORMAT_UNDEFINED and including a slink:VkExternalFormatANDROID
structure in the pname:pNext chain.
Images can: be created with an external format even if the Android hardware
buffer has a format which has an
<<memory-external-android-hardware-buffer-formats,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 slink:VkAndroidHardwareBufferFormatPropertiesANDROID structure to
flink:vkGetAndroidHardwareBufferPropertiesANDROID.


[[memory-external-android-hardware-buffer-image-resources]]
===== 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:
sname:VkMemoryDedicatedRequirements::pname:requiresDedicatedAllocation must:
be ename:VK_TRUE for images created with
slink:VkExternalMemoryImageCreateInfo::pname:handleTypes that includes
ename: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
basetype:AHardwareBuffer properties as described by the valid usage of
slink: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 code:width and code:height members of code:AHardwareBuffer_Desc
    must: be the same as the pname:width and pname:height members of
    slink:VkImageCreateInfo::pname:extent, respectively.
  * The code:layers member of code:AHardwareBuffer_Desc must: be the same as
    the pname:arrayLayers member of slink:VkImageCreateInfo.
  * The code:format member of code:AHardwareBuffer_Desc must: be equivalent
    to slink:VkImageCreateInfo::pname:format as defined by
    <<memory-external-android-hardware-buffer-formats,AHardwareBuffer Format
    Equivalence>>.
  * The code:usage member of code:AHardwareBuffer_Desc must: include bits
    corresponding to bits included in slink:VkImageCreateInfo::pname:usage
    and slink:VkImageCreateInfo::pname:flags where such a correspondence
    exists according to
    <<memory-external-android-hardware-buffer-usage,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
    slink: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
slink:VkExternalImageFormatProperties to
flink:vkGetPhysicalDeviceImageFormatProperties2 with pname:handleType set to
ename:VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID.
Any Android hardware buffer successfully allocated outside Vulkan with usage
that includes code: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.

[[memory-external-android-hardware-buffer-formats]]
.AHardwareBuffer Format Equivalence
[width="100%",options="header"]
|====
| AHardwareBuffer Format                         | Vulkan Format
| code:AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM     | ename:VK_FORMAT_R8G8B8A8_UNORM
| code:AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM ^1^ | ename:VK_FORMAT_R8G8B8A8_UNORM
| code:AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM       | ename:VK_FORMAT_R8G8B8_UNORM
| code:AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM       | ename:VK_FORMAT_R5G6B5_UNORM_PACK16
| code:AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT | ename:VK_FORMAT_R16G16B16A16_SFLOAT
| code:AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM  | ename:VK_FORMAT_A2B10G10R10_UNORM_PACK32
| code:AHARDWAREBUFFER_FORMAT_D16_UNORM          | ename:VK_FORMAT_D16_UNORM
| code:AHARDWAREBUFFER_FORMAT_D24_UNORM          | ename:VK_FORMAT_X8_D24_UNORM_PACK32
| code:AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT  | ename:VK_FORMAT_D24_UNORM_S8_UINT
| code:AHARDWAREBUFFER_FORMAT_D32_FLOAT          | ename:VK_FORMAT_D32_SFLOAT
| code:AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT  | ename:VK_FORMAT_D32_SFLOAT_S8_UINT
| code:AHARDWAREBUFFER_FORMAT_S8_UINT            | ename:VK_FORMAT_S8_UINT
|====

[[memory-external-android-hardware-buffer-usage]]
.AHardwareBuffer Usage Equivalence
[width="100%",options="header"]
|====
| AHardwareBuffer Usage                          | Vulkan Usage or Creation Flag
| None                                           | ename:VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| None                                           | ename:VK_IMAGE_USAGE_TRANSFER_DST_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE   | ename:VK_IMAGE_USAGE_SAMPLED_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE   | ename:VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER ^3^ | ename:VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER ^3^ | ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP        | ename:VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE | None ^2^
ifdef::VK_VERSION_1_1[]
| code:AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT   | ename:VK_IMAGE_CREATE_PROTECTED_BIT
endif::VK_VERSION_1_1[]
| None                                           | ename:VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
| None                                           | ename:VK_IMAGE_CREATE_EXTENDED_USAGE_BIT
| code:AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER ^4^ | ename:VK_IMAGE_USAGE_STORAGE_BIT
|====

1::
    Vulkan does not differentiate between
    code:AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM and
    code:AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: they both behave as
    ename:VK_FORMAT_R8G8B8A8_UNORM.
    After an external entity writes to a
    code:AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM Android hardware buffer, the
    values read by Vulkan from the X/A component are undefined:.
    To emulate the traditional behavior of the X component during sampling
    or blending, applications should: use ename:VK_COMPONENT_SWIZZLE_ONE in
    image view component mappings and ename:VK_BLEND_FACTOR_ONE in color
    blend factors.
    There is no way to avoid copying these undefined: values when copying
    from such an image to another image or buffer.

2::
    The code:AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE flag does not
    correspond to a Vulkan image usage or creation flag.
    Instead, its presence indicates that the Android hardware buffer
    contains a complete mipmap chain, and its absence indicates that the
    Android hardware buffer contains only a single mip level.

3::
    Only image usages valid for the format are valid.
    It would be invalid to take a Android Hardware Buffer with a format of
    code:AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM that has a
    code:AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER usage and try to create an
    image with ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT.

4::
    In combination with a hardware buffer format other than code:BLOB.

ifdef::VK_VERSION_1_2,VK_KHR_image_format_list[]
[NOTE]
.Note
====
When using ename:VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT with Android hardware
buffer images, applications should: use slink: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.
====
endif::VK_VERSION_1_2,VK_KHR_image_format_list[]


[[memory-external-android-hardware-buffer-buffer-resources]]
===== Android Hardware Buffer Buffer Resources

Android hardware buffers with a format of code:AHARDWAREBUFFER_FORMAT_BLOB
and usage that includes code:AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER can: be
used as the backing store for slink:VkBuffer objects.
Such Android hardware buffers have a size in bytes specified by their
code:width; code:height and code:layers are both `1`.

Unlike images, buffer resources backed by Android hardware buffers do not
require dedicated allocations.

Exported basetype:AHardwareBuffer objects that do not have dedicated images
must: have a format of code:AHARDWAREBUFFER_FORMAT_BLOB, usage must: include
code:AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER, code:width must: equal the
device memory allocation size, and code:height and code:layers must: be `1`.
endif::VK_KHR_external_memory_capabilities+VK_ANDROID_external_memory_android_hardware_buffer[]


ifdef::VK_VERSION_1_1,VK_KHR_device_group[]
[[memory-peer-memory-features]]
=== Peer Memory Features

[open,refpage='vkGetDeviceGroupPeerMemoryFeatures',desc='Query supported peer memory features of a device',type='protos']
--
_Peer memory_ is memory that is allocated for a given physical device and
then bound to a resource and accessed by a different physical device, in a
logical device that represents multiple physical devices.
Some ways of reading and writing peer memory may: not be supported by a
device.

To determine how peer memory can: be accessed, call:

ifdef::VK_VERSION_1_1[]
include::{generated}/api/protos/vkGetDeviceGroupPeerMemoryFeatures.adoc[]
endif::VK_VERSION_1_1[]

ifdef::VK_VERSION_1_1+VK_KHR_device_group[or the equivalent command]

ifdef::VK_KHR_device_group[]
include::{generated}/api/protos/vkGetDeviceGroupPeerMemoryFeaturesKHR.adoc[]
endif::VK_KHR_device_group[]

  * pname:device is the logical device that owns the memory.
  * pname:heapIndex is the index of the memory heap from which the memory is
    allocated.
  * pname:localDeviceIndex is the device index of the physical device that
    performs the memory access.
  * pname:remoteDeviceIndex is the device index of the physical device that
    the memory is allocated for.
  * pname:pPeerMemoryFeatures is a pointer to a
    tlink:VkPeerMemoryFeatureFlags bitmask indicating which types of memory
    accesses are supported for the combination of heap, local, and remote
    devices.

.Valid Usage
****
  * [[VUID-vkGetDeviceGroupPeerMemoryFeatures-heapIndex-00691]]
    pname:heapIndex must: be less than pname:memoryHeapCount
  * [[VUID-vkGetDeviceGroupPeerMemoryFeatures-localDeviceIndex-00692]]
    pname:localDeviceIndex must: be a valid device index
  * [[VUID-vkGetDeviceGroupPeerMemoryFeatures-remoteDeviceIndex-00693]]
    pname:remoteDeviceIndex must: be a valid device index
  * [[VUID-vkGetDeviceGroupPeerMemoryFeatures-localDeviceIndex-00694]]
    pname:localDeviceIndex must: not equal pname:remoteDeviceIndex
****

include::{generated}/validity/protos/vkGetDeviceGroupPeerMemoryFeatures.adoc[]
--

[open,refpage='VkPeerMemoryFeatureFlagBits',desc='Bitmask specifying supported peer memory features',type='enums']
--
Bits which may: be set in
flink:vkGetDeviceGroupPeerMemoryFeatures::pname:pPeerMemoryFeatures,
indicating supported peer memory features, are:

include::{generated}/api/enums/VkPeerMemoryFeatureFlagBits.adoc[]

ifdef::VK_KHR_device_group[]
or the equivalent

include::{generated}/api/enums/VkPeerMemoryFeatureFlagBitsKHR.adoc[]
endif::VK_KHR_device_group[]

  * ename:VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT specifies that the memory can:
    be accessed as the source of any ftext:vkCmdCopy* command.
  * ename:VK_PEER_MEMORY_FEATURE_COPY_DST_BIT specifies that the memory can:
    be accessed as the destination of any ftext:vkCmdCopy* command.
  * ename:VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT specifies that the memory
    can: be read as any memory access type.
  * ename:VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT specifies that the memory
    can: be written as any memory access type.
    Shader atomics are considered to be writes.

[NOTE]
.Note
====
The peer memory features of a memory heap also apply to any accesses that
may: be performed during <<synchronization-image-layout-transitions, image
layout transitions>>.
====

ename:VK_PEER_MEMORY_FEATURE_COPY_DST_BIT must: be supported for all host
local heaps and for at least one device-local memory heap.

If a device does not support a peer memory feature, it is still valid to use
a resource that includes both local and peer memory bindings with the
corresponding access type as long as only the local bindings are actually
accessed.
For example, an application doing split-frame rendering would use
framebuffer attachments that include both local and peer memory bindings,
but would scissor the rendering to only update local memory.
--

[open,refpage='VkPeerMemoryFeatureFlags',desc='Bitmask of VkPeerMemoryFeatureFlagBits',type='flags']
--
include::{generated}/api/flags/VkPeerMemoryFeatureFlags.adoc[]

ifdef::VK_KHR_device_group[]
or the equivalent

include::{generated}/api/flags/VkPeerMemoryFeatureFlagsKHR.adoc[]
endif::VK_KHR_device_group[]

tname:VkPeerMemoryFeatureFlags is a bitmask type for setting a mask of zero
or more elink:VkPeerMemoryFeatureFlagBits.
--
endif::VK_VERSION_1_1,VK_KHR_device_group[]

ifdef::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
=== Opaque Capture Address Query

[open,refpage='vkGetDeviceMemoryOpaqueCaptureAddress',desc='Query an opaque capture address of a memory object',type='protos',alias='vkGetDeviceMemoryOpaqueCaptureAddressKHR']
--
To query a 64-bit opaque capture address value from a memory object, call:

ifdef::VK_VERSION_1_2[]
include::{generated}/api/protos/vkGetDeviceMemoryOpaqueCaptureAddress.adoc[]
endif::VK_VERSION_1_2[]

ifdef::VK_VERSION_1_2+VK_KHR_buffer_device_address[or the equivalent command]

ifdef::VK_KHR_buffer_device_address[]
include::{generated}/api/protos/vkGetDeviceMemoryOpaqueCaptureAddressKHR.adoc[]
endif::VK_KHR_buffer_device_address[]

  * pname:device is the logical device that the memory object was allocated
    on.
  * pname:pInfo is a pointer to a
    slink:VkDeviceMemoryOpaqueCaptureAddressInfo structure specifying the
    memory object to retrieve an address for.

The 64-bit return value is an opaque address representing the start of
pname:pInfo->memory.

If the memory object was allocated with a non-zero value of
slink:VkMemoryOpaqueCaptureAddressAllocateInfo::pname:opaqueCaptureAddress,
the return value must: be the same address.

[NOTE]
.Note
====
The expected usage for these opaque addresses is only for trace
capture/replay tools to store these addresses in a trace and subsequently
specify them during replay.
====

.Valid Usage
****
  * [[VUID-vkGetDeviceMemoryOpaqueCaptureAddress-None-03334]]
    The <<features-bufferDeviceAddress, pname:bufferDeviceAddress>> feature
    must: be enabled
  * [[VUID-vkGetDeviceMemoryOpaqueCaptureAddress-device-03335]]
    If pname:device was created with multiple physical devices, then the
    <<features-bufferDeviceAddressMultiDevice,
    pname:bufferDeviceAddressMultiDevice>> feature must: be enabled
****

include::{generated}/validity/protos/vkGetDeviceMemoryOpaqueCaptureAddress.adoc[]
--

[open,refpage='VkDeviceMemoryOpaqueCaptureAddressInfo',desc='Structure specifying the memory object to query an address for',type='structs',alias='VkDeviceMemoryOpaqueCaptureAddressInfoKHR']
--
The sname:VkDeviceMemoryOpaqueCaptureAddressInfo structure is defined as:

include::{generated}/api/structs/VkDeviceMemoryOpaqueCaptureAddressInfo.adoc[]

ifdef::VK_KHR_buffer_device_address[]
or the equivalent

include::{generated}/api/structs/VkDeviceMemoryOpaqueCaptureAddressInfoKHR.adoc[]
endif::VK_KHR_buffer_device_address[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:memory specifies the memory whose address is being queried.

.Valid Usage
****
  * [[VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-03336]]
    pname:memory must: have been allocated with
    ename:VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT
****

include::{generated}/validity/structs/VkDeviceMemoryOpaqueCaptureAddressInfo.adoc[]
--
endif::VK_VERSION_1_2,VK_KHR_buffer_device_address[]
