anv: add support for VK_EXT_memory_budget
authorEric Engestrom <eric.engestrom@intel.com>
Tue, 8 Jan 2019 12:45:38 +0000 (12:45 +0000)
committerEric Engestrom <eric@engestrom.ch>
Tue, 30 Apr 2019 15:40:33 +0000 (15:40 +0000)
Signed-off-by: Eric Engestrom <eric.engestrom@intel.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
docs/relnotes/19.1.0.html
src/intel/vulkan/anv_device.c
src/intel/vulkan/anv_extensions.py
src/intel/vulkan/anv_private.h

index 950b595d200c39153f8bc1d019bbf10c5bedafb9..c27e65ea096da1b4b1a929c613d7e1dcacdbc78d 100644 (file)
@@ -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>
index e7c0212f2e9fe0a7bbaf46806067067b5d4c9beb..ef2c9b50193e6434cc9a34035a963ba796c82ca2 100644 (file)
@@ -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);
 }
 
index 1d3dbaaa9a9172b374e1bcc8facbf5a96f6754f2..962ebdbc58de378c5cdbbdd61f2b982ca09de710 100644 (file)
@@ -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'),
index f1875aa7642146abac67b21479ea5b3bb412e265..8727d56d90f67d43e63290e9f65436606a474753 100644 (file)
@@ -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 */