hk: 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-27 15:07:41 +01:00
parent 111ff08c40
commit a0415a4763
4 changed files with 42 additions and 50 deletions

View file

@ -14,6 +14,7 @@
#include "util/build_id.h"
#include "util/driconf.h"
#include "util/mesa-blake3.h"
#include "util/os_misc.h"
VKAPI_ATTR VkResult VKAPI_CALL
hk_EnumerateInstanceVersion(uint32_t *pApiVersion)
@ -77,6 +78,9 @@ hk_EnumerateInstanceExtensionProperties(const char *pLayerName,
&instance_extensions, pPropertyCount, pProperties);
}
/* Use 1/2 of total size to avoid swapping */
#define HK_HEAP_MEMORY_PERCENT (0.5f)
/* clang-format off */
static const driOptionDescription hk_dri_options[] = {
DRI_CONF_SECTION_PERFORMANCE
@ -94,6 +98,7 @@ static const driOptionDescription hk_dri_options[] = {
DRI_CONF_SECTION_END
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_HEAP_MEMORY_PERCENT(HK_HEAP_MEMORY_PERCENT)
DRI_CONF_HK_DISABLE_BORDER_EMULATION(false)
DRI_CONF_HK_FAKE_MINMAX(false)
DRI_CONF_HK_IMAGE_VIEW_MIN_LOD(false)
@ -115,6 +120,11 @@ hk_init_dri_options(struct hk_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 = HK_HEAP_MEMORY_PERCENT;
instance->no_border =
driQueryOptionb(&instance->dri_options, "hk_disable_border_emulation");

View file

@ -18,6 +18,7 @@ struct hk_instance {
uint8_t driver_build_sha[BLAKE3_KEY_LEN];
uint32_t force_vk_vendor;
float heap_memory_percent;
bool no_border;
bool fake_minmax;

View file

@ -11,6 +11,7 @@
#include "asahi/lib/agx_nir_lower_vbo.h"
#include "util/disk_cache.h"
#include "util/mesa-blake3.h"
#include "util/os_misc.h"
#include "git_sha1.h"
#include "hk_buffer.h"
#include "hk_entrypoints.h"
@ -24,6 +25,7 @@
#include "vulkan/vulkan_core.h"
#include "vulkan/wsi/wsi_common.h"
#include "vk_drm_syncobj.h"
#include "vk_physical_device.h"
#include "vk_shader_module.h"
#include <fcntl.h>
@ -1158,42 +1160,30 @@ hk_physical_device_free_disk_cache(struct hk_physical_device *pdev)
#endif
}
/* Use 1/2 of total size to avoid swapping */
#define SYSMEM_HEAP_FRACTION(x) (x * 1 / 2)
static uint64_t
hk_get_sysmem_heap_size(struct hk_physical_device *pdev)
{
if (pdev->sysmem)
return pdev->sysmem;
uint64_t sysmem_size_B = 0;
if (!os_get_total_physical_memory(&sysmem_size_B))
return 0;
return ROUND_DOWN_TO(SYSMEM_HEAP_FRACTION(sysmem_size_B), 1 << 20);
struct hk_instance *instance = hk_physical_device_instance(pdev);
return os_get_gpu_heap_size(instance->heap_memory_percent,
&instance->heap_memory_percent);
}
static uint64_t
hk_get_sysmem_heap_available(struct hk_physical_device *pdev)
{
if (pdev->sysmem) {
uint64_t total_used = 0;
for (unsigned i = 0; i < pdev->mem_heap_count; i++) {
const struct hk_memory_heap *heap = &pdev->mem_heaps[i];
uint64_t used = p_atomic_read(&heap->used);
total_used += used;
}
return pdev->sysmem - total_used;
assert(pdev->sysmem);
uint64_t total_used = 0;
for (unsigned i = 0; i < pdev->mem_heap_count; i++) {
const struct hk_memory_heap *heap = &pdev->mem_heaps[i];
uint64_t used = p_atomic_read(&heap->used);
total_used += used;
}
uint64_t sysmem_size_B = 0;
if (!os_get_available_system_memory(&sysmem_size_B)) {
vk_loge(VK_LOG_OBJS(pdev), "Failed to query available system memory");
return 0;
}
return ROUND_DOWN_TO(SYSMEM_HEAP_FRACTION(sysmem_size_B), 1 << 20);
return pdev->sysmem - total_used;
}
VkResult
@ -1309,7 +1299,6 @@ hk_create_drm_physical_device(struct vk_instance *_instance,
pdev->mem_heaps[sysmem_heap_idx] = (struct hk_memory_heap){
.size = sysmem_size_B,
.flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
.available = hk_get_sysmem_heap_available,
};
pdev->mem_types[pdev->mem_type_count++] = (VkMemoryType){
@ -1393,6 +1382,7 @@ hk_GetPhysicalDeviceMemoryProperties2(
VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
{
VK_FROM_HANDLE(hk_physical_device, pdev, physicalDevice);
struct hk_instance *instance = hk_physical_device_instance(pdev);
pMemoryProperties->memoryProperties.memoryHeapCount = pdev->mem_heap_count;
for (int i = 0; i < pdev->mem_heap_count; i++) {
@ -1412,6 +1402,9 @@ hk_GetPhysicalDeviceMemoryProperties2(
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
VkPhysicalDeviceMemoryBudgetPropertiesEXT *p = (void *)ext;
uint64_t sysmem_budget =
pdev->sysmem ? hk_get_sysmem_heap_available(pdev) : 0;
for (unsigned i = 0; i < pdev->mem_heap_count; i++) {
const struct hk_memory_heap *heap = &pdev->mem_heaps[i];
uint64_t used = p_atomic_read(&heap->used);
@ -1427,33 +1420,22 @@ hk_GetPhysicalDeviceMemoryProperties2(
*/
p->heapUsage[i] = used;
uint64_t available = heap->size;
if (heap->available)
available = heap->available(pdev);
/* Set the budget at 90% to avoid thrashing. */
float percent = 0.9f;
/* 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);
uint64_t budget;
if (sysmem_budget) {
budget = MIN2(sysmem_budget + used, heap->size);
budget = ROUND_DOWN_TO((uint64_t)(budget * percent), 1 << 20);
} else {
/* 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);
budget = vk_physical_device_heap_budget_from_system(
&pdev->vk, percent, heap->size, used);
}
p->heapBudget[i] = budget;
}
/* From the Vulkan 1.3.278 spec:

View file

@ -26,7 +26,6 @@ struct hk_memory_heap {
uint64_t size;
uint64_t used;
VkMemoryHeapFlags flags;
uint64_t (*available)(struct hk_physical_device *pdev);
};
struct hk_physical_device {