summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2011-02-20 17:57:47 +0100
committerChristoph Bumiller <[email protected]>2011-02-24 17:35:35 +0100
commita6ea37da4bd02241ce3bf522b93dd7ff0757f959 (patch)
treef1a13e36013b1d0e99c9b2505f59810f245adec9 /src
parent410a13c5ce799fe97a4e4503190d0f66fb2559a3 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_context.c22
-rw-r--r--src/gallium/drivers/nvc0/nvc0_context.h2
-rw-r--r--src/gallium/drivers/nvc0/nvc0_fence.c36
-rw-r--r--src/gallium/drivers/nvc0/nvc0_fence.h3
-rw-r--r--src/gallium/drivers/nvc0/nvc0_screen.h3
-rw-r--r--src/gallium/drivers/nvc0/nvc0_vbo.c6
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 20c1a31b5b3..f02de4d044a 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 a082ad4575c..3722f358d89 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 3a3dd75c152..f2d4b1451bf 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 e63c164bda4..3d8c3f8ba60 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 3b676fd21a1..5af96cbacea 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 19fd85273c1..2db43d8704b 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