vulkan-cereal: refactor instance/device filtering

- Separate out instance and device extension filtering
- Use the global VK instance to determine whether to request
  external and semaphore capabilities (even on MoltenVK)
- Always request external memory (both guest AHB and Fuchsia
  buffer collection required)
- Always request filtered device extensions when available

BUG=235485545
TEST=compile and run

Change-Id: I840107d8c9b5e077054a673fff59d99b3eeb53bc
diff --git a/stream-servers/vulkan/VkCommonOperations.cpp b/stream-servers/vulkan/VkCommonOperations.cpp
index b192bc2..18a7d52 100644
--- a/stream-servers/vulkan/VkCommonOperations.cpp
+++ b/stream-servers/vulkan/VkCommonOperations.cpp
@@ -517,6 +517,10 @@
 #endif
     };
 
+    std::vector<const char*> externalSemaphoreInstanceExtNames = {
+        VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
+    };
+
     uint32_t extCount = 0;
     gvk->vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
     std::vector<VkExtensionProperties>& exts = sVkEmulation->instanceExtensions;
@@ -525,6 +529,8 @@
 
     bool externalMemoryCapabilitiesSupported =
         extensionsSupported(exts, externalMemoryInstanceExtNames);
+    bool externalSemaphoreCapabilitiesSupported =
+        extensionsSupported(exts, externalSemaphoreInstanceExtNames);
     bool moltenVKSupported =
         (vk->vkGetMTLTextureMVK != nullptr) && (vk->vkSetMTLTextureMVK != nullptr);
 
@@ -633,6 +639,7 @@
     sVkEmulation->vulkanInstanceVersion = appInfo.apiVersion;
 
     sVkEmulation->instanceSupportsExternalMemoryCapabilities = externalMemoryCapabilitiesSupported;
+    sVkEmulation->instanceSupportsExternalSemaphoreCapabilities = externalSemaphoreCapabilitiesSupported;
     sVkEmulation->instanceSupportsMoltenVK = moltenVKSupported;
 
     if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
diff --git a/stream-servers/vulkan/VkCommonOperations.h b/stream-servers/vulkan/VkCommonOperations.h
index 7b91809..c9c73cf 100644
--- a/stream-servers/vulkan/VkCommonOperations.h
+++ b/stream-servers/vulkan/VkCommonOperations.h
@@ -103,6 +103,7 @@
     VulkanDispatch* dvk = nullptr;
 
     bool instanceSupportsExternalMemoryCapabilities = false;
+    bool instanceSupportsExternalSemaphoreCapabilities = false;
     PFN_vkGetPhysicalDeviceImageFormatProperties2KHR getImageFormatProperties2Func = nullptr;
     PFN_vkGetPhysicalDeviceProperties2KHR getPhysicalDeviceProperties2Func = nullptr;
     PFN_vkGetPhysicalDeviceFeatures2 getPhysicalDeviceFeatures2Func = nullptr;
diff --git a/stream-servers/vulkan/VkDecoderGlobalState.cpp b/stream-servers/vulkan/VkDecoderGlobalState.cpp
index 46285fd..a813558 100644
--- a/stream-servers/vulkan/VkDecoderGlobalState.cpp
+++ b/stream-servers/vulkan/VkDecoderGlobalState.cpp
@@ -88,9 +88,9 @@
 
 namespace goldfish_vk {
 
-// A list of extensions that should not be passed to the host driver.
+// A list of device extensions that should not be passed to the host driver.
 // These will mainly include Vulkan features that we emulate ourselves.
-static constexpr const char* const kEmulatedExtensions[] = {
+static constexpr const char* const kEmulatedDeviceExtensions[] = {
     "VK_ANDROID_external_memory_android_hardware_buffer",
     "VK_ANDROID_native_buffer",
     "VK_FUCHSIA_buffer_collection",
@@ -98,13 +98,19 @@
     "VK_FUCHSIA_external_semaphore",
     VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME,
     VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
-    VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
     VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
-    VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
     VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
-    VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
     VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME,
     VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME,
+    VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
+};
+
+// A list of instance extensions that should not be passed to the host driver.
+// On older pre-1.1 Vulkan platforms, gfxstream emulates these features.
+static constexpr const char* const kEmulatedInstanceExtensions[] = {
+    VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME,
+    VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+    VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
 };
 
 static constexpr uint32_t kMaxSafeVersion = VK_MAKE_VERSION(1, 1, 0);
@@ -387,7 +393,7 @@
     VkResult on_vkCreateInstance(android::base::BumpPool* pool,
                                  const VkInstanceCreateInfo* pCreateInfo,
                                  const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
-        std::vector<const char*> finalExts = filteredExtensionNames(
+        std::vector<const char*> finalExts = filteredInstanceExtensionNames(
             pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
 
         INFO("Creating Vulkan instance for app: %s engine: %s",
@@ -1139,17 +1145,9 @@
         auto physicalDevice = unbox_VkPhysicalDevice(boxed_physicalDevice);
         auto vk = dispatch_VkPhysicalDevice(boxed_physicalDevice);
 
-        std::vector<const char*> finalExts = filteredExtensionNames(
+        std::vector<const char*> finalExts = filteredDeviceExtensionNames(vk, physicalDevice,
             pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
 
-#ifdef _WIN32
-        // Always request VK_KHR_external_semaphore_win32 if it's supported. This fixes a crash
-        // when RenderDoc is used on Vulkan-on-Vulkan apps.
-        if (isExternalSemaphoreWin32Supported(vk, physicalDevice)) {
-            finalExts.push_back(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
-        }
-#endif
-
         // Run the underlying API call, filtering extensions.
         VkDeviceCreateInfo createInfoFiltered = *pCreateInfo;
         // According to the spec, it seems that the application can use compressed texture formats
@@ -3500,17 +3498,6 @@
                                                         properties.data());
     }
 
-#ifdef _WIN32
-    bool isExternalSemaphoreWin32Supported(VulkanDispatch* vk, VkPhysicalDevice physicalDevice) {
-        std::vector<VkExtensionProperties> properties;
-        VkResult result =
-            enumerateDeviceExtensionProperties(vk, physicalDevice, nullptr, properties);
-        if (result != VK_SUCCESS) return false;
-
-        return hasDeviceExtension(properties, VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
-    }
-#endif
-
     // VK_ANDROID_native_buffer
     VkResult on_vkGetSwapchainGrallocUsageANDROID(android::base::BumpPool* pool, VkDevice,
                                                   VkFormat format, VkImageUsageFlags imageUsage,
@@ -5220,13 +5207,16 @@
     VkDecoderSnapshot* snapshot() { return &mSnapshot; }
 
    private:
-    bool isEmulatedExtension(const char* name) const {
-        for (auto emulatedExt : kEmulatedExtensions) {
+    bool isEmulatedInstanceExtension(const char *name) const {
+        for (auto emulatedExt : kEmulatedInstanceExtensions) {
             if (!strcmp(emulatedExt, name)) return true;
         }
-        if (!strcmp(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, name)) {
-            return !m_emu->deviceInfo.hasSamplerYcbcrConversionExtension &&
-                   m_emu->enableYcbcrEmulation;
+        return false;
+    }
+
+    bool isEmulatedDeviceExtension(const char* name) const {
+        for (auto emulatedExt : kEmulatedDeviceExtensions) {
+            if (!strcmp(emulatedExt, name)) return true;
         }
         return false;
     }
@@ -5238,46 +5228,82 @@
         return !(usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(type == VK_IMAGE_TYPE_1D);
     }
 
-    std::vector<const char*> filteredExtensionNames(uint32_t count, const char* const* extNames) {
+    std::vector<const char*> filteredDeviceExtensionNames(VulkanDispatch* vk, VkPhysicalDevice physicalDevice,
+                                                          uint32_t count, const char* const* extNames) {
         std::vector<const char*> res;
+        std::vector<VkExtensionProperties> properties;
+        VkResult result;
+
         for (uint32_t i = 0; i < count; ++i) {
             auto extName = extNames[i];
-            if (!isEmulatedExtension(extName)) {
+            if (!isEmulatedDeviceExtension(extName)) {
                 res.push_back(extName);
                 continue;
             }
-            if (m_emu->instanceSupportsMoltenVK) {
-                continue;
-            }
-            if (!strcmp(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, extName)) {
-                res.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
-            }
-            if (!strcmp(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, extName)) {
-                res.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
-            }
-            if (!strcmp(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, extName)) {
-                res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
-            }
-            if (!strcmp(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, extName)) {
-                res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
-            }
-            if (!strcmp("VK_ANDROID_external_memory_android_hardware_buffer", extName) ||
-                !strcmp("VK_FUCHSIA_external_memory", extName)) {
+        }
+
+        result = enumerateDeviceExtensionProperties(vk, physicalDevice, nullptr, properties);
+        if (result != VK_SUCCESS) {
+            VKDGS_LOG("failed to enumerate device extensions");
+            return res;
+        }
+
+        if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
+        }
+
+        if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
+        }
+
+        if (hasDeviceExtension(properties, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
+
+        }
+
 #ifdef _WIN32
-                res.push_back(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
-#else
-                res.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
+        if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
+        }
+
+        if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
+        }
+#elif __unix__
+        if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
+        }
+
+        if (hasDeviceExtension(properties, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME)) {
+            res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
+        }
 #endif
-            }
-            // External semaphore - non-Windows case is handled here
-            // Windows case is handled in on_vkCreateDevice
-            if (!strcmp(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, extName)) {
-#ifndef _WIN32
-                res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
+
+#ifdef __linux__
+        if (hasDeviceExtension(properties, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME)) {
+            res.push_back(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME);
+        }
 #endif
+        return res;
+    }
+
+    std::vector<const char*> filteredInstanceExtensionNames(uint32_t count, const char* const* extNames) {
+        std::vector<const char*> res;
+        for (uint32_t i = 0; i < count; ++i) {
+            auto extName = extNames[i];
+            if (!isEmulatedInstanceExtension(extName)) {
+                res.push_back(extName);
             }
         }
 
+        if (m_emu->instanceSupportsExternalMemoryCapabilities) {
+            res.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
+        }
+
+        if (m_emu->instanceSupportsExternalSemaphoreCapabilities) {
+            res.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
+        }
+
         return res;
     }