Skip to content

Commit b634908

Browse files
committed
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. Cache the combined precondition as a Device::memory_budget bool, and fall back to vkGetPhysicalDeviceMemoryProperties with heap sizes when it is unset.
1 parent 599a8c5 commit b634908

2 files changed

Lines changed: 27 additions & 10 deletions

File tree

include/vsg/vk/Device.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ namespace vsg
8585
/// return true if Device was created with specified extension
8686
bool supportsDeviceExtension(const char* extensionName) const;
8787

88+
/// commonly checked extensions cached at construction
89+
const bool memory_budget = false; // VK_EXT_memory_budget usable on this Device
90+
8891
/// return the amount of remaining memory, compatible with specified flags, available that can be allocated.
8992
VkDeviceSize availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags, double allocatedMemoryLimit = 1.0) const;
9093

src/vsg/vk/Device.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ Device::Device(PhysicalDevice* physicalDevice, const QueueSettings& queueSetting
163163
}
164164

165165
_extensions = DeviceExtensions::create(this);
166+
167+
// Cache extension/version probes used on hot paths. VK_EXT_memory_budget piggy-backs on
168+
// vkGetPhysicalDeviceMemoryProperties2 which requires Vulkan 1.1 (or the KHR variant).
169+
const_cast<bool&>(memory_budget) = supportsApiVersion(VK_API_VERSION_1_1) &&
170+
supportsDeviceExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
166171
}
167172

168173
Device::~Device()
@@ -208,17 +213,24 @@ bool Device::supportsDeviceExtension(const char* extensionName) const
208213

209214
VkDeviceSize Device::availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags, double allocatedMemoryLimit) const
210215
{
211-
VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget;
212-
memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
213-
memoryBudget.pNext = nullptr;
216+
VkPhysicalDeviceMemoryProperties memoryProperties;
217+
VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget = {};
214218

215-
VkPhysicalDeviceMemoryProperties2 dmp;
216-
dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
217-
dmp.pNext = &memoryBudget;
219+
if (memory_budget)
220+
{
221+
memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
218222

219-
vkGetPhysicalDeviceMemoryProperties2(*(getPhysicalDevice()), &dmp);
223+
VkPhysicalDeviceMemoryProperties2 dmp = {};
224+
dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
225+
dmp.pNext = &memoryBudget;
220226

221-
auto& memoryProperties = dmp.memoryProperties;
227+
vkGetPhysicalDeviceMemoryProperties2(*(getPhysicalDevice()), &dmp);
228+
memoryProperties = dmp.memoryProperties;
229+
}
230+
else
231+
{
232+
vkGetPhysicalDeviceMemoryProperties(*(getPhysicalDevice()), &memoryProperties);
233+
}
222234

223235
VkDeviceSize availableSpace = 0;
224236
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
@@ -227,8 +239,10 @@ VkDeviceSize Device::availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags
227239
{
228240
uint32_t heapIndex = memoryProperties.memoryTypes[i].heapIndex;
229241

230-
VkDeviceSize heapBudget = static_cast<VkDeviceSize>(static_cast<double>(memoryBudget.heapBudget[heapIndex]) * allocatedMemoryLimit);
231-
VkDeviceSize heapUsage = memoryBudget.heapUsage[heapIndex];
242+
VkDeviceSize heapBudget = memory_budget ? memoryBudget.heapBudget[heapIndex] : memoryProperties.memoryHeaps[heapIndex].size;
243+
VkDeviceSize heapUsage = memory_budget ? memoryBudget.heapUsage[heapIndex] : 0;
244+
245+
heapBudget = static_cast<VkDeviceSize>(static_cast<double>(heapBudget) * allocatedMemoryLimit);
232246
VkDeviceSize heapAvailable = (heapUsage < heapBudget) ? heapBudget - heapUsage : 0;
233247
availableSpace += heapAvailable;
234248

0 commit comments

Comments
 (0)