From a4f83785d9ef827fc0a776cbce66c72a666d9da4 Mon Sep 17 00:00:00 2001 From: Matt Akins Date: Wed, 22 Jul 2026 11:31:25 -0700 Subject: [PATCH] Libretro: keep Vulkan feature setup valid - Use VkPhysicalDeviceFeatures2 when supplied by PPSSPP - Leave pEnabledFeatures null as Vulkan requires --- libretro/libretro_vulkan.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libretro/libretro_vulkan.cpp b/libretro/libretro_vulkan.cpp index db015761b9..8c32522900 100644 --- a/libretro/libretro_vulkan.cpp +++ b/libretro/libretro_vulkan.cpp @@ -110,27 +110,32 @@ static VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice_libretro(VkPhysicalDevice p newInfo.enabledExtensionCount = (uint32_t)enabledExtensionNames.size(); newInfo.ppEnabledExtensionNames = newInfo.enabledExtensionCount ? enabledExtensionNames.data() : nullptr; - // Then check for VkPhysicalDeviceFeatures2 chaining or pEnabledFeatures to enable required features. Note that when both - // structs are present Features2 takes precedence. vkCreateDevice parameters don't give us a simple way to detect - // VK_KHR_get_physical_device_properties2 usage so we'll always try both paths. + // Add required features through VkPhysicalDeviceFeatures2 when it is present. + // Vulkan requires pEnabledFeatures to be NULL in that case. std::unordered_map originalFeaturePointers; VkPhysicalDeviceFeatures placeholderEnabledFeatures{}; + bool has_features2 = false; for (const VkBaseOutStructure *next = (const VkBaseOutStructure *)pCreateInfo->pNext; next != nullptr;) { if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { VkPhysicalDeviceFeatures *enabledFeatures = &((VkPhysicalDeviceFeatures2 *)next)->features; originalFeaturePointers.try_emplace(enabledFeatures, *enabledFeatures); + has_features2 = true; } next = (const VkBaseOutStructure *)next->pNext; } - if (newInfo.pEnabledFeatures) { - placeholderEnabledFeatures = *newInfo.pEnabledFeatures; - } + if (!has_features2) { + if (newInfo.pEnabledFeatures) { + placeholderEnabledFeatures = *newInfo.pEnabledFeatures; + } - newInfo.pEnabledFeatures = &placeholderEnabledFeatures; - originalFeaturePointers.try_emplace((VkPhysicalDeviceFeatures *)newInfo.pEnabledFeatures, *newInfo.pEnabledFeatures); + newInfo.pEnabledFeatures = &placeholderEnabledFeatures; + originalFeaturePointers.try_emplace((VkPhysicalDeviceFeatures *)newInfo.pEnabledFeatures, *newInfo.pEnabledFeatures); + } else { + newInfo.pEnabledFeatures = nullptr; + } for (const auto& pair : originalFeaturePointers) { for (uint32_t i = 0; i < sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); i++) {