## 10.1. Host Memory

Host memory is memory needed by the Vulkan implementation for non-device-visible storage. This storage may be used for e.g. internal software structures.

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

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 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 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. The allocation scope is provided in the `allocationScope` parameter passed to callbacks defined in `VkAllocationCallbacks`. Possible values for this parameter are defined by `VkSystemAllocationScope`:

    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` - The allocation is scoped to the duration of the Vulkan command.
- `VK_SYSTEM_ALLOCATION_SCOPE_OBJECT` - The allocation is scoped to the lifetime of the Vulkan object that is being created or used.
- `VK_SYSTEM_ALLOCATION_SCOPE_CACHE` - The allocation is scoped to the lifetime of a `VkPipelineCache` object.
- `VK_SYSTEM_ALLOCATION_SCOPE_DEVICE` - The allocation is scoped to the lifetime of the Vulkan device.
- `VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE` - The allocation is scoped to the lifetime of the Vulkan instance.

Most Vulkan commands operate on a single object, or there is a sole object that is being created or manipulated. When an allocation uses an allocation scope of `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 `VkPipelineCache`, the allocator will use the `VK_SYSTEM_ALLOCATION_SCOPE_CACHE` allocation scope. The most specific allocator available is used (pipeline cache, else device, else instance). Else,
- If an allocation is scoped to the lifetime of an object, that object is being created or manipulated by the command, and that object’s type is not `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 ename VK_SYSTEM_ALLOCATION_SCOPE_DEVICE. The most specific allocator available is used (device, else instance). Else,
- If the allocation is scoped to the lifetime of an instance and the instance has an allocator, its allocator will be used with an allocation scope of `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` - 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 an `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 `pPipelineCache`
  - `vkCreateComputePipelines` for `pPipelineCache`

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