diff --git a/src/asahi/vulkan/hk_instance.c b/src/asahi/vulkan/hk_instance.c index e0db7a46633..699e63acb78 100644 --- a/src/asahi/vulkan/hk_instance.c +++ b/src/asahi/vulkan/hk_instance.c @@ -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"); diff --git a/src/asahi/vulkan/hk_instance.h b/src/asahi/vulkan/hk_instance.h index d4d1e2f031b..eded4e3675d 100644 --- a/src/asahi/vulkan/hk_instance.h +++ b/src/asahi/vulkan/hk_instance.h @@ -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; diff --git a/src/asahi/vulkan/hk_physical_device.c b/src/asahi/vulkan/hk_physical_device.c index fc1f737e868..05d54f764d6 100644 --- a/src/asahi/vulkan/hk_physical_device.c +++ b/src/asahi/vulkan/hk_physical_device.c @@ -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 @@ -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 heap’s 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: diff --git a/src/asahi/vulkan/hk_physical_device.h b/src/asahi/vulkan/hk_physical_device.h index ea286c92ace..6446672aced 100644 --- a/src/asahi/vulkan/hk_physical_device.h +++ b/src/asahi/vulkan/hk_physical_device.h @@ -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 {