Vulkan Logo

11. Memory Allocation

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

11.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:

// Provided by VK_VERSION_1_0
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 PFN_vkAllocationFunction pointer to an application-defined memory allocation function.

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

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

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

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

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

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

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

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

The type of pfnAllocation is:

// Provided by VK_VERSION_1_0
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 runtime 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:

// Provided by VK_VERSION_1_0
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 a compatible 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.

If the reallocation was successful, 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:

// Provided by VK_VERSION_1_0
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:

// Provided by VK_VERSION_1_0
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:

// Provided by VK_VERSION_1_0
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 defining 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:

// Provided by VK_VERSION_1_0
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 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 a VkPipelineCache object, 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:

// Provided by VK_VERSION_1_0
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 a VK_ERROR_OUT_OF_HOST_MEMORY error, as appropriate.

Allocation callbacks must not call any Vulkan commands.

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

pfnAllocation or pfnReallocation may be called in the following situations:

  • Allocations scoped to a VkDevice 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 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, or pfnReallocation with zero size, 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 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.

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

11.2.1. Device Memory Properties

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

To query memory properties, call:

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

  • pMemoryProperties is a pointer to a VkPhysicalDeviceMemoryProperties structure in which the properties are returned.

Valid Usage (Implicit)
  • VUID-vkGetPhysicalDeviceMemoryProperties-physicalDevice-parameter
    physicalDevice must be a valid VkPhysicalDevice handle

  • VUID-vkGetPhysicalDeviceMemoryProperties-pMemoryProperties-parameter
    pMemoryProperties must be a valid pointer to a VkPhysicalDeviceMemoryProperties structure

The VkPhysicalDeviceMemoryProperties structure is defined as:

// Provided by VK_VERSION_1_0
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 VK_MAX_MEMORY_TYPES 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 VK_MAX_MEMORY_HEAPS 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:

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

VK_MAX_MEMORY_TYPES is the length of an array of VkMemoryType structures describing memory types, as returned in VkPhysicalDeviceMemoryProperties::memoryTypes.

#define VK_MAX_MEMORY_TYPES               32U

VK_MAX_MEMORY_HEAPS is the length of an array of VkMemoryHeap structures describing memory heaps, as returned in VkPhysicalDeviceMemoryProperties::memoryHeaps.

#define VK_MAX_MEMORY_HEAPS               16U

To query memory properties, call:

// Provided by VK_VERSION_1_1
void vkGetPhysicalDeviceMemoryProperties2(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceMemoryProperties2*          pMemoryProperties);
  • physicalDevice is the handle to the device to query.

  • pMemoryProperties is a pointer to a 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)
  • VUID-vkGetPhysicalDeviceMemoryProperties2-physicalDevice-parameter
    physicalDevice must be a valid VkPhysicalDevice handle

  • VUID-vkGetPhysicalDeviceMemoryProperties2-pMemoryProperties-parameter
    pMemoryProperties must be a valid pointer to a VkPhysicalDeviceMemoryProperties2 structure

The VkPhysicalDeviceMemoryProperties2 structure is defined as:

// Provided by VK_VERSION_1_1
typedef struct VkPhysicalDeviceMemoryProperties2 {
    VkStructureType                     sType;
    void*                               pNext;
    VkPhysicalDeviceMemoryProperties    memoryProperties;
} VkPhysicalDeviceMemoryProperties2;
Valid Usage (Implicit)
  • VUID-VkPhysicalDeviceMemoryProperties2-sType-sType
    sType must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2

  • VUID-VkPhysicalDeviceMemoryProperties2-pNext-pNext
    pNext must be NULL

The VkMemoryHeap structure is defined as:

// Provided by VK_VERSION_1_0
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:

// Provided by VK_VERSION_1_0
typedef enum VkMemoryHeapFlagBits {
    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
  // Provided by VK_VERSION_1_1
    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 0x00000002,
} 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.

// Provided by VK_VERSION_1_0
typedef VkFlags VkMemoryHeapFlags;

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

The VkMemoryType structure is defined as:

// Provided by VK_VERSION_1_0
typedef struct VkMemoryType {
    VkMemoryPropertyFlags    propertyFlags;
    uint32_t                 heapIndex;
} VkMemoryType;

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

// Provided by VK_VERSION_1_0
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,
  // Provided by VK_VERSION_1_1
    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.

// Provided by VK_VERSION_1_0
typedef VkFlags VkMemoryPropertyFlags;

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

11.2.2. Device Memory Objects

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

// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)

11.2.3. Device Memory Allocation

To allocate memory objects, call:

// Provided by VK_VERSION_1_0
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 a VkMemoryAllocateInfo structure describing parameters of the allocation. A successfully 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 the contents 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. The maxMemoryAllocationCount feature describes the number of allocations that can exist simultaneously before encountering these internal limits.

Note

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

Note

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

Some platforms may have a limit on the maximum size of a single allocation. For example, certain systems may fail to create allocations with a size greater than or equal to 4GB. Such a limit is implementation-dependent, and if such a failure occurs then the error VK_ERROR_OUT_OF_DEVICE_MEMORY must be returned.

Valid Usage
Valid Usage (Implicit)
  • VUID-vkAllocateMemory-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkAllocateMemory-pAllocateInfo-parameter
    pAllocateInfo must be a valid pointer to a valid VkMemoryAllocateInfo structure

  • VUID-vkAllocateMemory-pAllocator-parameter
    If pAllocator is not NULL, pAllocator must be a valid pointer to a valid VkAllocationCallbacks structure

  • VUID-vkAllocateMemory-pMemory-parameter
    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_INVALID_EXTERNAL_HANDLE

The VkMemoryAllocateInfo structure is defined as:

// Provided by VK_VERSION_1_0
typedef struct VkMemoryAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceSize       allocationSize;
    uint32_t           memoryTypeIndex;
} VkMemoryAllocateInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this 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.

The internal data of an allocated device memory object must include a reference to implementation-specific resources, referred to as the memory object’s payload.

Valid Usage
  • VUID-VkMemoryAllocateInfo-allocationSize-07897
    allocationSize must be greater than 0

  • VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872
    If the protectedMemory feature is not enabled, the VkMemoryAllocateInfo::memoryTypeIndex must not indicate a memory type that reports VK_MEMORY_PROPERTY_PROTECTED_BIT

  • VUID-VkMemoryAllocateInfo-opaqueCaptureAddress-03329
    If VkMemoryOpaqueCaptureAddressAllocateInfo::opaqueCaptureAddress is not zero, VkMemoryAllocateFlagsInfo::flags must include VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT

  • VUID-VkMemoryAllocateInfo-flags-03330
    If VkMemoryAllocateFlagsInfo::flags includes VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT, the bufferDeviceAddressCaptureReplay feature must be enabled

  • VUID-VkMemoryAllocateInfo-flags-03331
    If VkMemoryAllocateFlagsInfo::flags includes VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, the bufferDeviceAddress feature must be enabled

  • VUID-VkMemoryAllocateInfo-opaqueCaptureAddress-03333
    If the parameters define an import operation, VkMemoryOpaqueCaptureAddressAllocateInfo::opaqueCaptureAddress must be zero

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:

// Provided by VK_VERSION_1_1
typedef struct VkMemoryDedicatedAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkImage            image;
    VkBuffer           buffer;
} VkMemoryDedicatedAllocateInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this 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
  • VUID-VkMemoryDedicatedAllocateInfo-image-01432
    At least one of image and buffer must be VK_NULL_HANDLE

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

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

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

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

Valid Usage (Implicit)
  • VUID-VkMemoryDedicatedAllocateInfo-sType-sType
    sType must be VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO

  • VUID-VkMemoryDedicatedAllocateInfo-image-parameter
    If image is not VK_NULL_HANDLE, image must be a valid VkImage handle

  • VUID-VkMemoryDedicatedAllocateInfo-buffer-parameter
    If buffer is not VK_NULL_HANDLE, buffer must be a valid VkBuffer handle

  • VUID-VkMemoryDedicatedAllocateInfo-commonparent
    Both of buffer, and image that are valid handles of non-ignored parameters must have been created, allocated, or retrieved from the same VkDevice

When allocating memory whose payload 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:

// Provided by VK_VERSION_1_1
typedef struct VkExportMemoryAllocateInfo {
    VkStructureType                    sType;
    const void*                        pNext;
    VkExternalMemoryHandleTypeFlags    handleTypes;
} VkExportMemoryAllocateInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this structure.

  • handleTypes is zero or 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)
  • VUID-VkExportMemoryAllocateInfo-sType-sType
    sType must be VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO

  • VUID-VkExportMemoryAllocateInfo-handleTypes-parameter
    handleTypes must be a valid combination of VkExternalMemoryHandleTypeFlagBits values

11.2.4. Device Group Memory Allocations

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:

// Provided by VK_VERSION_1_1
typedef struct VkMemoryAllocateFlagsInfo {
    VkStructureType          sType;
    const void*              pNext;
    VkMemoryAllocateFlags    flags;
    uint32_t                 deviceMask;
} VkMemoryAllocateFlagsInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this 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
  • VUID-VkMemoryAllocateFlagsInfo-deviceMask-00675
    If VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set, deviceMask must be a valid device mask

  • VUID-VkMemoryAllocateFlagsInfo-deviceMask-00676
    If VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT is set, deviceMask must not be zero

Valid Usage (Implicit)
  • VUID-VkMemoryAllocateFlagsInfo-sType-sType
    sType must be VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO

  • VUID-VkMemoryAllocateFlagsInfo-flags-parameter
    flags must be a valid combination of VkMemoryAllocateFlagBits values

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

// Provided by VK_VERSION_1_1
typedef enum VkMemoryAllocateFlagBits {
    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 0x00000001,
  // Provided by VK_VERSION_1_2
    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 0x00000002,
  // Provided by VK_VERSION_1_2
    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 0x00000004,
} VkMemoryAllocateFlagBits;
  • VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT specifies that memory will be allocated for the devices in VkMemoryAllocateFlagsInfo::deviceMask.

  • VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT specifies that the memory can be attached to a buffer object created with the VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT bit set in usage, and that the memory handle can be used to retrieve an opaque address via vkGetDeviceMemoryOpaqueCaptureAddress.

  • VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT specifies that the memory’s address can be saved and reused on a subsequent run (e.g. for trace capture and replay), see VkBufferOpaqueCaptureAddressCreateInfo for more detail.

// Provided by VK_VERSION_1_1
typedef VkFlags VkMemoryAllocateFlags;

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

11.2.5. Opaque Capture Address Allocation

To request a specific device address for a memory allocation, add a VkMemoryOpaqueCaptureAddressAllocateInfo structure to the pNext chain of the VkMemoryAllocateInfo structure. The VkMemoryOpaqueCaptureAddressAllocateInfo structure is defined as:

// Provided by VK_VERSION_1_2
typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo {
    VkStructureType    sType;
    const void*        pNext;
    uint64_t           opaqueCaptureAddress;
} VkMemoryOpaqueCaptureAddressAllocateInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this structure.

  • opaqueCaptureAddress is the opaque capture address requested for the memory allocation.

If opaqueCaptureAddress is zero, no specific address is requested.

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

Note

In most cases, it is expected that a non-zero opaqueAddress is an address retrieved from vkGetDeviceMemoryOpaqueCaptureAddress on an identically created memory allocation. If this is not the case, it is likely that VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS errors will occur.

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

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

Valid Usage (Implicit)
  • VUID-VkMemoryOpaqueCaptureAddressAllocateInfo-sType-sType
    sType must be VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO

11.2.6. Freeing Device Memory

To free a memory object, call:

// Provided by VK_VERSION_1_0
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. Memory can be freed whilst still bound to resources, but those resources must not be used afterwards. Freeing a memory object releases the reference it held, if any, to its payload. If there are still any bound images or buffers, the memory object’s payload may not be immediately released by the implementation, but must be released by the time all bound images and buffers have been destroyed. Once all references to a payload are released, it is returned to the heap from which it was allocated.

How memory objects are bound to Images and Buffers is described in detail in the 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
  • VUID-vkFreeMemory-memory-00677
    All submitted commands that refer to memory (via images or buffers) must have completed execution

Valid Usage (Implicit)
  • VUID-vkFreeMemory-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkFreeMemory-memory-parameter
    If memory is not VK_NULL_HANDLE, memory must be a valid VkDeviceMemory handle

  • VUID-vkFreeMemory-pAllocator-parameter
    If pAllocator is not NULL, pAllocator must be a valid pointer to a valid VkAllocationCallbacks structure

  • VUID-vkFreeMemory-memory-parent
    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

11.2.7. 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:

// Provided by VK_VERSION_1_0
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 is a pointer to a void* variable in which a host-accessible pointer to the beginning of the mapped range is returned. This pointer minus offset must be aligned to at least VkPhysicalDeviceLimits::minMemoryMapAlignment.

After a successful call to vkMapMemory the memory object memory is considered to be currently host mapped.

Note

It is an application error to call vkMapMemory on a memory object that is already host 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 host mapped, 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
  • VUID-vkMapMemory-memory-00678
    memory must not be currently host mapped

  • VUID-vkMapMemory-offset-00679
    offset must be less than the size of memory

  • VUID-vkMapMemory-size-00680
    If size is not equal to VK_WHOLE_SIZE, size must be greater than 0

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

  • VUID-vkMapMemory-memory-00682
    memory must have been created with a memory type that reports VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT

Valid Usage (Implicit)
  • VUID-vkMapMemory-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkMapMemory-memory-parameter
    memory must be a valid VkDeviceMemory handle

  • VUID-vkMapMemory-flags-zerobitmask
    flags must be 0

  • VUID-vkMapMemory-ppData-parameter
    ppData must be a valid pointer to a pointer value

  • VUID-vkMapMemory-memory-parent
    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

// Provided by VK_VERSION_1_0
typedef VkFlags VkMemoryMapFlags;

VkMemoryMapFlags is a bitmask type for setting a mask of zero or more VkMemoryMapFlagBits.

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.

After a successful call to vkMapMemory the memory object memory is considered to be currently host mapped.

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

// Provided by VK_VERSION_1_0
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 host 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 host mapped memory, and host writes that have not been flushed may not ever be visible to the device. However, implementations must ensure that writes that have not been flushed do not become visible to any other memory.

Note

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)
  • VUID-vkFlushMappedMemoryRanges-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkFlushMappedMemoryRanges-pMemoryRanges-parameter
    pMemoryRanges must be a valid pointer to an array of memoryRangeCount valid VkMappedMemoryRange structures

  • VUID-vkFlushMappedMemoryRanges-memoryRangeCount-arraylength
    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:

// Provided by VK_VERSION_1_0
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 host mapped, or the last time it was invalidated.

Note

Mapping non-coherent memory does not implicitly invalidate that memory.

Valid Usage (Implicit)
  • VUID-vkInvalidateMappedMemoryRanges-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkInvalidateMappedMemoryRanges-pMemoryRanges-parameter
    pMemoryRanges must be a valid pointer to an array of memoryRangeCount valid VkMappedMemoryRange structures

  • VUID-vkInvalidateMappedMemoryRanges-memoryRangeCount-arraylength
    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:

// Provided by VK_VERSION_1_0
typedef struct VkMappedMemoryRange {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
    VkDeviceSize       offset;
    VkDeviceSize       size;
} VkMappedMemoryRange;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this 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
  • VUID-VkMappedMemoryRange-memory-00684
    memory must be currently host mapped

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

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

  • VUID-VkMappedMemoryRange-offset-00687
    offset must be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize

  • VUID-VkMappedMemoryRange-size-01389
    If size is equal to VK_WHOLE_SIZE, the end of the current mapping of memory must either be a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize bytes from the beginning of the memory object, or be equal to the end of the memory object

  • VUID-VkMappedMemoryRange-size-01390
    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)
  • VUID-VkMappedMemoryRange-sType-sType
    sType must be VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE

  • VUID-VkMappedMemoryRange-pNext-pNext
    pNext must be NULL

  • VUID-VkMappedMemoryRange-memory-parameter
    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:

// Provided by VK_VERSION_1_0
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
  • VUID-vkUnmapMemory-memory-00689
    memory must be currently host mapped

Valid Usage (Implicit)
  • VUID-vkUnmapMemory-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkUnmapMemory-memory-parameter
    memory must be a valid VkDeviceMemory handle

  • VUID-vkUnmapMemory-memory-parent
    memory must have been created, allocated, or retrieved from device

Host Synchronization
  • Host access to memory must be externally synchronized

11.2.8. 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:

// Provided by VK_VERSION_1_0
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
  • VUID-vkGetDeviceMemoryCommitment-memory-00690
    memory must have been created with a memory type that reports VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

Valid Usage (Implicit)
  • VUID-vkGetDeviceMemoryCommitment-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkGetDeviceMemoryCommitment-memory-parameter
    memory must be a valid VkDeviceMemory handle

  • VUID-vkGetDeviceMemoryCommitment-pCommittedMemoryInBytes-parameter
    pCommittedMemoryInBytes must be a valid pointer to a VkDeviceSize value

  • VUID-vkGetDeviceMemoryCommitment-memory-parent
    memory must have been created, allocated, or retrieved from device

11.2.9. Protected Memory

Protected memory divides device memory into protected device memory and unprotected device memory.

Protected memory adds the following concepts:

  • Memory:

    • Unprotected device memory, which can be visible to the device and can be visible to the host

    • Protected device memory, which can be visible to the device but must not be visible to the host

  • Resources:

    • Unprotected images and unprotected buffers, to which unprotected memory can be bound

    • Protected images and protected buffers, to which protected memory can be bound

  • Command buffers:

    • Unprotected command buffers, which can be submitted to a device queue to execute unprotected queue operations

    • Protected command buffers, which can be submitted to a protected-capable device queue to execute protected queue operations

  • Device queues:

    • Unprotected device queues, to which unprotected command buffers can be submitted

    • Protected-capable device queues, to which unprotected command buffers or protected command buffers can be submitted

  • Queue submissions

    • Unprotected queue submissions, through which unprotected command buffers can be submitted

    • Protected queue submissions, through which protected command buffers can be submitted

  • Queue operations

    • Unprotected queue operations

    • Protected queue operations

Protected Memory Access Rules

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

  • Write to unprotected memory within protected queue operations.

  • Access protected memory within protected queue operations other than in framebuffer-space pipeline stages, the compute shader stage, or the transfer stage.

  • Perform a query within protected queue operations.

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

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

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

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

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

11.2.10. 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:

// Provided by VK_VERSION_1_1
void vkGetDeviceGroupPeerMemoryFeatures(
    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 VkPeerMemoryFeatureFlags bitmask indicating which types of memory accesses are supported for the combination of heap, local, and remote devices.

Valid Usage
  • VUID-vkGetDeviceGroupPeerMemoryFeatures-heapIndex-00691
    heapIndex must be less than memoryHeapCount

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-localDeviceIndex-00692
    localDeviceIndex must be a valid device index

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-remoteDeviceIndex-00693
    remoteDeviceIndex must be a valid device index

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-localDeviceIndex-00694
    localDeviceIndex must not equal remoteDeviceIndex

Valid Usage (Implicit)
  • VUID-vkGetDeviceGroupPeerMemoryFeatures-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkGetDeviceGroupPeerMemoryFeatures-pPeerMemoryFeatures-parameter
    pPeerMemoryFeatures must be a valid pointer to a VkPeerMemoryFeatureFlags value

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

// Provided by VK_VERSION_1_1
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,
} VkPeerMemoryFeatureFlagBits;
  • VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT specifies that the memory can be accessed as the source of any vkCmdCopy* command.

  • VK_PEER_MEMORY_FEATURE_COPY_DST_BIT specifies that the memory can be accessed as the destination of any vkCmdCopy* 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 memory heap.

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

// Provided by VK_VERSION_1_1
typedef VkFlags VkPeerMemoryFeatureFlags;

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

11.2.11. Opaque Capture Address Query

To query a 64-bit opaque capture address value from a memory object, call:

// Provided by VK_VERSION_1_2
uint64_t vkGetDeviceMemoryOpaqueCaptureAddress(
    VkDevice                                    device,
    const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
  • device is the logical device that the memory object was allocated on.

  • pInfo is a pointer to a VkDeviceMemoryOpaqueCaptureAddressInfo structure specifying the memory object to retrieve an address for.

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

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

Note

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

Valid Usage
  • VUID-vkGetDeviceMemoryOpaqueCaptureAddress-None-03334
    The bufferDeviceAddress feature must be enabled

  • VUID-vkGetDeviceMemoryOpaqueCaptureAddress-device-03335
    If device was created with multiple physical devices, then the bufferDeviceAddressMultiDevice feature must be enabled

Valid Usage (Implicit)
  • VUID-vkGetDeviceMemoryOpaqueCaptureAddress-device-parameter
    device must be a valid VkDevice handle

  • VUID-vkGetDeviceMemoryOpaqueCaptureAddress-pInfo-parameter
    pInfo must be a valid pointer to a valid VkDeviceMemoryOpaqueCaptureAddressInfo structure

The VkDeviceMemoryOpaqueCaptureAddressInfo structure is defined as:

// Provided by VK_VERSION_1_2
typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo {
    VkStructureType    sType;
    const void*        pNext;
    VkDeviceMemory     memory;
} VkDeviceMemoryOpaqueCaptureAddressInfo;
  • sType is a VkStructureType value identifying this structure.

  • pNext is NULL or a pointer to a structure extending this structure.

  • memory specifies the memory whose address is being queried.

Valid Usage
  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-03336
    memory must have been allocated with VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT

Valid Usage (Implicit)
  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-sType-sType
    sType must be VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO

  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-pNext-pNext
    pNext must be NULL

  • VUID-VkDeviceMemoryOpaqueCaptureAddressInfo-memory-parameter
    memory must be a valid VkDeviceMemory handle