Commit a221f970 authored by Eric Anholt's avatar Eric Anholt

v3d: Fix incorrect handling of two fences created back-to-back.

Recreating our context's syncobj with ALREADY_SIGNALED meant that if you
created two fences in a row, then waiting on the second would succeed
immediately.  Instead, export a sync file in the gallium fence (since we
don't have a syncobj clone ioctl), and just create a new syncobj to wait
on whenever we need to.

Noticed while debugging
parent fc28692a
......@@ -42,7 +42,7 @@
struct v3d_fence {
struct pipe_reference reference;
uint32_t sync;
int fd;
static void
......@@ -50,13 +50,12 @@ v3d_fence_reference(struct pipe_screen *pscreen,
struct pipe_fence_handle **pp,
struct pipe_fence_handle *pf)
struct v3d_screen *screen = v3d_screen(pscreen);
struct v3d_fence **p = (struct v3d_fence **)pp;
struct v3d_fence *f = (struct v3d_fence *)pf;
struct v3d_fence *old = *p;
if (pipe_reference(&(*p)->reference, &f->reference)) {
drmSyncobjDestroy(screen->fd, old->sync);
*p = f;
......@@ -70,12 +69,31 @@ v3d_fence_finish(struct pipe_screen *pscreen,
struct v3d_screen *screen = v3d_screen(pscreen);
struct v3d_fence *f = (struct v3d_fence *)pf;
int ret;
unsigned syncobj;
ret = drmSyncobjCreate(screen->fd, 0, &syncobj);
if (ret) {
fprintf(stderr, "Failed to create syncobj to wait on: %d\n",
return false;
drmSyncobjImportSyncFile(screen->fd, syncobj, f->fd);
if (ret) {
fprintf(stderr, "Failed to import fence to syncobj: %d\n", ret);
return false;
uint64_t abs_timeout = os_time_get_absolute_timeout(timeout_ns);
if (abs_timeout == OS_TIMEOUT_INFINITE)
abs_timeout = INT64_MAX;
return drmSyncobjWait(screen->fd, &f->sync, 1, abs_timeout,
0, NULL) >= 0;
ret = drmSyncobjWait(screen->fd, &syncobj, 1, abs_timeout, 0, NULL);
drmSyncobjDestroy(screen->fd, syncobj);
return ret >= 0;
struct v3d_fence *
......@@ -85,18 +103,19 @@ v3d_fence_create(struct v3d_context *v3d)
if (!f)
return NULL;
uint32_t new_sync;
/* Make a new sync object for the context. */
int ret = drmSyncobjCreate(v3d->fd, DRM_SYNCOBJ_CREATE_SIGNALED,
if (ret) {
/* Snapshot the last V3D rendering's 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).
drmSyncobjExportSyncFile(v3d->fd, v3d->out_sync, &f->fd);
if (f->fd == -1) {
fprintf(stderr, "export failed\n");
return NULL;
pipe_reference_init(&f->reference, 1);
f->sync = v3d->out_sync;
v3d->out_sync = new_sync;
return f;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment