mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-09 21:20:14 +01:00
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.
This commit is contained in:
parent
410a13c5ce
commit
a6ea37da4b
6 changed files with 46 additions and 26 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue