From: Thierry Reding <tred...@nvidia.com> Implements fence FDs based on new libdrm API and the accompanying IOCTL.
Signed-off-by: Thierry Reding <tred...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev