Memory Budget: Extended features
This sample demonstrates how to incorporate the Vulkan memory budget extension. Memory budget extension helps users to
sample the memory budget consumption on each heap from the physical device, and is able to tell
the property flag for each heap. Which is a proper debug tool to visualize the memory consumption in run-time.
Memory budget extension
In order to enable usage of memory budget extension features, an instance extension and a device extension were
introduced in the constructor of the MemoryBudget class, where:
add_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
add_device_extension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
Memory properties related structure instances were defined and initialized in the header of the MemoryBudget class,
listed as follows:
VkPhysicalDeviceMemoryBudgetPropertiesEXT physical_device_memory_budget_properties{};
VkPhysicalDeviceMemoryProperties2 device_memory_properties{};
Where, the sType and pNext variables were defined inside the initialize_device_memory_properties()
function, such that:
void MemoryBudget::initialize_device_memory_properties()
{
// Initialize physical device memory budget properties structures variables
physical_device_memory_budget_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
physical_device_memory_budget_properties.pNext = nullptr;
// Initialize physical device memory properties structure variables
device_memory_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
device_memory_properties.pNext = &physical_device_memory_budget_properties;
}
The sType of device_memory_properties is defined
as VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, and its pNext chained in a pointer of the
structure instance physical_device_memory_budget_properties. Where, the sType
of physical_device_memory_budget_properties is defined
as VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT and its pNext is defined as
a nullptr.
Each of the mentioned extension structure instances were defined in the header and initialized in
function initialize_device_memory_properties().
UI Overlay: Memory properties

In application’s UI overlay, total memory usage and total memory budget will be displayed. In addition, by pressing down
the arrow next to the “Memory Heap Details” tab, it expands a list of all memory usages and budgets from the heap count.
Where all memory properties were converted and displayed in proper units (e.g.,kilobytes, megabytes, etc.,).
Where:
void MemoryBudget::on_update_ui_overlay(vkb::Drawer &drawer)
{
converted_memory = update_converted_memory(device_memory_total_usage);
drawer.text("Total Memory Usage: %.2f %s", converted_memory.data, converted_memory.units.c_str());
converted_memory = update_converted_memory(device_memory_total_budget);
drawer.text("Total Memory Budget: %.2f %s", converted_memory.data, converted_memory.units.c_str());
if (drawer.header("Memory Heap Details"))
{
for (int i = 0; i < static_cast<int>(device_memory_heap_count); i++)
{
std::string header = "Memory Heap Index: " + std::to_string(i);
if (drawer.header(header.c_str()))
{
converted_memory = update_converted_memory(physical_device_memory_budget_properties.heapUsage[i]);
drawer.text("Usage: %.2f %s", converted_memory.data, converted_memory.units.c_str());
converted_memory = update_converted_memory(physical_device_memory_budget_properties.heapBudget[i]);
drawer.text("Budget: %.2f %s", converted_memory.data, converted_memory.units.c_str());
drawer.text("Heap Flag: %s", read_memoryHeap_flags(device_memory_properties.memoryProperties.memoryHeaps[i].flags).c_str());
}
}
}
}
The function update_device_memory_properties() measures and updates all memory properties related variables, by
calling the vkGetPhysicalDeviceMemoryProperties2() and evaluating the device_memory_total_usage
and device_memory_total_budget, where:
void MemoryBudget::update_device_memory_properties()
{
vkGetPhysicalDeviceMemoryProperties2(get_device().get_gpu().get_handle(), &device_memory_properties);
device_memory_heap_count = device_memory_properties.memoryProperties.memoryHeapCount;
device_memory_total_usage = 0;
device_memory_total_budget = 0;
for (uint32_t i = 0; i < device_memory_heap_count; i++)
{
device_memory_total_usage += physical_device_memory_budget_properties.heapUsage[i];
device_memory_total_budget += physical_device_memory_budget_properties.heapBudget[i];
}
}
And the function update_device_memory_properties() is assigned to the prepare_instance_data(). Which, in
this sample it will only need to be called once after everything was ready in the prepare_instance_data(), and
before it returns true.