panfrost: Use the per-batch fences to wait on the last submitted batch
We just replace the per-context out_sync object by a pointer to the the fence of the last last submitted batch. Pipelining of batches will come later. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
@@ -2696,12 +2696,6 @@ panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
|
|||||||
panfrost_blend_context_init(gallium);
|
panfrost_blend_context_init(gallium);
|
||||||
panfrost_compute_context_init(gallium);
|
panfrost_compute_context_init(gallium);
|
||||||
|
|
||||||
ASSERTED int ret;
|
|
||||||
|
|
||||||
ret = drmSyncobjCreate(pscreen->fd, DRM_SYNCOBJ_CREATE_SIGNALED,
|
|
||||||
&ctx->out_sync);
|
|
||||||
assert(!ret);
|
|
||||||
|
|
||||||
/* XXX: leaks */
|
/* XXX: leaks */
|
||||||
gallium->stream_uploader = u_upload_create_default(gallium);
|
gallium->stream_uploader = u_upload_create_default(gallium);
|
||||||
gallium->const_uploader = gallium->stream_uploader;
|
gallium->const_uploader = gallium->stream_uploader;
|
||||||
|
@@ -191,7 +191,8 @@ struct panfrost_context {
|
|||||||
/* True for t6XX, false for t8xx. */
|
/* True for t6XX, false for t8xx. */
|
||||||
bool is_t6xx;
|
bool is_t6xx;
|
||||||
|
|
||||||
uint32_t out_sync;
|
/* The out sync fence of the last submitted batch. */
|
||||||
|
struct panfrost_batch_fence *last_out_sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Corresponds to the CSO */
|
/* Corresponds to the CSO */
|
||||||
|
@@ -425,11 +425,13 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
|
|||||||
uint32_t *bo_handles;
|
uint32_t *bo_handles;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
submit.in_syncs = (u64) (uintptr_t) &ctx->out_sync;
|
|
||||||
submit.in_sync_count = 1;
|
|
||||||
|
|
||||||
submit.out_sync = ctx->out_sync;
|
if (ctx->last_out_sync) {
|
||||||
|
submit.in_sync_count = 1;
|
||||||
|
submit.in_syncs = (uintptr_t)&ctx->last_out_sync->syncobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
submit.out_sync = batch->out_sync->syncobj;
|
||||||
submit.jc = first_job_desc;
|
submit.jc = first_job_desc;
|
||||||
submit.requirements = reqs;
|
submit.requirements = reqs;
|
||||||
|
|
||||||
@@ -445,6 +447,14 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
|
|||||||
submit.bo_handles = (u64) (uintptr_t) bo_handles;
|
submit.bo_handles = (u64) (uintptr_t) bo_handles;
|
||||||
ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);
|
ret = drmIoctl(screen->fd, DRM_IOCTL_PANFROST_SUBMIT, &submit);
|
||||||
free(bo_handles);
|
free(bo_handles);
|
||||||
|
|
||||||
|
/* Release the last batch fence if any, and retain the new one */
|
||||||
|
if (ctx->last_out_sync)
|
||||||
|
panfrost_batch_fence_unreference(ctx->last_out_sync);
|
||||||
|
|
||||||
|
panfrost_batch_fence_reference(batch->out_sync);
|
||||||
|
ctx->last_out_sync = batch->out_sync;
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Error submitting: %m\n");
|
fprintf(stderr, "Error submitting: %m\n");
|
||||||
return errno;
|
return errno;
|
||||||
@@ -453,7 +463,8 @@ panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
|
|||||||
/* Trace the job if we're doing that */
|
/* Trace the job if we're doing that */
|
||||||
if (pan_debug & PAN_DBG_TRACE) {
|
if (pan_debug & PAN_DBG_TRACE) {
|
||||||
/* Wait so we can get errors reported back */
|
/* Wait so we can get errors reported back */
|
||||||
drmSyncobjWait(screen->fd, &ctx->out_sync, 1, INT64_MAX, 0, NULL);
|
drmSyncobjWait(screen->fd, &batch->out_sync->syncobj, 1,
|
||||||
|
INT64_MAX, 0, NULL);
|
||||||
pandecode_jc(submit.jc, FALSE);
|
pandecode_jc(submit.jc, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,6 +506,15 @@ panfrost_batch_submit(struct panfrost_batch *batch)
|
|||||||
* to wait on it.
|
* to wait on it.
|
||||||
*/
|
*/
|
||||||
batch->out_sync->signaled = true;
|
batch->out_sync->signaled = true;
|
||||||
|
|
||||||
|
/* Release the last batch fence if any, and set ->last_out_sync
|
||||||
|
* to NULL
|
||||||
|
*/
|
||||||
|
if (ctx->last_out_sync) {
|
||||||
|
panfrost_batch_fence_unreference(ctx->last_out_sync);
|
||||||
|
ctx->last_out_sync = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,8 +547,11 @@ out:
|
|||||||
* rendering is quite broken right now (to be fixed by the panfrost_job
|
* rendering is quite broken right now (to be fixed by the panfrost_job
|
||||||
* refactor, just take the perf hit for correctness)
|
* refactor, just take the perf hit for correctness)
|
||||||
*/
|
*/
|
||||||
drmSyncobjWait(pan_screen(ctx->base.screen)->fd, &ctx->out_sync, 1,
|
if (!batch->out_sync->signaled)
|
||||||
INT64_MAX, 0, NULL);
|
drmSyncobjWait(pan_screen(ctx->base.screen)->fd,
|
||||||
|
&batch->out_sync->syncobj, 1, INT64_MAX, 0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
panfrost_free_batch(batch);
|
panfrost_free_batch(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -590,8 +590,12 @@ panfrost_fence_finish(struct pipe_screen *pscreen,
|
|||||||
struct panfrost_screen *screen = pan_screen(pscreen);
|
struct panfrost_screen *screen = pan_screen(pscreen);
|
||||||
struct panfrost_fence *f = (struct panfrost_fence *)fence;
|
struct panfrost_fence *f = (struct panfrost_fence *)fence;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
unsigned syncobj;
|
unsigned syncobj;
|
||||||
|
|
||||||
|
/* The fence was already signaled */
|
||||||
|
if (f->fd == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
ret = drmSyncobjCreate(screen->fd, 0, &syncobj);
|
ret = drmSyncobjCreate(screen->fd, 0, &syncobj);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Failed to create syncobj to wait on: %m\n");
|
fprintf(stderr, "Failed to create syncobj to wait on: %m\n");
|
||||||
@@ -623,18 +627,28 @@ panfrost_fence_create(struct panfrost_context *ctx)
|
|||||||
if (!f)
|
if (!f)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
f->fd = -1;
|
||||||
|
|
||||||
|
/* There was no job flushed yet or the batch fence was already
|
||||||
|
* signaled, let's return a dummy fence object that returns true
|
||||||
|
* directly when ->fence_finish() is called.
|
||||||
|
*/
|
||||||
|
if (!ctx->last_out_sync || ctx->last_out_sync->signaled)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Snapshot the last Panfrost's rendering's out fence. We'd rather have
|
/* Snapshot the last Panfrost's rendering's out fence. We'd rather have
|
||||||
* another syncobj instead of a sync file, but this is all we get.
|
* another syncobj instead of a sync file, but this is all we get.
|
||||||
* (HandleToFD/FDToHandle just gives you another syncobj ID for the
|
* (HandleToFD/FDToHandle just gives you another syncobj ID for the
|
||||||
* same syncobj).
|
* same syncobj).
|
||||||
*/
|
*/
|
||||||
drmSyncobjExportSyncFile(screen->fd, ctx->out_sync, &f->fd);
|
drmSyncobjExportSyncFile(screen->fd, ctx->last_out_sync->syncobj, &f->fd);
|
||||||
if (f->fd == -1) {
|
if (f->fd == -1) {
|
||||||
fprintf(stderr, "export failed: %m\n");
|
fprintf(stderr, "export failed: %m\n");
|
||||||
free(f);
|
free(f);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
pipe_reference_init(&f->reference, 1);
|
pipe_reference_init(&f->reference, 1);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
|
Reference in New Issue
Block a user