From 0ce1149e413b031f596b59f98b5e4cc4ae4474d5 Mon Sep 17 00:00:00 2001
From: Wunkolo <Wunkolo@gmail.com>
Date: Sat, 20 Jan 2024 15:55:10 -0800
Subject: [PATCH] VulkanDevice: Optional `VK_EXT_external_memory_host`
 enablement

Allows usage of this extension only when the import-pointer-alignment
matches that of the hosts' page size.
---
 src/util/vulkan_device.cpp       | 13 +++++++++++++
 src/util/vulkan_device.h         |  1 +
 src/util/vulkan_entry_points.inl |  4 ++++
 3 files changed, 18 insertions(+)

diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp
index 5c0098332..b54239d4b 100644
--- a/src/util/vulkan_device.cpp
+++ b/src/util/vulkan_device.cpp
@@ -393,6 +393,8 @@ bool VulkanDevice::SelectDeviceExtensions(ExtensionList* extension_list, bool en
     SupportsExtension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, false) &&
     SupportsExtension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, false);
   m_optional_extensions.vk_khr_push_descriptor = SupportsExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, false);
+  m_optional_extensions.vk_ext_external_memory_host =
+    SupportsExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, false);
 
 #ifdef _WIN32
   m_optional_extensions.vk_ext_full_screen_exclusive =
@@ -632,6 +634,8 @@ void VulkanDevice::ProcessDeviceExtensions()
   VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, nullptr, {}};
   VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor_properties = {
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR, nullptr, 0u};
+  VkPhysicalDeviceExternalMemoryHostPropertiesEXT external_memory_host_properties = {
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, nullptr, 0};
 
   if (m_optional_extensions.vk_khr_driver_properties)
   {
@@ -641,12 +645,19 @@ void VulkanDevice::ProcessDeviceExtensions()
   if (m_optional_extensions.vk_khr_push_descriptor)
     Vulkan::AddPointerToChain(&properties2, &push_descriptor_properties);
 
+  if (m_optional_extensions.vk_ext_external_memory_host)
+    Vulkan::AddPointerToChain(&properties2, &external_memory_host_properties);
+
   // don't bother querying if we're not actually looking at any features
   if (vkGetPhysicalDeviceProperties2 && properties2.pNext)
     vkGetPhysicalDeviceProperties2(m_physical_device, &properties2);
 
   m_optional_extensions.vk_khr_push_descriptor &= (push_descriptor_properties.maxPushDescriptors >= 1);
 
+  // vk_ext_external_memory_host is only used if the import alignment is the same as the system's page size
+  m_optional_extensions.vk_ext_external_memory_host &=
+    (external_memory_host_properties.minImportedHostPointerAlignment == HOST_PAGE_SIZE);
+
   if (IsBrokenMobileDriver())
   {
     // Push descriptor is broken on Adreno v502.. don't want to think about dynamic rendending.
@@ -680,6 +691,8 @@ void VulkanDevice::ProcessDeviceExtensions()
                  m_optional_extensions.vk_khr_dynamic_rendering ? "supported" : "NOT supported");
   Log_InfoPrintf("VK_KHR_push_descriptor is %s",
                  m_optional_extensions.vk_khr_push_descriptor ? "supported" : "NOT supported");
+  Log_InfoPrintf("VK_EXT_external_memory_host is %s",
+                 m_optional_extensions.vk_ext_external_memory_host ? "supported" : "NOT supported");
 }
 
 bool VulkanDevice::CreateAllocator()
diff --git a/src/util/vulkan_device.h b/src/util/vulkan_device.h
index 6795c5270..d4f5fdc86 100644
--- a/src/util/vulkan_device.h
+++ b/src/util/vulkan_device.h
@@ -51,6 +51,7 @@ public:
     bool vk_khr_driver_properties : 1;
     bool vk_khr_dynamic_rendering : 1;
     bool vk_khr_push_descriptor : 1;
+    bool vk_ext_external_memory_host : 1;
   };
 
   static GPUTexture::Format GetFormatForVkFormat(VkFormat format);
diff --git a/src/util/vulkan_entry_points.inl b/src/util/vulkan_entry_points.inl
index 94994f745..10b262691 100644
--- a/src/util/vulkan_entry_points.inl
+++ b/src/util/vulkan_entry_points.inl
@@ -248,4 +248,8 @@ VULKAN_DEVICE_ENTRY_POINT(vkCmdEndRenderingKHR, false)
 // VK_KHR_push_descriptor
 VULKAN_DEVICE_ENTRY_POINT(vkCmdPushDescriptorSetKHR, false)
 
+// VK_EXT_external_memory_host
+VULKAN_DEVICE_ENTRY_POINT(vkGetMemoryHostPointerPropertiesEXT, false)
+
+
 #endif // VULKAN_DEVICE_ENTRY_POINT