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
dEQP-GLES3.functional.fence_sync.client_wait_sync_finish
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);
close(old->fd);
free(old);
}
*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",
ret);
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,
&new_sync);
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");
free(f);
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