VK_EXT_external_memory_metal

This extension allows memory sharing through imports from or export to Metal resource handles.

1. Problem Statement

An application may wish to reference device memory in multiple Vulkan device instances, in multiple processes, and/or in Metal API. This extension enables an application to export non-Vulkan handles from Vulkan memory objects such that the underlying resources can be referenced outside the scope of the Vulkan device instance that created them.

While VK_EXT_metal_objects provides a way to expose underlying Metal resources, when importing an image from an id<MTLTexture> handle, said images and their backing memory will be imported at VkImage creation. According to point 12.8 Memory Resource Association resources are created as virtual allocations with no backing memory. This leads to having to treat imported images through VK_EXT_metal_objects differently.

This extension aims to import both resources through VkDeviceMemory so that later can be bound to a existing VkImage or VkBuffer respectively.

2. Proposal

This extension aims to standardize memory imports and exports of Vulkan resources using VK_KHR_external_memory as baseline to conform to what other platforms have done with extensions like VK_KHR_external_memory_win32 and VK_ANDROID_external_memory_android_hardware_buffer to name a few.

This means that external Metal resources will be imported through VkDeviceMemory to later be bound.

3 new bit values will be added to VkExternalMemoryHandleTypeFlagBits:

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT to accommodate for Metal buffers (MTLBuffer)

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT to accommodate for Metal textures (MTLTexture)

  • VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT to accommodate for Metal heaps (MTLHeap)

Due to MTLTexture’s semantics in Metal API roughly align with that of an image with a dedicated allocation in Vulkan, implementations will be required to report VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT for VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT. When importing a MTLTexture through the creation of a VkDeviceMemory, the VkImage VkImage it will be bound to must have the same creation parameters as the MTLTexture used at import.

3. Examples

3.1. Importing a Metal texture from a id<MTLTexture>

void *metalTexture = /* Initialized to id<MTLTexture> */;
VkMemoryMetalHandlePropertiesEXT handleProperties;
VkResult result = vkGetMemoryMetalHandlePropertiesEXT(
    device,
    VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT,
    metalTexture,
    &handleProperties);

VkImageCreateInfo imageCreateInfo = {
    // This image creation parameters should match MTLTexture's, or the exported VkImage's
};
VkImage image;
result = vkCreateImage(
    device,
    &imageCreateInfo,
    NULL,               // pAllocator
    &image);

// Import image memory
VkImportMemoryMetalHandleInfoEXT importInfo = {
    .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT,
    .pNext = NULL,
    .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT,
    .handle = metalTexture
};
VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = {
    .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
    .pNext = &importInfo,
    .image = image,
    .buffer = VK_NULL_HANDLE,
};
VkMemoryAllocateInfo allocateInfo = {
    .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
    .pNext = &dedicatedInfo,
    .allocationSize = 0, // Ignored. The allocation will have the size of the Metal object
    .memoryTypeIndex = /* Select preferred memory type from handleProperties.memoryTypeBits */
};
// If the Metal object cannot be used for the VkImage we created, implementations will return VK_ERROR_INVALID_EXTERNAL_HANDLE
VkDeviceMemory memory;
result = vkAllocateMemory(
    device,
    &allocateInfo,
    NULL,
    &memory);

if (result == VK_SUCCESS) {
    // Bind memory to image
} else {
    // Handle failure
}

4. Issues

None identified.