anv: add a new vm_bind vfunc
authorPaulo Zanoni <paulo.r.zanoni@intel.com>
Fri, 4 Aug 2023 22:48:45 +0000 (15:48 -0700)
committerMarge Bot <emma+marge@anholt.net>
Mon, 11 Sep 2023 16:04:01 +0000 (16:04 +0000)
For Sparse Resources we need to be able to specify the address, size
and offsets and we also want to be able to issue multiple binds at the
same time. Extend xe_vm_bind_op() to handle those cases and add
the new vfunc.

v2:
 - use STACK_ARRAY() (Lionel)
 - no more need to work around xe.ko bug that was fixed (José)

Reviewed-by: José Roberto de Souza <jose.souza@intel.com> (v1)
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24681>

src/intel/vulkan/anv_gem_stubs.c
src/intel/vulkan/anv_kmd_backend.h
src/intel/vulkan/i915/anv_kmd_backend.c
src/intel/vulkan/xe/anv_kmd_backend.c

index 7cede99..74acc38 100644 (file)
@@ -152,6 +152,13 @@ anv_gem_fd_to_handle(struct anv_device *device, int fd)
 }
 
 static int
+stub_vm_bind(struct anv_device *device, int num_binds,
+             struct anv_vm_bind *binds)
+{
+   return 0;
+}
+
+static int
 stub_vm_bind_bo(struct anv_device *device, struct anv_bo *bo)
 {
    return 0;
@@ -164,6 +171,7 @@ const struct anv_kmd_backend *anv_stub_kmd_backend_get(void)
       .gem_create_userptr = stub_gem_create_userptr,
       .gem_close = stub_gem_close,
       .gem_mmap = stub_gem_mmap,
+      .vm_bind = stub_vm_bind,
       .vm_bind_bo = stub_vm_bind_bo,
       .vm_unbind_bo = stub_vm_bind_bo,
       .execute_simple_batch = stub_execute_simple_batch,
index c1e8243..a299b72 100644 (file)
@@ -39,6 +39,19 @@ struct anv_queue;
 struct anv_query_pool;
 struct anv_utrace_submit;
 
+enum anv_vm_bind_op {
+   ANV_VM_BIND,
+   ANV_VM_UNBIND,
+};
+
+struct anv_vm_bind {
+   struct anv_bo *bo;  /* Or NULL in case of a NULL binding. */
+   uint64_t address;   /* Includes the resource offset. */
+   uint64_t bo_offset; /* Also known as the memory offset. */
+   uint64_t size;
+   enum anv_vm_bind_op op;
+};
+
 struct anv_kmd_backend {
    /*
     * Create a gem buffer.
@@ -55,6 +68,9 @@ struct anv_kmd_backend {
    void *(*gem_mmap)(struct anv_device *device, struct anv_bo *bo,
                      uint64_t offset, uint64_t size,
                      VkMemoryPropertyFlags property_flags);
+   /* Bind things however you want. */
+   int (*vm_bind)(struct anv_device *device, int num_binds,
+                  struct anv_vm_bind *binds);
    /* Fully bind or unbind a BO. */
    int (*vm_bind_bo)(struct anv_device *device, struct anv_bo *bo);
    int (*vm_unbind_bo)(struct anv_device *device, struct anv_bo *bo);
index b4828f1..3ba2ca2 100644 (file)
@@ -169,6 +169,13 @@ i915_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
 }
 
 static int
+i915_vm_bind(struct anv_device *device, int num_binds,
+             struct anv_vm_bind *binds)
+{
+   return 0;
+}
+
+static int
 i915_vm_bind_bo(struct anv_device *device, struct anv_bo *bo)
 {
    return 0;
@@ -201,6 +208,7 @@ anv_i915_kmd_backend_get(void)
       .gem_create_userptr = i915_gem_create_userptr,
       .gem_close = i915_gem_close,
       .gem_mmap = i915_gem_mmap,
+      .vm_bind = i915_vm_bind,
       .vm_bind_bo = i915_vm_bind_bo,
       .vm_unbind_bo = i915_vm_bind_bo,
       .execute_simple_batch = i915_execute_simple_batch,
index 8a7ecb3..8551f4d 100644 (file)
@@ -94,38 +94,70 @@ xe_gem_mmap(struct anv_device *device, struct anv_bo *bo, uint64_t offset,
 }
 
 static inline int
-xe_vm_bind_op(struct anv_device *device, struct anv_bo *bo, uint32_t op)
+xe_vm_bind_op(struct anv_device *device, int num_binds,
+              struct anv_vm_bind *binds)
 {
    uint32_t syncobj_handle;
    int ret = drmSyncobjCreate(device->fd, 0, &syncobj_handle);
-
    if (ret)
       return ret;
 
-   uint32_t obj = op == XE_VM_BIND_OP_UNMAP ? 0 : bo->gem_handle;
-   uint64_t obj_offset = 0;
-   if (bo->from_host_ptr) {
-      obj = 0;
-      obj_offset = (uintptr_t)bo->map;
-      if (op == XE_VM_BIND_OP_MAP)
-         op = XE_VM_BIND_OP_MAP_USERPTR;
-   }
-
    struct drm_xe_sync sync = {
       .flags = DRM_XE_SYNC_SYNCOBJ | DRM_XE_SYNC_SIGNAL,
       .handle = syncobj_handle,
    };
    struct drm_xe_vm_bind args = {
       .vm_id = device->vm_id,
-      .num_binds = 1,
-      .bind.obj = obj,
-      .bind.obj_offset = obj_offset,
-      .bind.range = bo->actual_size,
-      .bind.addr = intel_48b_address(bo->offset),
-      .bind.op = op,
+      .num_binds = num_binds,
+      .bind = {},
       .num_syncs = 1,
       .syncs = (uintptr_t)&sync,
    };
+
+   STACK_ARRAY(struct drm_xe_vm_bind_op, xe_binds_stackarray, num_binds);
+   struct drm_xe_vm_bind_op *xe_binds;
+   if (num_binds > 1) {
+      if (!xe_binds_stackarray)
+         goto out_syncobj;
+
+      xe_binds = xe_binds_stackarray;
+      args.vector_of_binds = (uintptr_t)xe_binds;
+   } else {
+      xe_binds = &args.bind;
+   }
+
+   for (int i = 0; i < num_binds; i++) {
+      struct anv_vm_bind *bind = &binds[i];
+      struct anv_bo *bo = bind->bo;
+
+      struct drm_xe_vm_bind_op *xe_bind = &xe_binds[i];
+      *xe_bind = (struct drm_xe_vm_bind_op) {
+         .obj = 0,
+         .obj_offset = bind->bo_offset,
+         .range = bind->size,
+         .addr = intel_48b_address(bind->address),
+         .tile_mask = 0,
+         .op = XE_VM_BIND_OP_UNMAP,
+         .region = 0,
+      };
+
+      if (bind->op == ANV_VM_BIND) {
+         if (!bo) {
+            xe_bind->op = XE_VM_BIND_OP_MAP | XE_VM_BIND_FLAG_NULL;
+            assert(xe_bind->obj_offset == 0);
+         } else if (bo->from_host_ptr) {
+            xe_bind->op = XE_VM_BIND_OP_MAP_USERPTR;
+         } else {
+            xe_bind->op = XE_VM_BIND_OP_MAP;
+            xe_bind->obj = bo->gem_handle;
+         }
+      }
+
+      /* userptr and bo_offset are an union! */
+      if (bo && bo->from_host_ptr)
+         xe_bind->userptr = (uintptr_t)bo->map;
+   }
+
    ret = intel_ioctl(device->fd, DRM_IOCTL_XE_VM_BIND, &args);
    if (ret)
       goto bind_error;
@@ -141,18 +173,41 @@ xe_vm_bind_op(struct anv_device *device, struct anv_bo *bo, uint32_t op)
    intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
 
 bind_error:
+   STACK_ARRAY_FINISH(xe_binds_stackarray);
+out_syncobj:
    drmSyncobjDestroy(device->fd, syncobj_handle);
    return ret;
 }
 
+static int
+xe_vm_bind(struct anv_device *device, int num_binds,
+           struct anv_vm_bind *binds)
+{
+   return xe_vm_bind_op(device, num_binds, binds);
+}
+
 static int xe_vm_bind_bo(struct anv_device *device, struct anv_bo *bo)
 {
-   return xe_vm_bind_op(device, bo, XE_VM_BIND_OP_MAP);
+   struct anv_vm_bind bind = {
+      .bo = bo,
+      .address = bo->offset,
+      .bo_offset = 0,
+      .size = bo->actual_size,
+      .op = ANV_VM_BIND,
+   };
+   return xe_vm_bind_op(device, 1, &bind);
 }
 
 static int xe_vm_unbind_bo(struct anv_device *device, struct anv_bo *bo)
 {
-   return xe_vm_bind_op(device, bo, XE_VM_BIND_OP_UNMAP);
+   struct anv_vm_bind bind = {
+      .bo = bo,
+      .address = bo->offset,
+      .bo_offset = 0,
+      .size = bo->actual_size,
+      .op = ANV_VM_UNBIND,
+   };
+   return xe_vm_bind_op(device, 1, &bind);
 }
 
 static uint32_t
@@ -173,6 +228,7 @@ anv_xe_kmd_backend_get(void)
       .gem_create_userptr = xe_gem_create_userptr,
       .gem_close = xe_gem_close,
       .gem_mmap = xe_gem_mmap,
+      .vm_bind = xe_vm_bind,
       .vm_bind_bo = xe_vm_bind_bo,
       .vm_unbind_bo = xe_vm_unbind_bo,
       .execute_simple_batch = xe_execute_simple_batch,