{
struct panfrost_context *ctx = pan_context(pipe);
struct panfrost_device *dev = pan_device(pipe->screen);
- uint32_t syncobj = 0;
- if (fence)
- drmSyncobjCreate(dev->fd, 0, &syncobj);
/* Submit all pending jobs */
- panfrost_flush_all_batches(ctx, syncobj);
+ panfrost_flush_all_batches(ctx);
if (fence) {
- struct panfrost_fence *f = panfrost_fence_create(ctx, syncobj);
+ struct panfrost_fence *f = panfrost_fence_create(ctx);
pipe->screen->fence_reference(pipe->screen, fence, NULL);
*fence = (struct pipe_fence_handle *)f;
}
panfrost_texture_barrier(struct pipe_context *pipe, unsigned flags)
{
struct panfrost_context *ctx = pan_context(pipe);
- panfrost_flush_all_batches(ctx, 0);
+ panfrost_flush_all_batches(ctx);
}
#define DEFINE_CASE(c) case PIPE_PRIM_##c: return MALI_DRAW_MODE_##c;
case PIPE_QUERY_PRIMITIVES_GENERATED:
case PIPE_QUERY_PRIMITIVES_EMITTED:
- panfrost_flush_all_batches(ctx, 0);
+ panfrost_flush_all_batches(ctx);
vresult->u64 = query->end - query->start;
break;
ctx->sample_mask = ~0;
ctx->active_queries = true;
+ int ASSERTED ret;
+
+ /* Create a syncobj in a signaled state. Will be updated to point to the
+ * last queued job out_sync every time we submit a new job.
+ */
+ ret = drmSyncobjCreate(dev->fd, DRM_SYNCOBJ_CREATE_SIGNALED, &ctx->syncobj);
+ assert(!ret && ctx->syncobj);
+
return gallium;
}
panfrost_batch_submit_ioctl(struct panfrost_batch *batch,
mali_ptr first_job_desc,
uint32_t reqs,
+ uint32_t in_sync,
uint32_t out_sync)
{
struct panfrost_context *ctx = batch->ctx;
* after we're done but preventing double-frees if we were given a
* syncobj */
- bool our_sync = false;
-
- if (!out_sync && dev->debug & (PAN_DBG_TRACE | PAN_DBG_SYNC)) {
- drmSyncobjCreate(dev->fd, 0, &out_sync);
- our_sync = true;
- }
+ if (!out_sync && dev->debug & (PAN_DBG_TRACE | PAN_DBG_SYNC))
+ out_sync = ctx->syncobj;
submit.out_sync = out_sync;
submit.jc = first_job_desc;
submit.requirements = reqs;
+ if (in_sync) {
+ submit.in_syncs = (u64)(uintptr_t)(&in_sync);
+ submit.in_sync_count = 1;
+ }
bo_handles = calloc(panfrost_pool_num_bos(&batch->pool) +
panfrost_pool_num_bos(&batch->invisible_pool) +
if (dev->debug & PAN_DBG_MSGS)
fprintf(stderr, "Error submitting: %m\n");
- if (our_sync)
- drmSyncobjDestroy(dev->fd, out_sync);
-
return errno;
}
pandecode_jc(submit.jc, dev->quirks & IS_BIFROST, dev->gpu_id, minimal);
}
- /* Cleanup if we created the syncobj */
- if (our_sync)
- drmSyncobjDestroy(dev->fd, out_sync);
-
return 0;
}
* implicit dep between them) */
static int
-panfrost_batch_submit_jobs(struct panfrost_batch *batch, uint32_t out_sync)
+panfrost_batch_submit_jobs(struct panfrost_batch *batch, uint32_t in_sync, uint32_t out_sync)
{
bool has_draws = batch->scoreboard.first_job;
bool has_frag = batch->scoreboard.tiler_dep || batch->clear;
if (has_draws) {
ret = panfrost_batch_submit_ioctl(batch, batch->scoreboard.first_job,
- 0, has_frag ? 0 : out_sync);
+ 0, in_sync, has_frag ? 0 : out_sync);
assert(!ret);
}
mali_ptr fragjob = panfrost_fragment_job(batch,
batch->scoreboard.tiler_dep != 0);
ret = panfrost_batch_submit_ioctl(batch, fragjob,
- PANFROST_JD_REQ_FS, out_sync);
+ PANFROST_JD_REQ_FS, 0,
+ out_sync);
assert(!ret);
}
}
static void
-panfrost_batch_submit(struct panfrost_batch *batch, uint32_t out_sync)
+panfrost_batch_submit(struct panfrost_batch *batch,
+ uint32_t in_sync, uint32_t out_sync)
{
assert(batch);
struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
util_dynarray_foreach(&batch->dependencies,
struct panfrost_batch_fence *, dep) {
if ((*dep)->batch)
- panfrost_batch_submit((*dep)->batch, 0);
+ panfrost_batch_submit((*dep)->batch, 0, 0);
}
int ret;
/* Nothing to do! */
- if (!batch->scoreboard.first_job && !batch->clear) {
- if (out_sync)
- drmSyncobjSignal(dev->fd, &out_sync, 1);
+ if (!batch->scoreboard.first_job && !batch->clear)
goto out;
- }
panfrost_batch_draw_wallpaper(batch);
panfrost_scoreboard_initialize_tiler(&batch->pool, &batch->scoreboard, polygon_list);
- ret = panfrost_batch_submit_jobs(batch, out_sync);
+ ret = panfrost_batch_submit_jobs(batch, in_sync, out_sync);
if (ret && dev->debug & PAN_DBG_MSGS)
fprintf(stderr, "panfrost_batch_submit failed: %d\n", ret);
/* Submit all batches, applying the out_sync to the currently bound batch */
void
-panfrost_flush_all_batches(struct panfrost_context *ctx, uint32_t out_sync)
+panfrost_flush_all_batches(struct panfrost_context *ctx)
{
struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
- panfrost_batch_submit(batch, out_sync);
+ panfrost_batch_submit(batch, ctx->syncobj, ctx->syncobj);
hash_table_foreach(ctx->batches, hentry) {
struct panfrost_batch *batch = hentry->data;
assert(batch);
- panfrost_batch_submit(batch, 0);
+ panfrost_batch_submit(batch, ctx->syncobj, ctx->syncobj);
}
assert(!ctx->batches->entries);
return;
if (access->writer && access->writer->batch)
- panfrost_batch_submit(access->writer->batch, 0);
+ panfrost_batch_submit(access->writer->batch, ctx->syncobj, ctx->syncobj);
if (!flush_readers)
return;
util_dynarray_foreach(&access->readers, struct panfrost_batch_fence *,
reader) {
if (*reader && (*reader)->batch)
- panfrost_batch_submit((*reader)->batch, 0);
+ panfrost_batch_submit((*reader)->batch, ctx->syncobj, ctx->syncobj);
}
}
}
struct panfrost_fence *
-panfrost_fence_create(struct panfrost_context *ctx,
- uint32_t syncobj)
+panfrost_fence_create(struct panfrost_context *ctx)
{
struct panfrost_fence *f = calloc(1, sizeof(*f));
if (!f)
return NULL;
+ struct panfrost_device *dev = pan_device(ctx->base.screen);
+ int fd = -1, ret;
+
+ /* Snapshot the last rendering out fence. We'd rather have another
+ * syncobj instead of a sync file, but this is all we get.
+ * (HandleToFD/FDToHandle just gives you another syncobj ID for the
+ * same syncobj).
+ */
+ ret = drmSyncobjExportSyncFile(dev->fd, ctx->syncobj, &fd);
+ if (ret || fd == -1) {
+ fprintf(stderr, "export failed\n");
+ goto err_free_fence;
+ }
+
+ ret = drmSyncobjCreate(dev->fd, 0, &f->syncobj);
+ if (ret) {
+ fprintf(stderr, "create syncobj failed\n");
+ goto err_close_fd;
+ }
+
+ ret = drmSyncobjImportSyncFile(dev->fd, f->syncobj, fd);
+ if (ret) {
+ fprintf(stderr, "create syncobj failed\n");
+ goto err_destroy_syncobj;
+ }
+
+ assert(f->syncobj != ctx->syncobj);
+ close(fd);
pipe_reference_init(&f->reference, 1);
- f->syncobj = syncobj;
return f;
+
+err_destroy_syncobj:
+ drmSyncobjDestroy(dev->fd, f->syncobj);
+err_close_fd:
+ close(fd);
+err_free_fence:
+ free(f);
+ return NULL;
}
static const void *