Use VK_EXT_external_memory_metal on MoltenVK mode
Use the new external memory extension for the management of
external images and buffers. Previous extension and usage was
depending on some workarounds on managing metal objects which
was causing issues with the usage of VVL.
Requires a new version of MoltenVK prebuilts/binaries.
Bug: 349066492
Bug: 368409646
Bug: 351765838
Test: -gpu host -feature GuestAngle
Change-Id: I47f0f13bde9d7e3dc95da1af3673deac649745d7
diff --git a/codegen/vulkan/vulkan-docs-next/xml/vk.xml b/codegen/vulkan/vulkan-docs-next/xml/vk.xml
index d15bcce..20f350e 100644
--- a/codegen/vulkan/vulkan-docs-next/xml/vk.xml
+++ b/codegen/vulkan/vulkan-docs-next/xml/vk.xml
@@ -265,12 +265,6 @@
#else
typedef void* <name>MTLSharedEvent_id</name>;
#endif</type>
- <type category="basetype">#ifdef __OBJC__
-@protocol MTLResource;
-typedef __unsafe_unretained id<MTLResource> MTLResource_id;
-#else
-typedef void* <name>MTLResource_id</name>;
-#endif</type>
<type category="basetype">typedef struct __IOSurface* <name>IOSurfaceRef</name>;</type>
<type category="basetype">typedef <type>uint32_t</type> <name>VkSampleMask</name>;</type>
@@ -2747,7 +2741,7 @@
<member values="VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></member>
- <member optional="true"><type>MTLResource_id</type> <name>handle</name></member>
+ <member optional="true"><type>void</type>* <name>handle</name></member>
</type>
<type category="struct" name="VkMemoryMetalHandlePropertiesEXT" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_MEMORY_METAL_HANDLE_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -15071,13 +15065,13 @@
<proto><type>VkResult</type> <name>vkGetMemoryMetalHandleEXT</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param>const <type>VkMemoryGetMetalHandleInfoEXT</type>* <name>pGetMetalHandleInfo</name></param>
- <param><type>MTLResource_id</type>* <name>pHandle</name></param>
+ <param><type>void</type>** <name>pHandle</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INVALID_EXTERNAL_HANDLE">
<proto><type>VkResult</type> <name>vkGetMemoryMetalHandlePropertiesEXT</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></param>
- <param><type>MTLResource_id</type> <name>handle</name></param>
+ <param><type>void</type>* <name>handle</name></param>
<param><type>VkMemoryMetalHandlePropertiesEXT</type>* <name>pMemoryMetalHandleProperties</name></param>
</command>
</commands>
@@ -23740,10 +23734,10 @@
<enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_MEMORY_GET_METAL_HANDLE_INFO_EXT"/>
<enum bitpos="16" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT"/>
<enum bitpos="17" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT"/>
+ <enum bitpos="18" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT"/>
<type name="VkImportMemoryMetalHandleInfoEXT"/>
<type name="VkMemoryMetalHandlePropertiesEXT"/>
<type name="VkMemoryGetMetalHandleInfoEXT"/>
- <type name="MTLResource_id"/>
<command name="vkGetMemoryMetalHandleEXT"/>
<command name="vkGetMemoryMetalHandlePropertiesEXT"/>
</require>
diff --git a/common/vulkan/include/vulkan/vulkan_core.h b/common/vulkan/include/vulkan/vulkan_core.h
index f6e9025..f4cd457 100644
--- a/common/vulkan/include/vulkan/vulkan_core.h
+++ b/common/vulkan/include/vulkan/vulkan_core.h
@@ -5042,6 +5042,7 @@
VK_EXTERNAL_MEMORY_HANDLE_TYPE_SCREEN_BUFFER_BIT_QNX = 0x00004000,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT = 0x00010000,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT = 0x00020000,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT = 0x00040000,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
diff --git a/common/vulkan/include/vulkan/vulkan_metal.h b/common/vulkan/include/vulkan/vulkan_metal.h
index 1bc8780..1491cb0 100644
--- a/common/vulkan/include/vulkan/vulkan_metal.h
+++ b/common/vulkan/include/vulkan/vulkan_metal.h
@@ -191,12 +191,8 @@
// VK_EXT_external_memory_metal is a preprocessor guard. Do not pass it to API calls.
#define VK_EXT_external_memory_metal 1
-#ifdef __OBJC__
-@protocol MTLResource;
-typedef __unsafe_unretained id<MTLResource> MTLResource_id;
-#else
+
typedef void* MTLResource_id;
-#endif
#define VK_EXT_EXTERNAL_MEMORY_METAL_SPEC_VERSION 1
#define VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME "VK_EXT_external_memory_metal"
diff --git a/host/vulkan/VkAndroidNativeBuffer.cpp b/host/vulkan/VkAndroidNativeBuffer.cpp
index 9832fb6..71a97ec 100644
--- a/host/vulkan/VkAndroidNativeBuffer.cpp
+++ b/host/vulkan/VkAndroidNativeBuffer.cpp
@@ -185,22 +185,9 @@
};
#if defined(__APPLE__)
- VkImportMetalTextureInfoEXT metalImageImport = {
- VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT};
-
if (emu->instanceSupportsMoltenVK) {
- // Change handle type requested to mtltexture
- extImageCi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
-
- if (out->colorBufferHandle) {
- // TODO(b/333460957): External memory is not properly supported on MoltenVK
- // and although this works fine, it's not valid and causing validation layer issues
- metalImageImport.plane = VK_IMAGE_ASPECT_PLANE_0_BIT;
- metalImageImport.mtlTexture = getColorBufferMTLTexture(out->colorBufferHandle);
-
- // Insert metalImageImport to the chain
- vk_insert_struct(createImageCi, metalImageImport);
- }
+ // Change handle type requested to metal handle
+ extImageCi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
diff --git a/host/vulkan/VkCommonOperations.cpp b/host/vulkan/VkCommonOperations.cpp
index 541c7c5..782d04f 100644
--- a/host/vulkan/VkCommonOperations.cpp
+++ b/host/vulkan/VkCommonOperations.cpp
@@ -353,7 +353,7 @@
#if defined(__APPLE__)
if (sVkEmulation->instanceSupportsMoltenVK) {
// Using a different handle type when in MoltenVK mode
- extInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
+ extInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
@@ -421,11 +421,11 @@
VkExternalMemoryHandleTypeFlags compatibleHandleTypes =
outExternalProps.externalMemoryProperties.compatibleHandleTypes;
- VkExternalMemoryHandleTypeFlagBits handleTypeNeeded = VK_EXT_MEMORY_HANDLE_TYPE_BIT;
+ VkExternalMemoryHandleTypeFlags handleTypeNeeded = VK_EXT_MEMORY_HANDLE_TYPE_BIT;
#if defined(__APPLE__)
if (sVkEmulation->instanceSupportsMoltenVK) {
// Using a different handle type when in MoltenVK mode
- handleTypeNeeded = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
+ handleTypeNeeded = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
@@ -776,6 +776,7 @@
std::vector<const char*> moltenVkDeviceExtNames = {
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
VK_EXT_METAL_OBJECTS_EXTENSION_NAME,
+ VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME,
};
#endif
@@ -797,8 +798,13 @@
#if defined(__APPLE__)
const std::string vulkanIcd = android::base::getEnvironmentVariable("ANDROID_EMU_VK_ICD");
const bool moltenVKEnabled = (vulkanIcd == "moltenvk");
- bool moltenVKSupported = moltenVKEnabled &&
- extensionsSupported(instanceExts, moltenVkInstanceExtNames);
+ const bool moltenVKSupported = extensionsSupported(instanceExts, moltenVkInstanceExtNames);
+ if (moltenVKEnabled && !moltenVKSupported) {
+ // This might happen if the user manually changes moltenvk ICD library
+ ERR("MoltenVK requested, but the required extensions are not supported.");
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "MoltenVK requested, but the required extensions are not supported.";
+ }
+ const bool useMoltenVK = moltenVKEnabled && moltenVKSupported;
#endif
VkInstanceCreateInfo instCi = {
@@ -855,7 +861,7 @@
}
#if defined(__APPLE__)
- if (moltenVKSupported) {
+ if (useMoltenVK) {
INFO("MoltenVK is supported, enabling Vulkan portability.");
instCi.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
for (auto extension : moltenVkInstanceExtNames) {
@@ -958,7 +964,7 @@
sVkEmulation->instanceSupportsExternalFenceCapabilities = externalFenceCapabilitiesSupported;
sVkEmulation->instanceSupportsSurface = surfaceSupported;
#if defined(__APPLE__)
- sVkEmulation->instanceSupportsMoltenVK = moltenVKSupported;
+ sVkEmulation->instanceSupportsMoltenVK = useMoltenVK;
#endif
if (sVkEmulation->instanceSupportsGetPhysicalDeviceProperties2) {
@@ -980,8 +986,9 @@
#if defined(__APPLE__)
if (sVkEmulation->instanceSupportsMoltenVK) {
- // Using metal_objects extension on MacOS when moltenVK is used.
+ // Enable some specific extensions on MacOS when moltenVK is used.
externalMemoryDeviceExtNames.push_back(VK_EXT_METAL_OBJECTS_EXTENSION_NAME);
+ externalMemoryDeviceExtNames.push_back(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
} else {
// When MoltenVK is not used(e.g. SwiftShader), use memory fd extension for external memory.
externalMemoryDeviceExtNames.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
@@ -1024,7 +1031,7 @@
deviceInfos[i].glInteropSupported = 0; // set later
#if defined(__APPLE__)
- if (moltenVKSupported && !extensionsSupported(deviceExts, moltenVkDeviceExtNames)) {
+ if (useMoltenVK && !extensionsSupported(deviceExts, moltenVkDeviceExtNames)) {
VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
ABORT_REASON_OTHER,
"MoltenVK enabled but necessary device extensions are not supported.");
@@ -1272,7 +1279,7 @@
}
#if defined(__APPLE__)
- if (moltenVKSupported) {
+ if (useMoltenVK) {
for (auto extension : moltenVkDeviceExtNames) {
selectedDeviceExtensionNames_.emplace(extension);
}
@@ -1394,11 +1401,11 @@
}
#else
if (sVkEmulation->instanceSupportsMoltenVK) {
- // vkExportMetalObjectsEXT will be used directly
+ // We'll use vkGetMemoryMetalHandleEXT, no need to save into getMemoryHandleFunc
sVkEmulation->deviceInfo.getMemoryHandleFunc = nullptr;
- if (!dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkExportMetalObjectsEXT")) {
+ if (!dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetMemoryMetalHandleEXT")) {
VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
- "Cannot find vkExportMetalObjectsEXT");
+ "Cannot find vkGetMemoryMetalHandleEXT");
}
} else {
// Use vkGetMemoryFdKHR
@@ -1684,30 +1691,25 @@
}
#ifdef __APPLE__
-static MTLBufferRef getMtlBufferFromVkDeviceMemory(VulkanDispatch* vk, VkDeviceMemory memory) {
- VkExportMetalBufferInfoEXT exportMetalBufferInfo = {
- VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT, nullptr, memory, VK_NULL_HANDLE};
- VkExportMetalObjectsInfoEXT metalObjectsInfo = {VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT,
- &exportMetalBufferInfo};
- vk->vkExportMetalObjectsEXT(sVkEmulation->device, &metalObjectsInfo);
+static MTLResource_id getMtlResourceFromVkDeviceMemory(VulkanDispatch* vk, VkDeviceMemory memory) {
+ if (memory == VK_NULL_HANDLE) {
+ WARN("Requested metal resource handle for null memory!");
+ return nullptr;
+ }
- return exportMetalBufferInfo.mtlBuffer;
-}
-
-static MTLTextureRef getMtlTextureFromVkImage(VulkanDispatch* vk, VkImage image) {
- VkExportMetalTextureInfoEXT exportMetalTextureInfo = {
- VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT,
+ VkMemoryGetMetalHandleInfoEXT getMetalHandleInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_GET_METAL_HANDLE_INFO_EXT,
nullptr,
- image,
- VK_NULL_HANDLE,
- VK_NULL_HANDLE,
- VK_IMAGE_ASPECT_PLANE_0_BIT,
- VK_NULL_HANDLE};
- VkExportMetalObjectsInfoEXT metalObjectsInfo = {VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT,
- &exportMetalTextureInfo};
- vk->vkExportMetalObjectsEXT(sVkEmulation->device, &metalObjectsInfo);
+ memory,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT
+ };
- return exportMetalTextureInfo.mtlTexture;
+ MTLResource_id outputHandle = nullptr;
+ vk->vkGetMemoryMetalHandleEXT(sVkEmulation->device, &getMetalHandleInfo, &outputHandle);
+ if (outputHandle == nullptr) {
+ ERR("vkGetMemoryMetalHandleEXT returned null");
+ }
+ return outputHandle;
}
#endif
@@ -1738,24 +1740,15 @@
auto allocInfoChain = vk_make_chain_iterator(&allocInfo);
-#ifdef __APPLE__
- // On MoltenVK, use metal objects to export metal handles
- VkExportMetalObjectCreateInfoEXT metalBufferExport = {
- VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT, nullptr,
- VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT};
-#endif
if (sVkEmulation->deviceInfo.supportsExternalMemoryExport && actuallyExternal) {
#ifdef __APPLE__
if (sVkEmulation->instanceSupportsMoltenVK) {
- // Change handle type to metal buffers
- exportAi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR;
-
- // Append metal buffer export for getting metal handles for the allocation
- vk_append_struct(&allocInfoChain, &metalBufferExport);
+ // Change handle type for metal resources
+ exportAi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
- if (sVkEmulation->deviceInfo.supportsDmaBuf && actuallyExternal) {
+ if (sVkEmulation->deviceInfo.supportsDmaBuf) {
exportAi.handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
}
@@ -1859,11 +1852,12 @@
validHandle = (VK_EXT_MEMORY_HANDLE_INVALID != info->externalHandle);
info->streamHandleType = STREAM_MEM_HANDLE_TYPE_OPAQUE_WIN32;
#elif !defined(__QNX__)
- bool opaque_fd = true;
- if (sVkEmulation->instanceSupportsMoltenVK) {
- opaque_fd = false;
+
+ bool opaqueFd = true;
#if defined(__APPLE__)
- info->externalMetalHandle = getMtlBufferFromVkDeviceMemory(vk, info->memory);
+ if (sVkEmulation->instanceSupportsMoltenVK) {
+ opaqueFd = false;
+ info->externalMetalHandle = getMtlResourceFromVkDeviceMemory(vk, info->memory);
validHandle = (nullptr != info->externalMetalHandle);
if (validHandle) {
CFRetain(info->externalMetalHandle);
@@ -1871,9 +1865,10 @@
} else {
exportRes = VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
-#endif
}
- if (opaque_fd) {
+#endif
+
+ if (opaqueFd) {
if (sVkEmulation->deviceInfo.supportsDmaBuf) {
vkHandleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
info->streamHandleType = STREAM_MEM_HANDLE_TYPE_DMABUF;
@@ -1960,25 +1955,29 @@
};
importInfoPtr = &importInfo;
#else
+
+ bool opaqueFd = true;
+#ifdef __APPLE__
+ VkImportMemoryMetalHandleInfoEXT importInfoMetalInfo = {
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT,
+ 0,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT,
+ nullptr
+ };
+ if (sVkEmulation->instanceSupportsMoltenVK) {
+ opaqueFd = false;
+ importInfoMetalInfo.handle = info->externalMetalHandle;
+ importInfoPtr = &importInfoMetalInfo;
+ }
+#endif
+
VkImportMemoryFdInfoKHR importInfoFd = {
VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
0,
VK_EXT_MEMORY_HANDLE_TYPE_BIT,
VK_EXT_MEMORY_HANDLE_INVALID,
};
-
-#ifdef __APPLE__
- VkImportMetalBufferInfoEXT importInfoMetalBuffer = {
- VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT,
- 0,
- nullptr,
- };
- if (sVkEmulation->instanceSupportsMoltenVK) {
- importInfoMetalBuffer.mtlBuffer = info->externalMetalHandle;
- importInfoPtr = &importInfoMetalBuffer;
- } else
-#endif
- {
+ if (opaqueFd) {
importInfoFd.fd = dupExternalMemory(info->externalHandle);
importInfoPtr = &importInfoFd;
}
@@ -2028,25 +2027,29 @@
};
importInfoPtr = &importInfo;
#else
+
+ bool opaqueFd = true;
+#ifdef __APPLE__
+ VkImportMemoryMetalHandleInfoEXT importInfoMetalInfo = {
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT,
+ &dedicatedInfo,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT,
+ nullptr
+ };
+ if (sVkEmulation->instanceSupportsMoltenVK) {
+ importInfoMetalInfo.handle = info->externalMetalHandle;
+ importInfoPtr = &importInfoMetalInfo;
+ opaqueFd = false;
+ }
+#endif
+
VkImportMemoryFdInfoKHR importInfoFd = {
VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
&dedicatedInfo,
VK_EXT_MEMORY_HANDLE_TYPE_BIT,
-1,
};
-
-#ifdef __APPLE__
- VkImportMetalBufferInfoEXT importInfoMetalBuffer = {
- VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT,
- &dedicatedInfo,
- nullptr,
- };
- if (sVkEmulation->instanceSupportsMoltenVK) {
- importInfoMetalBuffer.mtlBuffer = info->externalMetalHandle;
- importInfoPtr = &importInfoMetalBuffer;
- } else
-#endif
- {
+ if (opaqueFd) {
importInfoFd.fd = dupExternalMemory(info->externalHandle);
importInfoPtr = &importInfoFd;
}
@@ -2346,6 +2349,14 @@
pInfo->size = screenBufferProps.allocationSize;
#endif
+#ifdef __APPLE__
+ // importExtMemoryHandleToVkColorBuffer is not supported with MoltenVK
+ if (sVkEmulation->instanceSupportsMoltenVK) {
+ WARN("Unexpected call to updateExternalMemoryInfo!");
+ pInfo->externalMetalHandle = nullptr;
+ }
+#endif
+
return true;
}
@@ -2434,15 +2445,9 @@
VK_EXT_MEMORY_HANDLE_TYPE_BIT,
};
#if defined(__APPLE__)
- VkExportMetalObjectCreateInfoEXT metalImageExportCI = {
- VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT, nullptr,
- VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT};
-
if (sVkEmulation->instanceSupportsMoltenVK) {
// Using a different handle type when in MoltenVK mode
- extImageCi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
-
- extImageCi.pNext = &metalImageExportCI;
+ extImageCi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
@@ -2614,14 +2619,6 @@
return false;
}
-#if defined(__APPLE__)
- if (sVkEmulation->instanceSupportsMoltenVK) {
- // Retrieve metal texture for this image
- infoPtr->mtlTexture = getMtlTextureFromVkImage(vk, infoPtr->image);
- CFRetain(infoPtr->mtlTexture);
- }
-#endif
-
sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->image, "ColorBuffer:%d",
colorBufferHandle);
sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->imageView, "ColorBuffer:%d",
@@ -2770,12 +2767,6 @@
vk->vkDestroySamplerYcbcrConversion(sVkEmulation->device, info.ycbcrConversion, nullptr);
vk->vkDestroyImage(sVkEmulation->device, info.image, nullptr);
freeExternalMemoryLocked(vk, &info.memory);
-
-#ifdef __APPLE__
- if (info.mtlTexture) {
- CFRelease(info.mtlTexture);
- }
-#endif
}
sVkEmulation->colorBuffers.erase(colorBufferHandle);
@@ -3319,7 +3310,7 @@
}
#ifdef __APPLE__
-MTLBufferRef getColorBufferMetalMemoryHandle(uint32_t colorBuffer) {
+MTLResource_id getColorBufferMetalMemoryHandle(uint32_t colorBuffer) {
if (!sVkEmulation || !sVkEmulation->live) return nullptr;
AutoLock lock(sVkEmulationLock);
@@ -3334,23 +3325,7 @@
return infoPtr->memory.externalMetalHandle;
}
-MTLTextureRef getColorBufferMTLTexture(uint32_t colorBufferHandle) {
- if (!sVkEmulation || !sVkEmulation->live) return nullptr;
-
- AutoLock lock(sVkEmulationLock);
-
- auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
-
- if (!infoPtr) {
- // Color buffer not found; this is usually OK.
- return nullptr;
- }
-
- CFRetain(infoPtr->mtlTexture);
- return infoPtr->mtlTexture;
-}
-
-// TODO(b/333460957): Temporary function for MoltenVK
+// TODO0(b/351765838): Temporary function for MoltenVK
VkImage getColorBufferVkImage(uint32_t colorBufferHandle) {
if (!sVkEmulation || !sVkEmulation->live) return nullptr;
@@ -3500,6 +3475,12 @@
0,
VK_EXT_MEMORY_HANDLE_TYPE_BIT,
};
+#if defined(__APPLE__)
+ if (sVkEmulation->instanceSupportsMoltenVK) {
+ // Using a different handle type when in MoltenVK mode
+ extBufferCi.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT;
+ }
+#endif
void* extBufferCiPtr = nullptr;
if (sVkEmulation->deviceInfo.supportsExternalMemoryImport ||
sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
@@ -3641,7 +3622,7 @@
}
#ifdef __APPLE__
-MTLBufferRef getBufferMetalMemoryHandle(uint32_t bufferHandle) {
+MTLResource_id getBufferMetalMemoryHandle(uint32_t bufferHandle) {
if (!sVkEmulation || !sVkEmulation->live) return nullptr;
AutoLock lock(sVkEmulationLock);
@@ -3859,7 +3840,7 @@
#if defined(__APPLE__)
if (sVkEmulation->instanceSupportsMoltenVK) {
// Using a different handle type when in MoltenVK mode
- handleTypeNeeded = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
+ handleTypeNeeded = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
res |= handleTypeNeeded;
@@ -3890,7 +3871,7 @@
#if defined(__APPLE__)
if (sVkEmulation->instanceSupportsMoltenVK) {
// Using a different handle type when in MoltenVK mode
- handleTypeUsed = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
+ handleTypeUsed = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
}
#endif
if ((res & handleTypeUsed) == handleTypeUsed) {
diff --git a/host/vulkan/VkCommonOperations.h b/host/vulkan/VkCommonOperations.h
index 1aeac51..23c40b3 100644
--- a/host/vulkan/VkCommonOperations.h
+++ b/host/vulkan/VkCommonOperations.h
@@ -266,7 +266,7 @@
VK_EXT_MEMORY_HANDLE externalHandle = VK_EXT_MEMORY_HANDLE_INVALID;
#ifdef __APPLE__
// This is used as an external handle when MoltenVK is enabled
- MTLBufferRef externalMetalHandle = nullptr;
+ MTLResource_id externalMetalHandle = nullptr;
#endif
uint32_t streamHandleType;
@@ -351,10 +351,6 @@
VulkanMode vulkanMode = VulkanMode::Default;
-#if defined(__APPLE__)
- MTLTextureRef mtlTexture = nullptr;
-#endif
-
std::optional<DeviceOpWaitable> latestUse;
DeviceOpTrackerPtr latestUseTracker = nullptr;
};
@@ -515,8 +511,7 @@
VkEmulation::ColorBufferInfo getColorBufferInfo(uint32_t colorBufferHandle);
VK_EXT_MEMORY_HANDLE getColorBufferExtMemoryHandle(uint32_t colorBufferHandle);
#ifdef __APPLE__
-MTLBufferRef getColorBufferMetalMemoryHandle(uint32_t colorBufferHandle);
-MTLTextureRef getColorBufferMTLTexture(uint32_t colorBufferHandle);
+MTLResource_id getColorBufferMetalMemoryHandle(uint32_t colorBufferHandle);
VkImage getColorBufferVkImage(uint32_t colorBufferHandle);
#endif
@@ -554,7 +549,7 @@
VK_EXT_MEMORY_HANDLE getBufferExtMemoryHandle(uint32_t bufferHandle, uint32_t* outStreamHandleType);
#ifdef __APPLE__
-MTLBufferRef getBufferMetalMemoryHandle(uint32_t bufferHandle);
+MTLResource_id getBufferMetalMemoryHandle(uint32_t bufferHandle);
#endif
bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes);
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 26a793b..aa07631 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -2330,24 +2330,6 @@
const VkNativeBufferANDROID* nativeBufferANDROID =
vk_find_struct<VkNativeBufferANDROID>(pCreateInfo);
-#if defined(__APPLE__)
- VkExportMetalObjectCreateInfoEXT metalImageExportCI = {
- VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT, nullptr,
- VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT};
-
- // Add VkExportMetalObjectCreateInfoEXT on MoltenVK
- if (m_emu->instanceSupportsMoltenVK) {
- const VkExternalMemoryImageCreateInfo* externalMemCI =
- vk_find_struct<VkExternalMemoryImageCreateInfo>(pCreateInfo);
- if (externalMemCI) {
- // Insert metalImageExportCI to the chain
- metalImageExportCI.pNext = externalMemCI->pNext;
- const_cast<VkExternalMemoryImageCreateInfo*>(externalMemCI)->pNext =
- &metalImageExportCI;
- }
- }
-#endif
-
VkResult createRes = VK_SUCCESS;
if (nativeBufferANDROID) {
@@ -4746,7 +4728,7 @@
const VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr =
vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo);
- VkMemoryDedicatedAllocateInfo localDedicatedAllocInfo;
+ VkMemoryDedicatedAllocateInfo localDedicatedAllocInfo = {};
if (dedicatedAllocInfoPtr) {
localDedicatedAllocInfo = vk_make_orphan_copy(*dedicatedAllocInfoPtr);
@@ -4810,16 +4792,18 @@
VK_EXT_MEMORY_HANDLE_TYPE_BIT,
VK_EXT_MEMORY_HANDLE_INVALID,
};
-#endif
#if defined(__APPLE__)
- VkImportMetalBufferInfoEXT importInfoMetalBuffer = {
- VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT,
+ VkImportMemoryMetalHandleInfoEXT importInfoMetalHandle = {
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT,
0,
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT,
nullptr,
};
#endif
+#endif
+
void* mappedPtr = nullptr;
ManagedDescriptor externalMemoryHandle;
if (importCbInfoPtr) {
@@ -4845,23 +4829,28 @@
m_emu->callbacks.invalidateColorBuffer(importCbInfoPtr->colorBuffer);
}
+ bool opaqueFd = true;
+
#if defined(__APPLE__)
// Use metal object extension on MoltenVK mode for color buffer import,
// non-moltenVK path on MacOS will use FD handles
if (m_emu->instanceSupportsMoltenVK) {
- // TODO(b/333460957): This is a temporary fix to get MoltenVK image memory
- // binding checks working as expected based on dedicated memory checks. It's
- // not a valid usage of Vulkan as the device of the image is different than
- // what's being used here
- localDedicatedAllocInfo = {
+
+ extern VkImage getColorBufferVkImage(uint32_t colorBufferHandle);
+ if (dedicatedAllocInfoPtr == nullptr || localDedicatedAllocInfo.image == VK_NULL_HANDLE) {
+ // TODO(b/351765838): This should not happen, but somehow the guest
+ // is not providing us the necessary information for video rendering.
+ localDedicatedAllocInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = nullptr,
.image = getColorBufferVkImage(importCbInfoPtr->colorBuffer),
.buffer = VK_NULL_HANDLE,
- };
- shouldUseDedicatedAllocInfo = true;
+ };
- MTLBufferRef cbExtMemoryHandle =
+ shouldUseDedicatedAllocInfo = true;
+ }
+
+ MTLResource_id cbExtMemoryHandle =
getColorBufferMetalMemoryHandle(importCbInfoPtr->colorBuffer);
if (cbExtMemoryHandle == nullptr) {
@@ -4871,12 +4860,15 @@
__func__, importCbInfoPtr->colorBuffer);
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
+ importInfoMetalHandle.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLHEAP_BIT_EXT;
+ importInfoMetalHandle.handle = cbExtMemoryHandle;
- importInfoMetalBuffer.mtlBuffer = cbExtMemoryHandle;
- vk_append_struct(&structChainIter, &importInfoMetalBuffer);
- } else
+ vk_append_struct(&structChainIter, &importInfoMetalHandle);
+ opaqueFd = false;
+ }
#endif
- if (m_emu->deviceInfo.supportsExternalMemoryImport) {
+
+ if (opaqueFd && m_emu->deviceInfo.supportsExternalMemoryImport) {
VK_EXT_MEMORY_HANDLE cbExtMemoryHandle =
getColorBufferExtMemoryHandle(importCbInfoPtr->colorBuffer);
@@ -4914,9 +4906,10 @@
shouldUseDedicatedAllocInfo &= bufferMemoryUsesDedicatedAlloc;
+ bool opaqueFd = true;
#ifdef __APPLE__
if (m_emu->instanceSupportsMoltenVK) {
- MTLBufferRef bufferMetalMemoryHandle =
+ MTLResource_id bufferMetalMemoryHandle =
getBufferMetalMemoryHandle(importBufferInfoPtr->buffer);
if (bufferMetalMemoryHandle == nullptr) {
@@ -4928,11 +4921,16 @@
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
- importInfoMetalBuffer.mtlBuffer = bufferMetalMemoryHandle;
- vk_append_struct(&structChainIter, &importInfoMetalBuffer);
- } else
+ importInfoMetalHandle.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT;
+ importInfoMetalHandle.handle = bufferMetalMemoryHandle;
+
+ vk_append_struct(&structChainIter, &importInfoMetalHandle);
+
+ opaqueFd = false;
+ }
#endif
- if (m_emu->deviceInfo.supportsExternalMemoryImport) {
+
+ if (opaqueFd && m_emu->deviceInfo.supportsExternalMemoryImport) {
uint32_t outStreamHandleType;
VK_EXT_MEMORY_HANDLE bufferExtMemoryHandle =
getBufferExtMemoryHandle(importBufferInfoPtr->buffer, &outStreamHandleType);
@@ -5084,7 +5082,10 @@
#if defined(__APPLE__)
if (m_emu->instanceSupportsMoltenVK) {
// Using a different handle type when in MoltenVK mode
- handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR;
+ handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT|VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_EXT;
+ }
+ else {
+ handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
}
#elif defined(_WIN32)
handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
@@ -7791,6 +7792,9 @@
if (hasDeviceExtension(properties, VK_EXT_METAL_OBJECTS_EXTENSION_NAME)) {
res.push_back(VK_EXT_METAL_OBJECTS_EXTENSION_NAME);
}
+ if (hasDeviceExtension(properties, VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME)) {
+ res.push_back(VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME);
+ }
} else {
// Non-MoltenVK path, use memory_fd
if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME)) {
diff --git a/host/vulkan/VulkanDispatch.cpp b/host/vulkan/VulkanDispatch.cpp
index 0d379bb..7f5f61a 100644
--- a/host/vulkan/VulkanDispatch.cpp
+++ b/host/vulkan/VulkanDispatch.cpp
@@ -109,6 +109,9 @@
// MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS is not working correctly
android::base::setEnvironmentVariable("MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", "0");
+ // MVK_CONFIG_USE_MTLHEAP is required for VK_EXT_external_memory_metal
+ android::base::setEnvironmentVariable("MVK_CONFIG_USE_MTLHEAP", "1");
+
// TODO(b/351765838): VVL won't work with MoltenVK due to the current
// way of external memory handling, add it into disable list to
// avoid users enabling it implicitly (i.e. via vkconfig).
diff --git a/host/vulkan/cereal/common/goldfish_vk_private_defs.h b/host/vulkan/cereal/common/goldfish_vk_private_defs.h
index 34b6597..e0204b3 100644
--- a/host/vulkan/cereal/common/goldfish_vk_private_defs.h
+++ b/host/vulkan/cereal/common/goldfish_vk_private_defs.h
@@ -20,22 +20,14 @@
#include <algorithm>
#endif
-// TODO(b/349066492): this is used as a placeholder extension to inform guest side
-// that host is using MoltenVK, it should be removed after external_memory_metal
-// extension is implemented.
+// We keep advertising VK_MVK_moltenvk on MacOS for backwards compatibility, since in the older
+// guest images the checks for the external memory support is done via this extension.
#ifndef VK_MVK_moltenvk
#define VK_MVK_moltenvk 1
#define VK_MVK_MOLTENVK_SPEC_VERSION 3
#define VK_MVK_MOLTENVK_EXTENSION_NAME "VK_MVK_moltenvk"
#endif // VK_MVK_moltenvk
-// These are internally defined MoltenVK flags for external memory usage
-// TODO(b/349066492): They should be removed after being ratified and put under the headers
-static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR =
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
-static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR =
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
-
// VulkanStream features
#define VULKAN_STREAM_FEATURE_NULL_OPTIONAL_STRINGS_BIT (1 << 0)
#define VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT (1 << 1)
@@ -46,16 +38,16 @@
#ifdef __cplusplus
-template<class T, typename F>
+template <class T, typename F>
bool arrayany(const T* arr, uint32_t begin, uint32_t end, const F& func) {
const T* e = arr + end;
return std::find_if(arr + begin, e, func) != e;
}
-#define DEFINE_ALIAS_FUNCTION(ORIGINAL_FN, ALIAS_FN) \
-template <typename... Args> \
-inline auto ALIAS_FN(Args&&... args) -> decltype(ORIGINAL_FN(std::forward<Args>(args)...)) { \
- return ORIGINAL_FN(std::forward<Args>(args)...); \
-}
+#define DEFINE_ALIAS_FUNCTION(ORIGINAL_FN, ALIAS_FN) \
+ template <typename... Args> \
+ inline auto ALIAS_FN(Args&&... args) -> decltype(ORIGINAL_FN(std::forward<Args>(args)...)) { \
+ return ORIGINAL_FN(std::forward<Args>(args)...); \
+ }
#endif
diff --git a/host/vulkan/cereal/common/vk_struct_id.h b/host/vulkan/cereal/common/vk_struct_id.h
index 20eb3b6..ada9eba 100644
--- a/host/vulkan/cereal/common/vk_struct_id.h
+++ b/host/vulkan/cereal/common/vk_struct_id.h
@@ -126,6 +126,13 @@
REGISTER_VK_STRUCT_ID(VkExportMetalObjectCreateInfoEXT,
VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT);
+
+REGISTER_VK_STRUCT_ID(VkImportMemoryMetalHandleInfoEXT,
+ VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT);
+REGISTER_VK_STRUCT_ID(VkMemoryMetalHandlePropertiesEXT,
+ VK_STRUCTURE_TYPE_MEMORY_METAL_HANDLE_PROPERTIES_EXT);
+REGISTER_VK_STRUCT_ID(VkMemoryGetMetalHandleInfoEXT,
+ VK_STRUCTURE_TYPE_MEMORY_GET_METAL_HANDLE_INFO_EXT);
#endif
REGISTER_VK_STRUCT_ID(VkPhysicalDeviceDiagnosticsConfigFeaturesNV,