[Mesa-dev] [PATCH] nouveau: Support fence FDs
Thierry Reding
thierry.reding at gmail.com
Thu Jan 11 22:30:04 UTC 2018
From: Thierry Reding <treding at nvidia.com>
Implements fence FDs based on new libdrm API and the accompanying IOCTL.
Signed-off-by: Thierry Reding <treding at nvidia.com>
---
For the kernel patches that add the new IOCTL, see the series at:
https://patchwork.freedesktop.org/series/36361/
The libdrm patch that adds the new API is here:
https://patchwork.freedesktop.org/series/36366/
src/gallium/drivers/nouveau/nouveau_context.h | 5 ++++
src/gallium/drivers/nouveau/nouveau_fence.c | 18 ++++++++++---
src/gallium/drivers/nouveau/nouveau_fence.h | 2 ++
src/gallium/drivers/nouveau/nouveau_screen.c | 36 +++++++++++++++++++++++++
src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 18 ++++++++++---
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 2 +-
6 files changed, 73 insertions(+), 8 deletions(-)
diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h
index c3bbb11bd604..0e40ad2f1046 100644
--- a/src/gallium/drivers/nouveau/nouveau_context.h
+++ b/src/gallium/drivers/nouveau/nouveau_context.h
@@ -54,6 +54,8 @@ struct nouveau_context {
uint32_t buf_cache_count;
uint32_t buf_cache_frame;
} stats;
+
+ int in_fence_fd;
};
static inline struct nouveau_context *
@@ -99,6 +101,9 @@ nouveau_context_destroy(struct nouveau_context *ctx)
if (ctx->scratch.bo[i])
nouveau_bo_ref(NULL, &ctx->scratch.bo[i]);
+ if (ctx->in_fence_fd >= 0)
+ close(ctx->in_fence_fd);
+
FREE(ctx);
}
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c
index d14c59b2dd15..b508b9b7163f 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.c
+++ b/src/gallium/drivers/nouveau/nouveau_fence.c
@@ -30,7 +30,8 @@
#endif
bool
-nouveau_fence_new(struct nouveau_screen *screen, struct nouveau_fence **fence)
+nouveau_fence_fd(struct nouveau_screen *screen, struct nouveau_fence **fence,
+ int fd)
{
*fence = CALLOC_STRUCT(nouveau_fence);
if (!*fence)
@@ -38,11 +39,18 @@ nouveau_fence_new(struct nouveau_screen *screen, struct nouveau_fence **fence)
(*fence)->screen = screen;
(*fence)->ref = 1;
+ (*fence)->fd = dup(fd);
LIST_INITHEAD(&(*fence)->work);
return true;
}
+bool
+nouveau_fence_new(struct nouveau_screen *screen, struct nouveau_fence **fence)
+{
+ return nouveau_fence_fd(screen, fence, -1);
+}
+
static void
nouveau_fence_trigger_work(struct nouveau_fence *fence)
{
@@ -105,6 +113,9 @@ nouveau_fence_del(struct nouveau_fence *fence)
nouveau_fence_trigger_work(fence);
}
+ if (fence->fd >= 0)
+ close(fence->fd);
+
FREE(fence);
}
@@ -175,9 +186,10 @@ nouveau_fence_kick(struct nouveau_fence *fence)
nouveau_fence_emit(fence);
}
- if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED)
- if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel))
+ if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED) {
+ if (nouveau_pushbuf_kick_fence(screen->pushbuf, screen->pushbuf->channel, &fence->fd))
return false;
+ }
if (fence == screen->fence.current)
nouveau_fence_next(screen);
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h
index e14572bce8f9..83a33c5af24b 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.h
+++ b/src/gallium/drivers/nouveau/nouveau_fence.h
@@ -24,6 +24,7 @@ struct nouveau_fence {
struct nouveau_screen *screen;
int state;
int ref;
+ int fd;
uint32_t sequence;
uint32_t work_count;
struct list_head work;
@@ -32,6 +33,7 @@ struct nouveau_fence {
void nouveau_fence_emit(struct nouveau_fence *);
void nouveau_fence_del(struct nouveau_fence *);
+bool nouveau_fence_fd(struct nouveau_screen *, struct nouveau_fence **, int);
bool nouveau_fence_new(struct nouveau_screen *, struct nouveau_fence **);
bool nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *);
void nouveau_fence_update(struct nouveau_screen *, bool flushed);
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index c144b39b2dd2..f40932b5defe 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -1,3 +1,5 @@
+#include <libsync.h>
+
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
@@ -86,6 +88,14 @@ nouveau_screen_fence_finish(struct pipe_screen *screen,
return nouveau_fence_wait(nouveau_fence(pfence), NULL);
}
+static int
+nouveau_screen_fence_get_fd(struct pipe_screen *screen,
+ struct pipe_fence_handle *pfence)
+{
+ struct nouveau_fence *fence = nouveau_fence(pfence);
+
+ return dup(fence->fd);
+}
struct nouveau_bo *
nouveau_screen_bo_from_handle(struct pipe_screen *pscreen,
@@ -239,6 +249,7 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
pscreen->fence_reference = nouveau_screen_fence_ref;
pscreen->fence_finish = nouveau_screen_fence_finish;
+ pscreen->fence_get_fd = nouveau_screen_fence_get_fd;
nouveau_disk_cache_create(screen);
@@ -296,8 +307,33 @@ nouveau_set_debug_callback(struct pipe_context *pipe,
memset(&context->debug, 0, sizeof(context->debug));
}
+static void
+nouveau_create_fence_fd(struct pipe_context *pipe,
+ struct pipe_fence_handle **pfence,
+ int fd)
+{
+ struct nouveau_screen *screen = nouveau_screen(pipe->screen);
+
+ nouveau_fence_fd(screen, (struct nouveau_fence **)pfence, fd);
+}
+
+static void
+nouveau_fence_server_sync(struct pipe_context *pipe,
+ struct pipe_fence_handle *pfence)
+{
+ struct nouveau_context *context = nouveau_context(pipe);
+ struct nouveau_fence *fence = nouveau_fence(pfence);
+
+ sync_accumulate("nouveau", &context->in_fence_fd, fence->fd);
+}
+
void
nouveau_context_init(struct nouveau_context *context)
{
+ context->in_fence_fd = -1;
+
context->pipe.set_debug_callback = nouveau_set_debug_callback;
+
+ context->pipe.create_fence_fd = nouveau_create_fence_fd;
+ context->pipe.fence_server_sync = nouveau_fence_server_sync;
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
index 2e4490b8d976..dfca894ca926 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
@@ -30,16 +30,26 @@
static void
nvc0_flush(struct pipe_context *pipe,
- struct pipe_fence_handle **fence,
+ struct pipe_fence_handle **pfence,
unsigned flags)
{
struct nvc0_context *nvc0 = nvc0_context(pipe);
struct nouveau_screen *screen = &nvc0->screen->base;
- if (fence)
- nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
+ if (pfence)
+ nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)pfence);
- PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */
+ if (flags & PIPE_FLUSH_FENCE_FD) {
+ struct nouveau_fence *fence = screen->fence.current;
+ struct nouveau_pushbuf *pushbuf = nvc0->base.pushbuf;
+ struct nouveau_object *channel = pushbuf->channel;
+ int fd = nvc0->base.in_fence_fd;
+
+ nouveau_pushbuf_kick_fence(pushbuf, channel, &fd);
+ fence->fd = fd;
+ } else {
+ PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */
+ }
nouveau_context_update_frame_stats(&nvc0->base);
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index d911884f78e2..6d1b491bf4e2 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -257,6 +257,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_COMPUTE:
case PIPE_CAP_CAN_BIND_CONST_BUFFER_AS_VERTEX:
case PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION:
+ case PIPE_CAP_NATIVE_FENCE_FD:
return 1;
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
return nouveau_screen(pscreen)->vram_domain & NOUVEAU_BO_VRAM ? 1 : 0;
@@ -297,7 +298,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_PCI_FUNCTION:
case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS:
case PIPE_CAP_TGSI_CAN_READ_OUTPUTS:
- case PIPE_CAP_NATIVE_FENCE_FD:
case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
--
2.15.1
More information about the mesa-dev
mailing list