From db6cc41b9db871ade06c6d14753af7efa1ca5f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 22 Oct 2026 18:31:13 +0200 Subject: [PATCH] Vulkan: Ask for portability drivers on Mac Through the Khronos loader (like the Vulkan SDK's, needed for the validation layers), MoltenVK is only listed if the instance enables VK_KHR_portability_enumeration. Without it, instance creation failed with VK_ERROR_INCOMPATIBLE_DRIVER and we fell back to OpenGL. Loading MoltenVK directly, as the app normally does, works as before. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/GPU/Vulkan/VulkanContext.cpp | 9 +++++++++ Common/GPU/Vulkan/VulkanLoader.cpp | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 08e7398961..8bcec8cb35 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -239,6 +239,15 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) { #if PPSSPP_VK_STATIC inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; +#elif PPSSPP_PLATFORM(MAC) + // Through the Khronos loader (like the SDK's, for the validation layers), MoltenVK is only + // listed if we ask for portability drivers. + if (IsInstanceExtensionAvailable(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) { + instance_extensions_enabled_.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + inst_info.enabledExtensionCount = (uint32_t)instance_extensions_enabled_.size(); + inst_info.ppEnabledExtensionNames = instance_extensions_enabled_.data(); + inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } #endif #if SIMULATE_VULKAN_FAILURE == 2 diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 86ec0b6d9e..5733dae1fe 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -494,6 +494,7 @@ bool VulkanMayBeAvailable() { std::vector devices; bool anyGood = false; const char *instanceExtensions[10]{}; + bool portabilityFound = false; VkInstance instance = VK_NULL_HANDLE; VkResult res = VK_SUCCESS; uint32_t physicalDeviceCount = 0; @@ -544,6 +545,11 @@ bool VulkanMayBeAvailable() { platformSurfaceExtensionFound = true; // Note: Can't stop here - the enumeration order isn't specified anywhere, so VK_KHR_surface // may well come after the platform one, and we need both. +#if PPSSPP_PLATFORM(MAC) + } else if (!strcmp(iter.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) { + // See VulkanContext::CreateInstance. + portabilityFound = true; +#endif } else if (!strcmp(iter.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) { instanceExtensions[ci.enabledExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME; surfaceExtensionFound = true; @@ -576,6 +582,10 @@ bool VulkanMayBeAvailable() { info.pEngineName = "VulkanCheckerEngine"; ci.pApplicationInfo = &info; ci.flags = 0; + if (portabilityFound) { + instanceExtensions[ci.enabledExtensionCount++] = VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME; + ci.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } INFO_LOG(Log::G3D, "VulkanMayBeAvailable: Calling vkCreateInstance"); res = localCreateInstance(&ci, nullptr, &instance); if (res != VK_SUCCESS) {