anv/sparse: don't use the bind_timeline when doing sparse binding

The bind_timeline is used to guarantee that non-sparse objects will
be bound when batches use them (although any batch will wait on the
most recent bind, even if that's not necessary). For sparse binding
resources, it's up to the user to guarantee synchronization: do not
force every single batch buffer to wait on the latest sparse binding
operation, as that adds unnecessary synchronization points.

v2: Document how each of the vfuncs interacts with bind_timeline
    (José).

Reviewed-by: José Roberto de Souza <jose.souza@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27926>
This commit is contained in:
Paulo Zanoni 2024-03-01 11:18:04 -08:00 committed by Marge Bot
parent 8051919b3c
commit 4863e12679
2 changed files with 35 additions and 16 deletions

View file

@ -73,12 +73,24 @@ struct anv_kmd_backend {
/* Returns MAP_FAILED on error */
void *(*gem_mmap)(struct anv_device *device, struct anv_bo *bo,
uint64_t offset, uint64_t size, void *placed_addr);
/* Bind things however you want. */
/*
* Bind things however you want.
* This is intended for sparse resources, so it does not use the
* bind_timeline interface: synchronization is up to the callers.
*/
int (*vm_bind)(struct anv_device *device,
struct anv_sparse_submission *submit);
/* Fully bind or unbind a BO. */
/*
* Fully bind or unbind a BO.
* This is intended for general buffer creation/destruction, so it creates
* a new point in the bind_timeline, which will be waited for the next time
* a batch is submitted.
*/
int (*vm_bind_bo)(struct anv_device *device, struct anv_bo *bo);
int (*vm_unbind_bo)(struct anv_device *device, struct anv_bo *bo);
VkResult (*execute_simple_batch)(struct anv_queue *queue,
struct anv_bo *batch_bo,
uint32_t batch_bo_size,

View file

@ -124,9 +124,11 @@ capture_vm_in_error_dump(struct anv_device *device, struct anv_bo *bo)
static inline int
xe_vm_bind_op(struct anv_device *device,
struct anv_sparse_submission *submit)
struct anv_sparse_submission *submit,
bool signal_bind_timeline)
{
int num_syncs = submit->wait_count + submit->signal_count + 1;
int num_syncs = submit->wait_count + submit->signal_count +
signal_bind_timeline;
STACK_ARRAY(struct drm_xe_sync, xe_syncs, num_syncs);
if (!xe_syncs)
return -ENOMEM;
@ -160,12 +162,14 @@ xe_vm_bind_op(struct anv_device *device,
.timeline_value = val,
};
}
xe_syncs[sync_idx++] = (struct drm_xe_sync) {
.type = DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ,
.flags = DRM_XE_SYNC_FLAG_SIGNAL,
.handle = intel_bind_timeline_get_syncobj(&device->bind_timeline),
/* .timeline_value will be set later. */
};
if (signal_bind_timeline) {
xe_syncs[sync_idx++] = (struct drm_xe_sync) {
.type = DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ,
.flags = DRM_XE_SYNC_FLAG_SIGNAL,
.handle = intel_bind_timeline_get_syncobj(&device->bind_timeline),
/* .timeline_value will be set later. */
};
}
assert(sync_idx == num_syncs);
struct drm_xe_vm_bind args = {
@ -237,10 +241,13 @@ xe_vm_bind_op(struct anv_device *device,
xe_bind->userptr = (uintptr_t)bo->map;
}
xe_syncs[num_syncs - 1].timeline_value =
intel_bind_timeline_bind_begin(&device->bind_timeline);
if (signal_bind_timeline) {
xe_syncs[num_syncs - 1].timeline_value =
intel_bind_timeline_bind_begin(&device->bind_timeline);
}
ret = intel_ioctl(device->fd, DRM_IOCTL_XE_VM_BIND, &args);
intel_bind_timeline_bind_end(&device->bind_timeline);
if (signal_bind_timeline)
intel_bind_timeline_bind_end(&device->bind_timeline);
if (ret)
goto out_stackarray;
@ -258,7 +265,7 @@ out_syncs:
static int
xe_vm_bind(struct anv_device *device, struct anv_sparse_submission *submit)
{
return xe_vm_bind_op(device, submit);
return xe_vm_bind_op(device, submit, false);
}
static int xe_vm_bind_bo(struct anv_device *device, struct anv_bo *bo)
@ -278,7 +285,7 @@ static int xe_vm_bind_bo(struct anv_device *device, struct anv_bo *bo)
.wait_count = 0,
.signal_count = 0,
};
return xe_vm_bind_op(device, &submit);
return xe_vm_bind_op(device, &submit, true);
}
static int xe_vm_unbind_bo(struct anv_device *device, struct anv_bo *bo)
@ -298,7 +305,7 @@ static int xe_vm_unbind_bo(struct anv_device *device, struct anv_bo *bo)
.wait_count = 0,
.signal_count = 0,
};
return xe_vm_bind_op(device, &submit);
return xe_vm_bind_op(device, &submit, true);
}
static uint32_t