From 7a8ee058a83f1eda2c783d83fc5967fd9ef75660 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Mar 2011 10:17:28 +1000 Subject: [PATCH] nv50: move onto shared fence code Signed-off-by: Ben Skeggs --- src/gallium/drivers/nv50/Makefile | 1 - src/gallium/drivers/nv50/nv50_buffer.c | 24 ++- src/gallium/drivers/nv50/nv50_context.c | 9 +- src/gallium/drivers/nv50/nv50_fence.c | 216 ----------------------- src/gallium/drivers/nv50/nv50_fence.h | 49 ----- src/gallium/drivers/nv50/nv50_query.c | 2 +- src/gallium/drivers/nv50/nv50_resource.h | 6 +- src/gallium/drivers/nv50/nv50_screen.c | 48 ++--- src/gallium/drivers/nv50/nv50_screen.h | 35 +--- src/gallium/drivers/nv50/nv50_vbo.c | 2 +- 10 files changed, 45 insertions(+), 347 deletions(-) delete mode 100644 src/gallium/drivers/nv50/nv50_fence.c delete mode 100644 src/gallium/drivers/nv50/nv50_fence.h diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index d0a60c7ac13..61fb94913b3 100644 --- a/src/gallium/drivers/nv50/Makefile +++ b/src/gallium/drivers/nv50/Makefile @@ -26,7 +26,6 @@ C_SOURCES = \ nv50_pc_optimize.c \ nv50_pc_regalloc.c \ nv50_push.c \ - nv50_fence.c \ nv50_mm.c \ nv50_query.c diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c index 5cb2e628e7a..21aad9f9496 100644 --- a/src/gallium/drivers/nv50/nv50_buffer.c +++ b/src/gallium/drivers/nv50/nv50_buffer.c @@ -49,13 +49,9 @@ nv50_buffer_allocate(struct nv50_screen *screen, struct nv50_resource *buf, } static INLINE void -release_allocation(struct nv50_mm_allocation **mm, struct nv50_fence *fence) +release_allocation(struct nv50_mm_allocation **mm, struct nouveau_fence *fence) { - if (fence && fence->state != NV50_FENCE_STATE_SIGNALLED) { - nv50_fence_sched_release(fence, *mm); - } else { - nv50_mm_free(*mm); - } + nouveau_fence_work(fence, nv50_mm_free, *mm); (*mm) = NULL; } @@ -153,7 +149,7 @@ nv50_buffer_upload(struct nv50_context *nv50, struct nv50_resource *buf, nouveau_bo_ref(NULL, &bounce); if (mm) - release_allocation(&mm, nv50->screen->fence.current); + release_allocation(&mm, nv50->screen->base.fence.current); if (start == 0 && size == buf->base.width0) buf->status &= ~NV50_BUFFER_STATUS_DIRTY; @@ -217,17 +213,17 @@ nv50_buffer_sync(struct nv50_resource *buf, unsigned rw) if (rw == PIPE_TRANSFER_READ) { if (!buf->fence_wr) return TRUE; - if (!nv50_fence_wait(buf->fence_wr)) + if (!nouveau_fence_wait(buf->fence_wr)) return FALSE; } else { if (!buf->fence) return TRUE; - if (!nv50_fence_wait(buf->fence)) + if (!nouveau_fence_wait(buf->fence)) return FALSE; - nv50_fence_reference(&buf->fence, NULL); + nouveau_fence_ref(NULL, &buf->fence); } - nv50_fence_reference(&buf->fence_wr, NULL); + nouveau_fence_ref(NULL, &buf->fence_wr); return TRUE; } @@ -236,9 +232,9 @@ static INLINE boolean nv50_buffer_busy(struct nv50_resource *buf, unsigned rw) { if (rw == PIPE_TRANSFER_READ) - return (buf->fence_wr && !nv50_fence_signalled(buf->fence_wr)); + return (buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)); else - return (buf->fence && !nv50_fence_signalled(buf->fence)); + return (buf->fence && !nouveau_fence_signalled(buf->fence)); } static void * @@ -453,7 +449,7 @@ nv50_buffer_migrate(struct nv50_context *nv50, nouveau_bo_ref(NULL, &bo); if (mm) - release_allocation(&mm, screen->fence.current); + release_allocation(&mm, screen->base.fence.current); } else if (new_domain == NOUVEAU_BO_VRAM && old_domain == 0) { if (!nv50_buffer_allocate(screen, buf, NOUVEAU_BO_VRAM)) diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 8eb59e20d8d..4380945a1ee 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -44,8 +44,8 @@ nv50_flush(struct pipe_context *pipe, unsigned flags, } if (fence) - nv50_fence_reference((struct nv50_fence **)fence, - nv50->screen->fence.current); + nouveau_fence_ref(nv50->screen->base.fence.current, + (struct nouveau_fence **)fence); if (flags & (PIPE_FLUSH_SWAPBUFFERS | PIPE_FLUSH_FRAME)) FIRE_RING(chan); @@ -59,9 +59,8 @@ nv50_default_flush_notify(struct nouveau_channel *chan) if (!nv50) return; - nv50_screen_fence_update(nv50->screen, TRUE); - - nv50_screen_fence_next(nv50->screen); + nouveau_fence_update(&nv50->screen->base, TRUE); + nouveau_fence_next(&nv50->screen->base); } static void diff --git a/src/gallium/drivers/nv50/nv50_fence.c b/src/gallium/drivers/nv50/nv50_fence.c deleted file mode 100644 index 936cf81ac75..00000000000 --- a/src/gallium/drivers/nv50/nv50_fence.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2010 Christoph Bumiller - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv50_fence.h" -#include "nv50_context.h" -#include "nv50_screen.h" - -#ifdef PIPE_OS_UNIX -#include -#endif - -boolean -nv50_screen_fence_new(struct nv50_screen *screen, struct nv50_fence **fence, - boolean emit) -{ - *fence = CALLOC_STRUCT(nv50_fence); - if (!*fence) - return FALSE; - - (*fence)->screen = screen; - (*fence)->ref = 1; - - if (emit) - nv50_fence_emit(*fence); - - return TRUE; -} - -void -nv50_fence_emit(struct nv50_fence *fence) -{ - struct nv50_screen *screen = fence->screen; - struct nouveau_channel *chan = screen->base.channel; - - fence->sequence = ++screen->fence.sequence; - - assert(fence->state == NV50_FENCE_STATE_AVAILABLE); - - MARK_RING (chan, 5, 2); - BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4); - OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR); - OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR); - OUT_RING (chan, fence->sequence); - OUT_RING (chan, - NV50_3D_QUERY_GET_MODE_WRITE_UNK0 | - NV50_3D_QUERY_GET_UNK4 | - NV50_3D_QUERY_GET_UNIT_CROP | - NV50_3D_QUERY_GET_TYPE_QUERY | - NV50_3D_QUERY_GET_QUERY_SELECT_ZERO | - NV50_3D_QUERY_GET_SHORT); - - - ++fence->ref; - - if (screen->fence.tail) - screen->fence.tail->next = fence; - else - screen->fence.head = fence; - - screen->fence.tail = fence; - - fence->state = NV50_FENCE_STATE_EMITTED; -} - -static void -nv50_fence_trigger_release_buffers(struct nv50_fence *fence); - -void -nv50_fence_del(struct nv50_fence *fence) -{ - struct nv50_fence *it; - struct nv50_screen *screen = fence->screen; - - if (fence->state == NV50_FENCE_STATE_EMITTED || - fence->state == NV50_FENCE_STATE_FLUSHED) { - if (fence == screen->fence.head) { - screen->fence.head = fence->next; - if (!screen->fence.head) - screen->fence.tail = NULL; - } else { - for (it = screen->fence.head; it && it->next != fence; it = it->next); - it->next = fence->next; - if (screen->fence.tail == fence) - screen->fence.tail = it; - } - } - - if (fence->buffers) { - debug_printf("WARNING: deleting fence with buffers " - "still hooked to it !\n"); - nv50_fence_trigger_release_buffers(fence); - } - - FREE(fence); -} - -static void -nv50_fence_trigger_release_buffers(struct nv50_fence *fence) -{ - struct nv50_mm_allocation *alloc = fence->buffers; - - while (alloc) { - struct nv50_mm_allocation *next = alloc->next; - nv50_mm_free(alloc); - alloc = next; - }; - fence->buffers = NULL; -} - -void -nv50_screen_fence_update(struct nv50_screen *screen, boolean flushed) -{ - struct nv50_fence *fence; - struct nv50_fence *next = NULL; - uint32_t sequence = screen->fence.map[0]; - - if (screen->fence.sequence_ack == sequence) - return; - screen->fence.sequence_ack = sequence; - - for (fence = screen->fence.head; fence; fence = next) { - next = fence->next; - sequence = fence->sequence; - - fence->state = NV50_FENCE_STATE_SIGNALLED; - - if (fence->buffers) - nv50_fence_trigger_release_buffers(fence); - - nv50_fence_reference(&fence, NULL); - - if (sequence == screen->fence.sequence_ack) - break; - } - screen->fence.head = next; - if (!next) - screen->fence.tail = NULL; - - if (flushed) { - for (fence = next; fence; fence = fence->next) - fence->state = NV50_FENCE_STATE_FLUSHED; - } -} - -#define NV50_FENCE_MAX_SPINS (1 << 31) - -boolean -nv50_fence_signalled(struct nv50_fence *fence) -{ - struct nv50_screen *screen = fence->screen; - - if (fence->state >= NV50_FENCE_STATE_EMITTED) - nv50_screen_fence_update(screen, FALSE); - - return fence->state == NV50_FENCE_STATE_SIGNALLED; -} - -boolean -nv50_fence_wait(struct nv50_fence *fence) -{ - struct nv50_screen *screen = fence->screen; - uint32_t spins = 0; - - if (fence->state < NV50_FENCE_STATE_EMITTED) { - nv50_fence_emit(fence); - - if (fence == screen->fence.current) - nv50_screen_fence_new(screen, &screen->fence.current, FALSE); - } - if (fence->state < NV50_FENCE_STATE_FLUSHED) - FIRE_RING(screen->base.channel); - - do { - nv50_screen_fence_update(screen, FALSE); - - if (fence->state == NV50_FENCE_STATE_SIGNALLED) - return TRUE; - spins++; -#ifdef PIPE_OS_UNIX - if (!(spins % 8)) /* donate a few cycles */ - sched_yield(); -#endif - } while (spins < NV50_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); - - return FALSE; -} - -void -nv50_screen_fence_next(struct nv50_screen *screen) -{ - nv50_fence_emit(screen->fence.current); - nv50_screen_fence_new(screen, &screen->fence.current, FALSE); -} diff --git a/src/gallium/drivers/nv50/nv50_fence.h b/src/gallium/drivers/nv50/nv50_fence.h deleted file mode 100644 index dd0b74e89fa..00000000000 --- a/src/gallium/drivers/nv50/nv50_fence.h +++ /dev/null @@ -1,49 +0,0 @@ - -#ifndef __NV50_FENCE_H__ -#define __NV50_FENCE_H__ - -#include "util/u_inlines.h" -#include "util/u_double_list.h" - -#define NV50_FENCE_STATE_AVAILABLE 0 -#define NV50_FENCE_STATE_EMITTED 1 -#define NV50_FENCE_STATE_FLUSHED 2 -#define NV50_FENCE_STATE_SIGNALLED 3 - -struct nv50_mm_allocation; - -struct nv50_fence { - struct nv50_fence *next; - struct nv50_screen *screen; - int state; - int ref; - uint32_t sequence; - struct nv50_mm_allocation *buffers; -}; - -void nv50_fence_emit(struct nv50_fence *); -void nv50_fence_del(struct nv50_fence *); - -boolean nv50_fence_wait(struct nv50_fence *); -boolean nv50_fence_signalled(struct nv50_fence *); - -static INLINE void -nv50_fence_reference(struct nv50_fence **ref, struct nv50_fence *fence) -{ - if (*ref) { - if (--(*ref)->ref == 0) - nv50_fence_del(*ref); - } - if (fence) - ++fence->ref; - - *ref = fence; -} - -static INLINE struct nv50_fence * -nv50_fence(struct pipe_fence_handle *fence) -{ - return (struct nv50_fence *)fence; -} - -#endif // __NV50_FENCE_H__ diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index e769aa18fe9..42391ec5b1f 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -64,7 +64,7 @@ nv50_query_allocate(struct nv50_context *nv50, struct nv50_query *q, int size) if (q->ready) nv50_mm_free(q->mm); else - nv50_fence_sched_release(screen->fence.current, q->mm); + nouveau_fence_work(screen->base.fence.current, nv50_mm_free, q->mm); } } if (size) { diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h index f0e022b320b..f42179c88f3 100644 --- a/src/gallium/drivers/nv50/nv50_resource.h +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -8,8 +8,6 @@ #include "nouveau/nouveau_winsys.h" #undef NOUVEAU_NVC0 -#include "nv50_fence.h" - struct pipe_resource; struct nouveau_bo; struct nv50_context; @@ -45,8 +43,8 @@ struct nv50_resource { int16_t score; /* low if mapped very often, if high can move to VRAM */ - struct nv50_fence *fence; - struct nv50_fence *fence_wr; + struct nouveau_fence *fence; + struct nouveau_fence *fence_wr; struct nv50_mm_allocation *mm; }; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 77cf959940d..e5b50103ef7 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -23,7 +23,6 @@ #include "util/u_format_s3tc.h" #include "pipe/p_screen.h" -#include "nv50_fence.h" #include "nv50_context.h" #include "nv50_screen.h" @@ -211,9 +210,9 @@ nv50_screen_destroy(struct pipe_screen *pscreen) { struct nv50_screen *screen = nv50_screen(pscreen); - if (screen->fence.current) { - nv50_fence_wait(screen->fence.current); - nv50_fence_reference(&screen->fence.current, NULL); + if (screen->base.fence.current) { + nouveau_fence_wait(screen->base.fence.current); + nouveau_fence_ref (NULL, &screen->base.fence.current); } nouveau_bo_ref(NULL, &screen->code); @@ -246,27 +245,29 @@ nv50_screen_destroy(struct pipe_screen *pscreen) } static void -nv50_screen_fence_reference(struct pipe_screen *pscreen, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) +nv50_screen_fence_emit(struct pipe_screen *pscreen, u32 sequence) { - nv50_fence_reference((struct nv50_fence **)ptr, nv50_fence(fence)); -} + struct nv50_screen *screen = nv50_screen(pscreen); + struct nouveau_channel *chan = screen->base.channel; -static int -nv50_screen_fence_signalled(struct pipe_screen *pscreen, - struct pipe_fence_handle *fence, - unsigned flags) -{ - return !(nv50_fence_signalled(nv50_fence(fence))); + MARK_RING (chan, 5, 2); + BEGIN_RING(chan, RING_3D(QUERY_ADDRESS_HIGH), 4); + OUT_RELOCh(chan, screen->fence.bo, 0, NOUVEAU_BO_WR); + OUT_RELOCl(chan, screen->fence.bo, 0, NOUVEAU_BO_WR); + OUT_RING (chan, sequence); + OUT_RING (chan, NV50_3D_QUERY_GET_MODE_WRITE_UNK0 | + NV50_3D_QUERY_GET_UNK4 | + NV50_3D_QUERY_GET_UNIT_CROP | + NV50_3D_QUERY_GET_TYPE_QUERY | + NV50_3D_QUERY_GET_QUERY_SELECT_ZERO | + NV50_3D_QUERY_GET_SHORT); } -static int -nv50_screen_fence_finish(struct pipe_screen *pscreen, - struct pipe_fence_handle *fence, - unsigned flags) +static u32 +nv50_screen_fence_update(struct pipe_screen *pscreen) { - return nv50_fence_wait((struct nv50_fence *)fence) != TRUE; + struct nv50_screen *screen = nv50_screen(pscreen); + return screen->fence.map[0]; } #define FAIL_SCREEN_INIT(str, err) \ @@ -306,9 +307,6 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_param = nv50_screen_get_param; pscreen->get_shader_param = nv50_screen_get_shader_param; pscreen->get_paramf = nv50_screen_get_paramf; - pscreen->fence_reference = nv50_screen_fence_reference; - pscreen->fence_signalled = nv50_screen_fence_signalled; - pscreen->fence_finish = nv50_screen_fence_finish; nv50_screen_init_resource_functions(pscreen); @@ -322,6 +320,8 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) nouveau_bo_map(screen->fence.bo, NOUVEAU_BO_RDWR); screen->fence.map = screen->fence.bo->map; nouveau_bo_unmap(screen->fence.bo); + screen->base.fence.emit = nv50_screen_fence_emit; + screen->base.fence.update = nv50_screen_fence_update; ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) @@ -591,7 +591,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) screen->mm_VRAM = nv50_mm_create(dev, NOUVEAU_BO_VRAM, 0x000); screen->mm_VRAM_fe0 = nv50_mm_create(dev, NOUVEAU_BO_VRAM, 0xfe0); - nv50_screen_fence_new(screen, &screen->fence.current, FALSE); + nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE); return pscreen; diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index c78ed50fe35..c2ec3b58dc2 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -3,6 +3,7 @@ #define NOUVEAU_NVC0 #include "nouveau/nouveau_screen.h" +#include "nouveau/nouveau_fence.h" #undef NOUVEAU_NVC0 #include "nv50_winsys.h" #include "nv50_stateobj.h" @@ -12,7 +13,6 @@ struct nv50_mman; struct nv50_context; -struct nv50_fence; #define NV50_SCRATCH_SIZE (2 << 20) #define NV50_SCRATCH_NR_BUFFERS 2 @@ -49,11 +49,6 @@ struct nv50_screen { struct { uint32_t *map; - struct nv50_fence *head; - struct nv50_fence *tail; - struct nv50_fence *current; - uint32_t sequence; - uint32_t sequence_ack; struct nouveau_bo *bo; } fence; @@ -83,13 +78,6 @@ struct nv50_mm_allocation { uint32_t offset; }; -static INLINE void -nv50_fence_sched_release(struct nv50_fence *nf, struct nv50_mm_allocation *mm) -{ - mm->next = nf->buffers; - nf->buffers = mm; -} - extern struct nv50_mman * nv50_mm_create(struct nouveau_device *, uint32_t domain, uint32_t storage_type); @@ -113,10 +101,10 @@ nv50_resource_fence(struct nv50_resource *res, uint32_t flags) struct nv50_screen *screen = nv50_screen(res->base.screen); if (res->mm) { - nv50_fence_reference(&res->fence, screen->fence.current); + nouveau_fence_ref(screen->base.fence.current, &res->fence); if (flags & NOUVEAU_BO_WR) - nv50_fence_reference(&res->fence_wr, screen->fence.current); + nouveau_fence_ref(screen->base.fence.current, &res->fence_wr); } } @@ -132,23 +120,6 @@ nv50_resource_validate(struct nv50_resource *res, uint32_t flags) } } - -boolean -nv50_screen_fence_new(struct nv50_screen *, struct nv50_fence **, boolean emit); - -void -nv50_screen_fence_next(struct nv50_screen *); -void -nv50_screen_fence_update(struct nv50_screen *, boolean flushed); - -static INLINE boolean -nv50_screen_fence_emit(struct nv50_screen *screen) -{ - nv50_fence_emit(screen->fence.current); - - return nv50_screen_fence_new(screen, &screen->fence.current, FALSE); -} - struct nv50_format { uint32_t rt; uint32_t tic; diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 0e0d48d661c..d18b2dffd1d 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -393,7 +393,7 @@ nv50_draw_vbo_flush_notify(struct nouveau_channel *chan) { struct nv50_context *nv50 = chan->user_private; - nv50_screen_fence_update(nv50->screen, TRUE); + nouveau_fence_update(&nv50->screen->base, TRUE); nv50_bufctx_emit_relocs(nv50); } -- 2.30.2