diff options
-rw-r--r-- | docs/relnotes/19.1.0.html | 1 | ||||
-rw-r--r-- | src/intel/vulkan/anv_device.c | 89 | ||||
-rw-r--r-- | src/intel/vulkan/anv_extensions.py | 1 | ||||
-rw-r--r-- | src/intel/vulkan/anv_private.h | 2 |
4 files changed, 93 insertions, 0 deletions
diff --git a/docs/relnotes/19.1.0.html b/docs/relnotes/19.1.0.html index 950b595d200..c27e65ea096 100644 --- a/docs/relnotes/19.1.0.html +++ b/docs/relnotes/19.1.0.html @@ -63,6 +63,7 @@ TBD. <li>VK_EXT_descriptor_indexing on Intel.</li> <li>VK_KHR_shader_float16_int8 on Intel and RADV.</li> <li>GL_INTEL_conservative_rasterization on iris.</li> +<li>VK_EXT_memory_budget on Intel.</li> </ul> <h2>Bug fixes</h2> diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index e7c0212f2e9..ef2c9b50193 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -37,6 +37,8 @@ #include "util/build_id.h" #include "util/disk_cache.h" #include "util/mesa-sha1.h" +#include "util/os_file.h" +#include "util/u_atomic.h" #include "util/u_string.h" #include "git_sha1.h" #include "vk_util.h" @@ -342,6 +344,29 @@ anv_physical_device_free_disk_cache(struct anv_physical_device *device) #endif } +static uint64_t +get_available_system_memory() +{ + char *meminfo = os_read_file("/proc/meminfo"); + if (!meminfo) + return 0; + + char *str = strstr(meminfo, "MemAvailable:"); + if (!str) { + free(meminfo); + return 0; + } + + uint64_t kb_mem_available; + if (sscanf(str, "MemAvailable: %" PRIx64, &kb_mem_available) == 1) { + free(meminfo); + return kb_mem_available << 10; + } + + free(meminfo); + return 0; +} + static VkResult anv_physical_device_init(struct anv_physical_device *device, struct anv_instance *instance, @@ -481,6 +506,8 @@ anv_physical_device_init(struct anv_physical_device *device, */ device->has_bindless_samplers = device->info.gen >= 8; + device->has_mem_available = get_available_system_memory() != 0; + /* Starting with Gen10, the timestamp frequency of the command streamer may * vary from one part to another. We can query the value from the kernel. */ @@ -1617,6 +1644,58 @@ void anv_GetPhysicalDeviceMemoryProperties( } } +static void +anv_get_memory_budget(VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget) +{ + ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice); + uint64_t sys_available = get_available_system_memory(); + assert(sys_available > 0); + + VkDeviceSize total_heaps_size = 0; + for (size_t i = 0; i < device->memory.heap_count; i++) + total_heaps_size += device->memory.heaps[i].size; + + for (size_t i = 0; i < device->memory.heap_count; i++) { + VkDeviceSize heap_size = device->memory.heaps[i].size; + VkDeviceSize heap_used = device->memory.heaps[i].used; + VkDeviceSize heap_budget; + + double heap_proportion = (double) heap_size / total_heaps_size; + VkDeviceSize sys_available_prop = sys_available * heap_proportion; + + /* + * Let's not incite the app to starve the system: report at most 90% of + * available system memory. + */ + uint64_t heap_available = sys_available_prop * 9 / 10; + heap_budget = MIN2(heap_size, heap_used + heap_available); + + /* + * Round down to the nearest MB + */ + heap_budget &= ~((1ull << 20) - 1); + + /* + * The heapBudget value must be non-zero for array elements less than + * VkPhysicalDeviceMemoryProperties::memoryHeapCount. The heapBudget + * value must be less than or equal to VkMemoryHeap::size for each heap. + */ + assert(0 < heap_budget && heap_budget <= heap_size); + + memoryBudget->heapUsage[i] = heap_used; + memoryBudget->heapBudget[i] = heap_budget; + } + + /* The heapBudget and heapUsage values must be zero for array elements + * greater than or equal to VkPhysicalDeviceMemoryProperties::memoryHeapCount + */ + for (uint32_t i = device->memory.heap_count; i < VK_MAX_MEMORY_HEAPS; i++) { + memoryBudget->heapBudget[i] = 0; + memoryBudget->heapUsage[i] = 0; + } +} + void anv_GetPhysicalDeviceMemoryProperties2( VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) @@ -1626,6 +1705,9 @@ void anv_GetPhysicalDeviceMemoryProperties2( vk_foreach_struct(ext, pMemoryProperties->pNext) { switch (ext->sType) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: + anv_get_memory_budget(physicalDevice, (void*)ext); + break; default: anv_debug_ignored_stype(ext->sType); break; @@ -2815,6 +2897,9 @@ VkResult anv_AllocateMemory( *pMem = anv_device_memory_to_handle(mem); + p_atomic_add(&pdevice->memory.heaps[mem->type->heapIndex].used, + mem->bo->size); + return VK_SUCCESS; fail: @@ -2900,6 +2985,7 @@ void anv_FreeMemory( { ANV_FROM_HANDLE(anv_device, device, _device); ANV_FROM_HANDLE(anv_device_memory, mem, _mem); + struct anv_physical_device *pdevice = &device->instance->physicalDevice; if (mem == NULL) return; @@ -2918,6 +3004,9 @@ void anv_FreeMemory( AHardwareBuffer_release(mem->ahw); #endif + p_atomic_add(&pdevice->memory.heaps[mem->type->heapIndex].used, + -mem->bo->size); + vk_free2(&device->alloc, pAllocator, mem); } diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index 1d3dbaaa9a9..962ebdbc58d 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -133,6 +133,7 @@ EXTENSIONS = [ 'device->has_context_priority'), Extension('VK_EXT_host_query_reset', 1, True), Extension('VK_EXT_inline_uniform_block', 1, True), + Extension('VK_EXT_memory_budget', 1, 'device->has_mem_available'), Extension('VK_EXT_pci_bus_info', 2, True), Extension('VK_EXT_pipeline_creation_feedback', 1, True), Extension('VK_EXT_post_depth_coverage', 1, 'device->info.gen >= 9'), diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index f1875aa7642..8727d56d90f 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -912,6 +912,7 @@ struct anv_memory_heap { uint64_t vma_start; uint64_t vma_size; bool supports_48bit_addresses; + VkDeviceSize used; }; struct anv_physical_device { @@ -949,6 +950,7 @@ struct anv_physical_device { bool has_context_priority; bool use_softpin; bool has_context_isolation; + bool has_mem_available; bool always_use_bindless; /** True if we can access buffers using A64 messages */ |