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

Reply via email to