summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-07-09 12:41:46 -0700
committerEric Anholt <[email protected]>2018-07-20 11:11:29 -0700
commita221f9709efeaf0ac901c7b0568e8aa311aa1b96 (patch)
tree2a63be1670bbca761fbc141936eb86afeb05ddde /src
parentfc28692a5af22754818e2eda20409f9502daa088 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/v3d/v3d_fence.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/src/gallium/drivers/v3d/v3d_fence.c b/src/gallium/drivers/v3d/v3d_fence.c
index f07ea17b0d3..0edcb66d911 100644
--- a/src/gallium/drivers/v3d/v3d_fence.c
+++ b/src/gallium/drivers/v3d/v3d_fence.c
@@ -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;
}