10. Memory Allocation

Vulkan memory is broken up into two categories, host memory and device memory.

10.1. Host Memory

Host memory is memory needed by the Vulkan implementation for non-device-visible storage.

Note

This memory may be used to store the implementation’s representation and state of Vulkan objects.

Vulkan provides applications the opportunity to perform host memory allocations on behalf of the Vulkan implementation. If this feature is not used, the implementation will perform its own memory allocations. Since most memory allocations are off the critical path, this is not meant as a performance feature. Rather, this can be useful for certain embedded systems, for debugging purposes (e.g. putting a guard page after all host allocations), or for memory allocation logging.

Allocators are provided by the application as a pointer to a VkAllocationCallbacks structure:

typedef struct VkAllocationCallbacks {
    void*                                   pUserData;
    PFN_vkAllocationFunction                pfnAllocation;
    PFN_vkReallocationFunction              pfnReallocation;
    PFN_vkFreeFunction                      pfnFree;
    PFN_vkInternalAllocationNotification    pfnInternalAllocation;
    PFN_vkInternalFreeNotification          pfnInternalFree;
} VkAllocationCallbacks;
  • pUserData is a value to be interpreted by the implementation of the callbacks. When any of the callbacks in 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.

  • pfnAllocation is a pointer to an application-defined memory allocation function of type PFN_vkAllocationFunction.

  • pfnReallocation is a pointer to an application-defined memory reallocation function of type PFN_vkReallocationFunction.

  • pfnFree is a pointer to an application-defined memory free function of type PFN_vkFreeFunction.

  • pfnInternalAllocation is a pointer to an application-defined function that is called by the implementation when the implementation makes internal allocations, and it is of type PFN_vkInternalAllocationNotification.

  • pfnInternalFree is a pointer to an application-defined function that is called by the implementation when the implementation frees internal allocations, and it is of type PFN_vkInternalFreeNotification.

Valid Usage
  • pfnAllocation must be a valid pointer to a valid user-defined PFN_vkAllocationFunction

  • pfnReallocation must be a valid pointer to a valid user-defined PFN_vkReallocationFunction

  • pfnFree must be a valid pointer to a valid user-defined PFN_vkFreeFunction

  • If either of pfnInternalAllocation or pfnInternalFree is not NULL, both must be valid callbacks

The type of pfnAllocation is:

typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)(
    void*                                       pUserData,
    size_t                                      size,
    size_t                                      alignment,
    VkSystemAllocationScope                     allocationScope);
  • pUserData is the value specified for VkAllocationCallbacks::pUserData in the allocator specified by the application.

  • size is the size in bytes of the requested allocation.

  • alignment is the requested alignment of the allocation in bytes and must be a power of two.

  • allocationScope is a VkSystemAllocationScope value specifying the allocation scope of the lifetime of the allocation, as described here.

If 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 size bytes, and with the pointer value being a multiple of alignment.

Note

Correct Vulkan operation cannot be assumed if the application does not follow these rules.

For example, pfnAllocation (or pfnReallocation) could cause termination of running Vulkan instance(s) on a failed allocation for debugging purposes, either directly or indirectly. In these circumstances, it cannot be assumed that any part of any affected VkInstance objects are going to operate correctly (even vkDestroyInstance), and the application must ensure it cleans up properly via other means (e.g. process termination).

If pfnAllocation returns NULL, and if the implementation is unable to continue correct processing of the current command without the requested allocation, it must treat this as a run-time error, and generate VK_ERROR_OUT_OF_HOST_MEMORY at the appropriate time for the command in which the condition was detected, as described in 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 VK_ERROR_OUT_OF_HOST_MEMORY as a result of this failed allocation.

The type of pfnReallocation is:

typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)(
    void*                                       pUserData,
    void*                                       pOriginal,
    size_t                                      size,
    size_t                                      alignment,
    VkSystemAllocationScope                     allocationScope);
  • pUserData is the value specified for VkAllocationCallbacks::pUserData in the allocator specified by the application.

  • pOriginal must be either NULL or a pointer previously returned by pfnReallocation or pfnAllocation of the same allocator.

  • size is the size in bytes of the requested allocation.

  • alignment is the requested alignment of the allocation in bytes and must be a power of two.

  • allocationScope is a VkSystemAllocationScope value specifying the allocation scope of the lifetime of the allocation, as described here.

pfnReallocation must return an allocation with enough space for size bytes, and the contents of the original allocation from bytes zero to min(original size, new size) - 1 must be preserved in the returned allocation. If 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 pOriginal is NULL, then pfnReallocation must behave equivalently to a call to PFN_vkAllocationFunction with the same parameter values (without pOriginal).

If size is zero, then pfnReallocation must behave equivalently to a call to PFN_vkFreeFunction with the same pUserData parameter value, and pMemory equal to pOriginal.

If pOriginal is non-NULL, the implementation must ensure that alignment is equal to the alignment used to originally allocate pOriginal.

If this function fails and pOriginal is non-NULL the application must not free the old allocation.

pfnReallocation must follow the same rules for return values as PFN_vkAllocationFunction.

The type of pfnFree is:

typedef void (VKAPI_PTR *PFN_vkFreeFunction)(
    void*                                       pUserData,
    void*                                       pMemory);
  • pUserData is the value specified for VkAllocationCallbacks::pUserData in the allocator specified by the application.

  • pMemory is the allocation to be freed.

pMemory may be NULL, which the callback must handle safely. If pMemory is non-NULL, it must be a pointer previously allocated by pfnAllocation or pfnReallocation. The application should free this memory.

The type of pfnInternalAllocation is:

typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
    void*                                       pUserData,
    size_t                                      size,
    VkInternalAllocationType                    allocationType,
    VkSystemAllocationScope                     allocationScope);
  • pUserData is the value specified for VkAllocationCallbacks::pUserData in the allocator specified by the application.

  • size is the requested size of an allocation.

  • allocationType is a VkInternalAllocationType value specifying the requested type of an allocation.

  • allocationScope is a VkSystemAllocationScope value specifying the allocation scope of the lifetime of the allocation, as described here.

This is a purely informational callback.

The type of pfnInternalFree is:

typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)(
    void*                                       pUserData,
    size_t                                      size,
    VkInternalAllocationType                    allocationType,
    VkSystemAllocationScope                     allocationScope);
  • pUserData is the value specified for VkAllocationCallbacks::pUserData in the allocator specified by the application.

  • size is the requested size of an allocation.

  • allocationType is a VkInternalAllocationType value specifying the requested type of an allocation.

  • allocationScope is a VkSystemAllocationScope value specifying the allocation scope of the lifetime of the allocation, as described here.

Each allocation has an allocation scope which defines its lifetime and which object it is associated with. Possible values passed to the allocationScope parameter of the callback functions specified by VkAllocationCallbacks, indicating the allocation scope, are:

typedef enum VkSystemAllocationScope {
    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
    VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
} VkSystemAllocationScope;
  • VK_SYSTEM_ALLOCATION_SCOPE_COMMAND specifies that the allocation is scoped to the duration of the Vulkan command.

  • VK_SYSTEM_ALLOCATION_SCOPE_OBJECT specifies that the allocation is scoped to the lifetime of the Vulkan object that is being created or used.

  • VK_SYSTEM_ALLOCATION_SCOPE_CACHE specifies that the allocation is scoped to the lifetime of a VkPipelineCache or VkValidationCacheEXT object.

  • VK_SYSTEM_ALLOCATION_SCOPE_DEVICE specifies that the allocation is scoped to the lifetime of the Vulkan device.

  • 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 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT or 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 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 VkDevice has an allocator it will be used, else if the parent VkInstance has an allocator it will be used. Else,

  • If an allocation is associated with an object of type VkValidationCacheEXT or VkPipelineCache, the allocator will use the 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 VkDevice or VkInstance, the allocator will use an allocation scope of 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 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 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, pfnInternalAllocation will be called. Upon freeing executable memory, pfnInternalFree will be called. An implementation will only call an informational callback for executable memory allocations and frees.

The allocationType parameter to the pfnInternalAllocation and pfnInternalFree functions may be one of the following values:

typedef enum VkInternalAllocationType {
    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
} VkInternalAllocationType;
  • 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 VkAllocationCallbacks structure between the time a vkCreate* command returns and the time a corresponding vkDestroy* command begins, that implementation must save a copy of the allocator before the vkCreate* command returns. The callback functions and any data structures they rely upon must remain valid for the lifetime of the object they are associated with.

If an allocator is provided to a vkCreate* command, a compatible allocator must be provided to the corresponding vkDestroy* command. Two VkAllocationCallbacks structures are compatible if memory allocated with pfnAllocation or pfnReallocation in each can be freed with pfnReallocation or pfnFree in the other. An allocator must not be provided to a vkDestroy* command if an allocator was not provided to the corresponding vkCreate* command.

If a non-NULL allocator is used, the pfnAllocation, pfnReallocation and pfnFree members must be non-NULL and point to valid implementations of the callbacks. An application can choose to not provide informational callbacks by setting both pfnInternalAllocation and pfnInternalFree to NULL. pfnInternalAllocation and pfnInternalFree must either both be NULL or both be non-NULL.

If pfnAllocation or pfnReallocation fail, the implementation may fail object creation and/or generate an VK_ERROR_OUT_OF_HOST_MEMORY error, as appropriate.

Allocation callbacks must not call any Vulkan commands.

The following sets of rules define when an implementation is permitted to call the allocator callbacks.

pfnAllocation or pfnReallocation may be called in the following situations:

  • Allocations scoped to a VkDevice or VkInstance may be allocated from any API command.

  • Allocations scoped to a command may be allocated from any API command.

  • Allocations scoped to a VkPipelineCache may only be allocated from:

    • vkCreatePipelineCache

    • vkMergePipelineCaches for dstCache

    • vkCreateGraphicsPipelines for pipelineCache

    • vkCreateComputePipelines for pipelineCache

  • Allocations scoped to a VkValidationCacheEXT may only be allocated from:

    • vkCreateValidationCacheEXT

    • vkMergeValidationCachesEXT for dstCache

    • vkCreateShaderModule for validationCache in VkShaderModuleValidationCacheCreateInfoEXT

  • Allocations scoped to a VkDescriptorPool may only be allocated from:

    • any command that takes the pool as a direct argument

    • vkAllocateDescriptorSets for the descriptorPool member of its pAllocateInfo parameter

    • vkCreateDescriptorPool

  • Allocations scoped to a VkCommandPool may only be allocated from:

    • any command that takes the pool as a direct argument

    • vkCreateCommandPool

    • vkAllocateCommandBuffers for the commandPool member of its pAllocateInfo parameter

    • any vkCmd* command whose commandBuffer was allocated from that VkCommandPool

  • Allocations scoped to any other object may only be allocated in that object’s vkCreate* command.

pfnFree may be called in the following situations:

  • Allocations scoped to a VkDevice or 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 VkPipelineCache may be freed from vkDestroyPipelineCache.

  • Allocations scoped to a VkValidationCacheEXT may be freed from vkDestroyValidationCacheEXT.

  • Allocations scoped to a VkDescriptorPool may be freed from

    • any command that takes the pool as a direct argument

  • Allocations scoped to a VkCommandPool may be freed from:

    • any command that takes the pool as a direct argument

    • vkResetCommandBuffer whose commandBuffer was allocated from that VkCommandPool

  • Allocations scoped to any other object may be freed in that object’s vkDestroy* command.

  • Any command that allocates host memory may also free host memory of the same scope.

10.2. 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 properties of a physical device describe the memory heaps and memory types available.

To query memory properties, call:

void vkGetPhysicalDeviceMemoryProperties(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties*           pMemoryProperties);
  • physicalDevice is the handle to the device to query.

  • pMemoryProperties points to an instance of VkPhysicalDeviceMemoryProperties structure in which the properties are returned.

Valid Usage (Implicit)
  • physicalDevice must be a valid VkPhysicalDevice handle

  • pMemoryProperties must be a valid pointer to a VkPhysicalDeviceMemoryProperties structure

The VkPhysicalDeviceMemoryProperties structure is defined as:

typedef struct VkPhysicalDeviceMemoryProperties {
    uint32_t        memoryTypeCount;
    VkMemoryType    memoryTypes[VK_MAX_MEMORY_TYPES];
    uint32_t        memoryHeapCount;
    VkMemoryHeap    memoryHeaps[VK_MAX_MEMORY_HEAPS];
} VkPhysicalDeviceMemoryProperties;
  • memoryTypeCount is the number of valid elements in the memoryTypes array.

  • memoryTypes is an array of VkMemoryType structures describing the memory types that can be used to access memory allocated from the heaps specified by memoryHeaps.

  • memoryHeapCount is the number of valid elements in the memoryHeaps array.

  • memoryHeaps is an array of VkMemoryHeap structures describing the memory heaps from which memory can be allocated.

The 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 memoryHeapCount and is less than or equal to VK_MAX_MEMORY_HEAPS. Each heap is described by an element of the memoryHeaps array as a VkMemoryHeap structure. The number of memory types available across all memory heaps is given by memoryTypeCount and is less than or equal to VK_MAX_MEMORY_TYPES. Each memory type is described by an element of the memoryTypes array as a VkMemoryType structure.

At least one heap must include VK_MEMORY_HEAP_DEVICE_LOCAL_BIT in VkMemoryHeap::flags. If there are multiple heaps that all have similar performance characteristics, they may all include VK_MEMORY_HEAP_DEVICE_LOCAL_BIT. In a unified memory architecture (UMA) system there is often only a single memory heap which is considered to be equally “local” to the host and to the device, and such an implementation must advertise the heap as device-local.

Each memory type returned by vkGetPhysicalDeviceMemoryProperties must have its propertyFlags set to one of the following values:

  • 0

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

  • VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

  • VK_MEMORY_PROPERTY_PROTECTED_BIT

  • VK_MEMORY_PROPERTY_PROTECTED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT

There must be at least one memory type with both the VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bits set in its propertyFlags. There must be at least one memory type with the VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT bit set in its propertyFlags.

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

  • either the set of bit flags returned in the propertyFlags member of X is a strict subset of the set of bit flags returned in the propertyFlags member of Y.

  • or the 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).

Note

There is no ordering requirement between X and Y elements for the case their 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 list of all allowed memory property flag combinations is written in a valid order. But if instead VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT was before VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, the list would still be in a valid order.

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

// 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);

To query memory properties, call:

void vkGetPhysicalDeviceMemoryProperties2(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);

or the equivalent command

void vkGetPhysicalDeviceMemoryProperties2KHR(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);
  • physicalDevice is the handle to the device to query.

  • pMemoryProperties points to an instance of VkPhysicalDeviceMemoryProperties2 structure in which the properties are returned.

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

Valid Usage (Implicit)
  • physicalDevice must be a valid VkPhysicalDevice handle

  • pMemoryProperties must be a valid pointer to a VkPhysicalDeviceMemoryProperties2 structure

The VkPhysicalDeviceMemoryProperties2 structure is defined as:

typedef struct VkPhysicalDeviceMemoryProperties2 {
    VkStructureType                     sType;
    void*                               pNext;
    VkPhysicalDeviceMemoryProperties    memoryProperties;
} VkPhysicalDeviceMemoryProperties2;

or the equivalent

typedef VkPhysicalDeviceMemoryProperties2 VkPhysicalDeviceMemoryProperties2KHR;
Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2

  • pNext must be NULL

The VkMemoryHeap structure is defined as:

typedef struct VkMemoryHeap {
    VkDeviceSize         size;
    VkMemoryHeapFlags    flags;
} VkMemoryHeap;
  • size is the total memory size in bytes in the heap.

  • flags is a bitmask of VkMemoryHeapFlagBits specifying attribute flags for the heap.

Bits which may be set in VkMemoryHeap::flags, indicating attribute flags for the heap, are:

typedef enum VkMemoryHeapFlagBits {
    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT_KHR = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT,
} VkMemoryHeapFlagBits;
  • 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.

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

typedef VkFlags VkMemoryHeapFlags;

VkMemoryHeapFlags is a bitmask type for setting a mask of zero or more VkMemoryHeapFlagBits.

The VkMemoryType structure is defined as:

typedef struct VkMemoryType {
    VkMemoryPropertyFlags    propertyFlags;
    uint32_t                 heapIndex;
} VkMemoryType;

Bits which may be set in VkMemoryType::propertyFlags, indicating properties of a memory heap, are:

typedef enum VkMemoryPropertyFlagBits {
    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
    VK_MEMORY_PROPERTY_PROTECTED_BIT = 0x00000020,
} VkMemoryPropertyFlagBits;
  • 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 VK_MEMORY_HEAP_DEVICE_LOCAL_BIT set.

  • VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit specifies that memory allocated with this type can be mapped for host access using vkMapMemory.

  • VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the host cache management commands vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges are not needed to flush host writes to the device or make device writes visible to the host, respectively.

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

  • 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 VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT and VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set. Additionally, the object’s backing memory may be provided by the implementation lazily as specified in Lazily Allocated Memory.

  • 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 VK_MEMORY_PROPERTY_PROTECTED_BIT set and any of VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set, or VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set, or VK_MEMORY_PROPERTY_HOST_CACHED_BIT set.

typedef VkFlags VkMemoryPropertyFlags;

VkMemoryPropertyFlags is a bitmask type for setting a mask of zero or more VkMemoryPropertyFlagBits.

A Vulkan device operates on data in device memory via memory objects that are represented in the API by a VkDeviceMemory handle:

VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)

To allocate memory objects, call:

VkResult vkAllocateMemory(
    VkDevice                                    device,
    const VkMemoryAllocateInfo*                 pAllocateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkDeviceMemory*                             pMemory);
  • device is the logical device that owns the memory.

  • pAllocateInfo is a pointer to an instance of the VkMemoryAllocateInfo structure describing parameters of the allocation. A successful returned allocation must use the requested parameters — no substitution is permitted by the implementation.

  • pAllocator controls host memory allocation as described in the Memory Allocation chapter.

  • pMemory is a pointer to a VkDeviceMemory handle in which information about the allocated memory is returned.

Allocations returned by 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.

When memory is allocated, its contents are undefined with the following constraint:

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

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.

The maximum number of valid memory allocations that can exist simultaneously within a VkDevice may be restricted by implementation- or platform-dependent limits. If a call to vkAllocateMemory would cause the total number of allocations to exceed these limits, such a call will fail and must return VK_ERROR_TOO_MANY_OBJECTS. The maxMemoryAllocationCount feature describes the number of allocations that can exist simultaneously before encountering these internal limits.

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 VK_ERROR_OUT_OF_DEVICE_MEMORY must be returned. This limit is advertised in VkPhysicalDeviceMaintenance3Properties::maxMemoryAllocationSize.

Valid Usage
Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pAllocateInfo must be a valid pointer to a valid VkMemoryAllocateInfo structure

  • If pAllocator is not NULL, pAllocator must be a valid pointer to a valid VkAllocationCallbacks structure

  • pMemory must be a valid pointer to a VkDeviceMemory handle

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_INVALID_EXTERNAL_HANDLE

The VkMemoryAllocateInfo structure is defined as:

typedef struct VkMemoryAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeIndex;
} VkMemoryAllocateInfo;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • allocationSize is the size of the allocation in bytes

  • memoryTypeIndex is an index identifying a memory type from the memoryTypes array of the VkPhysicalDeviceMemoryProperties structure

An instance of the VkMemoryAllocateInfo structure defines a memory import operation if the pNext chain contains an instance of one of the following structures:

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

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.

When performing a memory import operation, it is the responsibility of the application to ensure the external handles meet all valid usage requirements. However, implementations must perform sufficient validation of external handles 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 VK_ERROR_INVALID_EXTERNAL_HANDLE.

Valid Usage
  • If the pNext chain contains an instance of VkExportMemoryAllocateInfo, and any of the handle types specified in VkExportMemoryAllocateInfo::handleTypes require a dedicated allocation, as reported by vkGetPhysicalDeviceImageFormatProperties2 in VkExternalImageFormatProperties::externalMemoryProperties::externalMemoryFeatures or VkExternalBufferProperties::externalMemoryProperties::externalMemoryFeatures, the pNext chain must contain an instance of VkMemoryDedicatedAllocateInfo or VkDedicatedAllocationMemoryAllocateInfoNV with either its image or buffer field set to a value other than VK_NULL_HANDLE.

  • If the pNext chain contains an instance of VkExportMemoryAllocateInfo, it must not contain an instance of VkExportMemoryAllocateInfoNV or VkExportMemoryWin32HandleInfoNV.

  • If the pNext chain contains an instance of VkImportMemoryWin32HandleInfoKHR, it must not contain an instance of VkImportMemoryWin32HandleInfoNV.

  • If the parameters define an import operation, the external handle specified was created by the Vulkan API, and the external handle type is VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, then the values of allocationSize and memoryTypeIndex must match those specified when the memory object being imported was created.

  • If the parameters define an import operation and the external handle specified was created by the Vulkan API, the device mask specified by VkMemoryAllocateFlagsInfo must match that specified when the memory object being imported was allocated.

  • 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 vkAllocateMemory must match the list of physical devices that comprise the logical device on which the memory was originally allocated.

  • 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 memoryTypeIndex must be one of those returned by vkGetMemoryWin32HandlePropertiesKHR.

  • If the parameters define an import operation, the external handle was created by the Vulkan API, and the external handle type is VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR or VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR, then the values of allocationSize and memoryTypeIndex must match those specified when the memory object being imported was created.

  • If the parameters define an import operation and the external handle type is VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, or VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, allocationSize must match the size reported in the memory requirements of the image or buffer member of the instance of VkDedicatedAllocationMemoryAllocateInfoNV included in the pNext chain.

  • If the parameters define an import operation and the external handle type is VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, allocationSize must match the size specified when creating the Direct3D 12 heap from which the external handle was extracted.

  • 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 memoryTypeIndex must be one of those returned by vkGetMemoryFdPropertiesKHR.

  • If the protected memory feature is not enabled, the VkMemoryAllocateInfo::memoryTypeIndex must not indicate a memory type that reports VK_MEMORY_PROPERTY_PROTECTED_BIT.

  • If the parameters define an import operation and the external handle is a host pointer, the value of memoryTypeIndex must be one of those returned by vkGetMemoryHostPointerPropertiesEXT

  • If the parameters define an import operation and the external handle is a host pointer, allocationSize must be an integer multiple of VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment

  • If the parameters define an import operation and the external handle type is VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:

  • If the parameters do not define an import operation, and the pNext chain contains an instance of VkExportMemoryAllocateInfo with VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID included in its handleTypes member, and the pNext contains an instance of VkMemoryDedicatedAllocateInfo with image not equal to VK_NULL_HANDLE, then allocationSize must be 0, otherwise allocationSize must be greater than 0.

  • If the parameters define an import operation, the external handle is an Android hardware buffer, and the pNext chain includes an instance of VkMemoryDedicatedAllocateInfo with image that is not VK_NULL_HANDLE:

    • The Android hardware buffer’s usage must include at least one of AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT or AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE

    • The format of image must be VK_FORMAT_UNDEFINED or the format returned by vkGetAndroidHardwareBufferPropertiesANDROID in VkAndroidHardwareBufferFormatPropertiesANDROID::format for the Android hardware buffer.

    • The width, height, and array layer dimensions of image and the Android hardware buffer must be identical

    • If the Android hardware buffer’s usage includes AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE, the image must either have a complete mipmap chain, or it must have exactly 1 mip level.

    • Each bit set in the usage of image must be listed in AHardwareBuffer Usage Equivalence, and if there is a corresponding AHARDWAREBUFFER_USAGE bit listed that bit must be included in the Android hardware buffer’s usage

Valid Usage (Implicit)

If the pNext chain includes a VkMemoryDedicatedAllocateInfo structure, then that structure includes a handle of the sole buffer or image resource that the memory can be bound to.

The VkMemoryDedicatedAllocateInfo structure is defined as:

typedef struct VkMemoryDedicatedAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkImage            image;
    VkBuffer           buffer;
} VkMemoryDedicatedAllocateInfo;

or the equivalent

typedef VkMemoryDedicatedAllocateInfo VkMemoryDedicatedAllocateInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • image is VK_NULL_HANDLE or a handle of an image which this memory will be bound to.

  • buffer is VK_NULL_HANDLE or a handle of a buffer which this memory will be bound to.

Valid Usage
  • At least one of image and buffer must be VK_NULL_HANDLE

  • If image is not VK_NULL_HANDLE, VkMemoryAllocateInfo::allocationSize must equal the VkMemoryRequirements::size of the image

  • If image is not VK_NULL_HANDLE, image must have been created without VK_IMAGE_CREATE_SPARSE_BINDING_BIT set in VkImageCreateInfo::flags

  • If buffer is not VK_NULL_HANDLE, VkMemoryAllocateInfo::allocationSize must equal the VkMemoryRequirements::size of the buffer

  • If buffer is not VK_NULL_HANDLE, buffer must have been created without VK_BUFFER_CREATE_SPARSE_BINDING_BIT set in VkBufferCreateInfo::flags

  • If image is not VK_NULL_HANDLE and VkMemoryAllocateInfo defines a memory import operation with handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or 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 image must be identical to the image associated with the imported memory.

  • If buffer is not VK_NULL_HANDLE and VkMemoryAllocateInfo defines a memory import operation with handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or 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 buffer must be identical to the buffer associated with the imported memory.

  • If image is not VK_NULL_HANDLE and VkMemoryAllocateInfo defines a memory import operation with handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, the memory being imported must also be a dedicated image allocation and image must be identical to the image associated with the imported memory.

  • If buffer is not VK_NULL_HANDLE and VkMemoryAllocateInfo defines a memory import operation with handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, the memory being imported must also be a dedicated buffer allocation and buffer must be identical to the buffer associated with the imported memory.

  • If image is not VK_NULL_HANDLE, image must not have been created with VK_IMAGE_CREATE_DISJOINT_BIT set in VkImageCreateInfo::flags

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO

  • If image is not VK_NULL_HANDLE, image must be a valid VkImage handle

  • If buffer is not VK_NULL_HANDLE, buffer must be a valid VkBuffer handle

  • Both of buffer, and image that are valid handles must have been created, allocated, or retrieved from the same VkDevice

If the pNext chain includes a VkDedicatedAllocationMemoryAllocateInfoNV structure, then that structure includes a handle of the sole buffer or image resource that the memory can be bound to.

The VkDedicatedAllocationMemoryAllocateInfoNV structure is defined as:

typedef struct VkDedicatedAllocationMemoryAllocateInfoNV {
    VkStructureType    sType;
    const void*        pNext;
    VkImage            image;
    VkBuffer           buffer;
} VkDedicatedAllocationMemoryAllocateInfoNV;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • image is VK_NULL_HANDLE or a handle of an image which this memory will be bound to.

  • buffer is VK_NULL_HANDLE or a handle of a buffer which this memory will be bound to.

Valid Usage
  • At least one of image and buffer must be VK_NULL_HANDLE

  • If image is not VK_NULL_HANDLE, the image must have been created with VkDedicatedAllocationImageCreateInfoNV::dedicatedAllocation equal to VK_TRUE

  • If buffer is not VK_NULL_HANDLE, the buffer must have been created with VkDedicatedAllocationBufferCreateInfoNV::dedicatedAllocation equal to VK_TRUE

  • If image is not VK_NULL_HANDLE, VkMemoryAllocateInfo::allocationSize must equal the VkMemoryRequirements::size of the image

  • If buffer is not VK_NULL_HANDLE, VkMemoryAllocateInfo::allocationSize must equal the VkMemoryRequirements::size of the buffer

  • If image is not VK_NULL_HANDLE and VkMemoryAllocateInfo defines a memory import operation, the memory being imported must also be a dedicated image allocation and image must be identical to the image associated with the imported memory.

  • If buffer is not VK_NULL_HANDLE and VkMemoryAllocateInfo defines a memory import operation, the memory being imported must also be a dedicated buffer allocation and buffer must be identical to the buffer associated with the imported memory.

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV

  • If image is not VK_NULL_HANDLE, image must be a valid VkImage handle

  • If buffer is not VK_NULL_HANDLE, buffer must be a valid VkBuffer handle

  • Both of buffer, and image that are valid handles must have been created, allocated, or retrieved from the same VkDevice

When allocating memory that may be exported to another process or Vulkan instance, add a VkExportMemoryAllocateInfo structure to the pNext chain of the VkMemoryAllocateInfo structure, specifying the handle types that may be exported.

The VkExportMemoryAllocateInfo structure is defined as:

typedef struct VkExportMemoryAllocateInfo {
    VkStructureType                    sType;
    const void*                        pNext;
    VkExternalMemoryHandleTypeFlags    handleTypes;
} VkExportMemoryAllocateInfo;

or the equivalent

typedef VkExportMemoryAllocateInfo VkExportMemoryAllocateInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • handleTypes is a bitmask of 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
Valid Usage (Implicit)

To specify additional attributes of NT handles exported from a memory object, add the VkExportMemoryWin32HandleInfoKHR structure to the pNext chain of the VkMemoryAllocateInfo structure. The VkExportMemoryWin32HandleInfoKHR structure is defined as:

typedef struct VkExportMemoryWin32HandleInfoKHR {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
    LPCWSTR                       name;
} VkExportMemoryWin32HandleInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • pAttributes is a pointer to a Windows SECURITY_ATTRIBUTES structure specifying security attributes of the handle.

  • dwAccess is a DWORD specifying access rights of the handle.

  • name is a NULL-terminated UTF-16 string to associate with the underlying resource referenced by NT handles exported from the created memory.

If this structure is not present, or if 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 will be

DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE

for handles of the following types:

VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT

And

GENERIC_ALL

for handles of the following types:

VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT

Valid Usage
  • If VkExportMemoryAllocateInfo::handleTypes does not include VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, VkExportMemoryWin32HandleInfoKHR must not be in the pNext chain of VkMemoryAllocateInfo.

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR

  • If pAttributes is not NULL, pAttributes must be a valid pointer to a valid SECURITY_ATTRIBUTES value

To import memory from a Windows handle, add a VkImportMemoryWin32HandleInfoKHR structure to the pNext chain of the VkMemoryAllocateInfo structure.

The VkImportMemoryWin32HandleInfoKHR structure is defined as:

typedef struct VkImportMemoryWin32HandleInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    HANDLE                                handle;
    LPCWSTR                               name;
} VkImportMemoryWin32HandleInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • handleType specifies the type of handle or name.

  • handle is the external handle to import, or NULL.

  • name is a NULL-terminated UTF-16 string naming the underlying memory resource to import, or NULL.

Importing memory objects 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 ownership using the CloseHandle system call when the handle is no longer needed.

Applications can import the same underlying memory into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance. In all cases, each import operation must create a distinct VkDeviceMemory object.

Valid Usage
  • If handleType is not 0, it must be supported for import, as reported by VkExternalImageFormatProperties or VkExternalBufferProperties.

  • The memory from which handle was exported, or the memory named by name must have been created on the same underlying physical device as device.

  • If handleType is not 0, it must be defined as an NT handle or a global share handle.

  • If handleType is not VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT, VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT, or VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT, name must be NULL.

  • If handleType is not 0 and handle is NULL, name must name a valid memory resource of the type specified by handleType.

  • If handleType is not 0 and name is NULL, handle must be a valid handle of the type specified by handleType.

  • if handle is not NULL, name must be NULL.

  • If handle is not NULL, it must obey any requirements listed for handleType in external memory handle types compatibility.

  • If name is not NULL, it must obey any requirements listed for handleType in external memory handle types compatibility.

Valid Usage (Implicit)

To export a Windows handle representing the underlying resources of a Vulkan device memory object, call:

VkResult vkGetMemoryWin32HandleKHR(
    VkDevice                                    device,
    const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
    HANDLE*                                     pHandle);
  • device is the logical device that created the device memory being exported.

  • pGetWin32HandleInfo is a pointer to an instance of the VkMemoryGetWin32HandleInfoKHR structure containing parameters of the export operation.

  • pHandle will return the Windows handle representing the underlying resources of the device memory object.

For handle types defined as NT handles, the handles returned by vkGetMemoryWin32HandleKHR are owned by the application. To avoid leaking resources, the application must release ownership of them using the CloseHandle system call when they are no longer needed.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pGetWin32HandleInfo must be a valid pointer to a valid VkMemoryGetWin32HandleInfoKHR structure

  • pHandle must be a valid pointer to a HANDLE value

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

The VkMemoryGetWin32HandleInfoKHR structure is defined as:

typedef struct VkMemoryGetWin32HandleInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetWin32HandleInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memory is the memory object from which the handle will be exported.

  • handleType is the type of handle requested.

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

Valid Usage
  • handleType must have been included in VkExportMemoryAllocateInfo::handleTypes when memory was created.

  • If handleType is defined as an NT handle, vkGetMemoryWin32HandleKHR must be called no more than once for each valid unique combination of memory and handleType.

  • handleType must be defined as an NT handle or a global share handle.

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR

  • pNext must be NULL

  • memory must be a valid VkDeviceMemory handle

  • handleType must be a valid VkExternalMemoryHandleTypeFlagBits value

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:

VkResult vkGetMemoryWin32HandlePropertiesKHR(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    HANDLE                                      handle,
    VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties);
  • device is the logical device that will be importing handle.

  • handleType is the type of the handle handle.

  • handle is the handle which will be imported.

  • pMemoryWin32HandleProperties will return properties of handle.

Valid Usage
  • handle must be an external memory handle created outside of the Vulkan API.

  • handleType must not be one of the handle types defined as opaque.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • handleType must be a valid VkExternalMemoryHandleTypeFlagBits value

  • pMemoryWin32HandleProperties must be a valid pointer to a VkMemoryWin32HandlePropertiesKHR structure

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_INVALID_EXTERNAL_HANDLE

The VkMemoryWin32HandlePropertiesKHR structure returned is defined as:

typedef struct VkMemoryWin32HandlePropertiesKHR {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryWin32HandlePropertiesKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memoryTypeBits is a bitmask containing one bit set for every memory type which the specified windows handle can be imported as.

To import memory from a POSIX file descriptor handle, add a VkImportMemoryFdInfoKHR structure to the pNext chain of the VkMemoryAllocateInfo structure. The VkImportMemoryFdInfoKHR structure is defined as:

typedef struct VkImportMemoryFdInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    int                                   fd;
} VkImportMemoryFdInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • handleType specifies the handle type of fd.

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

Applications can import the same underlying memory into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance. In all cases, each import operation must create a distinct VkDeviceMemory object.

Valid Usage
Valid Usage (Implicit)

To export a POSIX file descriptor representing the underlying resources of a Vulkan device memory object, call:

VkResult vkGetMemoryFdKHR(
    VkDevice                                    device,
    const VkMemoryGetFdInfoKHR*                 pGetFdInfo,
    int*                                        pFd);
  • device is the logical device that created the device memory being exported.

  • pGetFdInfo is a pointer to an instance of the VkMemoryGetFdInfoKHR structure containing parameters of the export operation.

  • pFd will return a file descriptor representing the underlying resources of the device memory object.

Each call to vkGetMemoryFdKHR must create a new file descriptor and transfer ownership of it to the application. To avoid leaking resources, the application must release ownership of the file descriptor using the 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 execve system call is made.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pGetFdInfo must be a valid pointer to a valid VkMemoryGetFdInfoKHR structure

  • pFd must be a valid pointer to a int value

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

The VkMemoryGetFdInfoKHR structure is defined as:

typedef struct VkMemoryGetFdInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetFdInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memory is the memory object from which the handle will be exported.

  • handleType is the type of handle requested.

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

Note

The size of the exported file may be larger than the size requested by VkMemoryAllocateInfo::allocationSize. If handleType is VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, then the application can query the file’s actual size with lseek(2).

Valid Usage
  • handleType must have been included in VkExportMemoryAllocateInfo::handleTypes when memory was created.

  • handleType must be defined as a POSIX file descriptor handle.

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR

  • pNext must be NULL

  • memory must be a valid VkDeviceMemory handle

  • handleType must be a valid VkExternalMemoryHandleTypeFlagBits value

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:

VkResult vkGetMemoryFdPropertiesKHR(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    int                                         fd,
    VkMemoryFdPropertiesKHR*                    pMemoryFdProperties);
  • device is the logical device that will be importing fd.

  • handleType is the type of the handle fd.

  • fd is the handle which will be imported.

  • pMemoryFdProperties will return properties of the handle fd.

Valid Usage
  • fd must be an external memory handle created outside of the Vulkan API.

  • handleType must not be VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • handleType must be a valid VkExternalMemoryHandleTypeFlagBits value

  • pMemoryFdProperties must be a valid pointer to a VkMemoryFdPropertiesKHR structure

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_INVALID_EXTERNAL_HANDLE

The VkMemoryFdPropertiesKHR structure returned is defined as:

typedef struct VkMemoryFdPropertiesKHR {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryFdPropertiesKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memoryTypeBits is a bitmask containing one bit set for every memory type which the specified file descriptor can be imported as.

To import memory from a host pointer, add a VkImportMemoryHostPointerInfoEXT structure to the pNext chain of the VkMemoryAllocateInfo structure. The VkImportMemoryHostPointerInfoEXT structure is defined as:

typedef struct VkImportMemoryHostPointerInfoEXT {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    void*                                 pHostPointer;
} VkImportMemoryHostPointerInfoEXT;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • handleType specifies the handle type.

  • 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 underlying memory as defined in Host Access to Device Memory Objects.

Applications can import the same underlying memory into multiple instances of Vulkan and multiple times into a given Vulkan instance. However, implementations may fail to import the same underlying memory 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 VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR.

The application must ensure that the imported memory range remains valid and accessible for the lifetime of the imported memory object.

Valid Usage
  • If handleType is not 0, it must be supported for import, as reported in VkExternalMemoryPropertiesKHR

  • If handleType is not 0, it must be VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT or VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT

  • pHostPointer must be a pointer aligned to an integer multiple of VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment

  • If handleType is VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, pHostPointer must be a pointer to allocationSize number of bytes of host memory, where allocationSize is the member of the VkMemoryAllocateInfo structure this structure is chained to

  • If handleType is VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT, pHostPointer must be a pointer to allocationSize number of bytes of host mapped foreign memory, where allocationSize is the member of the VkMemoryAllocateInfo structure this structure is chained to

Valid Usage (Implicit)

To determine the correct parameters to use when importing host pointers, call:

VkResult vkGetMemoryHostPointerPropertiesEXT(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    const void*                                 pHostPointer,
    VkMemoryHostPointerPropertiesEXT*           pMemoryHostPointerProperties);
  • device is the logical device that will be importing pHostPointer.

  • handleType is the type of the handle pHostPointer.

  • pHostPointer is the host pointer to import from.

Valid Usage
  • handleType must be VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT or VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT

  • pHostPointer must be a pointer aligned to an integer multiple of VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment

  • If handleType is VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, pHostPointer must be a pointer to host memory

  • If handleType is VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT, pHostPointer must be a pointer to host mapped foreign memory

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • handleType must be a valid VkExternalMemoryHandleTypeFlagBits value

  • pMemoryHostPointerProperties must be a valid pointer to a VkMemoryHostPointerPropertiesEXT structure

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_INVALID_EXTERNAL_HANDLE

The VkMemoryHostPointerPropertiesEXT structure is defined as:

typedef struct VkMemoryHostPointerPropertiesEXT {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryHostPointerPropertiesEXT;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memoryTypeBits is a bitmask containing one bit set for every memory type which the specified host pointer can be imported as.

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT

  • pNext must be NULL

To import memory created outside of the current Vulkan instance from an Android hardware buffer, add a VkImportAndroidHardwareBufferInfoANDROID structure to the pNext chain of the VkMemoryAllocateInfo structure. The VkImportAndroidHardwareBufferInfoANDROID structure is defined as:

typedef struct VkImportAndroidHardwareBufferInfoANDROID {
    VkStructureType            sType;
    const void*                pNext;
    struct AHardwareBuffer*    buffer;
} VkImportAndroidHardwareBufferInfoANDROID;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • buffer is the Android hardware buffer to import.

If the 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
Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID

  • buffer must be a valid pointer to a AHardwareBuffer value

To export an Android hardware buffer representing the underlying resources of a Vulkan device memory object, call:

VkResult vkGetMemoryAndroidHardwareBufferANDROID(
    VkDevice                                    device,
    const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
    struct AHardwareBuffer**                    pBuffer);
  • device is the logical device that created the device memory being exported.

  • pInfo is a pointer to an instance of the VkMemoryGetAndroidHardwareBufferInfoANDROID structure containing parameters of the export operation.

  • pBuffer will return an Android hardware buffer representing the underlying resources of the device memory object.

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

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pInfo must be a valid pointer to a valid VkMemoryGetAndroidHardwareBufferInfoANDROID structure

  • pBuffer must be a valid pointer to a valid pointer to a AHardwareBuffer value

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

The VkMemoryGetAndroidHardwareBufferInfoANDROID structure is defined as:

typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
} VkMemoryGetAndroidHardwareBufferInfoANDROID;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memory is the memory object from which the Android hardware buffer will be exported.

Valid Usage

To determine the memory parameters to use when importing an Android hardware buffer, call:

VkResult vkGetAndroidHardwareBufferPropertiesANDROID(
    VkDevice                                    device,
    const struct AHardwareBuffer*               buffer,
    VkAndroidHardwareBufferPropertiesANDROID*   pProperties);
  • device is the logical device that will be importing buffer.

  • buffer is the Android hardware buffer which will be imported.

  • pProperties will return properties of buffer.

Valid Usage
  • buffer must be a valid Android hardware buffer object with at least one of the AHARDWAREBUFFER_USAGE_GPU_* usage flags.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • buffer must be a valid pointer to a valid AHardwareBuffer value

  • pProperties must be a valid pointer to a VkAndroidHardwareBufferPropertiesANDROID structure

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR

The VkAndroidHardwareBufferPropertiesANDROID structure returned is defined as:

typedef struct VkAndroidHardwareBufferPropertiesANDROID {
    VkStructureType    sType;
    void*              pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeBits;
} VkAndroidHardwareBufferPropertiesANDROID;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • allocationSize is the size of the external memory

  • memoryTypeBits is a bitmask containing one bit set for every memory type which the specified Android hardware buffer can be imported as.

To obtain format properties of an Android hardware buffer, include an instance of VkAndroidHardwareBufferFormatPropertiesANDROID in the pNext chain of the VkAndroidHardwareBufferPropertiesANDROID instance passed to vkGetAndroidHardwareBufferPropertiesANDROID. This structure is defined as:

typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID {
    VkStructureType                  sType;
    void*                            pNext;
    VkFormat                         format;
    uint64_t                         externalFormat;
    VkFormatFeatureFlags             formatFeatures;
    VkComponentMapping               samplerYcbcrConversionComponents;
    VkSamplerYcbcrModelConversion    suggestedYcbcrModel;
    VkSamplerYcbcrRange              suggestedYcbcrRange;
    VkChromaLocation                 suggestedXChromaOffset;
    VkChromaLocation                 suggestedYChromaOffset;
} VkAndroidHardwareBufferFormatPropertiesANDROID;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • format is the Vulkan format corresponding to the Android hardware buffer’s format, or VK_FORMAT_UNDEFINED if there is not an equivalent Vulkan format.

  • externalFormat is an implementation-defined external format identifier for use with VkExternalFormatANDROID. It must not be zero.

  • formatFeatures describes the capabilities of this external format when used with an image bound to memory imported from buffer.

  • samplerYcbcrConversionComponents is the component swizzle that should be used in VkSamplerYcbcrConversionCreateInfo.

  • suggestedYcbcrModel is a suggested color model to use in the VkSamplerYcbcrConversionCreateInfo.

  • suggestedYcbcrRange is a suggested numerical value range to use in VkSamplerYcbcrConversionCreateInfo.

  • suggestedXChromaOffset is a suggested X chroma offset to use in VkSamplerYcbcrConversionCreateInfo.

  • suggestedYChromaOffset is a suggested Y chroma offset to use in VkSamplerYcbcrConversionCreateInfo.

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

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

Note

The formatFeatures member only indicates the features available when using an external-format image created from the Android hardware buffer. Images from Android hardware buffers with a format other than VK_FORMAT_UNDEFINED are subject to the format capabilities obtained from vkGetPhysicalDeviceFormatProperties2, and vkGetPhysicalDeviceImageFormatProperties2 with appropriate parameters. These sets of features are independent of each other, e.g. the external format will support sampler Y’CBCR 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 VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT, VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT, VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT, and VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT. in formatFeatures. Other format features may differ between Android hardware buffers that have the same external format. This allows applications to use the same VkSamplerYcbcrConversion object (and samplers and pipelines created from them) for any Android hardware buffers that have the same external format.

If format is not VK_FORMAT_UNDEFINED, then the value of samplerYcbcrConversionComponents must be valid when used as the components member of VkSamplerYcbcrConversionCreateInfo with that format. If format is VK_FORMAT_UNDEFINED, all members of samplerYcbcrConversionComponents must be VK_COMPONENT_SWIZZLE_IDENTITY.

Implementations may not always be able to determine the color model, numerical range, or chroma offsets of the image contents, so the values in 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 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 samplerExternalOES in OpenGL ES using equivalent sampler parameters.

Note

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

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID

When allocating memory that may be exported to another process or Vulkan instance, add a VkExportMemoryAllocateInfoNV structure to the pNext chain of the VkMemoryAllocateInfo structure, specifying the handle types that may be exported.

The VkExportMemoryAllocateInfoNV structure is defined as:

typedef struct VkExportMemoryAllocateInfoNV {
    VkStructureType                      sType;
    const void*                          pNext;
    VkExternalMemoryHandleTypeFlagsNV    handleTypes;
} VkExportMemoryAllocateInfoNV;
Valid Usage (Implicit)

When VkExportMemoryAllocateInfoNV::handleTypes includes VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV, add a VkExportMemoryWin32HandleInfoNV to the pNext chain of the VkExportMemoryAllocateInfoNV structure to specify security attributes and access rights for the memory object’s external handle.

The VkExportMemoryWin32HandleInfoNV structure is defined as:

typedef struct VkExportMemoryWin32HandleInfoNV {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
} VkExportMemoryWin32HandleInfoNV;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • pAttributes is a pointer to a Windows SECURITY_ATTRIBUTES structure specifying security attributes of the handle.

  • dwAccess is a DWORD specifying access rights of the handle.

If this structure is not present, or if 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 will be

DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE
Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV

  • If pAttributes is not NULL, pAttributes must be a valid pointer to a valid SECURITY_ATTRIBUTES value

To import memory created on the same physical device but outside of the current Vulkan instance, add a VkImportMemoryWin32HandleInfoNV structure to the pNext chain of the VkMemoryAllocateInfo structure, specifying a handle to and the type of the memory.

The VkImportMemoryWin32HandleInfoNV structure is defined as:

typedef struct VkImportMemoryWin32HandleInfoNV {
    VkStructureType                      sType;
    const void*                          pNext;
    VkExternalMemoryHandleTypeFlagsNV    handleType;
    HANDLE                               handle;
} VkImportMemoryWin32HandleInfoNV;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • handleType is 0 or a VkExternalMemoryHandleTypeFlagBitsNV value specifying the type of memory handle in handle.

  • handle is a Windows HANDLE referring to the memory.

If handleType is 0, this structure is ignored by consumers of the VkMemoryAllocateInfo structure it is chained from.

Valid Usage
  • handleType must not have more than one bit set.

  • handle must be a valid handle to memory, obtained as specified by handleType.

Valid Usage (Implicit)

Bits which can be set in handleType are:

Possible values of VkImportMemoryWin32HandleInfoNV::handleType, specifying the type of an external memory handle, are:

typedef enum VkExternalMemoryHandleTypeFlagBitsNV {
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
} VkExternalMemoryHandleTypeFlagBitsNV;
  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV specifies a handle to memory returned by vkGetMemoryWin32HandleNV.

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV specifies a handle to memory returned by vkGetMemoryWin32HandleNV, or one duplicated from such a handle using DuplicateHandle().

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV specifies a valid NT handle to memory returned by IDXGIResource1::CreateSharedHandle(), or a handle duplicated from such a handle using DuplicateHandle().

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV specifies a handle to memory returned by IDXGIResource::GetSharedHandle().

typedef VkFlags VkExternalMemoryHandleTypeFlagsNV;

VkExternalMemoryHandleTypeFlagsNV is a bitmask type for setting a mask of zero or more VkExternalMemoryHandleTypeFlagBitsNV.

To retrieve the handle corresponding to a device memory object created with VkExportMemoryAllocateInfoNV::handleTypes set to include VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV or VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV, call:

VkResult vkGetMemoryWin32HandleNV(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkExternalMemoryHandleTypeFlagsNV           handleType,
    HANDLE*                                     pHandle);
  • device is the logical device that owns the memory.

  • memory is the VkDeviceMemory object.

  • handleType is a bitmask of VkExternalMemoryHandleTypeFlagBitsNV containing a single bit specifying the type of handle requested.

  • handle points to a Windows HANDLE in which the handle is returned.

Valid Usage
Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • memory must be a valid VkDeviceMemory handle

  • handleType must be a valid combination of VkExternalMemoryHandleTypeFlagBitsNV values

  • handleType must not be 0

  • pHandle must be a valid pointer to a HANDLE value

  • memory must have been created, allocated, or retrieved from device

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_TOO_MANY_OBJECTS

  • VK_ERROR_OUT_OF_HOST_MEMORY

If the pNext chain of VkMemoryAllocateInfo includes a VkMemoryAllocateFlagsInfo structure, then that structure includes flags and a device mask controlling how many instances of the memory will be allocated.

The VkMemoryAllocateFlagsInfo structure is defined as:

typedef struct VkMemoryAllocateFlagsInfo {
    VkStructureType          sType;
    const void*              pNext;
    VkMemoryAllocateFlags    flags;
    uint32_t                 deviceMask;
} VkMemoryAllocateFlagsInfo;

or the equivalent

typedef VkMemoryAllocateFlagsInfo VkMemoryAllocateFlagsInfoKHR;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • flags is a bitmask of VkMemoryAllocateFlagBits controlling the allocation.

  • deviceMask is a mask of physical devices in the logical device, indicating that memory must be allocated on each device in the mask, if VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set in flags.

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

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

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
  • If VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set, deviceMask must be a valid device mask.

  • If VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set, deviceMask must not be zero

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO

  • flags must be a valid combination of VkMemoryAllocateFlagBits values

Bits which can be set in VkMemoryAllocateFlagsInfo::flags, controlling device memory allocation, are:

typedef enum VkMemoryAllocateFlagBits {
    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT,
} VkMemoryAllocateFlagBits;

or the equivalent

typedef VkMemoryAllocateFlagBits VkMemoryAllocateFlagBitsKHR;
  • VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT specifies that memory will be allocated for the devices in VkMemoryAllocateFlagsInfo::deviceMask.

typedef VkFlags VkMemoryAllocateFlags;

or the equivalent

typedef VkMemoryAllocateFlags VkMemoryAllocateFlagsKHR;

VkMemoryAllocateFlags is a bitmask type for setting a mask of zero or more VkMemoryAllocateFlagBits.

To free a memory object, call:

void vkFreeMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    const VkAllocationCallbacks*                pAllocator);
  • device is the logical device that owns the memory.

  • memory is the VkDeviceMemory object to be freed.

  • pAllocator controls host memory allocation as described in the 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. The memory can remain bound to images or buffers at the time the memory object is freed, but any further use of them (on host or device) for anything other than destroying those objects will result in undefined behavior. If there are still any bound images or buffers, the memory may not be immediately released by the implementation, but must be released by the time all bound images and buffers have been destroyed. Once memory is released, it is returned to the heap from which it was allocated.

How memory objects are bound to Images and Buffers is described in detail in the Resource Memory Association section.

If a memory object is mapped at the time it is freed, it is implicitly unmapped.

Note

As described 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
  • All submitted commands that refer to memory (via images or buffers) must have completed execution

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • If memory is not VK_NULL_HANDLE, memory must be a valid VkDeviceMemory handle

  • If pAllocator is not NULL, pAllocator must be a valid pointer to a valid VkAllocationCallbacks structure

  • If memory is a valid handle, it must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to memory must be externally synchronized

10.2.1. Host Access to Device Memory Objects

Memory objects created with vkAllocateMemory are not directly host accessible.

Memory objects created with the memory property VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT are considered mappable. Memory objects must be mappable in order to be successfully mapped on the host.

To retrieve a host virtual address pointer to a region of a mappable memory object, call:

VkResult vkMapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkDeviceSize                                offset,
    VkDeviceSize                                size,
    VkMemoryMapFlags                            flags,
    void**                                      ppData);
  • device is the logical device that owns the memory.

  • memory is the VkDeviceMemory object to be mapped.

  • offset is a zero-based byte offset from the beginning of the memory object.

  • size is the size of the memory range to map, or VK_WHOLE_SIZE to map from offset to the end of the allocation.

  • flags is reserved for future use.

  • ppData points to a pointer in which is returned a host-accessible pointer to the beginning of the mapped range. This pointer minus offset must be aligned to at least VkPhysicalDeviceLimits::minMemoryMapAlignment.

It is an application error to call vkMapMemory on a memory object that is already mapped.

Note

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, vkMapMemory must return VK_ERROR_MEMORY_MAP_FAILED. The application can improve the likelihood of success by reducing the size of the mapped range and/or removing unneeded mappings using VkUnmapMemory.

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 here for details on fulfilling such a guarantee). If the device memory was allocated without the 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 VkPhysicalDeviceLimits::nonCoherentAtomSize, and round the end of the range up to the nearest multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.

While a range of device memory is mapped for host access, the application is responsible for synchronizing both device and host access to that memory range.

Note

It is important for the application developer to become meticulously familiar with all of the mechanisms described in the chapter on Synchronization and Cache Control as they are crucial to maintaining memory access ordering.

Valid Usage
  • memory must not be currently mapped

  • offset must be less than the size of memory

  • If size is not equal to VK_WHOLE_SIZE, size must be greater than 0

  • If size is not equal to VK_WHOLE_SIZE, size must be less than or equal to the size of the memory minus offset

  • memory must have been created with a memory type that reports VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT

  • memory must not have been allocated with multiple instances.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • memory must be a valid VkDeviceMemory handle

  • flags must be 0

  • ppData must be a valid pointer to a pointer value

  • memory must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to memory must be externally synchronized

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_MEMORY_MAP_FAILED

typedef VkFlags VkMemoryMapFlags;

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: vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges.

Note

If the memory object was created with the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set, vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges are unnecessary and may have a performance cost. However, availability and visibility operations still need to be managed on the device. See the description of host access types for more information.

To flush ranges of non-coherent memory from the host caches, call:

VkResult vkFlushMappedMemoryRanges(
    VkDevice                                    device,
    uint32_t                                    memoryRangeCount,
    const VkMappedMemoryRange*                  pMemoryRanges);
  • device is the logical device that owns the memory ranges.

  • memoryRangeCount is the length of the pMemoryRanges array.

  • pMemoryRanges is a pointer to an array of VkMappedMemoryRange structures describing the memory ranges to flush.

vkFlushMappedMemoryRanges guarantees that host writes to the memory ranges described by pMemoryRanges are made available to the host memory domain, such that they can be made available to the device memory domain via memory domain operations using the VK_ACCESS_HOST_WRITE_BIT access type.

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

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

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

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pMemoryRanges must be a valid pointer to an array of memoryRangeCount valid VkMappedMemoryRange structures

  • memoryRangeCount must be greater than 0

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

To invalidate ranges of non-coherent memory from the host caches, call:

VkResult vkInvalidateMappedMemoryRanges(
    VkDevice                                    device,
    uint32_t                                    memoryRangeCount,
    const VkMappedMemoryRange*                  pMemoryRanges);
  • device is the logical device that owns the memory ranges.

  • memoryRangeCount is the length of the pMemoryRanges array.

  • pMemoryRanges is a pointer to an array of VkMappedMemoryRange structures describing the memory ranges to invalidate.

vkInvalidateMappedMemoryRanges guarantees that device writes to the memory ranges described by pMemoryRanges, which have been made available to the host memory domain using the VK_ACCESS_HOST_WRITE_BIT and VK_ACCESS_HOST_READ_BIT 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 pMemoryRanges, each set of nonCoherentAtomSize bytes in that range is invalidated if any byte in that set has been written by the device since it was first mapped, or the last time it was invalidated.

Note

Mapping non-coherent memory does not implicitly invalidate the mapped memory, and device writes that have not been invalidated must be made visible before the host reads or overwrites them.

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pMemoryRanges must be a valid pointer to an array of memoryRangeCount valid VkMappedMemoryRange structures

  • memoryRangeCount must be greater than 0

Return Codes
Success
  • VK_SUCCESS

Failure
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

The VkMappedMemoryRange structure is defined as:

typedef struct VkMappedMemoryRange {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
    VkDeviceSize       offset;
    VkDeviceSize       size;
} VkMappedMemoryRange;
  • sType is the type of this structure.

  • pNext is NULL or a pointer to an extension-specific structure.

  • memory is the memory object to which this range belongs.

  • offset is the zero-based byte offset from the beginning of the memory object.

  • size is either the size of range, or VK_WHOLE_SIZE to affect the range from offset to the end of the current mapping of the allocation.

Valid Usage
  • memory must be currently mapped

  • If size is not equal to VK_WHOLE_SIZE, offset and size must specify a range contained within the currently mapped range of memory

  • If size is equal to VK_WHOLE_SIZE, offset must be within the currently mapped range of memory

  • If size is equal to VK_WHOLE_SIZE, the end of the current mapping of memory must be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize bytes from the beginning of the memory object.

  • offset must be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize

  • If size is not equal to VK_WHOLE_SIZE, size must either be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize, or offset plus size must equal the size of memory.

Valid Usage (Implicit)
  • sType must be VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE

  • pNext must be NULL

  • memory must be a valid VkDeviceMemory handle

To unmap a memory object once host access to it is no longer needed by the application, call:

void vkUnmapMemory(
    VkDevice                                    device,
    VkDeviceMemory                              memory);
  • device is the logical device that owns the memory.

  • memory is the memory object to be unmapped.

Valid Usage
  • memory must be currently mapped

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • memory must be a valid VkDeviceMemory handle

  • memory must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to memory must be externally synchronized

10.2.2. Lazily Allocated Memory

If the memory object is allocated from a heap with the VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT bit set, that object’s backing memory may be provided by the implementation lazily. The actual committed size of the memory may initially be as small as zero (or as large as the requested size), and monotonically increases as additional memory is needed.

A memory type with this flag set is only allowed to be bound to a VkImage whose usage flags include VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT.

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.

To determine the amount of lazily-allocated memory that is currently committed for a memory object, call:

void vkGetDeviceMemoryCommitment(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkDeviceSize*                               pCommittedMemoryInBytes);
  • device is the logical device that owns the memory.

  • memory is the memory object being queried.

  • pCommittedMemoryInBytes is a pointer to a VkDeviceSize value in which the number of bytes currently committed is returned, on success.

The implementation may update the commitment at any time, and the value returned by this query may be out of date.

The implementation guarantees to allocate any committed memory from the heapIndex indicated by the memory type that the memory object was created with.

Valid Usage
  • memory must have been created with a memory type that reports VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • memory must be a valid VkDeviceMemory handle

  • pCommittedMemoryInBytes must be a valid pointer to a VkDeviceSize value

  • memory must have been created, allocated, or retrieved from device

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

      • Any read from or write to protected memory during unprotected queue operations results in undefined behavior but is subject to the inviolable rules below.

    • Protected queue operations

      • Any write to unprotected memory during protected queue operations results in undefined behavior but is subject to the inviolable rules below.

      • Except for framebuffer-space pipeline stages, compute shader stage, and transfer stage, any read from or write to protected memory during protected queue operations results in undefined behavior but is subject to the inviolable rules below.

      • Any queries during protected queue operations results in undefined behavior but is subject to the inviolable rules below.

Protected memory inviolable rules

Implementations must ensure that correct usage or incorrect usage by an application does not affect the integrity of the memory protection system.

The implementation must guarantee that:

  • Protected device memory must not be visible to the host.

  • Values written to unprotected device memory must not be a function of data from protected memory.

Incorrect usage by an application of the memory protection system results in undefined behavior which may include process termination or device loss.

10.2.4. External Memory Handle Types

Android Hardware Buffer

Android’s NDK defines AHardwareBuffer objects, which represent device memory that is shareable across processes and that can be accessed by a variety of media APIs and the hardware used to implement them. These Android hardware buffer objects may be imported into VkDeviceMemory objects for access via Vulkan, or exported from Vulkan.

Android hardware buffer objects are reference-counted using Android NDK functions outside of the scope of this specification. A VkDeviceMemory imported from an Android hardware buffer or that can be exported to an Android hardware buffer must acquire a reference to its AHardwareBuffer object, and must release this reference when the device memory is freed. During the host execution of a Vulkan command that has an Android hardware buffer as a parameter (including indirect parameters via pNext chains), the application must not decrement the Android hardware buffer’s reference count to zero.

Android hardware buffers can be mapped and unmapped for CPU access using the NDK functions. These lock and unlock APIs are considered to acquire and release ownership of the Android hardware buffer, and applications must follow the rules described in External Resource Sharing to transfer ownership between the Vulkan instance and these native APIs.

Android hardware buffers can be shared with external APIs and Vulkan instances on the same device, and also with foreign devices. When transferring ownership of the Android hardware buffer, the external and foreign special queue families described in Queue Family Ownership Transfer are not identical. All APIs which produce or consume Android hardware buffers are considered to use foreign devices, except OpenGL ES contexts and Vulkan logical devices that have matching device and driver UUIDs. Implementations may treat a transfer to or from the foreign queue family as if it were a transfer to or from the external queue family when the Android hardware buffer’s usage only permits it to be used on the same physical device.

Android Hardware Buffer Optimal Usages

Vulkan buffer and image usage flags do not correspond exactly to Android hardware buffer usage flags. When allocating Android hardware buffers with non-Vulkan APIs, if any AHARDWAREBUFFER_USAGE_GPU_* usage bits are included, by default the allocator must allocate the memory in such a way that it supports Vulkan usages and creation flags in the usage equivalence table which do not have Android hardware buffer equivalents.

The VkAndroidHardwareBufferUsageANDROID structure can be attached to the pNext chain of a VkImageFormatProperties2 instance passed to vkGetPhysicalDeviceImageFormatProperties2 to obtain optimal Android hardware buffer usage flags for specific Vulkan resource creation parameters. Some usage flags returned by these commands are required based on the input parameters, but additional vendor-specific usage flags (AHARDWAREBUFFER_USAGE_VENDOR_*) may also be returned. Any Android hardware buffer allocated with these vendor-specific usage flags and imported to Vulkan must only be bound to resources created with parameters that are a subset of the parameters used to obtain the Android hardware buffer usage, since the memory may have been allocated in a way incompatible with other parameters. If an Android hardware buffer is successfully allocated with additional non-vendor-specific usage flags in addition to the recommended usage, it must support being used in the same ways as an Android hardware buffer allocated with only the recommended usage, and also in ways indicated by the additional usage.

Android Hardware Buffer External Formats

Android hardware buffers may represent images using implementation-specific formats, layouts, color models, etc., which do not have Vulkan equivalents. Such external formats are commonly used by external image sources such as video decoders or cameras. Vulkan can import Android hardware buffers that have external formats, but since the image contents are in an undiscoverable and possibly proprietary representation, images with external formats must only be used as sampled images, must only be sampled with a sampler that has Y’CBCR conversion enabled, and must have optimal tiling.

Images that will be backed by an Android hardware buffer can use an external format by setting VkImageCreateInfo::format to VK_FORMAT_UNDEFINED and including an instance of VkExternalFormatANDROID in the pNext chain. Images can be created with an external format even if the Android hardware buffer has a format which has an equivalent Vulkan format to enable consistent handling of images from sources that might use either category of format. However, all images created with an external format are subject to the valid usage requirements associated with external formats, even if the Android hardware buffer’s format has a Vulkan equivalent. The external format of an Android hardware buffer can be obtained by passing an instance of VkAndroidHardwareBufferFormatPropertiesANDROID to vkGetAndroidHardwareBufferPropertiesANDROID.

Android Hardware Buffer Image Resources

Android hardware buffers have intrinsic width, height, format, and usage properties, so Vulkan images bound to memory imported from an Android hardware buffer must use dedicated allocations: VkMemoryDedicatedRequirements::requiresDedicatedAllocation must be VK_TRUE for images created with VkExternalMemoryImageCreateInfo::handleTypes that includes VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID. When creating an image that will be bound to an imported Android hardware buffer, the image creation parameters must be equivalent to the AHardwareBuffer properties as described by the valid usage of VkMemoryAllocateInfo. Similarly, device memory allocated for a dedicated image must not be exported to an Android hardware buffer until it has been bound to that image, and the implementation must return an Android hardware buffer with properties derived from the image:

  • The width and height members of AHardwareBuffer_desc must be the same as the width and height members of VkImageCreateInfo::extent, respectively.

  • The layers member of AHardwareBuffer_desc must be the same as the arrayLayers member of VkImageCreateInfo.

  • The format member of AHardwareBuffer_desc must be equivalent to VkImageCreateInfo::format as defined by AHardwareBuffer Format Equivalence.

  • The usage member of AHardwareBuffer_desc must include bits corresponding to bits included in VkImageCreateInfo::usage and VkImageCreateInfo::flags where such a correspondence exists according to AHardwareBuffer Usage Equivalence. It may also include additional usage bits, including vendor-specific usages. Presence of vendor usage bits may make the Android hardware buffer only usable in ways indicated by the image creation parameters, even when used outside Vulkan, in a similar way that allocating the Android hardware buffer with usage returned in VkAndroidHardwareBufferUsageANDROID.

Implementations may support fewer combinations of image creation parameters for images with Android hardware buffer external handle type than for non-external images. Support for a given set of parameters can be determined by passing VkExternalImageFormatProperties to vkGetPhysicalDeviceImageFormatProperties2 with handleType set to VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID. Any Android hardware buffer successfully allocated outside Vulkan with usage that includes AHARDWAREBUFFER_USAGE_GPU_* must be supported when using equivalent Vulkan image parameters. If a given choice of image parameters are supported for import, they can also be used to create an image and memory that will be exported to an Android hardware buffer.

Table 13. AHardwareBuffer Format Equivalence
AHardwareBuffer Format Vulkan Format

AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM

VK_FORMAT_R8G8B8A8_UNORM

AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM

VK_FORMAT_R8G8B8A8_UNORM

AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM

VK_FORMAT_R8G8B8_UNORM

AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM

VK_FORMAT_R5G6B5_UNORM_PACK16

AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT

VK_FORMAT_R16G16B16A16_SFLOAT

AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM

VK_FORMAT_A2B10G10R10_UNORM_PACK32

AHARDWAREBUFFER_FORMAT_D16_UNORM

VK_FORMAT_D16_UNORM

AHARDWAREBUFFER_FORMAT_D24_UNORM

VK_FORMAT_X8_D24_UNORM_PACK32

AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT

VK_FORMAT_D24_UNORM_S8_UINT

AHARDWAREBUFFER_FORMAT_D32_FLOAT

VK_FORMAT_D32_SFLOAT

AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT

VK_FORMAT_D32_SFLOAT_S8_UINT

AHARDWAREBUFFER_FORMAT_S8_UINT

VK_FORMAT_S8_UINT

Table 14. AHardwareBuffer Usage Equivalence
AHardwareBuffer Usage Vulkan Usage or Creation Flag

None

VK_IMAGE_USAGE_TRANSFER_SRC_BIT

None

VK_IMAGE_USAGE_TRANSFER_DST_BIT

AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE

VK_IMAGE_USAGE_SAMPLED_BIT

AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE

VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT

AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT

VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT

AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP

VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT

AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE

None 2

AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT

VK_IMAGE_CREATE_PROTECTED_BIT

None

VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT

None

VK_IMAGE_CREATE_EXTENDED_USAGE_BIT

2

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

Note

When using VK_IMAGE_USAGE_MUTABLE_FORMAT_BIT with Android hardware buffer images, applications should use VkImageFormatListCreateInfoKHR to inform the implementation which view formats will be used with the image. For some common sets of format, this allows some implementations to provide significantly better performance when accessing the image via Vulkan.

Android Hardware Buffer Buffer Resources

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

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

Exported AHardwareBuffer objects that do not have dedicated images must have a format of AHARDWAREBUFFER_FORMAT_BLOB, usage must include AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER, width must equal the device memory allocation size, and height and layers must be 1.

10.2.5. Peer Memory Features

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:

void vkGetDeviceGroupPeerMemoryFeatures(
    VkDevice                                    device,
    uint32_t                                    heapIndex,
    uint32_t                                    localDeviceIndex,
    uint32_t                                    remoteDeviceIndex,
    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);

or the equivalent command

void vkGetDeviceGroupPeerMemoryFeaturesKHR(
    VkDevice                                    device,
    uint32_t                                    heapIndex,
    uint32_t                                    localDeviceIndex,
    uint32_t                                    remoteDeviceIndex,
    VkPeerMemoryFeatureFlags*                   pPeerMemoryFeatures);
  • device is the logical device that owns the memory.

  • heapIndex is the index of the memory heap from which the memory is allocated.

  • localDeviceIndex is the device index of the physical device that performs the memory access.

  • remoteDeviceIndex is the device index of the physical device that the memory is allocated for.

  • pPeerMemoryFeatures is a pointer to a bitmask of VkPeerMemoryFeatureFlagBits indicating which types of memory accesses are supported for the combination of heap, local, and remote devices.

Valid Usage
  • heapIndex must be less than memoryHeapCount

  • localDeviceIndex must be a valid device index

  • remoteDeviceIndex must be a valid device index

  • localDeviceIndex must not equal remoteDeviceIndex

Valid Usage (Implicit)
  • device must be a valid VkDevice handle

  • pPeerMemoryFeatures must be a valid pointer to a VkPeerMemoryFeatureFlags value

Bits which may be set in the value returned for vkGetDeviceGroupPeerMemoryFeatures::pPeerMemoryFeatures, indicating the supported peer memory features, are:

typedef enum VkPeerMemoryFeatureFlagBits {
    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 0x00000001,
    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 0x00000002,
    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 0x00000004,
    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 0x00000008,
    VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT,
    VK_PEER_MEMORY_FEATURE_COPY_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_COPY_DST_BIT,
    VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT,
    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT_KHR = VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT,
} VkPeerMemoryFeatureFlagBits;

or the equivalent

typedef VkPeerMemoryFeatureFlagBits VkPeerMemoryFeatureFlagBitsKHR;
  • VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT specifies that the memory can be accessed as the source of a vkCmdCopyBuffer, vkCmdCopyImage, vkCmdCopyBufferToImage, or vkCmdCopyImageToBuffer command.

  • VK_PEER_MEMORY_FEATURE_COPY_DST_BIT specifies that the memory can be accessed as the destination of a vkCmdCopyBuffer, vkCmdCopyImage, vkCmdCopyBufferToImage, or vkCmdCopyImageToBuffer command.

  • VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT specifies that the memory can be read as any memory access type.

  • 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

The peer memory features of a memory heap also apply to any accesses that may be performed during image layout transitions.

VK_PEER_MEMORY_FEATURE_COPY_DST_BIT must be supported for all host local heaps and for at least one device local 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.

typedef VkFlags VkPeerMemoryFeatureFlags;

or the equivalent

typedef VkPeerMemoryFeatureFlags VkPeerMemoryFeatureFlagsKHR;

VkPeerMemoryFeatureFlags is a bitmask type for setting a mask of zero or more VkPeerMemoryFeatureFlagBits.