anv: Make anv_vma_alloc/free a lot dumber
authorJason Ekstrand <jason@jlekstrand.net>
Wed, 22 Jan 2020 22:40:13 +0000 (16:40 -0600)
committerMarge Bot <eric+marge@anholt.net>
Sat, 25 Jan 2020 02:18:33 +0000 (02:18 +0000)
All they do now is take a size, align, and flags and figure out which
heap to allocate in.  All of the actual code to deal with the BO is in
anv_allocator.c.  We want to leave anv_vma_alloc/free in anv_device.c
because it deals with API-exposed heaps so it still makes sense to have
it there.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3519>

src/intel/vulkan/anv_allocator.c
src/intel/vulkan/anv_device.c
src/intel/vulkan/anv_private.h

index 6cf1d5fa36af32d05ee8f19d90e17b6f3d5b8f37..d88b521e1609c43fad0b268938ba755fe118dea2 100644 (file)
@@ -1521,6 +1521,18 @@ anv_bo_alloc_flags_to_bo_flags(struct anv_device *device,
    return bo_flags;
 }
 
+static uint32_t
+anv_device_get_bo_align(struct anv_device *device)
+{
+   /* Gen12 CCS surface addresses need to be 64K aligned. We have no way of
+    * telling what this allocation is for so pick the largest alignment.
+    */
+   if (device->info.gen >= 12)
+      return 64 * 1024;
+
+   return 4096;
+}
+
 VkResult
 anv_device_alloc_bo(struct anv_device *device,
                     uint64_t size,
@@ -1535,6 +1547,8 @@ anv_device_alloc_bo(struct anv_device *device,
    /* The kernel is going to give us whole pages anyway */
    size = align_u64(size, 4096);
 
+   const uint32_t align = anv_device_get_bo_align(device);
+
    uint32_t gem_handle = anv_gem_create(device, size);
    if (gem_handle == 0)
       return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
@@ -1581,14 +1595,18 @@ anv_device_alloc_bo(struct anv_device *device,
    if (alloc_flags & ANV_BO_ALLOC_FIXED_ADDRESS) {
       new_bo.has_fixed_address = true;
       new_bo.offset = explicit_address;
-   } else {
-      if (!anv_vma_alloc(device, &new_bo, explicit_address)) {
+   } else if (new_bo.flags & EXEC_OBJECT_PINNED) {
+      new_bo.offset = anv_vma_alloc(device, new_bo.size, align,
+                                    alloc_flags, explicit_address);
+      if (new_bo.offset == 0) {
          if (new_bo.map)
             anv_gem_munmap(new_bo.map, size);
          anv_gem_close(device, new_bo.gem_handle);
          return vk_errorf(device, NULL, VK_ERROR_OUT_OF_DEVICE_MEMORY,
                           "failed to allocate virtual address for BO");
       }
+   } else {
+      assert(!new_bo.has_client_visible_address);
    }
 
    assert(new_bo.gem_handle);
@@ -1670,11 +1688,25 @@ anv_device_import_bo_from_host_ptr(struct anv_device *device,
       };
 
       assert(client_address == gen_48b_address(client_address));
-      if (!anv_vma_alloc(device, &new_bo, client_address)) {
-         anv_gem_close(device, new_bo.gem_handle);
-         pthread_mutex_unlock(&cache->mutex);
-         return vk_errorf(device, NULL, VK_ERROR_OUT_OF_DEVICE_MEMORY,
-                          "failed to allocate virtual address for BO");
+      if (new_bo.flags & EXEC_OBJECT_PINNED) {
+         /* Gen12 CCS surface addresses need to be 64K aligned. We have no way
+          * of telling what this allocation is for so pick the largest
+          * alignment.
+          */
+         const uint32_t align = device->info.gen >= 12 ? (64 * 1024) :
+                                                         (4 * 1024);
+
+         new_bo.offset = anv_vma_alloc(device, new_bo.size,
+                                       anv_device_get_bo_align(device),
+                                       alloc_flags, client_address);
+         if (new_bo.offset == 0) {
+            anv_gem_close(device, new_bo.gem_handle);
+            pthread_mutex_unlock(&cache->mutex);
+            return vk_errorf(device, NULL, VK_ERROR_OUT_OF_DEVICE_MEMORY,
+                             "failed to allocate virtual address for BO");
+         }
+      } else {
+         assert(!new_bo.has_client_visible_address);
       }
 
       *bo = new_bo;
@@ -1789,11 +1821,18 @@ anv_device_import_bo(struct anv_device *device,
       };
 
       assert(client_address == gen_48b_address(client_address));
-      if (!anv_vma_alloc(device, &new_bo, client_address)) {
-         anv_gem_close(device, new_bo.gem_handle);
-         pthread_mutex_unlock(&cache->mutex);
-         return vk_errorf(device, NULL, VK_ERROR_OUT_OF_DEVICE_MEMORY,
-                          "failed to allocate virtual address for BO");
+      if (new_bo.flags & EXEC_OBJECT_PINNED) {
+         new_bo.offset = anv_vma_alloc(device, new_bo.size,
+                                       anv_device_get_bo_align(device),
+                                       alloc_flags, client_address);
+         if (new_bo.offset == 0) {
+            anv_gem_close(device, new_bo.gem_handle);
+            pthread_mutex_unlock(&cache->mutex);
+            return vk_errorf(device, NULL, VK_ERROR_OUT_OF_DEVICE_MEMORY,
+                             "failed to allocate virtual address for BO");
+         }
+      } else {
+         assert(!new_bo.has_client_visible_address);
       }
 
       *bo = new_bo;
@@ -1875,8 +1914,8 @@ anv_device_release_bo(struct anv_device *device,
    if (bo->map && !bo->from_host_ptr)
       anv_gem_munmap(bo->map, bo->size);
 
-   if (!bo->has_fixed_address)
-      anv_vma_free(device, bo);
+   if ((bo->flags & EXEC_OBJECT_PINNED) && !bo->has_fixed_address)
+      anv_vma_free(device, bo->offset, bo->size);
 
    uint32_t gem_handle = bo->gem_handle;
 
index 8ef415e3eea1f2690ed1ba59edd8bce2be07214f..a0d9e9616dbcdba5c7d4d438b111ee9a431822d8 100644 (file)
@@ -3201,40 +3201,24 @@ VkResult anv_DeviceWaitIdle(
    return anv_queue_submit_simple_batch(&device->queue, NULL);
 }
 
-bool
-anv_vma_alloc(struct anv_device *device, struct anv_bo *bo,
+uint64_t
+anv_vma_alloc(struct anv_device *device,
+              uint64_t size, uint64_t align,
+              enum anv_bo_alloc_flags alloc_flags,
               uint64_t client_address)
 {
-   const struct gen_device_info *devinfo = &device->info;
-   /* Gen12 CCS surface addresses need to be 64K aligned. We have no way of
-    * telling what this allocation is for so pick the largest alignment.
-    */
-   const uint32_t vma_alignment =
-      devinfo->gen >= 12 ? (64 * 1024) : (4 * 1024);
-
-   if (!(bo->flags & EXEC_OBJECT_PINNED)) {
-      assert(!(bo->has_client_visible_address));
-      return true;
-   }
-
    pthread_mutex_lock(&device->vma_mutex);
 
-   bo->offset = 0;
+   uint64_t addr = 0;
 
-   if (bo->has_client_visible_address) {
-      assert(bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS);
+   if (alloc_flags & ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS) {
       if (client_address) {
          if (util_vma_heap_alloc_addr(&device->vma_cva,
-                                      client_address, bo->size)) {
-            bo->offset = gen_canonical_address(client_address);
+                                      client_address, size)) {
+            addr = client_address;
          }
       } else {
-         uint64_t addr =
-            util_vma_heap_alloc(&device->vma_cva, bo->size, vma_alignment);
-         if (addr) {
-            bo->offset = gen_canonical_address(addr);
-            assert(addr == gen_48b_address(bo->offset));
-         }
+         addr = util_vma_heap_alloc(&device->vma_cva, size, align);
       }
       /* We don't want to fall back to other heaps */
       goto done;
@@ -3242,54 +3226,39 @@ anv_vma_alloc(struct anv_device *device, struct anv_bo *bo,
 
    assert(client_address == 0);
 
-   if (bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) {
-      uint64_t addr =
-         util_vma_heap_alloc(&device->vma_hi, bo->size, vma_alignment);
-      if (addr) {
-         bo->offset = gen_canonical_address(addr);
-         assert(addr == gen_48b_address(bo->offset));
-      }
-   }
+   if (!(alloc_flags & ANV_BO_ALLOC_32BIT_ADDRESS))
+      addr = util_vma_heap_alloc(&device->vma_hi, size, align);
 
-   if (bo->offset == 0) {
-      uint64_t addr =
-         util_vma_heap_alloc(&device->vma_lo, bo->size, vma_alignment);
-      if (addr) {
-         bo->offset = gen_canonical_address(addr);
-         assert(addr == gen_48b_address(bo->offset));
-      }
-   }
+   if (addr == 0)
+      addr = util_vma_heap_alloc(&device->vma_lo, size, align);
 
 done:
    pthread_mutex_unlock(&device->vma_mutex);
 
-   return bo->offset != 0;
+   assert(addr == gen_48b_address(addr));
+   return gen_canonical_address(addr);
 }
 
 void
-anv_vma_free(struct anv_device *device, struct anv_bo *bo)
+anv_vma_free(struct anv_device *device,
+             uint64_t address, uint64_t size)
 {
-   if (!(bo->flags & EXEC_OBJECT_PINNED))
-      return;
-
-   const uint64_t addr_48b = gen_48b_address(bo->offset);
+   const uint64_t addr_48b = gen_48b_address(address);
 
    pthread_mutex_lock(&device->vma_mutex);
 
    if (addr_48b >= LOW_HEAP_MIN_ADDRESS &&
        addr_48b <= LOW_HEAP_MAX_ADDRESS) {
-      util_vma_heap_free(&device->vma_lo, addr_48b, bo->size);
+      util_vma_heap_free(&device->vma_lo, addr_48b, size);
    } else if (addr_48b >= CLIENT_VISIBLE_HEAP_MIN_ADDRESS &&
               addr_48b <= CLIENT_VISIBLE_HEAP_MAX_ADDRESS) {
-      util_vma_heap_free(&device->vma_cva, addr_48b, bo->size);
+      util_vma_heap_free(&device->vma_cva, addr_48b, size);
    } else {
       assert(addr_48b >= HIGH_HEAP_MIN_ADDRESS);
-      util_vma_heap_free(&device->vma_hi, addr_48b, bo->size);
+      util_vma_heap_free(&device->vma_hi, addr_48b, size);
    }
 
    pthread_mutex_unlock(&device->vma_mutex);
-
-   bo->offset = 0;
 }
 
 VkResult anv_AllocateMemory(
index 477e891fde4986ec1d8531c33af2ac5151d29d9f..8f63882bdacdb134af04d0736fe7e75d1c5509e7 100644 (file)
@@ -1467,9 +1467,12 @@ int anv_gem_syncobj_wait(struct anv_device *device,
                          uint32_t *handles, uint32_t num_handles,
                          int64_t abs_timeout_ns, bool wait_all);
 
-bool anv_vma_alloc(struct anv_device *device, struct anv_bo *bo,
-                   uint64_t client_address);
-void anv_vma_free(struct anv_device *device, struct anv_bo *bo);
+uint64_t anv_vma_alloc(struct anv_device *device,
+                       uint64_t size, uint64_t align,
+                       enum anv_bo_alloc_flags alloc_flags,
+                       uint64_t client_address);
+void anv_vma_free(struct anv_device *device,
+                  uint64_t address, uint64_t size);
 
 struct anv_reloc_list {
    uint32_t                                     num_relocs;