Implement HostMappedForeignMemory DeviceMemory
From VK_EXT_external_memory_host, there is a type of VkDeviceMemory
that takes a pointer to host mapped foreign memory, where the
underlying memory is owned by the host, not the device.
This is used by ANGLE on Mac when creating a VkDeviceMemory given an
IOSurface.
Tests: dEQP-VK.*
Bug: chromium:1965434
Change-Id: I944a5d3cd23ad8b193f58981829a8847419a4b0d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39968
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Jonah Ryan-Davis <jonahr@google.com>
diff --git a/src/Vulkan/VkDeviceMemory.cpp b/src/Vulkan/VkDeviceMemory.cpp
index c524570..6f3ad1c 100644
--- a/src/Vulkan/VkDeviceMemory.cpp
+++ b/src/Vulkan/VkDeviceMemory.cpp
@@ -130,6 +130,79 @@
} // namespace vk
+// Host-allocated memory and host-mapped foreign memory
+class ExternalMemoryHost : public vk::DeviceMemory::ExternalBase
+{
+public:
+ struct AllocateInfo
+ {
+ bool supported = false;
+ void *hostPointer = nullptr;
+
+ AllocateInfo() = default;
+
+ AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
+ {
+ const auto *createInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
+ while(createInfo)
+ {
+ switch(createInfo->sType)
+ {
+ case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
+ {
+ const auto *importInfo = reinterpret_cast<const VkImportMemoryHostPointerInfoEXT *>(createInfo);
+
+ if(importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT && importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT)
+ {
+ UNSUPPORTED("importInfo->handleType");
+ }
+ hostPointer = importInfo->pHostPointer;
+ supported = true;
+ break;
+ }
+ default:
+ break;
+ }
+ createInfo = createInfo->pNext;
+ }
+ }
+ };
+
+ static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT);
+
+ static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
+ {
+ AllocateInfo info(pAllocateInfo);
+ return info.supported;
+ }
+
+ explicit ExternalMemoryHost(const VkMemoryAllocateInfo *pAllocateInfo)
+ : allocateInfo(pAllocateInfo)
+ {
+ }
+
+ VkResult allocate(size_t size, void **pBuffer) override
+ {
+ if(allocateInfo.supported)
+ {
+ *pBuffer = allocateInfo.hostPointer;
+ return VK_SUCCESS;
+ }
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+
+ void deallocate(void *buffer, size_t size) override
+ {}
+
+ VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
+ {
+ return typeFlagBit;
+ }
+
+private:
+ AllocateInfo allocateInfo;
+};
+
#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
# if defined(__linux__) || defined(__ANDROID__)
# include "VkDeviceMemoryExternalLinux.hpp"
@@ -163,6 +236,10 @@
return;
}
#endif
+ if(parseCreateInfo<ExternalMemoryHost>(pAllocateInfo, pTraits))
+ {
+ return;
+ }
parseCreateInfo<DeviceMemoryHostExternalBase>(pAllocateInfo, pTraits);
}
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index f293ca5..64ac9f8 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -381,6 +381,13 @@
} },
#endif
+ // VK_EXT_external_memory_host
+ {
+ VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME,
+ {
+ MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryHostPointerPropertiesEXT),
+ } },
+
#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
// VK_ANDROID_external_memory_android_hardware_buffer
{
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 5e55954..42d9a8c 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -428,6 +428,11 @@
pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
}
+void PhysicalDevice::getProperties(VkPhysicalDeviceExternalMemoryHostPropertiesEXT *properties) const
+{
+ properties->minImportedHostPointerAlignment = REQUIRED_MEMORY_ALIGNMENT;
+}
+
void PhysicalDevice::getProperties(VkPhysicalDeviceDriverPropertiesKHR *properties) const
{
properties->driverID = VK_DRIVER_ID_GOOGLE_SWIFTSHADER_KHR;
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp
index 6b13faa..0193c71 100644
--- a/src/Vulkan/VkPhysicalDevice.hpp
+++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -62,6 +62,7 @@
void getProperties(const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) const;
void getProperties(const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties) const;
void getProperties(const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) const;
+ void getProperties(VkPhysicalDeviceExternalMemoryHostPropertiesEXT *properties) const;
void getProperties(VkPhysicalDeviceDriverPropertiesKHR *properties) const;
void getProperties(VkPhysicalDeviceLineRasterizationPropertiesEXT *properties) const;
void getProperties(VkPhysicalDeviceProvokingVertexPropertiesEXT *properties) const;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 2baf038..92a123a 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -341,6 +341,9 @@
#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
{ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_SPEC_VERSION },
#endif
+
+ { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, VK_EXT_EXTERNAL_MEMORY_HOST_SPEC_VERSION },
+
#if VK_USE_PLATFORM_FUCHSIA
{ VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION },
#endif
@@ -952,6 +955,16 @@
// Ignore
break;
#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
+ {
+ auto *importInfo = reinterpret_cast<const VkImportMemoryHostPointerInfoEXT *>(allocationInfo);
+ if(importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT && importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT)
+ {
+ UNSUPPORTED("importInfo->handleType %u", importInfo->handleType);
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ break;
+ }
default:
WARN("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str());
break;
@@ -1025,6 +1038,21 @@
}
#endif // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void *pHostPointer, VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties)
+{
+ TRACE("(VkDevice device = %p, VkExternalMemoryHandleTypeFlagBits handleType = %x, const void *pHostPointer = %p, VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties = %p)",
+ device, handleType, pHostPointer, pMemoryHostPointerProperties);
+
+ if(handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT && handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT)
+ {
+ UNSUPPORTED("handleType %u", handleType);
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ pMemoryHostPointerProperties->memoryTypeBits = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+
+ return VK_SUCCESS;
+}
+
#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, struct AHardwareBuffer **pBuffer)
{
@@ -2855,9 +2883,11 @@
sizeof(deviceExtensionProperties) / sizeof(deviceExtensionProperties[0])));
break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT:
- ASSERT(!HasExtensionProperty(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionProperties,
- sizeof(deviceExtensionProperties) / sizeof(deviceExtensionProperties[0])));
- break;
+ {
+ auto properties = reinterpret_cast<VkPhysicalDeviceExternalMemoryHostPropertiesEXT *>(extensionProperties);
+ vk::Cast(physicalDevice)->getProperties(properties);
+ }
+ break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR:
{
auto properties = reinterpret_cast<VkPhysicalDeviceDriverPropertiesKHR *>(extensionProperties);