Mesa (master): nvc0: improve userspace fencing

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Thu Feb 24 16:36:24 UTC 2011


Module: Mesa
Branch: master
Commit: a6ea37da4bd02241ce3bf522b93dd7ff0757f959
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a6ea37da4bd02241ce3bf522b93dd7ff0757f959

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Sun Feb 20 17:57:47 2011 +0100

nvc0: improve userspace fencing

Before, there were situations in which we never checked the fences
for completion (some loading screens for example) and thus never
released memory.

---

 src/gallium/drivers/nvc0/nvc0_context.c |   22 +++++++++++++------
 src/gallium/drivers/nvc0/nvc0_context.h |    2 +
 src/gallium/drivers/nvc0/nvc0_fence.c   |   36 ++++++++++++++++++-------------
 src/gallium/drivers/nvc0/nvc0_fence.h   |    3 +-
 src/gallium/drivers/nvc0/nvc0_screen.h  |    3 +-
 src/gallium/drivers/nvc0/nvc0_vbo.c     |    6 +++-
 6 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c
index 20c1a31..f02de4d 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nvc0/nvc0_context.c
@@ -47,15 +47,12 @@ nvc0_flush(struct pipe_context *pipe, unsigned flags,
       OUT_RING  (chan, 0);
    }
 
-   if (fence) {
-      nvc0_screen_fence_new(nvc0->screen, (struct nvc0_fence **)fence, TRUE);
-   }
+   if (fence)
+      nvc0_fence_reference((struct nvc0_fence **)fence,
+                           nvc0->screen->fence.current);
 
-   if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME)) {
+   if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME))
       FIRE_RING(chan);
-
-      nvc0_screen_fence_next(nvc0->screen);
-   }
 }
 
 static void
@@ -71,6 +68,16 @@ nvc0_destroy(struct pipe_context *pipe)
    FREE(nvc0);
 }
 
+void
+nvc0_default_flush_notify(struct nouveau_channel *chan)
+{
+   struct nvc0_context *nvc0 = chan->user_private;
+
+   nvc0_screen_fence_update(nvc0->screen, TRUE);
+
+   nvc0_screen_fence_next(nvc0->screen);
+}
+
 struct pipe_context *
 nvc0_create(struct pipe_screen *pscreen, void *priv)
 {
@@ -95,6 +102,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
    nvc0->pipe.flush = nvc0_flush;
 
    screen->base.channel->user_private = nvc0;
+   screen->base.channel->flush_notify = nvc0_default_flush_notify;
 
    nvc0_init_query_functions(nvc0);
    nvc0_init_surface_functions(nvc0);
diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h
index a082ad4..3722f35 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nvc0/nvc0_context.h
@@ -156,6 +156,8 @@ nvc0_surface(struct pipe_surface *ps)
 /* nvc0_context.c */
 struct pipe_context *nvc0_create(struct pipe_screen *, void *);
 
+void nvc0_default_flush_notify(struct nouveau_channel *);
+
 void nvc0_bufctx_emit_relocs(struct nvc0_context *);
 void nvc0_bufctx_add_resident(struct nvc0_context *, int ctx,
                               struct nvc0_resource *, uint32_t flags);
diff --git a/src/gallium/drivers/nvc0/nvc0_fence.c b/src/gallium/drivers/nvc0/nvc0_fence.c
index 3a3dd75..f2d4b14 100644
--- a/src/gallium/drivers/nvc0/nvc0_fence.c
+++ b/src/gallium/drivers/nvc0/nvc0_fence.c
@@ -84,7 +84,8 @@ nvc0_fence_del(struct nvc0_fence *fence)
    struct nvc0_fence *it;
    struct nvc0_screen *screen = fence->screen;
 
-   if (fence->state == NVC0_FENCE_STATE_EMITTED) {
+   if (fence->state == NVC0_FENCE_STATE_EMITTED ||
+       fence->state == NVC0_FENCE_STATE_FLUSHED) {
       if (fence == screen->fence.head) {
          screen->fence.head = fence->next;
          if (!screen->fence.head)
@@ -119,8 +120,8 @@ nvc0_fence_trigger_release_buffers(struct nvc0_fence *fence)
    fence->buffers = NULL;
 }
 
-static void
-nvc0_screen_fence_update(struct nvc0_screen *screen)
+void
+nvc0_screen_fence_update(struct nvc0_screen *screen, boolean flushed)
 {
    struct nvc0_fence *fence;
    struct nvc0_fence *next = NULL;
@@ -147,38 +148,43 @@ nvc0_screen_fence_update(struct nvc0_screen *screen)
    screen->fence.head = next;
    if (!next)
       screen->fence.tail = NULL;
-}
 
-#define NVC0_FENCE_MAX_SPINS (1 << 17)
+   if (flushed) {
+      for (fence = next; fence; fence = fence->next)
+         fence->state = NVC0_FENCE_STATE_FLUSHED;
+   }
+}
 
 boolean
 nvc0_fence_signalled(struct nvc0_fence *fence)
 {
    struct nvc0_screen *screen = fence->screen;
 
-   if (fence->state == NVC0_FENCE_STATE_EMITTED)
-      nvc0_screen_fence_update(screen);
+   if (fence->state >= NVC0_FENCE_STATE_EMITTED)
+      nvc0_screen_fence_update(screen, FALSE);
 
    return fence->state == NVC0_FENCE_STATE_SIGNALLED;
 }
 
+#define NVC0_FENCE_MAX_SPINS (1 << 31)
+
 boolean
 nvc0_fence_wait(struct nvc0_fence *fence)
 {
    struct nvc0_screen *screen = fence->screen;
-   int spins = 0;
+   uint32_t spins = 0;
 
-   if (fence->state == NVC0_FENCE_STATE_AVAILABLE) {
+   if (fence->state < NVC0_FENCE_STATE_EMITTED) {
       nvc0_fence_emit(fence);
 
-      FIRE_RING(screen->base.channel);
-
       if (fence == screen->fence.current)
          nvc0_screen_fence_new(screen, &screen->fence.current, FALSE);
    }
+   if (fence->state < NVC0_FENCE_STATE_FLUSHED)
+      FIRE_RING(screen->base.channel);
 
    do {
-      nvc0_screen_fence_update(screen);
+      nvc0_screen_fence_update(screen, FALSE);
 
       if (fence->state == NVC0_FENCE_STATE_SIGNALLED)
          return TRUE;
@@ -189,8 +195,9 @@ nvc0_fence_wait(struct nvc0_fence *fence)
 #endif
    } while (spins < NVC0_FENCE_MAX_SPINS);
 
-   if (spins > 9000)
-      NOUVEAU_ERR("fence %x: been spinning too long\n", fence->sequence);
+   debug_printf("Wait on fence %u (ack = %u, next = %u) timed out !\n",
+                fence->sequence,
+                screen->fence.sequence_ack, screen->fence.sequence);
 
    return FALSE;
 }
@@ -200,5 +207,4 @@ nvc0_screen_fence_next(struct nvc0_screen *screen)
 {
    nvc0_fence_emit(screen->fence.current);
    nvc0_screen_fence_new(screen, &screen->fence.current, FALSE);
-   nvc0_screen_fence_update(screen);
 }
diff --git a/src/gallium/drivers/nvc0/nvc0_fence.h b/src/gallium/drivers/nvc0/nvc0_fence.h
index e63c164..3d8c3f8 100644
--- a/src/gallium/drivers/nvc0/nvc0_fence.h
+++ b/src/gallium/drivers/nvc0/nvc0_fence.h
@@ -7,7 +7,8 @@
 
 #define NVC0_FENCE_STATE_AVAILABLE 0
 #define NVC0_FENCE_STATE_EMITTED   1
-#define NVC0_FENCE_STATE_SIGNALLED 2
+#define NVC0_FENCE_STATE_FLUSHED   2
+#define NVC0_FENCE_STATE_SIGNALLED 3
 
 struct nvc0_mm_allocation;
 
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h
index 3b676fd..5af96cb 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.h
+++ b/src/gallium/drivers/nvc0/nvc0_screen.h
@@ -138,9 +138,10 @@ nvc0_resource_validate(struct nvc0_resource *res, uint32_t flags)
 
 boolean
 nvc0_screen_fence_new(struct nvc0_screen *, struct nvc0_fence **, boolean emit);
-
 void
 nvc0_screen_fence_next(struct nvc0_screen *);
+void
+nvc0_screen_fence_update(struct nvc0_screen *, boolean flushed);
 
 static INLINE boolean
 nvc0_screen_fence_emit(struct nvc0_screen *screen)
diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c
index 19fd852..2db43d8 100644
--- a/src/gallium/drivers/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nvc0/nvc0_vbo.c
@@ -371,6 +371,8 @@ nvc0_draw_vbo_flush_notify(struct nouveau_channel *chan)
 {
    struct nvc0_context *nvc0 = chan->user_private;
 
+   nvc0_screen_fence_update(nvc0->screen, TRUE);
+
    nvc0_bufctx_emit_relocs(nvc0);
 }
 
@@ -398,7 +400,7 @@ nvc0_draw_arrays(struct nvc0_context *nvc0,
       prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;
    }
 
-   chan->flush_notify = NULL;
+   chan->flush_notify = nvc0_default_flush_notify;
 }
 
 static void
@@ -568,7 +570,7 @@ nvc0_draw_elements(struct nvc0_context *nvc0, boolean shorten,
       }
    }
 
-   chan->flush_notify = NULL;
+   chan->flush_notify = nvc0_default_flush_notify;
 }
 
 void




More information about the mesa-commit mailing list