v3dv: fix job serialization for single sync path

The idea in the single sync path is that we serialize any job that
needs to wait, however, our ANY queue syncobj only tracks the last job
submitted to any hardware queue, so in practice when we wait on this
we are only serializing against the queue to which we have submitted
the last job, which is not correct.

Fix that by accumulating the last job sync into the ANY queue synbcobj
to ensure that waiting on this syncobj effectively waits on all
hardware queues.

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
cc: mesa-stable

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20078>
This commit is contained in:
Iago Toral Quiroga 2022-12-01 11:02:12 +01:00 committed by Marge Bot
parent 95b9293eeb
commit 4276ec9f2a

View file

@ -413,6 +413,12 @@ handle_csd_indirect_cpu_job(struct v3dv_queue *queue,
return VK_SUCCESS;
}
/**
* This handles semaphore waits for the single sync path by accumulating
* wait semaphores into the QUEUE_ANY syncobj. Notice this is only required
* to ensure we accumulate any *external* semaphores (since for anything else
* we are already accumulating out syncs with each submission to the kernel).
*/
static VkResult
process_singlesync_waits(struct v3dv_queue *queue,
uint32_t count, struct vk_sync_wait *waits)
@ -677,6 +683,43 @@ fail:
return;
}
/* This must be called after every submission in the single-sync path to
* accumulate the out_sync into the QUEUE_ANY sync so we can serialize
* jobs by waiting on the QUEUE_ANY sync.
*/
static int
update_any_queue_sync(struct v3dv_queue *queue, uint32_t out_sync)
{
struct v3dv_device *device = queue->device;
assert(!device->pdevice->caps.multisync);
int render_fd = device->pdevice->render_fd;
int fd_any = -1, fd_out_sync = -1;
int err;
err = drmSyncobjExportSyncFile(render_fd,
queue->last_job_syncs.syncs[V3DV_QUEUE_ANY],
&fd_any);
if (err)
goto fail;
err = drmSyncobjExportSyncFile(render_fd, out_sync, &fd_out_sync);
if (err)
goto fail;
err = sync_accumulate("v3dv", &fd_any, fd_out_sync);
if (err)
goto fail;
err = drmSyncobjImportSyncFile(render_fd,
queue->last_job_syncs.syncs[V3DV_QUEUE_ANY],
fd_any);
fail:
close(fd_any);
close(fd_out_sync);
return err;
}
static VkResult
handle_cl_job(struct v3dv_queue *queue,
struct v3dv_job *job,
@ -793,7 +836,7 @@ handle_cl_job(struct v3dv_queue *queue,
uint32_t last_job_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_ANY];
submit.in_sync_bcl = needs_bcl_sync ? last_job_sync : 0;
submit.in_sync_rcl = needs_rcl_sync ? last_job_sync : 0;
submit.out_sync = last_job_sync;
submit.out_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_CL];
}
v3dv_clif_dump(device, job, &submit);
@ -807,6 +850,9 @@ handle_cl_job(struct v3dv_queue *queue,
warned = true;
}
if (!device->pdevice->caps.multisync && ret == 0)
ret = update_any_queue_sync(queue, submit.out_sync);
free(bo_handles);
multisync_free(device, &ms);
@ -846,11 +892,14 @@ handle_tfu_job(struct v3dv_queue *queue,
} else {
uint32_t last_job_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_ANY];
job->tfu.in_sync = needs_sync ? last_job_sync : 0;
job->tfu.out_sync = last_job_sync;
job->tfu.out_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_TFU];
}
int ret = v3dv_ioctl(device->pdevice->render_fd,
DRM_IOCTL_V3D_SUBMIT_TFU, &job->tfu);
if (!device->pdevice->caps.multisync && ret == 0)
ret = update_any_queue_sync(queue, job->tfu.out_sync);
multisync_free(device, &ms);
queue->last_job_syncs.first[V3DV_QUEUE_TFU] = false;
@ -913,7 +962,7 @@ handle_csd_job(struct v3dv_queue *queue,
} else {
uint32_t last_job_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_ANY];
submit->in_sync = needs_sync ? last_job_sync : 0;
submit->out_sync = last_job_sync;
submit->out_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_CSD];
}
submit->perfmon_id = job->perf ?
job->perf->kperfmon_ids[counter_pass_idx] : 0;
@ -928,6 +977,9 @@ handle_csd_job(struct v3dv_queue *queue,
warned = true;
}
if (!device->pdevice->caps.multisync && ret == 0)
ret = update_any_queue_sync(queue, submit->out_sync);
free(bo_handles);
multisync_free(device, &ms);