nvc0: improve userspace fencing
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sun, 20 Feb 2011 16:57:47 +0000 (17:57 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 24 Feb 2011 16:35:35 +0000 (17:35 +0100)
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
src/gallium/drivers/nvc0/nvc0_context.h
src/gallium/drivers/nvc0/nvc0_fence.c
src/gallium/drivers/nvc0/nvc0_fence.h
src/gallium/drivers/nvc0/nvc0_screen.h
src/gallium/drivers/nvc0/nvc0_vbo.c

index 20c1a31b5b33b578ca8b1767802590b19dcd0a27..f02de4d044a8e0b267ef7798d80177c78d32ac4e 100644 (file)
@@ -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);
index a082ad4575c399949befe2518c2e471d6a20fa48..3722f358d897e0e98e7d8abc1309cf7844247643 100644 (file)
@@ -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);
index 3a3dd75c152a946f70acb813b16646681df67b4d..f2d4b1451bf1f54b57d0eb08f3ba32ae95f8a2da 100644 (file)
@@ -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);
 }
index e63c164bda42638c1b64f94cd3757c91d1305139..3d8c3f8ba604083fd812b0f51cda3cf570859c9f 100644 (file)
@@ -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;
 
index 3b676fd21a1f9df8ff8a16228d93d35f8ecb0d04..5af96cbacea791c487abb6bd4ead7000f5fb7834 100644 (file)
@@ -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)
index 19fd85273c105ae5a5388d8d123960937d247d4f..2db43d8704bc99e10cf6b11a5ff27db6ee41dc5d 100644 (file)
@@ -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