From 9d802edf0a6c3b0c7c95c283f4e20ae110c31457 Mon Sep 17 00:00:00 2001 From: Alexander Solovets Date: Sun, 17 May 2026 08:53:49 +1000 Subject: [PATCH] Fix Device::availableMemory crash on Vulkan 1.0 instances vkGetPhysicalDeviceMemoryProperties2 and VkPhysicalDeviceMemoryBudgetPropertiesEXT were called unconditionally, but the former requires Vulkan 1.1 and the latter requires VK_EXT_memory_budget. On a 1.0 instance this triggered undefined behaviour and crashed Lavapipe during scene compilation. Gate the 1.1 path on both preconditions and fall back to vkGetPhysicalDeviceMemoryProperties with heap sizes when either is missing. --- src/vsg/vk/Device.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/vsg/vk/Device.cpp b/src/vsg/vk/Device.cpp index 9fe862597..5acdfdc47 100644 --- a/src/vsg/vk/Device.cpp +++ b/src/vsg/vk/Device.cpp @@ -208,17 +208,30 @@ bool Device::supportsDeviceExtension(const char* extensionName) const VkDeviceSize Device::availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags, double allocatedMemoryLimit) const { - VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget; - memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; - memoryBudget.pNext = nullptr; + // vkGetPhysicalDeviceMemoryProperties2 requires Vulkan 1.1, and the chained + // VkPhysicalDeviceMemoryBudgetPropertiesEXT additionally requires VK_EXT_memory_budget. + // Fall back to the 1.0 query (no live budget tracking) when either is missing. + const bool useBudget = supportsApiVersion(VK_API_VERSION_1_1) && + supportsDeviceExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); - VkPhysicalDeviceMemoryProperties2 dmp; - dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; - dmp.pNext = &memoryBudget; + VkPhysicalDeviceMemoryProperties memoryProperties; + VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget = {}; - vkGetPhysicalDeviceMemoryProperties2(*(getPhysicalDevice()), &dmp); + if (useBudget) + { + memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; + + VkPhysicalDeviceMemoryProperties2 dmp = {}; + dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; + dmp.pNext = &memoryBudget; - auto& memoryProperties = dmp.memoryProperties; + vkGetPhysicalDeviceMemoryProperties2(*(getPhysicalDevice()), &dmp); + memoryProperties = dmp.memoryProperties; + } + else + { + vkGetPhysicalDeviceMemoryProperties(*(getPhysicalDevice()), &memoryProperties); + } VkDeviceSize availableSpace = 0; for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) @@ -227,8 +240,10 @@ VkDeviceSize Device::availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags { uint32_t heapIndex = memoryProperties.memoryTypes[i].heapIndex; - VkDeviceSize heapBudget = static_cast(static_cast(memoryBudget.heapBudget[heapIndex]) * allocatedMemoryLimit); - VkDeviceSize heapUsage = memoryBudget.heapUsage[heapIndex]; + VkDeviceSize heapBudget = useBudget ? memoryBudget.heapBudget[heapIndex] : memoryProperties.memoryHeaps[heapIndex].size; + VkDeviceSize heapUsage = useBudget ? memoryBudget.heapUsage[heapIndex] : 0; + + heapBudget = static_cast(static_cast(heapBudget) * allocatedMemoryLimit); VkDeviceSize heapAvailable = (heapUsage < heapBudget) ? heapBudget - heapUsage : 0; availableSpace += heapAvailable;