[Mesa-dev] [PATCH 6/7] nouveau: make fence API independent from nouveau_screen

Karol Herbst kherbst at redhat.com
Wed Dec 5 21:04:56 UTC 2018


Signed-off-by: Karol Herbst <kherbst at redhat.com>
---
 src/gallium/drivers/nouveau/nouveau_buffer.c  | 37 +++----
 src/gallium/drivers/nouveau/nouveau_buffer.h  |  2 +-
 src/gallium/drivers/nouveau/nouveau_fence.c   | 96 +++++++++----------
 src/gallium/drivers/nouveau/nouveau_fence.h   | 38 ++++++--
 src/gallium/drivers/nouveau/nouveau_screen.c  |  6 +-
 src/gallium/drivers/nouveau/nouveau_screen.h  | 12 +--
 .../drivers/nouveau/nv30/nv30_context.c       |  4 +-
 .../drivers/nouveau/nv30/nv30_miptree.c       |  2 +-
 .../drivers/nouveau/nv30/nv30_screen.c        | 17 ++--
 src/gallium/drivers/nouveau/nv30/nv30_vbo.c   |  2 +-
 .../drivers/nouveau/nv50/nv50_compute.c       |  2 +-
 .../drivers/nouveau/nv50/nv50_context.c       |  4 +-
 .../drivers/nouveau/nv50/nv50_miptree.c       |  2 +-
 .../drivers/nouveau/nv50/nv50_query_hw.c      |  2 +-
 .../drivers/nouveau/nv50/nv50_screen.c        | 22 ++---
 .../drivers/nouveau/nv50/nv50_transfer.c      |  2 +-
 src/gallium/drivers/nouveau/nv50/nv50_vbo.c   |  4 +-
 .../drivers/nouveau/nvc0/nvc0_context.c       |  4 +-
 .../drivers/nouveau/nvc0/nvc0_query_hw.c      |  6 +-
 .../drivers/nouveau/nvc0/nvc0_screen.c        | 25 +++--
 .../drivers/nouveau/nvc0/nvc0_transfer.c      |  6 +-
 src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c   |  2 +-
 22 files changed, 157 insertions(+), 140 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c
index 97305d993ff..03f214dae4c 100644
--- a/src/gallium/drivers/nouveau/nouveau_buffer.c
+++ b/src/gallium/drivers/nouveau/nouveau_buffer.c
@@ -69,24 +69,25 @@ nouveau_buffer_allocate(struct nouveau_screen *screen,
 
 static inline void
 release_allocation(struct nouveau_mm_allocation **mm,
-                   struct nouveau_fence *fence)
+                   struct nouveau_fence *fence,
+                   struct nouveau_pushbuf *push)
 {
-   nouveau_fence_work(fence, nouveau_mm_free_work, *mm);
+   nouveau_fence_work(fence, push, nouveau_mm_free_work, *mm);
    (*mm) = NULL;
 }
 
 inline void
-nouveau_buffer_release_gpu_storage(struct nv04_resource *buf)
+nouveau_buffer_release_gpu_storage(struct nouveau_pushbuf *push, struct nv04_resource *buf)
 {
    if (buf->fence && buf->fence->state < NOUVEAU_FENCE_STATE_FLUSHED) {
-      nouveau_fence_work(buf->fence, nouveau_fence_unref_bo, buf->bo);
+      nouveau_fence_work(buf->fence, push, nouveau_fence_unref_bo, buf->bo);
       buf->bo = NULL;
    } else {
       nouveau_bo_ref(NULL, &buf->bo);
    }
 
    if (buf->mm)
-      release_allocation(&buf->mm, buf->fence);
+      release_allocation(&buf->mm, buf->fence, push);
 
    if (buf->domain == NOUVEAU_BO_VRAM)
       NOUVEAU_DRV_STAT_RES(buf, buf_obj_current_bytes_vid, -(uint64_t)buf->base.width0);
@@ -97,10 +98,10 @@ nouveau_buffer_release_gpu_storage(struct nv04_resource *buf)
 }
 
 static inline bool
-nouveau_buffer_reallocate(struct nouveau_screen *screen,
+nouveau_buffer_reallocate(struct nouveau_screen *screen, struct nouveau_pushbuf *push,
                           struct nv04_resource *buf, unsigned domain)
 {
-   nouveau_buffer_release_gpu_storage(buf);
+   nouveau_buffer_release_gpu_storage(push, buf);
 
    nouveau_fence_ref(NULL, &buf->fence);
    nouveau_fence_ref(NULL, &buf->fence_wr);
@@ -116,7 +117,7 @@ nouveau_buffer_destroy(struct pipe_screen *pscreen,
 {
    struct nv04_resource *res = nv04_resource(presource);
 
-   nouveau_buffer_release_gpu_storage(res);
+   nouveau_buffer_release_gpu_storage(nouveau_screen(pscreen)->pushbuf, res);
 
    if (res->data && !(res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY))
       align_free(res->data);
@@ -231,14 +232,14 @@ nouveau_buffer_sync(struct nouveau_context *nv,
          return true;
       NOUVEAU_DRV_STAT_RES(buf, buf_non_kernel_fence_sync_count,
                            !nouveau_fence_signalled(buf->fence_wr));
-      if (!nouveau_fence_wait(buf->fence_wr, &nv->debug))
+      if (!nouveau_fence_wait(buf->fence_wr, nv->pushbuf, &nv->debug))
          return false;
    } else {
       if (!buf->fence)
          return true;
       NOUVEAU_DRV_STAT_RES(buf, buf_non_kernel_fence_sync_count,
                            !nouveau_fence_signalled(buf->fence));
-      if (!nouveau_fence_wait(buf->fence, &nv->debug))
+      if (!nouveau_fence_wait(buf->fence, nv->pushbuf, &nv->debug))
          return false;
 
       nouveau_fence_ref(NULL, &buf->fence);
@@ -285,10 +286,10 @@ nouveau_buffer_transfer_del(struct nouveau_context *nv,
 {
    if (tx->map) {
       if (likely(tx->bo)) {
-         nouveau_fence_work(nv->screen->fence.current,
+         nouveau_fence_work(nv->screen->fence.current, nv->pushbuf,
                             nouveau_fence_unref_bo, tx->bo);
          if (tx->mm)
-            release_allocation(&tx->mm, nv->screen->fence.current);
+            release_allocation(&tx->mm, nv->screen->fence.current, nv->pushbuf);
       } else {
          align_free(tx->map -
                     (tx->base.box.x & NOUVEAU_MIN_BUFFER_MAP_ALIGN_MASK));
@@ -442,7 +443,7 @@ nouveau_buffer_transfer_map(struct pipe_context *pipe,
 
    if (nouveau_buffer_should_discard(buf, usage)) {
       int ref = buf->base.reference.count - 1;
-      nouveau_buffer_reallocate(nv->screen, buf, buf->domain);
+      nouveau_buffer_reallocate(nv->screen, nv->pushbuf, buf, buf->domain);
       if (ref > 0) /* any references inside context possible ? */
          nv->invalidate_resource_storage(nv, &buf->base, ref);
    }
@@ -785,9 +786,9 @@ nouveau_buffer_migrate(struct nouveau_context *nv,
       nv->copy_data(nv, buf->bo, buf->offset, new_domain,
                     bo, offset, old_domain, buf->base.width0);
 
-      nouveau_fence_work(screen->fence.current, nouveau_fence_unref_bo, bo);
+      nouveau_fence_work(screen->fence.current, nv->pushbuf, nouveau_fence_unref_bo, bo);
       if (mm)
-         release_allocation(&mm, screen->fence.current);
+         release_allocation(&mm, screen->fence.current, nv->pushbuf);
    } else
    if (new_domain == NOUVEAU_BO_VRAM && old_domain == 0) {
       struct nouveau_transfer tx;
@@ -824,7 +825,7 @@ nouveau_user_buffer_upload(struct nouveau_context *nv,
    assert(buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY);
 
    buf->base.width0 = base + size;
-   if (!nouveau_buffer_reallocate(screen, buf, NOUVEAU_BO_GART))
+   if (!nouveau_buffer_reallocate(screen, nv->pushbuf, buf, NOUVEAU_BO_GART))
       return false;
 
    ret = nouveau_bo_map(buf->bo, 0, nv->client);
@@ -862,7 +863,7 @@ nouveau_buffer_invalidate(struct pipe_context *pipe,
    if (buf->mm && !nouveau_buffer_busy(buf, PIPE_TRANSFER_WRITE)) {
       util_range_set_empty(&buf->valid_buffer_range);
    } else {
-      nouveau_buffer_reallocate(nv->screen, buf, buf->domain);
+      nouveau_buffer_reallocate(nv->screen, nv->pushbuf, buf, buf->domain);
       if (ref > 0) /* any references inside context possible ? */
          nv->invalidate_resource_storage(nv, &buf->base, ref);
    }
@@ -897,7 +898,7 @@ nouveau_scratch_runout_release(struct nouveau_context *nv)
    if (!nv->scratch.runout)
       return;
 
-   if (!nouveau_fence_work(nv->screen->fence.current, nouveau_scratch_unref_bos,
+   if (!nouveau_fence_work(nv->screen->fence.current, nv->pushbuf, nouveau_scratch_unref_bos,
          nv->scratch.runout))
       return;
 
diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.h b/src/gallium/drivers/nouveau/nouveau_buffer.h
index 3a33fae9ce2..836778892ba 100644
--- a/src/gallium/drivers/nouveau/nouveau_buffer.h
+++ b/src/gallium/drivers/nouveau/nouveau_buffer.h
@@ -53,7 +53,7 @@ struct nv04_resource {
 };
 
 void
-nouveau_buffer_release_gpu_storage(struct nv04_resource *);
+nouveau_buffer_release_gpu_storage(struct nouveau_pushbuf *push, struct nv04_resource *);
 
 void
 nouveau_copy_buffer(struct nouveau_context *,
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c
index d14c59b2dd1..97a7223f950 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.c
+++ b/src/gallium/drivers/nouveau/nouveau_fence.c
@@ -30,13 +30,13 @@
 #endif
 
 bool
-nouveau_fence_new(struct nouveau_screen *screen, struct nouveau_fence **fence)
+nouveau_fence_new(struct nouveau_fence_list *list, struct nouveau_fence **fence)
 {
    *fence = CALLOC_STRUCT(nouveau_fence);
    if (!*fence)
       return false;
 
-   (*fence)->screen = screen;
+   (*fence)->list = list;
    (*fence)->ref = 1;
    LIST_INITHEAD(&(*fence)->work);
 
@@ -56,9 +56,9 @@ nouveau_fence_trigger_work(struct nouveau_fence *fence)
 }
 
 void
-nouveau_fence_emit(struct nouveau_fence *fence)
+nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_pushbuf *push)
 {
-   struct nouveau_screen *screen = fence->screen;
+   struct nouveau_fence_list *list = fence->list;
 
    assert(fence->state == NOUVEAU_FENCE_STATE_AVAILABLE);
 
@@ -67,14 +67,14 @@ nouveau_fence_emit(struct nouveau_fence *fence)
 
    ++fence->ref;
 
-   if (screen->fence.tail)
-      screen->fence.tail->next = fence;
+   if (list->tail)
+      list->tail->next = fence;
    else
-      screen->fence.head = fence;
+      list->head = fence;
 
-   screen->fence.tail = fence;
+   list->tail = fence;
 
-   screen->fence.emit(&screen->base, &fence->sequence);
+   list->emit(list, push, &fence->sequence);
 
    assert(fence->state == NOUVEAU_FENCE_STATE_EMITTING);
    fence->state = NOUVEAU_FENCE_STATE_EMITTED;
@@ -84,19 +84,19 @@ void
 nouveau_fence_del(struct nouveau_fence *fence)
 {
    struct nouveau_fence *it;
-   struct nouveau_screen *screen = fence->screen;
+   struct nouveau_fence_list *list = fence->list;
 
    if (fence->state == NOUVEAU_FENCE_STATE_EMITTED ||
        fence->state == NOUVEAU_FENCE_STATE_FLUSHED) {
-      if (fence == screen->fence.head) {
-         screen->fence.head = fence->next;
-         if (!screen->fence.head)
-            screen->fence.tail = NULL;
+      if (fence == list->head) {
+         list->head = fence->next;
+         if (!list->head)
+            list->tail = NULL;
       } else {
-         for (it = screen->fence.head; it && it->next != fence; it = it->next);
+         for (it = list->head; it && it->next != fence; it = it->next);
          it->next = fence->next;
-         if (screen->fence.tail == fence)
-            screen->fence.tail = it;
+         if (list->tail == fence)
+            list->tail = it;
       }
    }
 
@@ -109,17 +109,17 @@ nouveau_fence_del(struct nouveau_fence *fence)
 }
 
 void
-nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
+nouveau_fence_update(struct nouveau_fence_list *list, bool flushed)
 {
    struct nouveau_fence *fence;
    struct nouveau_fence *next = NULL;
-   u32 sequence = screen->fence.update(&screen->base);
+   u32 sequence = list->update(list);
 
-   if (screen->fence.sequence_ack == sequence)
+   if (list->sequence_ack == sequence)
       return;
-   screen->fence.sequence_ack = sequence;
+   list->sequence_ack = sequence;
 
-   for (fence = screen->fence.head; fence; fence = next) {
+   for (fence = list->head; fence; fence = next) {
       next = fence->next;
       sequence = fence->sequence;
 
@@ -128,12 +128,12 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
       nouveau_fence_trigger_work(fence);
       nouveau_fence_ref(NULL, &fence);
 
-      if (sequence == screen->fence.sequence_ack)
+      if (sequence == list->sequence_ack)
          break;
    }
-   screen->fence.head = next;
+   list->head = next;
    if (!next)
-      screen->fence.tail = NULL;
+      list->tail = NULL;
 
    if (flushed) {
       for (fence = next; fence; fence = fence->next)
@@ -147,57 +147,52 @@ nouveau_fence_update(struct nouveau_screen *screen, bool flushed)
 bool
 nouveau_fence_signalled(struct nouveau_fence *fence)
 {
-   struct nouveau_screen *screen = fence->screen;
-
    if (fence->state == NOUVEAU_FENCE_STATE_SIGNALLED)
       return true;
 
    if (fence->state >= NOUVEAU_FENCE_STATE_EMITTED)
-      nouveau_fence_update(screen, false);
+      nouveau_fence_update(fence->list, false);
 
    return fence->state == NOUVEAU_FENCE_STATE_SIGNALLED;
 }
 
 static bool
-nouveau_fence_kick(struct nouveau_fence *fence)
+nouveau_fence_kick(struct nouveau_fence *fence, struct nouveau_pushbuf *push)
 {
-   struct nouveau_screen *screen = fence->screen;
-
    /* wtf, someone is waiting on a fence in flush_notify handler? */
    assert(fence->state != NOUVEAU_FENCE_STATE_EMITTING);
 
    if (fence->state < NOUVEAU_FENCE_STATE_EMITTED) {
-      PUSH_SPACE(screen->pushbuf, 8);
+      PUSH_SPACE(push, 8);
       /* The space allocation might trigger a flush, which could emit the
        * current fence. So check again.
        */
       if (fence->state < NOUVEAU_FENCE_STATE_EMITTED)
-         nouveau_fence_emit(fence);
+         nouveau_fence_emit(fence, push);
    }
 
    if (fence->state < NOUVEAU_FENCE_STATE_FLUSHED)
-      if (nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel))
+      if (nouveau_pushbuf_kick(push, push->channel))
          return false;
 
-   if (fence == screen->fence.current)
-      nouveau_fence_next(screen);
+   if (fence == fence->list->current)
+      nouveau_fence_next(fence->list, push);
 
-   nouveau_fence_update(screen, false);
+   nouveau_fence_update(fence->list, false);
 
    return true;
 }
 
 bool
-nouveau_fence_wait(struct nouveau_fence *fence, struct pipe_debug_callback *debug)
+nouveau_fence_wait(struct nouveau_fence *fence, struct nouveau_pushbuf *push, struct pipe_debug_callback *debug)
 {
-   struct nouveau_screen *screen = fence->screen;
    uint32_t spins = 0;
    int64_t start = 0;
 
    if (debug && debug->debug_message)
       start = os_time_get_nano();
 
-   if (!nouveau_fence_kick(fence))
+   if (!nouveau_fence_kick(fence, push))
       return false;
 
    do {
@@ -209,36 +204,36 @@ nouveau_fence_wait(struct nouveau_fence *fence, struct pipe_debug_callback *debu
          return true;
       }
       if (!spins)
-         NOUVEAU_DRV_STAT(screen, any_non_kernel_fence_sync_count, 1);
+         NOUVEAU_DRV_STAT(fence->list->screen, any_non_kernel_fence_sync_count, 1);
       spins++;
 #ifdef PIPE_OS_UNIX
       if (!(spins % 8)) /* donate a few cycles */
          sched_yield();
 #endif
 
-      nouveau_fence_update(screen, false);
+      nouveau_fence_update(fence->list, false);
    } while (spins < NOUVEAU_FENCE_MAX_SPINS);
 
    debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n",
                 fence->sequence,
-                screen->fence.sequence_ack, screen->fence.sequence);
+                fence->list->sequence_ack, fence->list->sequence);
 
    return false;
 }
 
 void
-nouveau_fence_next(struct nouveau_screen *screen)
+nouveau_fence_next(struct nouveau_fence_list *list, struct nouveau_pushbuf *push)
 {
-   if (screen->fence.current->state < NOUVEAU_FENCE_STATE_EMITTING) {
-      if (screen->fence.current->ref > 1)
-         nouveau_fence_emit(screen->fence.current);
+   if (list->current->state < NOUVEAU_FENCE_STATE_EMITTING) {
+      if (list->current->ref > 1)
+         nouveau_fence_emit(list->current, push);
       else
          return;
    }
 
-   nouveau_fence_ref(NULL, &screen->fence.current);
+   nouveau_fence_ref(NULL, &list->current);
 
-   nouveau_fence_new(screen, &screen->fence.current);
+   nouveau_fence_new(list, &list->current);
 }
 
 void
@@ -251,6 +246,7 @@ nouveau_fence_unref_bo(void *data)
 
 bool
 nouveau_fence_work(struct nouveau_fence *fence,
+                   struct nouveau_pushbuf *push,
                    void (*func)(void *), void *data)
 {
    struct nouveau_fence_work *work;
@@ -268,6 +264,6 @@ nouveau_fence_work(struct nouveau_fence *fence,
    LIST_ADD(&work->list, &fence->work);
    p_atomic_inc(&fence->work_count);
    if (fence->work_count > 64)
-      nouveau_fence_kick(fence);
+      nouveau_fence_kick(fence, push);
    return true;
 }
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h
index e14572bce8f..d4c5f03b66f 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.h
+++ b/src/gallium/drivers/nouveau/nouveau_fence.h
@@ -13,6 +13,10 @@
 
 struct pipe_debug_callback;
 
+struct nouveau_fence_list;
+struct nouveau_pushbuf;
+struct nouveau_screen;
+
 struct nouveau_fence_work {
    struct list_head list;
    void (*func)(void *);
@@ -21,7 +25,7 @@ struct nouveau_fence_work {
 
 struct nouveau_fence {
    struct nouveau_fence *next;
-   struct nouveau_screen *screen;
+   struct nouveau_fence_list *list;
    int state;
    int ref;
    uint32_t sequence;
@@ -29,18 +33,38 @@ struct nouveau_fence {
    struct list_head work;
 };
 
-void nouveau_fence_emit(struct nouveau_fence *);
+struct nouveau_fence_list {
+   struct nouveau_fence *head;
+   struct nouveau_fence *tail;
+   struct nouveau_fence *current;
+
+   struct nouveau_screen *screen;
+   void *data;
+
+   uint32_t sequence;
+   uint32_t sequence_ack;
+   void (*emit)(struct nouveau_fence_list *, struct nouveau_pushbuf *, uint32_t *sequence);
+   uint32_t  (*update)(struct nouveau_fence_list *);
+};
+
+void nouveau_fence_emit(struct nouveau_fence *, struct nouveau_pushbuf *);
 void nouveau_fence_del(struct nouveau_fence *);
 
-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);
-void nouveau_fence_next(struct nouveau_screen *);
-bool nouveau_fence_wait(struct nouveau_fence *, struct pipe_debug_callback *);
+bool nouveau_fence_new(struct nouveau_fence_list *list, struct nouveau_fence **);
+bool nouveau_fence_work(struct nouveau_fence *, struct nouveau_pushbuf *, void (*)(void *), void *);
+void nouveau_fence_update(struct nouveau_fence_list *, bool flushed);
+void nouveau_fence_next(struct nouveau_fence_list *, struct nouveau_pushbuf *);
+bool nouveau_fence_wait(struct nouveau_fence *, struct nouveau_pushbuf *push, struct pipe_debug_callback *);
 bool nouveau_fence_signalled(struct nouveau_fence *);
 
 void nouveau_fence_unref_bo(void *data); /* generic unref bo callback */
 
+static inline void
+nouveau_fence_list_init(struct nouveau_fence_list *list,
+                        struct nouveau_screen *screen)
+{
+   list->screen = screen;
+}
 
 static inline void
 nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref)
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index 07cdb370c13..ee874a1fce7 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -80,10 +80,12 @@ nouveau_screen_fence_finish(struct pipe_screen *screen,
                             struct pipe_fence_handle *pfence,
                             uint64_t timeout)
 {
+   struct nouveau_pushbuf *push = ctx ? nouveau_context(ctx)->pushbuf : nouveau_screen(screen)->pushbuf;
+
    if (!timeout)
       return nouveau_fence_signalled(nouveau_fence(pfence));
 
-   return nouveau_fence_wait(nouveau_fence(pfence), NULL);
+   return nouveau_fence_wait(nouveau_fence(pfence), push, NULL);
 }
 
 
@@ -224,6 +226,8 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
    if (ret)
       return ret;
 
+   nouveau_fence_list_init(&screen->fence, screen);
+
    /* getting CPU time first appears to be more accurate */
    screen->cpu_gpu_time_delta = os_time_get();
 
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
index 9273d52c1de..7f16ee3f269 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -9,6 +9,8 @@
 # define NOUVEAU_ENABLE_DRIVER_STATISTICS
 #endif
 
+#include "nouveau_fence.h"
+
 typedef uint32_t u32;
 typedef uint16_t u16;
 
@@ -38,15 +40,7 @@ struct nouveau_screen {
 
    uint16_t class_3d;
 
-   struct {
-      struct nouveau_fence *head;
-      struct nouveau_fence *tail;
-      struct nouveau_fence *current;
-      u32 sequence;
-      u32 sequence_ack;
-      void (*emit)(struct pipe_screen *, u32 *sequence);
-      u32  (*update)(struct pipe_screen *);
-   } fence;
+   struct nouveau_fence_list fence;
 
    struct nouveau_mman *mm_VRAM;
    struct nouveau_mman *mm_GART;
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c
index 18eb2c41618..3fd5e2b28c0 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c
@@ -45,8 +45,8 @@ nv30_context_kick_notify(struct nouveau_pushbuf *push)
    nv30 = container_of(push->user_priv, nv30, bufctx);
    screen = &nv30->screen->base;
 
-   nouveau_fence_next(screen);
-   nouveau_fence_update(screen, true);
+   nouveau_fence_next(&screen->fence, push);
+   nouveau_fence_update(&screen->fence, true);
 
    if (push->bufctx) {
       struct nouveau_bufref *bref;
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c
index 4f991776323..1518d8f433f 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c
@@ -343,7 +343,7 @@ nv30_miptree_transfer_unmap(struct pipe_context *pipe,
       nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
 
       /* Allow the copies above to finish executing before freeing the source */
-      nouveau_fence_work(nv30->screen->base.fence.current,
+      nouveau_fence_work(nv30->screen->base.fence.current, nv30->base.pushbuf,
                          nouveau_fence_unref_bo, tx->tmp.bo);
    } else {
       nouveau_bo_ref(NULL, &tx->tmp.bo);
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
index d7563f4a60e..41169be7108 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
@@ -442,12 +442,9 @@ nv30_screen_is_format_supported(struct pipe_screen *pscreen,
 }
 
 static void
-nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence)
+nv30_screen_fence_emit(struct nouveau_fence_list *fence, struct nouveau_pushbuf *push, uint32_t *sequence)
 {
-   struct nv30_screen *screen = nv30_screen(pscreen);
-   struct nouveau_pushbuf *push = screen->base.pushbuf;
-
-   *sequence = ++screen->base.fence.sequence;
+   *sequence = ++fence->sequence;
 
    assert(PUSH_AVAIL(push) + push->rsvd_kick >= 3);
    PUSH_DATA (push, NV30_3D_FENCE_OFFSET |
@@ -457,9 +454,9 @@ nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence)
 }
 
 static uint32_t
-nv30_screen_fence_update(struct pipe_screen *pscreen)
+nv30_screen_fence_update(struct nouveau_fence_list *list)
 {
-   struct nv30_screen *screen = nv30_screen(pscreen);
+   struct nv30_screen *screen = list->data;
    struct nv04_notify *fence = screen->fence->data;
    return *(uint32_t *)((char *)screen->notify->map + fence->offset);
 }
@@ -479,7 +476,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
        * _current_ one, and remove both.
        */
       nouveau_fence_ref(screen->base.fence.current, &current);
-      nouveau_fence_wait(current, NULL);
+      nouveau_fence_wait(current, screen->base.pushbuf, NULL);
       nouveau_fence_ref(NULL, &current);
       nouveau_fence_ref(NULL, &screen->base.fence.current);
    }
@@ -592,6 +589,8 @@ nv30_screen_create(struct nouveau_device *dev)
    if (ret)
       FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret);
 
+   screen->base.fence.data = screen;
+
    screen->base.vidmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
    screen->base.sysmem_bindings |= PIPE_BIND_VERTEX_BUFFER;
    if (oclass == NV40_3D_CLASS) {
@@ -788,6 +787,6 @@ nv30_screen_create(struct nouveau_device *dev)
 
    nouveau_pushbuf_kick(push, push->channel);
 
-   nouveau_fence_new(&screen->base, &screen->base.fence.current);
+   nouveau_fence_new(&screen->base.fence, &screen->base.fence.current);
    return &screen->base;
 }
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c
index bb0a8a0b1d5..5c92af0cfb3 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c
@@ -173,7 +173,7 @@ nv30_release_user_vbufs(struct nv30_context *nv30)
       int i = ffs(vbo_user) - 1;
       vbo_user &= ~(1 << i);
 
-      nouveau_buffer_release_gpu_storage(nv04_resource(nv30->vtxbuf[i].buffer.resource));
+      nouveau_buffer_release_gpu_storage(nv30->base.pushbuf, nv04_resource(nv30->vtxbuf[i].buffer.resource));
    }
 
    nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXTMP);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c
index aac60bba54d..440d7b48fff 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c
@@ -219,7 +219,7 @@ nv50_compute_upload_input(struct nv50_context *nv50, const uint32_t *input)
       BEGIN_NV04(push, NV50_CP(USER_PARAM(0)), size / 4);
       nouveau_pushbuf_data(push, bo, offset, size);
 
-      nouveau_fence_work(screen->base.fence.current, nouveau_mm_free_work, mm);
+      nouveau_fence_work(screen->base.fence.current, push, nouveau_mm_free_work, mm);
       nouveau_bo_ref(NULL, &bo);
       nouveau_bufctx_reset(nv50->bufctx, 0);
    }
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c
index 398560c0fca..e54a06d39ec 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c
@@ -120,8 +120,8 @@ nv50_default_kick_notify(struct nouveau_pushbuf *push)
    struct nv50_screen *screen = push->user_priv;
 
    if (screen) {
-      nouveau_fence_next(&screen->base);
-      nouveau_fence_update(&screen->base, true);
+      nouveau_fence_next(&screen->base.fence, push);
+      nouveau_fence_update(&screen->base.fence, true);
       if (screen->cur_ctx)
          screen->cur_ctx->state.flushed = true;
    }
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_miptree.c b/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
index f2e304fde62..04f9d8416fa 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
@@ -164,7 +164,7 @@ nv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
    struct nv50_miptree *mt = nv50_miptree(pt);
 
    if (mt->base.fence && mt->base.fence->state < NOUVEAU_FENCE_STATE_FLUSHED)
-      nouveau_fence_work(mt->base.fence, nouveau_fence_unref_bo, mt->base.bo);
+      nouveau_fence_work(mt->base.fence, nouveau_screen(pscreen)->pushbuf, nouveau_fence_unref_bo, mt->base.bo);
    else
       nouveau_bo_ref(NULL, &mt->base.bo);
 
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c
index 5be7a4eea1c..c12f9da701d 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_query_hw.c
@@ -57,7 +57,7 @@ nv50_hw_query_allocate(struct nv50_context *nv50, struct nv50_query *q,
          if (hq->state == NV50_HW_QUERY_STATE_READY)
             nouveau_mm_free(hq->mm);
          else
-            nouveau_fence_work(screen->base.fence.current,
+            nouveau_fence_work(screen->base.fence.current, nv50->base.pushbuf,
                                nouveau_mm_free_work, hq->mm);
       }
    }
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index 0fc7002d640..0373620fe53 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -503,7 +503,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
        * _current_ one, and remove both.
        */
       nouveau_fence_ref(screen->base.fence.current, &current);
-      nouveau_fence_wait(current, NULL);
+      nouveau_fence_wait(current, screen->base.pushbuf, NULL);
       nouveau_fence_ref(NULL, &current);
       nouveau_fence_ref(NULL, &screen->base.fence.current);
    }
@@ -543,18 +543,17 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
 }
 
 static void
-nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
+nv50_screen_fence_emit(struct nouveau_fence_list *fence, struct nouveau_pushbuf *push, u32 *sequence)
 {
-   struct nv50_screen *screen = nv50_screen(pscreen);
-   struct nouveau_pushbuf *push = screen->base.pushbuf;
+   struct nouveau_bo *bo = fence->data;
 
    /* we need to do it after possible flush in MARK_RING */
-   *sequence = ++screen->base.fence.sequence;
+   *sequence = ++fence->sequence;
 
    assert(PUSH_AVAIL(push) + push->rsvd_kick >= 5);
    PUSH_DATA (push, NV50_FIFO_PKHDR(NV50_3D(QUERY_ADDRESS_HIGH), 4));
-   PUSH_DATAh(push, screen->fence.bo->offset);
-   PUSH_DATA (push, screen->fence.bo->offset);
+   PUSH_DATAh(push, bo->offset);
+   PUSH_DATA (push, bo->offset);
    PUSH_DATA (push, *sequence);
    PUSH_DATA (push, NV50_3D_QUERY_GET_MODE_WRITE_UNK0 |
                     NV50_3D_QUERY_GET_UNK4 |
@@ -565,9 +564,10 @@ nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
 }
 
 static u32
-nv50_screen_fence_update(struct pipe_screen *pscreen)
+nv50_screen_fence_update(struct nouveau_fence_list *fence)
 {
-   uint32_t *map = nv50_screen(pscreen)->fence.bo->map;
+   struct nouveau_bo *bo = fence->data;
+   uint32_t *map = bo->map;
    return map[0];
 }
 
@@ -933,8 +933,8 @@ nv50_screen_create(struct nouveau_device *dev)
       NOUVEAU_ERR("Failed to allocate fence bo: %d\n", ret);
       goto fail;
    }
-
    nouveau_bo_map(screen->fence.bo, 0, NULL);
+   screen->base.fence.data = screen->fence.bo;
    screen->base.fence.emit = nv50_screen_fence_emit;
    screen->base.fence.update = nv50_screen_fence_update;
 
@@ -1076,7 +1076,7 @@ nv50_screen_create(struct nouveau_device *dev)
       goto fail;
    }
 
-   nouveau_fence_new(&screen->base, &screen->base.fence.current);
+   nouveau_fence_new(&screen->base.fence, &screen->base.fence.current);
 
    return &screen->base;
 
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c
index d08095a0f6f..863e67d47ea 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c
@@ -360,7 +360,7 @@ nv50_miptree_transfer_unmap(struct pipe_context *pctx,
       }
 
       /* Allow the copies above to finish executing before freeing the source */
-      nouveau_fence_work(nv50->screen->base.fence.current,
+      nouveau_fence_work(nv50->screen->base.fence.current, nv50->base.pushbuf,
                          nouveau_fence_unref_bo, tx->rect[1].bo);
    } else {
       nouveau_bo_ref(NULL, &tx->rect[1].bo);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
index ed041121a26..260b55e9b01 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
@@ -632,7 +632,7 @@ nv50_draw_elements(struct nv50_context *nv50, bool shorten,
        * pushbuf submit, but it's probably not a big performance difference.
        */
       if (buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr))
-         nouveau_fence_wait(buf->fence_wr, &nv50->base.debug);
+         nouveau_fence_wait(buf->fence_wr, push, &nv50->base.debug);
 
       while (instance_count--) {
          BEGIN_NV04(push, NV50_3D(VERTEX_BEGIN_GL), 1);
@@ -757,7 +757,7 @@ nv50_draw_vbo_kick_notify(struct nouveau_pushbuf *chan)
 {
    struct nv50_screen *screen = chan->user_priv;
 
-   nouveau_fence_update(&screen->base, true);
+   nouveau_fence_update(&screen->base.fence, true);
 
    nv50_bufctx_fence(screen->cur_ctx->bufctx_3d, true);
 }
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
index 962e9ddef04..471078c56b4 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
@@ -225,8 +225,8 @@ nvc0_default_kick_notify(struct nouveau_pushbuf *push)
    struct nvc0_screen *screen = push->user_priv;
 
    if (screen) {
-      nouveau_fence_next(&screen->base);
-      nouveau_fence_update(&screen->base, true);
+      nouveau_fence_next(&screen->base.fence, push);
+      nouveau_fence_update(&screen->base.fence, true);
       if (screen->cur_ctx)
          screen->cur_ctx->state.flushed = true;
       NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c
index 00d12d19c35..40cc552a29b 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query_hw.c
@@ -49,7 +49,7 @@ nvc0_hw_query_allocate(struct nvc0_context *nvc0, struct nvc0_query *q,
          if (hq->state == NVC0_HW_QUERY_STATE_READY)
             nouveau_mm_free(hq->mm);
          else
-            nouveau_fence_work(screen->base.fence.current,
+            nouveau_fence_work(screen->base.fence.current, nvc0->base.pushbuf,
                                nouveau_mm_free_work, hq->mm);
       }
    }
@@ -405,7 +405,7 @@ nvc0_hw_get_query_result_resource(struct nvc0_context *nvc0,
     * of the following logic more complicated.
     */
    if (hq->is64bit && hq->fence->state < NOUVEAU_FENCE_STATE_EMITTED)
-      nouveau_fence_emit(hq->fence);
+      nouveau_fence_emit(hq->fence, push);
 
    /* We either need to compute a 32- or 64-bit difference between 2 values,
     * and then store the result as either a 32- or 64-bit value. As such let's
@@ -627,7 +627,7 @@ nvc0_hw_query_fifo_wait(struct nvc0_context *nvc0, struct nvc0_query *q)
 
    /* ensure the query's fence has been emitted */
    if (hq->is64bit && hq->fence->state < NOUVEAU_FENCE_STATE_EMITTED)
-      nouveau_fence_emit(hq->fence);
+      nouveau_fence_emit(hq->fence, push);
 
    PUSH_SPACE(push, 5);
    PUSH_REFN (push, hq->bo, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index 6fb95e89712..26642c2629d 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -603,7 +603,7 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
        * _current_ one, and remove both.
        */
       nouveau_fence_ref(screen->base.fence.current, &current);
-      nouveau_fence_wait(current, NULL);
+      nouveau_fence_wait(current, screen->base.pushbuf, NULL);
       nouveau_fence_ref(NULL, &current);
       nouveau_fence_ref(NULL, &screen->base.fence.current);
    }
@@ -728,28 +728,27 @@ nvc0_magic_3d_init(struct nouveau_pushbuf *push, uint16_t obj_class)
 }
 
 static void
-nvc0_screen_fence_emit(struct pipe_screen *pscreen, u32 *sequence)
+nvc0_screen_fence_emit(struct nouveau_fence_list *list, struct nouveau_pushbuf *push, u32 *sequence)
 {
-   struct nvc0_screen *screen = nvc0_screen(pscreen);
-   struct nouveau_pushbuf *push = screen->base.pushbuf;
+   struct nouveau_bo *bo = list->data;
 
    /* we need to do it after possible flush in MARK_RING */
-   *sequence = ++screen->base.fence.sequence;
+   *sequence = ++list->sequence;
 
    assert(PUSH_AVAIL(push) + push->rsvd_kick >= 5);
    PUSH_DATA (push, NVC0_FIFO_PKHDR_SQ(NVC0_3D(QUERY_ADDRESS_HIGH), 4));
-   PUSH_DATAh(push, screen->fence.bo->offset);
-   PUSH_DATA (push, screen->fence.bo->offset);
+   PUSH_DATAh(push, bo->offset);
+   PUSH_DATA (push, bo->offset);
    PUSH_DATA (push, *sequence);
    PUSH_DATA (push, NVC0_3D_QUERY_GET_FENCE | NVC0_3D_QUERY_GET_SHORT |
               (0xf << NVC0_3D_QUERY_GET_UNIT__SHIFT));
 }
 
-static u32
-nvc0_screen_fence_update(struct pipe_screen *pscreen)
+static uint32_t
+nvc0_screen_fence_update(struct nouveau_fence_list *list)
 {
-   struct nvc0_screen *screen = nvc0_screen(pscreen);
-   uint32_t *map = screen->fence.bo->map;
+   struct nouveau_bo *bo = list->data;
+   uint32_t *map = bo->map;
    return map[0];
 }
 
@@ -973,10 +972,10 @@ nvc0_screen_create(struct nouveau_device *dev)
    if (ret)
       FAIL_SCREEN_INIT("Error allocating fence BO: %d\n", ret);
    nouveau_bo_map(screen->fence.bo, 0, NULL);
+   screen->base.fence.data = screen->fence.bo;
    screen->base.fence.emit = nvc0_screen_fence_emit;
    screen->base.fence.update = nvc0_screen_fence_update;
 
-
    ret = nouveau_object_new(chan, (dev->chipset < 0xe0) ? 0x1f906e : 0x906e,
                             NVIF_CLASS_SW_GF100, NULL, 0, &screen->nvsw);
    if (ret)
@@ -1390,7 +1389,7 @@ nvc0_screen_create(struct nouveau_device *dev)
    screen->default_tsc = CALLOC_STRUCT(nv50_tsc_entry);
    screen->default_tsc->tsc[0] = G80_TSC_0_SRGB_CONVERSION;
 
-   nouveau_fence_new(&screen->base, &screen->base.fence.current);
+   nouveau_fence_new(&screen->base.fence, &screen->base.fence.current);
 
    return &screen->base;
 
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c
index 853ce12b13c..440d00dcc94 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c
@@ -362,8 +362,8 @@ nvc0_mt_sync(struct nvc0_context *nvc0, struct nv50_miptree *mt, unsigned usage)
       return !nouveau_bo_wait(mt->base.bo, access, nvc0->base.client);
    }
    if (usage & PIPE_TRANSFER_WRITE)
-      return !mt->base.fence || nouveau_fence_wait(mt->base.fence, &nvc0->base.debug);
-   return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr, &nvc0->base.debug);
+      return !mt->base.fence || nouveau_fence_wait(mt->base.fence, nvc0->base.pushbuf, &nvc0->base.debug);
+   return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr, nvc0->base.pushbuf, &nvc0->base.debug);
 }
 
 void *
@@ -518,7 +518,7 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
       NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_transfers_wr, 1);
 
       /* Allow the copies above to finish executing before freeing the source */
-      nouveau_fence_work(nvc0->base.fence.current,
+      nouveau_fence_work(nvc0->screen->base.fence.current, nvc0->base.pushbuf,
                          nouveau_fence_unref_bo, tx->rect[1].bo);
    } else {
       nouveau_bo_ref(NULL, &tx->rect[1].bo);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
index 66de6d9e2fa..31bb910c551 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
@@ -554,7 +554,7 @@ nvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push)
 {
    struct nvc0_screen *screen = push->user_priv;
 
-   nouveau_fence_update(&screen->base, true);
+   nouveau_fence_update(&screen->base.fence, true);
 
    NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
 }
-- 
2.19.2



More information about the mesa-dev mailing list