nvk: Add support for sparse buffers
authorDave Airlie <airlied@redhat.com>
Wed, 19 Jul 2023 21:45:27 +0000 (16:45 -0500)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:32:07 +0000 (21:32 +0000)
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/vulkan/nvk_buffer.c
src/nouveau/vulkan/nvk_buffer.h
src/nouveau/vulkan/nvk_cmd_buffer.c

index 2040965..c4aa191 100644 (file)
@@ -7,7 +7,7 @@
 uint32_t
 nvk_get_buffer_alignment(UNUSED const struct nvk_physical_device *pdev,
                          VkBufferUsageFlags2KHR usage_flags,
-                         UNUSED VkBufferCreateFlags create_flags)
+                         VkBufferCreateFlags create_flags)
 {
    uint32_t alignment = 16;
 
@@ -21,6 +21,9 @@ nvk_get_buffer_alignment(UNUSED const struct nvk_physical_device *pdev,
                       VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR))
       alignment = MAX2(alignment, NVK_MIN_UBO_ALIGNMENT);
 
+   if (create_flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)
+      alignment = MAX2(alignment, 4096);
+
    return alignment;
 }
 
@@ -38,6 +41,23 @@ nvk_CreateBuffer(VkDevice device,
    if (!buffer)
       return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
 
+#if NVK_NEW_UAPI == 1
+   if (buffer->vk.create_flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) {
+      const uint32_t alignment =
+         nvk_get_buffer_alignment(nvk_device_physical(dev),
+                                  buffer->vk.usage,
+                                  buffer->vk.create_flags);
+      assert(alignment >= 4096);
+      buffer->vma_size_B = ALIGN_POT(buffer->vk.size, alignment);
+
+      const bool sparse_residency =
+         buffer->vk.create_flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT;
+
+      buffer->addr = nouveau_ws_alloc_vma(dev->ws_dev, buffer->vma_size_B,
+                                          alignment, sparse_residency);
+   }
+#endif
+
    *pBuffer = nvk_buffer_to_handle(buffer);
 
    return VK_SUCCESS;
@@ -54,6 +74,17 @@ nvk_DestroyBuffer(VkDevice device,
    if (!buffer)
       return;
 
+#if NVK_NEW_UAPI == 1
+   if (buffer->vma_size_B > 0) {
+      const bool sparse_residency =
+         buffer->vk.create_flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT;
+
+      nouveau_ws_bo_unbind_vma(dev->ws_dev, buffer->addr, buffer->vma_size_B);
+      nouveau_ws_free_vma(dev->ws_dev, buffer->addr, buffer->vma_size_B,
+                          sparse_residency);
+   }
+#endif
+
    vk_buffer_destroy(&dev->vk, pAllocator, &buffer->vk);
 }
 
@@ -145,8 +176,22 @@ nvk_BindBufferMemory2(VkDevice device,
       VK_FROM_HANDLE(nvk_device_memory, mem, pBindInfos[i].memory);
       VK_FROM_HANDLE(nvk_buffer, buffer, pBindInfos[i].buffer);
 
+#if NVK_NEW_UAPI == 1
+      if (buffer->vma_size_B) {
+         VK_FROM_HANDLE(nvk_device, dev, device);
+         nouveau_ws_bo_bind_vma(dev->ws_dev,
+                                mem->bo,
+                                buffer->addr,
+                                buffer->vma_size_B,
+                                pBindInfos[i].memoryOffset,
+                                0 /* pte_kind */);
+      } else {
+         buffer->addr = mem->bo->offset + pBindInfos[i].memoryOffset;
+      }
+#else
       buffer->mem = mem;
       buffer->addr = mem->bo->offset + pBindInfos[i].memoryOffset;
+#endif
    }
    return VK_SUCCESS;
 }
index 07f8e96..9afa0f1 100644 (file)
@@ -17,8 +17,14 @@ nvk_get_buffer_alignment(const struct nvk_physical_device *pdev,
 
 struct nvk_buffer {
    struct vk_buffer vk;
-   struct nvk_device_memory *mem;
    uint64_t addr;
+
+#if NVK_NEW_UAPI == 1
+   /** Size of the reserved VMA range for sparse buffers, zero otherwise. */
+   uint64_t vma_size_B;
+#else
+   struct nvk_device_memory *mem;
+#endif
 };
 
 VK_DEFINE_NONDISP_HANDLE_CASTS(nvk_buffer, vk.base, VkBuffer, VK_OBJECT_TYPE_BUFFER)
index eaae440..46e5339 100644 (file)
@@ -153,6 +153,9 @@ nvk_cmd_buffer_push_indirect_buffer(struct nvk_cmd_buffer *cmd,
 {
    nvk_cmd_buffer_flush_push(cmd);
 
+#if NVK_NEW_UAPI == 1
+   unreachable("Does not yet support sparse");
+#else
    /* TODO: The new uAPI should just take addresses */
    struct nouveau_ws_bo *bo = buffer->mem->bo;
    uint64_t bo_offset = nvk_buffer_address(buffer, offset) - bo->offset;
@@ -164,6 +167,7 @@ nvk_cmd_buffer_push_indirect_buffer(struct nvk_cmd_buffer *cmd,
       .range = NVC0_IB_ENTRY_1_NO_PREFETCH | range,
    };
    util_dynarray_append(&cmd->pushes, struct nvk_cmd_push, push);
+#endif
 }
 
 VkResult