nvk: Add heap_memory_percent driconf support

The budget calculation has changes slightly as the budget scaling
is applied prior to adding the used up heap memory.

Signed-off-by: Karmjit Mahil <karmjit.mahil@igalia.com>
This commit is contained in:
Karmjit Mahil 2026-04-28 10:00:49 +01:00
parent 253f3a30eb
commit 00f006d841
3 changed files with 35 additions and 39 deletions

View file

@ -13,6 +13,7 @@
#include "util/detect_os.h"
#include "util/driconf.h"
#include "util/mesa-blake3.h"
#include "util/os_misc.h"
#include "util/u_debug.h"
VKAPI_ATTR VkResult VKAPI_CALL
@ -97,6 +98,8 @@ nvk_init_debug_flags(struct nvk_instance *instance)
instance->debug_flags = parse_debug_string(os_get_option("NVK_DEBUG"), flags);
}
#define NVK_HEAP_MEMORY_PERCENT (0.75f)
static const driOptionDescription nvk_dri_options[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_ADAPTIVE_SYNC(true)
@ -113,6 +116,10 @@ static const driOptionDescription nvk_dri_options[] = {
DRI_CONF_VK_ZERO_VRAM(false)
DRI_CONF_NVK_APP_LAYER()
DRI_CONF_SECTION_END
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_HEAP_MEMORY_PERCENT(NVK_HEAP_MEMORY_PERCENT)
DRI_CONF_SECTION_END
};
static void
@ -126,6 +133,11 @@ nvk_init_dri_options(struct nvk_instance *instance)
instance->force_vk_vendor =
driQueryOptioni(&instance->dri_options, "force_vk_vendor");
instance->heap_memory_percent =
driQueryOptionf(&instance->dri_options, "heap_memory_percent");
if (instance->heap_memory_percent == OS_GPU_HEAP_SIZE_HEURISTIC)
instance->heap_memory_percent = NVK_HEAP_MEMORY_PERCENT;
if (driQueryOptionb(&instance->dri_options, "vk_zero_vram"))
instance->debug_flags |= NVK_DEBUG_ZERO_MEMORY;

View file

@ -22,6 +22,7 @@ struct nvk_instance {
uint8_t driver_build_sha[BLAKE3_KEY_LEN];
uint32_t force_vk_vendor;
float heap_memory_percent;
};
VK_DEFINE_HANDLE_CASTS(nvk_instance, vk.base, VkInstance, VK_OBJECT_TYPE_INSTANCE)

View file

@ -21,10 +21,12 @@
#include "util/detect_os.h"
#include "util/disk_cache.h"
#include "util/mesa-blake3.h"
#include "util/os_misc.h"
#include "vk_android.h"
#include "vk_device.h"
#include "vk_drm_syncobj.h"
#include "vk_physical_device.h"
#include "vk_shader_module.h"
#include "vulkan/wsi/wsi_common.h"
@ -1379,17 +1381,6 @@ nvk_physical_device_free_disk_cache(struct nvk_physical_device *pdev)
#endif
}
static uint64_t
nvk_get_sysmem_heap_size(void)
{
uint64_t sysmem_size_B = 0;
if (!os_get_total_physical_memory(&sysmem_size_B))
return 0;
/* Use 3/4 of total size to avoid swapping */
return ROUND_DOWN_TO(sysmem_size_B * 3 / 4, 1 << 20);
}
static uint64_t
nvk_get_sysmem_heap_available(struct nvk_physical_device *pdev)
{
@ -1399,8 +1390,7 @@ nvk_get_sysmem_heap_available(struct nvk_physical_device *pdev)
return 0;
}
/* Use 3/4 of available to avoid swapping */
return ROUND_DOWN_TO(sysmem_size_B * 3 / 4, 1 << 20);
return ROUND_DOWN_TO(sysmem_size_B, 1 << 20);
}
static uint64_t
@ -1509,8 +1499,10 @@ nvk_create_drm_physical_device(struct vk_instance *_instance,
nvk_physical_device_init_pipeline_cache(pdev);
uint64_t sysmem_size_B = nvk_get_sysmem_heap_size();
if (sysmem_size_B == 0) {
uint64_t heap_size =
os_get_gpu_heap_size(instance->heap_memory_percent,
&instance->heap_memory_percent);
if (heap_size == 0) {
result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
"Failed to query total system memory");
goto fail_disk_cache;
@ -1555,7 +1547,7 @@ nvk_create_drm_physical_device(struct vk_instance *_instance,
uint32_t sysmem_heap_idx = pdev->mem_heap_count++;
pdev->mem_heaps[sysmem_heap_idx] = (struct nvk_memory_heap) {
.size = sysmem_size_B,
.size = heap_size,
.flags = 0,
.available = nvk_get_sysmem_heap_available,
};
@ -1677,6 +1669,8 @@ nvk_GetPhysicalDeviceMemoryProperties2(
switch (ext->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
VkPhysicalDeviceMemoryBudgetPropertiesEXT *p = (void *)ext;
const struct nvk_instance *instance =
nvk_physical_device_instance(pdev);
for (unsigned i = 0; i < pdev->mem_heap_count; i++) {
const struct nvk_memory_heap *heap = &pdev->mem_heaps[i];
@ -1693,33 +1687,22 @@ nvk_GetPhysicalDeviceMemoryProperties2(
*/
p->heapUsage[i] = used;
/* Set the budget at 90% to avoid thrashing */
float percent = 0.9f;
uint64_t available = heap->size;
if (heap->available)
if (heap->available) {
available = heap->available(pdev);
/* From the Vulkan 1.3.278 spec:
*
* "heapBudget is an array of VK_MAX_MEMORY_HEAPS VkDeviceSize
* values in which memory budgets are returned, with one
* element for each memory heap. A heaps budget is a rough
* estimate of how much memory the process can allocate from
* that heap before allocations may fail or cause performance
* degradation. The budget includes any currently allocated
* device memory."
*
* and
*
* "The heapBudget value must be less than or equal to
* VkMemoryHeap::size for each heap."
*
* available (queried above) is the total amount free memory
* system-wide and does not include our allocations so we need
* to add that in.
*/
uint64_t budget = MIN2(available + used, heap->size);
if (heap->available == nvk_get_sysmem_heap_available) {
/* Scale the budget the same way the heap was scaled. */
percent *= instance->heap_memory_percent;
}
}
/* Set the budget at 90% of available to avoid thrashing */
p->heapBudget[i] = ROUND_DOWN_TO(budget * 9 / 10, 1 << 20);
p->heapBudget[i] =
vk_physical_device_heap_budget(available, percent, heap->size,
used);
}
/* From the Vulkan 1.3.278 spec: