From f80c03e1875fe96ff2f4c022e3cb76357828140d Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Mon, 28 Feb 2011 12:41:09 +0100 Subject: nv50: replace most of it with nvc0 driver ported to nv50 We'll have to do some unification now to reduce code duplication. --- src/gallium/drivers/nv50/nv50_screen.h | 190 ++++++++++++++++++++++++++++----- 1 file changed, 165 insertions(+), 25 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 6e15230b48..c78ed50fe3 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -1,53 +1,193 @@ #ifndef __NV50_SCREEN_H__ #define __NV50_SCREEN_H__ +#define NOUVEAU_NVC0 #include "nouveau/nouveau_screen.h" +#undef NOUVEAU_NVC0 +#include "nv50_winsys.h" +#include "nv50_stateobj.h" +#define NV50_TIC_MAX_ENTRIES 2048 +#define NV50_TSC_MAX_ENTRIES 2048 + +struct nv50_mman; struct nv50_context; +struct nv50_fence; + +#define NV50_SCRATCH_SIZE (2 << 20) +#define NV50_SCRATCH_NR_BUFFERS 2 struct nv50_screen { - struct nouveau_screen base; + struct nouveau_screen base; + struct nouveau_winsys *nvws; + + struct nv50_context *cur_ctx; + + struct nouveau_bo *code; + struct nouveau_bo *uniforms; + struct nouveau_bo *txc; /* TIC (offset 0) and TSC (65536) */ + struct nouveau_bo *stack_bo; + struct nouveau_bo *tls_bo; + + uint64_t tls_size; + + struct nouveau_resource *vp_code_heap; + struct nouveau_resource *gp_code_heap; + struct nouveau_resource *fp_code_heap; + + struct { + void **entries; + int next; + uint32_t lock[NV50_TIC_MAX_ENTRIES / 32]; + } tic; + + struct { + void **entries; + int next; + uint32_t lock[NV50_TSC_MAX_ENTRIES / 32]; + } tsc; + + 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; + + struct nouveau_notifier *sync; + + struct nv50_mman *mm_GART; + struct nv50_mman *mm_VRAM; + struct nv50_mman *mm_VRAM_fe0; + + struct nouveau_grobj *tesla; + struct nouveau_grobj *eng2d; + struct nouveau_grobj *m2mf; +}; - struct nouveau_winsys *nvws; +static INLINE struct nv50_screen * +nv50_screen(struct pipe_screen *screen) +{ + return (struct nv50_screen *)screen; +} - struct nv50_context *cur_ctx; +/* Since a resource can be migrated, we need to decouple allocations from + * them. This struct is linked with fences for delayed freeing of allocs. + */ +struct nv50_mm_allocation { + struct nv50_mm_allocation *next; + void *priv; + uint32_t offset; +}; - struct nouveau_grobj *tesla; - struct nouveau_grobj *eng2d; - struct nouveau_grobj *m2mf; - struct nouveau_notifier *sync; +static INLINE void +nv50_fence_sched_release(struct nv50_fence *nf, struct nv50_mm_allocation *mm) +{ + mm->next = nf->buffers; + nf->buffers = mm; +} - struct nouveau_bo *constbuf_misc[1]; - struct nouveau_bo *constbuf_parm[PIPE_SHADER_TYPES]; +extern struct nv50_mman * +nv50_mm_create(struct nouveau_device *, uint32_t domain, uint32_t storage_type); - struct nouveau_resource *immd_heap; +extern void +nv50_mm_destroy(struct nv50_mman *); - struct nouveau_bo *tic; - struct nouveau_bo *tsc; +extern struct nv50_mm_allocation * +nv50_mm_allocate(struct nv50_mman *, + uint32_t size, struct nouveau_bo **, uint32_t *offset); +extern void +nv50_mm_free(struct nv50_mm_allocation *); - struct nouveau_bo *stack_bo; /* control flow stack */ - struct nouveau_bo *local_bo; /* l[] memory */ +void nv50_screen_make_buffers_resident(struct nv50_screen *); - boolean force_push; -}; +int nv50_screen_tic_alloc(struct nv50_screen *, void *); +int nv50_screen_tsc_alloc(struct nv50_screen *, void *); -static INLINE struct nv50_screen * -nv50_screen(struct pipe_screen *screen) +static INLINE void +nv50_resource_fence(struct nv50_resource *res, uint32_t flags) { - return (struct nv50_screen *)screen; + struct nv50_screen *screen = nv50_screen(res->base.screen); + + if (res->mm) { + nv50_fence_reference(&res->fence, screen->fence.current); + + if (flags & NOUVEAU_BO_WR) + nv50_fence_reference(&res->fence_wr, screen->fence.current); + } } -extern void nv50_screen_relocs(struct nv50_screen *); +static INLINE void +nv50_resource_validate(struct nv50_resource *res, uint32_t flags) +{ + struct nv50_screen *screen = nv50_screen(res->base.screen); + + if (likely(res->bo)) { + nouveau_bo_validate(screen->base.channel, res->bo, flags); + + nv50_resource_fence(res, flags); + } +} -extern void nv50_screen_reloc_constbuf(struct nv50_screen *, unsigned cbi); + +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; - uint32_t vtx; - uint32_t usage; + uint32_t rt; + uint32_t tic; + uint32_t vtx; + uint32_t usage; }; extern const struct nv50_format nv50_format_table[]; +static INLINE void +nv50_screen_tic_unlock(struct nv50_screen *screen, struct nv50_tic_entry *tic) +{ + if (tic->id >= 0) + screen->tic.lock[tic->id / 32] &= ~(1 << (tic->id % 32)); +} + +static INLINE void +nv50_screen_tsc_unlock(struct nv50_screen *screen, struct nv50_tsc_entry *tsc) +{ + if (tsc->id >= 0) + screen->tsc.lock[tsc->id / 32] &= ~(1 << (tsc->id % 32)); +} + +static INLINE void +nv50_screen_tic_free(struct nv50_screen *screen, struct nv50_tic_entry *tic) +{ + if (tic->id >= 0) { + screen->tic.entries[tic->id] = NULL; + screen->tic.lock[tic->id / 32] &= ~(1 << (tic->id % 32)); + } +} + +static INLINE void +nv50_screen_tsc_free(struct nv50_screen *screen, struct nv50_tsc_entry *tsc) +{ + if (tsc->id >= 0) { + screen->tsc.entries[tsc->id] = NULL; + screen->tsc.lock[tsc->id / 32] &= ~(1 << (tsc->id % 32)); + } +} + #endif -- cgit v1.2.3 From 7a8ee058a83f1eda2c783d83fc5967fd9ef75660 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Mar 2011 10:17:28 +1000 Subject: 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 (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index d0a60c7ac1..61fb94913b 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 5cb2e628e7..21aad9f949 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 8eb59e20d8..4380945a1e 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 936cf81ac7..0000000000 --- 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 dd0b74e89f..0000000000 --- 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 e769aa18fe..42391ec5b1 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 f0e022b320..f42179c88f 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 77cf959940..e5b50103ef 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 c78ed50fe3..c2ec3b58dc 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 0e0d48d661..d18b2dffd1 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); } -- cgit v1.2.3 From 2f30a5bdaad480118e23ac4243de3b4a11ba62a8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Mar 2011 10:27:45 +1000 Subject: nv50: make mm available as common code Signed-off-by: Ben Skeggs --- src/gallium/drivers/nouveau/Makefile | 3 +- src/gallium/drivers/nouveau/nouveau_mm.c | 280 +++++++++++++++++++++++++++++++ src/gallium/drivers/nouveau/nouveau_mm.h | 29 ++++ src/gallium/drivers/nv50/Makefile | 1 - src/gallium/drivers/nv50/nv50_buffer.c | 25 +-- src/gallium/drivers/nv50/nv50_mm.c | 277 ------------------------------ src/gallium/drivers/nv50/nv50_query.c | 8 +- src/gallium/drivers/nv50/nv50_resource.h | 2 +- src/gallium/drivers/nv50/nv50_screen.c | 14 +- src/gallium/drivers/nv50/nv50_screen.h | 29 +--- 10 files changed, 340 insertions(+), 328 deletions(-) create mode 100644 src/gallium/drivers/nouveau/nouveau_mm.c create mode 100644 src/gallium/drivers/nouveau/nouveau_mm.h delete mode 100644 src/gallium/drivers/nv50/nv50_mm.c (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile index a338be9a0b..f9ab9d1860 100644 --- a/src/gallium/drivers/nouveau/Makefile +++ b/src/gallium/drivers/nouveau/Makefile @@ -8,6 +8,7 @@ LIBRARY_INCLUDES = \ -I$(TOP)/src/gallium/drivers/nouveau/include C_SOURCES = nouveau_screen.c \ - nouveau_fence.c + nouveau_fence.c \ + nouveau_mm.c include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nouveau_mm.c b/src/gallium/drivers/nouveau/nouveau_mm.c new file mode 100644 index 0000000000..1c4bb61af8 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_mm.c @@ -0,0 +1,280 @@ + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_double_list.h" + +#include "nouveau_screen.h" +#include "nouveau_mm.h" + +#include "nouveau/nouveau_bo.h" + +#define MM_MIN_ORDER 7 +#define MM_MAX_ORDER 20 + +#define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1) + +#define MM_MIN_SIZE (1 << MM_MIN_ORDER) +#define MM_MAX_SIZE (1 << MM_MAX_ORDER) + +struct mm_bucket { + struct list_head free; + struct list_head used; + struct list_head full; + int num_free; +}; + +struct nouveau_mman { + struct nouveau_device *dev; + struct mm_bucket bucket[MM_NUM_BUCKETS]; + uint32_t storage_type; + uint32_t domain; + uint64_t allocated; +}; + +struct mm_slab { + struct list_head head; + struct nouveau_bo *bo; + struct nouveau_mman *cache; + int order; + int count; + int free; + uint32_t bits[0]; +}; + +static int +mm_slab_alloc(struct mm_slab *slab) +{ + int i, n, b; + + if (slab->free == 0) + return -1; + + for (i = 0; i < (slab->count + 31) / 32; ++i) { + b = ffs(slab->bits[i]) - 1; + if (b >= 0) { + n = i * 32 + b; + assert(n < slab->count); + slab->free--; + slab->bits[i] &= ~(1 << b); + return n; + } + } + return -1; +} + +static INLINE void +mm_slab_free(struct mm_slab *slab, int i) +{ + assert(i < slab->count); + slab->bits[i / 32] |= 1 << (i % 32); + slab->free++; + assert(slab->free <= slab->count); +} + +static INLINE int +mm_get_order(uint32_t size) +{ + int s = __builtin_clz(size) ^ 31; + + if (size > (1 << s)) + s += 1; + return s; +} + +static struct mm_bucket * +mm_bucket_by_order(struct nouveau_mman *cache, int order) +{ + if (order > MM_MAX_ORDER) + return NULL; + return &cache->bucket[MAX2(order, MM_MIN_ORDER) - MM_MIN_ORDER]; +} + +static struct mm_bucket * +mm_bucket_by_size(struct nouveau_mman *cache, unsigned size) +{ + return mm_bucket_by_order(cache, mm_get_order(size)); +} + +/* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */ +static INLINE uint32_t +mm_default_slab_size(unsigned chunk_order) +{ + static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] = + { + 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22 + }; + + assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); + + return 1 << slab_order[chunk_order - MM_MIN_ORDER]; +} + +static int +mm_slab_new(struct nouveau_mman *cache, int chunk_order) +{ + struct mm_slab *slab; + int words, ret; + const uint32_t size = mm_default_slab_size(chunk_order); + + words = ((size >> chunk_order) + 31) / 32; + assert(words); + + slab = MALLOC(sizeof(struct mm_slab) + words * 4); + if (!slab) + return PIPE_ERROR_OUT_OF_MEMORY; + + memset(&slab->bits[0], ~0, words * 4); + + slab->bo = NULL; + ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size, + 0, cache->storage_type, &slab->bo); + if (ret) { + FREE(slab); + return PIPE_ERROR_OUT_OF_MEMORY; + } + + LIST_INITHEAD(&slab->head); + + slab->cache = cache; + slab->order = chunk_order; + slab->count = slab->free = size >> chunk_order; + + LIST_ADD(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free); + + cache->allocated += size; + + debug_printf("MM: new slab, total memory = %lu KiB\n", + cache->allocated / 1024); + + return PIPE_OK; +} + +/* @return token to identify slab or NULL if we just allocated a new bo */ +struct nouveau_mm_allocation * +nouveau_mm_allocate(struct nouveau_mman *cache, + uint32_t size, struct nouveau_bo **bo, uint32_t *offset) +{ + struct mm_bucket *bucket; + struct mm_slab *slab; + struct nouveau_mm_allocation *alloc; + int ret; + + bucket = mm_bucket_by_size(cache, size); + if (!bucket) { + ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size, + 0, cache->storage_type, bo); + if (ret) + debug_printf("bo_new(%x, %x): %i\n", size, cache->storage_type, ret); + + *offset = 0; + return NULL; + } + + if (!LIST_IS_EMPTY(&bucket->used)) { + slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head); + } else { + if (LIST_IS_EMPTY(&bucket->free)) { + mm_slab_new(cache, MAX2(mm_get_order(size), MM_MIN_ORDER)); + } + slab = LIST_ENTRY(struct mm_slab, bucket->free.next, head); + + LIST_DEL(&slab->head); + LIST_ADD(&slab->head, &bucket->used); + } + + *offset = mm_slab_alloc(slab) << slab->order; + + alloc = MALLOC_STRUCT(nouveau_mm_allocation); + if (!alloc) + return NULL; + + nouveau_bo_ref(slab->bo, bo); + + if (slab->free == 0) { + LIST_DEL(&slab->head); + LIST_ADD(&slab->head, &bucket->full); + } + + alloc->next = NULL; + alloc->offset = *offset; + alloc->priv = (void *)slab; + + return alloc; +} + +void +nouveau_mm_free(struct nouveau_mm_allocation *alloc) +{ + struct mm_slab *slab = (struct mm_slab *)alloc->priv; + struct mm_bucket *bucket = mm_bucket_by_order(slab->cache, slab->order); + + mm_slab_free(slab, alloc->offset >> slab->order); + + if (slab->free == 1) { + LIST_DEL(&slab->head); + + if (slab->count > 1) + LIST_ADDTAIL(&slab->head, &bucket->used); + else + LIST_ADDTAIL(&slab->head, &bucket->free); + } + + FREE(alloc); +} + +struct nouveau_mman * +nouveau_mm_create(struct nouveau_device *dev, uint32_t domain, + uint32_t storage_type) +{ + struct nouveau_mman *cache = MALLOC_STRUCT(nouveau_mman); + int i; + + if (!cache) + return NULL; + + cache->dev = dev; + cache->domain = domain; + cache->storage_type = storage_type; + cache->allocated = 0; + + for (i = 0; i < MM_NUM_BUCKETS; ++i) { + LIST_INITHEAD(&cache->bucket[i].free); + LIST_INITHEAD(&cache->bucket[i].used); + LIST_INITHEAD(&cache->bucket[i].full); + } + + return cache; +} + +static INLINE void +nouveau_mm_free_slabs(struct list_head *head) +{ + struct mm_slab *slab, *next; + + LIST_FOR_EACH_ENTRY_SAFE(slab, next, head, head) { + LIST_DEL(&slab->head); + nouveau_bo_ref(NULL, &slab->bo); + FREE(slab); + } +} + +void +nouveau_mm_destroy(struct nouveau_mman *cache) +{ + int i; + + if (!cache) + return; + + for (i = 0; i < MM_NUM_BUCKETS; ++i) { + if (!LIST_IS_EMPTY(&cache->bucket[i].used) || + !LIST_IS_EMPTY(&cache->bucket[i].full)) + debug_printf("WARNING: destroying GPU memory cache " + "with some buffers still in use\n"); + + nouveau_mm_free_slabs(&cache->bucket[i].free); + nouveau_mm_free_slabs(&cache->bucket[i].used); + nouveau_mm_free_slabs(&cache->bucket[i].full); + } +} + diff --git a/src/gallium/drivers/nouveau/nouveau_mm.h b/src/gallium/drivers/nouveau/nouveau_mm.h new file mode 100644 index 0000000000..23e50d4ae5 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_mm.h @@ -0,0 +1,29 @@ +#ifndef __NOUVEAU_MM_H__ +#define __NOUVEAU_MM_H__ + +struct nouveau_mman; + +/* Since a resource can be migrated, we need to decouple allocations from + * them. This struct is linked with fences for delayed freeing of allocs. + */ +struct nouveau_mm_allocation { + struct nouveau_mm_allocation *next; + void *priv; + uint32_t offset; +}; + +extern struct nouveau_mman * +nouveau_mm_create(struct nouveau_device *, uint32_t domain, + uint32_t storage_type); + +extern void +nouveau_mm_destroy(struct nouveau_mman *); + +extern struct nouveau_mm_allocation * +nouveau_mm_allocate(struct nouveau_mman *, uint32_t size, + struct nouveau_bo **, uint32_t *offset); + +extern void +nouveau_mm_free(struct nouveau_mm_allocation *); + +#endif // __NOUVEAU_MM_H__ diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index 61fb94913b..dc9ea0eeba 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_mm.c \ nv50_query.c LIBRARY_INCLUDES = \ diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c index 21aad9f949..f808adb0f6 100644 --- a/src/gallium/drivers/nv50/nv50_buffer.c +++ b/src/gallium/drivers/nv50/nv50_buffer.c @@ -6,6 +6,7 @@ #define NOUVEAU_NVC0 #include "nouveau/nouveau_screen.h" #include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_mm.h" #undef NOUVEAU_NVC0 #include "nv50_context.h" @@ -26,14 +27,14 @@ nv50_buffer_allocate(struct nv50_screen *screen, struct nv50_resource *buf, unsigned domain) { if (domain == NOUVEAU_BO_VRAM) { - buf->mm = nv50_mm_allocate(screen->mm_VRAM, buf->base.width0, &buf->bo, - &buf->offset); + buf->mm = nouveau_mm_allocate(screen->mm_VRAM, buf->base.width0, &buf->bo, + &buf->offset); if (!buf->bo) return nv50_buffer_allocate(screen, buf, NOUVEAU_BO_GART); } else if (domain == NOUVEAU_BO_GART) { - buf->mm = nv50_mm_allocate(screen->mm_GART, buf->base.width0, &buf->bo, - &buf->offset); + buf->mm = nouveau_mm_allocate(screen->mm_GART, buf->base.width0, &buf->bo, + &buf->offset); if (!buf->bo) return FALSE; } @@ -49,9 +50,9 @@ nv50_buffer_allocate(struct nv50_screen *screen, struct nv50_resource *buf, } static INLINE void -release_allocation(struct nv50_mm_allocation **mm, struct nouveau_fence *fence) +release_allocation(struct nouveau_mm_allocation **mm, struct nouveau_fence *fence) { - nouveau_fence_work(fence, nv50_mm_free, *mm); + nouveau_fence_work(fence, nouveau_mm_free, *mm); (*mm) = NULL; } @@ -94,13 +95,13 @@ boolean nv50_buffer_download(struct nv50_context *nv50, struct nv50_resource *buf, unsigned start, unsigned size) { - struct nv50_mm_allocation *mm; + struct nouveau_mm_allocation *mm; struct nouveau_bo *bounce = NULL; uint32_t offset; assert(buf->domain == NOUVEAU_BO_VRAM); - mm = nv50_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset); + mm = nouveau_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset); if (!bounce) return FALSE; @@ -117,7 +118,7 @@ nv50_buffer_download(struct nv50_context *nv50, struct nv50_resource *buf, nouveau_bo_ref(NULL, &bounce); if (mm) - nv50_mm_free(mm); + nouveau_mm_free(mm); return TRUE; } @@ -125,7 +126,7 @@ static boolean nv50_buffer_upload(struct nv50_context *nv50, struct nv50_resource *buf, unsigned start, unsigned size) { - struct nv50_mm_allocation *mm; + struct nouveau_mm_allocation *mm; struct nouveau_bo *bounce = NULL; uint32_t offset; @@ -135,7 +136,7 @@ nv50_buffer_upload(struct nv50_context *nv50, struct nv50_resource *buf, return TRUE; } - mm = nv50_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset); + mm = nouveau_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset); if (!bounce) return FALSE; @@ -429,7 +430,7 @@ nv50_buffer_migrate(struct nv50_context *nv50, FREE(buf->data); } else if (old_domain != 0 && new_domain != 0) { - struct nv50_mm_allocation *mm = buf->mm; + struct nouveau_mm_allocation *mm = buf->mm; if (new_domain == NOUVEAU_BO_VRAM) { /* keep a system memory copy of our data in case we hit a fallback */ diff --git a/src/gallium/drivers/nv50/nv50_mm.c b/src/gallium/drivers/nv50/nv50_mm.c deleted file mode 100644 index f991d6192e..0000000000 --- a/src/gallium/drivers/nv50/nv50_mm.c +++ /dev/null @@ -1,277 +0,0 @@ - -#include "util/u_inlines.h" -#include "util/u_memory.h" -#include "util/u_double_list.h" - -#include "nv50_screen.h" - -#define MM_MIN_ORDER 7 -#define MM_MAX_ORDER 20 - -#define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1) - -#define MM_MIN_SIZE (1 << MM_MIN_ORDER) -#define MM_MAX_SIZE (1 << MM_MAX_ORDER) - -struct mm_bucket { - struct list_head free; - struct list_head used; - struct list_head full; - int num_free; -}; - -struct nv50_mman { - struct nouveau_device *dev; - struct mm_bucket bucket[MM_NUM_BUCKETS]; - uint32_t storage_type; - uint32_t domain; - uint64_t allocated; -}; - -struct mm_slab { - struct list_head head; - struct nouveau_bo *bo; - struct nv50_mman *cache; - int order; - int count; - int free; - uint32_t bits[0]; -}; - -static int -mm_slab_alloc(struct mm_slab *slab) -{ - int i, n, b; - - if (slab->free == 0) - return -1; - - for (i = 0; i < (slab->count + 31) / 32; ++i) { - b = ffs(slab->bits[i]) - 1; - if (b >= 0) { - n = i * 32 + b; - assert(n < slab->count); - slab->free--; - slab->bits[i] &= ~(1 << b); - return n; - } - } - return -1; -} - -static INLINE void -mm_slab_free(struct mm_slab *slab, int i) -{ - assert(i < slab->count); - slab->bits[i / 32] |= 1 << (i % 32); - slab->free++; - assert(slab->free <= slab->count); -} - -static INLINE int -mm_get_order(uint32_t size) -{ - int s = __builtin_clz(size) ^ 31; - - if (size > (1 << s)) - s += 1; - return s; -} - -static struct mm_bucket * -mm_bucket_by_order(struct nv50_mman *cache, int order) -{ - if (order > MM_MAX_ORDER) - return NULL; - return &cache->bucket[MAX2(order, MM_MIN_ORDER) - MM_MIN_ORDER]; -} - -static struct mm_bucket * -mm_bucket_by_size(struct nv50_mman *cache, unsigned size) -{ - return mm_bucket_by_order(cache, mm_get_order(size)); -} - -/* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */ -static INLINE uint32_t -mm_default_slab_size(unsigned chunk_order) -{ - static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] = - { - 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22 - }; - - assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); - - return 1 << slab_order[chunk_order - MM_MIN_ORDER]; -} - -static int -mm_slab_new(struct nv50_mman *cache, int chunk_order) -{ - struct mm_slab *slab; - int words, ret; - const uint32_t size = mm_default_slab_size(chunk_order); - - words = ((size >> chunk_order) + 31) / 32; - assert(words); - - slab = MALLOC(sizeof(struct mm_slab) + words * 4); - if (!slab) - return PIPE_ERROR_OUT_OF_MEMORY; - - memset(&slab->bits[0], ~0, words * 4); - - slab->bo = NULL; - ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size, - 0, cache->storage_type, &slab->bo); - if (ret) { - FREE(slab); - return PIPE_ERROR_OUT_OF_MEMORY; - } - - LIST_INITHEAD(&slab->head); - - slab->cache = cache; - slab->order = chunk_order; - slab->count = slab->free = size >> chunk_order; - - LIST_ADD(&slab->head, &mm_bucket_by_order(cache, chunk_order)->free); - - cache->allocated += size; - - debug_printf("MM: new slab, total memory = %lu KiB\n", - cache->allocated / 1024); - - return PIPE_OK; -} - -/* @return token to identify slab or NULL if we just allocated a new bo */ -struct nv50_mm_allocation * -nv50_mm_allocate(struct nv50_mman *cache, - uint32_t size, struct nouveau_bo **bo, uint32_t *offset) -{ - struct mm_bucket *bucket; - struct mm_slab *slab; - struct nv50_mm_allocation *alloc; - int ret; - - bucket = mm_bucket_by_size(cache, size); - if (!bucket) { - ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size, - 0, cache->storage_type, bo); - if (ret) - debug_printf("bo_new(%x, %x): %i\n", size, cache->storage_type, ret); - - *offset = 0; - return NULL; - } - - if (!LIST_IS_EMPTY(&bucket->used)) { - slab = LIST_ENTRY(struct mm_slab, bucket->used.next, head); - } else { - if (LIST_IS_EMPTY(&bucket->free)) { - mm_slab_new(cache, MAX2(mm_get_order(size), MM_MIN_ORDER)); - } - slab = LIST_ENTRY(struct mm_slab, bucket->free.next, head); - - LIST_DEL(&slab->head); - LIST_ADD(&slab->head, &bucket->used); - } - - *offset = mm_slab_alloc(slab) << slab->order; - - alloc = MALLOC_STRUCT(nv50_mm_allocation); - if (!alloc) - return NULL; - - nouveau_bo_ref(slab->bo, bo); - - if (slab->free == 0) { - LIST_DEL(&slab->head); - LIST_ADD(&slab->head, &bucket->full); - } - - alloc->next = NULL; - alloc->offset = *offset; - alloc->priv = (void *)slab; - - return alloc; -} - -void -nv50_mm_free(struct nv50_mm_allocation *alloc) -{ - struct mm_slab *slab = (struct mm_slab *)alloc->priv; - struct mm_bucket *bucket = mm_bucket_by_order(slab->cache, slab->order); - - mm_slab_free(slab, alloc->offset >> slab->order); - - if (slab->free == 1) { - LIST_DEL(&slab->head); - - if (slab->count > 1) - LIST_ADDTAIL(&slab->head, &bucket->used); - else - LIST_ADDTAIL(&slab->head, &bucket->free); - } - - FREE(alloc); -} - -struct nv50_mman * -nv50_mm_create(struct nouveau_device *dev, uint32_t domain, - uint32_t storage_type) -{ - struct nv50_mman *cache = MALLOC_STRUCT(nv50_mman); - int i; - - if (!cache) - return NULL; - - cache->dev = dev; - cache->domain = domain; - cache->storage_type = storage_type; - cache->allocated = 0; - - for (i = 0; i < MM_NUM_BUCKETS; ++i) { - LIST_INITHEAD(&cache->bucket[i].free); - LIST_INITHEAD(&cache->bucket[i].used); - LIST_INITHEAD(&cache->bucket[i].full); - } - - return cache; -} - -static INLINE void -nv50_mm_free_slabs(struct list_head *head) -{ - struct mm_slab *slab, *next; - - LIST_FOR_EACH_ENTRY_SAFE(slab, next, head, head) { - LIST_DEL(&slab->head); - nouveau_bo_ref(NULL, &slab->bo); - FREE(slab); - } -} - -void -nv50_mm_destroy(struct nv50_mman *cache) -{ - int i; - - if (!cache) - return; - - for (i = 0; i < MM_NUM_BUCKETS; ++i) { - if (!LIST_IS_EMPTY(&cache->bucket[i].used) || - !LIST_IS_EMPTY(&cache->bucket[i].full)) - debug_printf("WARNING: destroying GPU memory cache " - "with some buffers still in use\n"); - - nv50_mm_free_slabs(&cache->bucket[i].free); - nv50_mm_free_slabs(&cache->bucket[i].used); - nv50_mm_free_slabs(&cache->bucket[i].full); - } -} - diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 42391ec5b1..8a2bca6850 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -41,7 +41,7 @@ struct nv50_query { uint32_t offset; /* base + i * 16 */ boolean ready; boolean is64bit; - struct nv50_mm_allocation *mm; + struct nouveau_mm_allocation *mm; }; #define NV50_QUERY_ALLOC_SPACE 128 @@ -62,13 +62,13 @@ nv50_query_allocate(struct nv50_context *nv50, struct nv50_query *q, int size) nouveau_bo_ref(NULL, &q->bo); if (q->mm) { if (q->ready) - nv50_mm_free(q->mm); + nouveau_mm_free(q->mm); else - nouveau_fence_work(screen->base.fence.current, nv50_mm_free, q->mm); + nouveau_fence_work(screen->base.fence.current, nouveau_mm_free, q->mm); } } if (size) { - q->mm = nv50_mm_allocate(screen->mm_GART, size, &q->bo, &q->base); + q->mm = nouveau_mm_allocate(screen->mm_GART, size, &q->bo, &q->base); if (!q->bo) return FALSE; q->offset = q->base; diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h index f42179c88f..64563421fd 100644 --- a/src/gallium/drivers/nv50/nv50_resource.h +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -46,7 +46,7 @@ struct nv50_resource { struct nouveau_fence *fence; struct nouveau_fence *fence_wr; - struct nv50_mm_allocation *mm; + struct nouveau_mm_allocation *mm; }; void diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index e5b50103ef..bd645b8716 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -229,9 +229,9 @@ nv50_screen_destroy(struct pipe_screen *pscreen) if (screen->tic.entries) FREE(screen->tic.entries); - nv50_mm_destroy(screen->mm_GART); - nv50_mm_destroy(screen->mm_VRAM); - nv50_mm_destroy(screen->mm_VRAM_fe0); + nouveau_mm_destroy(screen->mm_GART); + nouveau_mm_destroy(screen->mm_VRAM); + nouveau_mm_destroy(screen->mm_VRAM_fe0); nouveau_grobj_free(&screen->tesla); nouveau_grobj_free(&screen->eng2d); @@ -586,10 +586,10 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) screen->tic.entries = CALLOC(4096, sizeof(void *)); screen->tsc.entries = screen->tic.entries + 2048; - screen->mm_GART = nv50_mm_create(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0x000); - screen->mm_VRAM = nv50_mm_create(dev, NOUVEAU_BO_VRAM, 0x000); - screen->mm_VRAM_fe0 = nv50_mm_create(dev, NOUVEAU_BO_VRAM, 0xfe0); + screen->mm_GART = nouveau_mm_create(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0x000); + screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0x000); + screen->mm_VRAM_fe0 = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0xfe0); nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index c2ec3b58dc..672891b6b7 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -4,6 +4,7 @@ #define NOUVEAU_NVC0 #include "nouveau/nouveau_screen.h" #include "nouveau/nouveau_fence.h" +#include "nouveau/nouveau_mm.h" #undef NOUVEAU_NVC0 #include "nv50_winsys.h" #include "nv50_stateobj.h" @@ -11,7 +12,6 @@ #define NV50_TIC_MAX_ENTRIES 2048 #define NV50_TSC_MAX_ENTRIES 2048 -struct nv50_mman; struct nv50_context; #define NV50_SCRATCH_SIZE (2 << 20) @@ -54,9 +54,9 @@ struct nv50_screen { struct nouveau_notifier *sync; - struct nv50_mman *mm_GART; - struct nv50_mman *mm_VRAM; - struct nv50_mman *mm_VRAM_fe0; + struct nouveau_mman *mm_GART; + struct nouveau_mman *mm_VRAM; + struct nouveau_mman *mm_VRAM_fe0; struct nouveau_grobj *tesla; struct nouveau_grobj *eng2d; @@ -69,27 +69,6 @@ nv50_screen(struct pipe_screen *screen) return (struct nv50_screen *)screen; } -/* Since a resource can be migrated, we need to decouple allocations from - * them. This struct is linked with fences for delayed freeing of allocs. - */ -struct nv50_mm_allocation { - struct nv50_mm_allocation *next; - void *priv; - uint32_t offset; -}; - -extern struct nv50_mman * -nv50_mm_create(struct nouveau_device *, uint32_t domain, uint32_t storage_type); - -extern void -nv50_mm_destroy(struct nv50_mman *); - -extern struct nv50_mm_allocation * -nv50_mm_allocate(struct nv50_mman *, - uint32_t size, struct nouveau_bo **, uint32_t *offset); -extern void -nv50_mm_free(struct nv50_mm_allocation *); - void nv50_screen_make_buffers_resident(struct nv50_screen *); int nv50_screen_tic_alloc(struct nv50_screen *, void *); -- cgit v1.2.3 From cd24fcedecfc41d77047fb827a88db528ed292ca Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Mar 2011 10:49:36 +1000 Subject: nouveau: create linear gart/vram mman in common screen init Signed-off-by: Ben Skeggs --- src/gallium/drivers/nouveau/nouveau_screen.c | 9 +++++++++ src/gallium/drivers/nouveau/nouveau_screen.h | 3 +++ src/gallium/drivers/nv50/nv50_buffer.c | 12 ++++++------ src/gallium/drivers/nv50/nv50_query.c | 2 +- src/gallium/drivers/nv50/nv50_screen.c | 5 ----- src/gallium/drivers/nv50/nv50_screen.h | 2 -- 6 files changed, 19 insertions(+), 14 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index e14f2346a3..e6cd3064c9 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -251,6 +251,10 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) util_format_s3tc_init(); + screen->mm_GART = nouveau_mm_create(dev, + NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + 0x000); + screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0x000); return 0; } @@ -258,7 +262,12 @@ void nouveau_screen_fini(struct nouveau_screen *screen) { struct pipe_winsys *ws = screen->base.winsys; + + nouveau_mm_destroy(screen->mm_GART); + nouveau_mm_destroy(screen->mm_VRAM); + nouveau_channel_free(&screen->channel); + if (ws) ws->destroy(ws); } diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index e4a460ec65..173592d6ea 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -24,6 +24,9 @@ struct nouveau_screen { void (*emit)(struct pipe_screen *, u32 sequence); u32 (*update)(struct pipe_screen *); } fence; + + struct nouveau_mman *mm_VRAM; + struct nouveau_mman *mm_GART; }; static INLINE struct nouveau_screen * diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c index 7b2b47a1e0..ae65591e7f 100644 --- a/src/gallium/drivers/nv50/nv50_buffer.c +++ b/src/gallium/drivers/nv50/nv50_buffer.c @@ -27,14 +27,14 @@ nv50_buffer_allocate(struct nv50_screen *screen, struct nv50_resource *buf, unsigned domain) { if (domain == NOUVEAU_BO_VRAM) { - buf->mm = nouveau_mm_allocate(screen->mm_VRAM, buf->base.width0, &buf->bo, - &buf->offset); + buf->mm = nouveau_mm_allocate(screen->base.mm_VRAM, buf->base.width0, + &buf->bo, &buf->offset); if (!buf->bo) return nv50_buffer_allocate(screen, buf, NOUVEAU_BO_GART); } else if (domain == NOUVEAU_BO_GART) { - buf->mm = nouveau_mm_allocate(screen->mm_GART, buf->base.width0, &buf->bo, - &buf->offset); + buf->mm = nouveau_mm_allocate(screen->base.mm_GART, buf->base.width0, + &buf->bo, &buf->offset); if (!buf->bo) return FALSE; } @@ -101,7 +101,7 @@ nv50_buffer_download(struct nv50_context *nv50, struct nv50_resource *buf, assert(buf->domain == NOUVEAU_BO_VRAM); - mm = nouveau_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset); + mm = nouveau_mm_allocate(nv50->screen->base.mm_GART, size, &bounce, &offset); if (!bounce) return FALSE; @@ -136,7 +136,7 @@ nv50_buffer_upload(struct nv50_context *nv50, struct nv50_resource *buf, return TRUE; } - mm = nouveau_mm_allocate(nv50->screen->mm_GART, size, &bounce, &offset); + mm = nouveau_mm_allocate(nv50->screen->base.mm_GART, size, &bounce, &offset); if (!bounce) return FALSE; diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 2803626d18..2e65c54e54 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -68,7 +68,7 @@ nv50_query_allocate(struct nv50_context *nv50, struct nv50_query *q, int size) } } if (size) { - q->mm = nouveau_mm_allocate(screen->mm_GART, size, &q->bo, &q->base); + q->mm = nouveau_mm_allocate(screen->base.mm_GART, size, &q->bo, &q->base); if (!q->bo) return FALSE; q->offset = q->base; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index bd645b8716..f2b03e8156 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -229,8 +229,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen) if (screen->tic.entries) FREE(screen->tic.entries); - nouveau_mm_destroy(screen->mm_GART); - nouveau_mm_destroy(screen->mm_VRAM); nouveau_mm_destroy(screen->mm_VRAM_fe0); nouveau_grobj_free(&screen->tesla); @@ -586,9 +584,6 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) screen->tic.entries = CALLOC(4096, sizeof(void *)); screen->tsc.entries = screen->tic.entries + 2048; - screen->mm_GART = nouveau_mm_create(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, - 0x000); - screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0x000); screen->mm_VRAM_fe0 = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, 0xfe0); nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 672891b6b7..3bf67eb656 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -54,8 +54,6 @@ struct nv50_screen { struct nouveau_notifier *sync; - struct nouveau_mman *mm_GART; - struct nouveau_mman *mm_VRAM; struct nouveau_mman *mm_VRAM_fe0; struct nouveau_grobj *tesla; -- cgit v1.2.3 From 79079141fa7cbf395d1ffc77364ac301d9824211 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Mar 2011 12:26:20 +1000 Subject: nv50: move onto common linear buffer manager Signed-off-by: Ben Skeggs --- src/gallium/drivers/nouveau/nouveau_buffer.h | 4 +- src/gallium/drivers/nv50/Makefile | 1 - src/gallium/drivers/nv50/nv50_buffer.c | 491 --------------------------- src/gallium/drivers/nv50/nv50_context.c | 6 +- src/gallium/drivers/nv50/nv50_context.h | 10 +- src/gallium/drivers/nv50/nv50_push.c | 16 +- src/gallium/drivers/nv50/nv50_resource.c | 6 +- src/gallium/drivers/nv50/nv50_resource.h | 141 +------- src/gallium/drivers/nv50/nv50_screen.c | 2 + src/gallium/drivers/nv50/nv50_screen.h | 4 +- src/gallium/drivers/nv50/nv50_shader_state.c | 14 +- src/gallium/drivers/nv50/nv50_state.c | 3 +- src/gallium/drivers/nv50/nv50_tex.c | 7 +- src/gallium/drivers/nv50/nv50_transfer.c | 8 +- src/gallium/drivers/nv50/nv50_vbo.c | 41 +-- src/gallium/drivers/nv50/nv50_winsys.h | 10 +- 16 files changed, 74 insertions(+), 690 deletions(-) delete mode 100644 src/gallium/drivers/nv50/nv50_buffer.c (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.h b/src/gallium/drivers/nouveau/nouveau_buffer.h index e0d75dcc9f..d75bc4e0c3 100644 --- a/src/gallium/drivers/nouveau/nouveau_buffer.h +++ b/src/gallium/drivers/nouveau/nouveau_buffer.h @@ -1,5 +1,5 @@ -#ifndef __NOUVEAU_RESOURCE_H__ -#define __NOUVEAU_RESOURCE_H__ +#ifndef __NOUVEAU_BUFFER_H__ +#define __NOUVEAU_BUFFER_H__ #include "util/u_transfer.h" #include "util/u_double_list.h" diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index dc9ea0eeba..02bcc26cfb 100644 --- a/src/gallium/drivers/nv50/Makefile +++ b/src/gallium/drivers/nv50/Makefile @@ -4,7 +4,6 @@ include $(TOP)/configs/current LIBNAME = nv50 C_SOURCES = \ - nv50_buffer.c \ nv50_context.c \ nv50_draw.c \ nv50_formats.c \ diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c deleted file mode 100644 index ae65591e7f..0000000000 --- a/src/gallium/drivers/nv50/nv50_buffer.c +++ /dev/null @@ -1,491 +0,0 @@ - -#include "util/u_inlines.h" -#include "util/u_memory.h" -#include "util/u_math.h" - -#define NOUVEAU_NVC0 -#include "nouveau/nouveau_screen.h" -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_mm.h" -#undef NOUVEAU_NVC0 - -#include "nv50_context.h" -#include "nv50_resource.h" - -struct nv50_transfer { - struct pipe_transfer base; -}; - -static INLINE struct nv50_transfer * -nv50_transfer(struct pipe_transfer *transfer) -{ - return (struct nv50_transfer *)transfer; -} - -static INLINE boolean -nv50_buffer_allocate(struct nv50_screen *screen, struct nv50_resource *buf, - unsigned domain) -{ - if (domain == NOUVEAU_BO_VRAM) { - buf->mm = nouveau_mm_allocate(screen->base.mm_VRAM, buf->base.width0, - &buf->bo, &buf->offset); - if (!buf->bo) - return nv50_buffer_allocate(screen, buf, NOUVEAU_BO_GART); - } else - if (domain == NOUVEAU_BO_GART) { - buf->mm = nouveau_mm_allocate(screen->base.mm_GART, buf->base.width0, - &buf->bo, &buf->offset); - if (!buf->bo) - return FALSE; - } - if (domain != NOUVEAU_BO_GART) { - if (!buf->data) { - buf->data = MALLOC(buf->base.width0); - if (!buf->data) - return FALSE; - } - } - buf->domain = domain; - return TRUE; -} - -static INLINE void -release_allocation(struct nouveau_mm_allocation **mm, struct nouveau_fence *fence) -{ - nouveau_fence_work(fence, nouveau_mm_free_work, *mm); - (*mm) = NULL; -} - -INLINE void -nv50_buffer_release_gpu_storage(struct nv50_resource *buf) -{ - nouveau_bo_ref(NULL, &buf->bo); - - if (buf->mm) - release_allocation(&buf->mm, buf->fence); - - buf->domain = 0; -} - -static INLINE boolean -nv50_buffer_reallocate(struct nv50_screen *screen, struct nv50_resource *buf, - unsigned domain) -{ - nv50_buffer_release_gpu_storage(buf); - - return nv50_buffer_allocate(screen, buf, domain); -} - -static void -nv50_buffer_destroy(struct pipe_screen *pscreen, - struct pipe_resource *presource) -{ - struct nv50_resource *res = nv50_resource(presource); - - nv50_buffer_release_gpu_storage(res); - - if (res->data && !(res->status & NV50_BUFFER_STATUS_USER_MEMORY)) - FREE(res->data); - - FREE(res); -} - -/* Maybe just migrate to GART right away if we actually need to do this. */ -boolean -nv50_buffer_download(struct nv50_context *nv50, struct nv50_resource *buf, - unsigned start, unsigned size) -{ - struct nouveau_mm_allocation *mm; - struct nouveau_bo *bounce = NULL; - uint32_t offset; - - assert(buf->domain == NOUVEAU_BO_VRAM); - - mm = nouveau_mm_allocate(nv50->screen->base.mm_GART, size, &bounce, &offset); - if (!bounce) - return FALSE; - - nv50_m2mf_copy_linear(nv50, bounce, offset, NOUVEAU_BO_GART, - buf->bo, buf->offset + start, NOUVEAU_BO_VRAM, - size); - - if (nouveau_bo_map_range(bounce, offset, size, NOUVEAU_BO_RD)) - return FALSE; - memcpy(buf->data + start, bounce->map, size); - nouveau_bo_unmap(bounce); - - buf->status &= ~NV50_BUFFER_STATUS_DIRTY; - - nouveau_bo_ref(NULL, &bounce); - if (mm) - nouveau_mm_free(mm); - return TRUE; -} - -static boolean -nv50_buffer_upload(struct nv50_context *nv50, struct nv50_resource *buf, - unsigned start, unsigned size) -{ - struct nouveau_mm_allocation *mm; - struct nouveau_bo *bounce = NULL; - uint32_t offset; - - if (size <= 192) { - nv50_sifc_linear_u8(nv50, buf->bo, buf->domain, buf->offset + start, - size, buf->data + start); - return TRUE; - } - - mm = nouveau_mm_allocate(nv50->screen->base.mm_GART, size, &bounce, &offset); - if (!bounce) - return FALSE; - - nouveau_bo_map_range(bounce, offset, size, - NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC); - memcpy(bounce->map, buf->data + start, size); - nouveau_bo_unmap(bounce); - - nv50_m2mf_copy_linear(nv50, buf->bo, buf->offset + start, NOUVEAU_BO_VRAM, - bounce, offset, NOUVEAU_BO_GART, size); - - nouveau_bo_ref(NULL, &bounce); - if (mm) - release_allocation(&mm, nv50->screen->base.fence.current); - - if (start == 0 && size == buf->base.width0) - buf->status &= ~NV50_BUFFER_STATUS_DIRTY; - return TRUE; -} - -static struct pipe_transfer * -nv50_buffer_transfer_get(struct pipe_context *pipe, - struct pipe_resource *resource, - unsigned level, - unsigned usage, - const struct pipe_box *box) -{ - struct nv50_resource *buf = nv50_resource(resource); - struct nv50_transfer *xfr = CALLOC_STRUCT(nv50_transfer); - if (!xfr) - return NULL; - - xfr->base.resource = resource; - xfr->base.box.x = box->x; - xfr->base.box.width = box->width; - xfr->base.usage = usage; - - if (buf->domain == NOUVEAU_BO_VRAM) { - if (usage & PIPE_TRANSFER_READ) { - if (buf->status & NV50_BUFFER_STATUS_DIRTY) - nv50_buffer_download(nv50_context(pipe), buf, 0, buf->base.width0); - } - } - - return &xfr->base; -} - -static void -nv50_buffer_transfer_destroy(struct pipe_context *pipe, - struct pipe_transfer *transfer) -{ - struct nv50_resource *buf = nv50_resource(transfer->resource); - struct nv50_transfer *xfr = nv50_transfer(transfer); - - if (xfr->base.usage & PIPE_TRANSFER_WRITE) { - /* writing is worse */ - nv50_buffer_adjust_score(nv50_context(pipe), buf, -5000); - - if (buf->domain == NOUVEAU_BO_VRAM) { - nv50_buffer_upload(nv50_context(pipe), buf, - transfer->box.x, transfer->box.width); - } - - if (buf->domain != 0 && (buf->base.bind & (PIPE_BIND_VERTEX_BUFFER | - PIPE_BIND_INDEX_BUFFER))) - nv50_context(pipe)->vbo_dirty = TRUE; - } - - FREE(xfr); -} - -static INLINE boolean -nv50_buffer_sync(struct nv50_resource *buf, unsigned rw) -{ - if (rw == PIPE_TRANSFER_READ) { - if (!buf->fence_wr) - return TRUE; - if (!nouveau_fence_wait(buf->fence_wr)) - return FALSE; - } else { - if (!buf->fence) - return TRUE; - if (!nouveau_fence_wait(buf->fence)) - return FALSE; - - nouveau_fence_ref(NULL, &buf->fence); - } - nouveau_fence_ref(NULL, &buf->fence_wr); - - return TRUE; -} - -static INLINE boolean -nv50_buffer_busy(struct nv50_resource *buf, unsigned rw) -{ - if (rw == PIPE_TRANSFER_READ) - return (buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)); - else - return (buf->fence && !nouveau_fence_signalled(buf->fence)); -} - -static void * -nv50_buffer_transfer_map(struct pipe_context *pipe, - struct pipe_transfer *transfer) -{ - struct nv50_transfer *xfr = nv50_transfer(transfer); - struct nv50_resource *buf = nv50_resource(transfer->resource); - struct nouveau_bo *bo = buf->bo; - uint8_t *map; - int ret; - uint32_t offset = xfr->base.box.x; - uint32_t flags; - - nv50_buffer_adjust_score(nv50_context(pipe), buf, -250); - - if (buf->domain != NOUVEAU_BO_GART) - return buf->data + offset; - - if (buf->mm) - flags = NOUVEAU_BO_NOSYNC | NOUVEAU_BO_RDWR; - else - flags = nouveau_screen_transfer_flags(xfr->base.usage); - - offset += buf->offset; - - ret = nouveau_bo_map_range(buf->bo, offset, xfr->base.box.width, flags); - if (ret) - return NULL; - map = bo->map; - - /* Unmap right now. Since multiple buffers can share a single nouveau_bo, - * not doing so might make future maps fail or trigger "reloc while mapped" - * errors. For now, mappings to userspace are guaranteed to be persistent. - */ - nouveau_bo_unmap(bo); - - if (buf->mm) { - if (xfr->base.usage & PIPE_TRANSFER_DONTBLOCK) { - if (nv50_buffer_busy(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE)) - return NULL; - } else - if (!(xfr->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { - nv50_buffer_sync(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE); - } - } - return map; -} - - - -static void -nv50_buffer_transfer_flush_region(struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - struct nv50_resource *res = nv50_resource(transfer->resource); - struct nouveau_bo *bo = res->bo; - unsigned offset = res->offset + transfer->box.x + box->x; - - /* not using non-snoop system memory yet, no need for cflush */ - if (1) - return; - - /* XXX: maybe need to upload for VRAM buffers here */ - - nouveau_screen_bo_map_flush_range(pipe->screen, bo, offset, box->width); -} - -static void -nv50_buffer_transfer_unmap(struct pipe_context *pipe, - struct pipe_transfer *transfer) -{ - /* we've called nouveau_bo_unmap right after map */ -} - -const struct u_resource_vtbl nv50_buffer_vtbl = -{ - u_default_resource_get_handle, /* get_handle */ - nv50_buffer_destroy, /* resource_destroy */ - NULL, /* is_resource_referenced */ - nv50_buffer_transfer_get, /* get_transfer */ - nv50_buffer_transfer_destroy, /* transfer_destroy */ - nv50_buffer_transfer_map, /* transfer_map */ - nv50_buffer_transfer_flush_region, /* transfer_flush_region */ - nv50_buffer_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ -}; - -struct pipe_resource * -nv50_buffer_create(struct pipe_screen *pscreen, - const struct pipe_resource *templ) -{ - struct nv50_screen *screen = nv50_screen(pscreen); - struct nv50_resource *buffer; - boolean ret; - - buffer = CALLOC_STRUCT(nv50_resource); - if (!buffer) - return NULL; - - buffer->base = *templ; - buffer->vtbl = &nv50_buffer_vtbl; - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.screen = pscreen; - - if (buffer->base.bind & PIPE_BIND_CONSTANT_BUFFER) - ret = nv50_buffer_allocate(screen, buffer, 0); - else - ret = nv50_buffer_allocate(screen, buffer, NOUVEAU_BO_GART); - - if (ret == FALSE) - goto fail; - - return &buffer->base; - -fail: - FREE(buffer); - return NULL; -} - - -struct pipe_resource * -nv50_user_buffer_create(struct pipe_screen *pscreen, - void *ptr, - unsigned bytes, - unsigned bind) -{ - struct nv50_resource *buffer; - - buffer = CALLOC_STRUCT(nv50_resource); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->vtbl = &nv50_buffer_vtbl; - buffer->base.screen = pscreen; - buffer->base.format = PIPE_FORMAT_R8_UNORM; - buffer->base.usage = PIPE_USAGE_IMMUTABLE; - buffer->base.bind = bind; - buffer->base.width0 = bytes; - buffer->base.height0 = 1; - buffer->base.depth0 = 1; - - buffer->data = ptr; - buffer->status = NV50_BUFFER_STATUS_USER_MEMORY; - - return &buffer->base; -} - -/* Like download, but for GART buffers. Merge ? */ -static INLINE boolean -nv50_buffer_data_fetch(struct nv50_resource *buf, - struct nouveau_bo *bo, unsigned offset, unsigned size) -{ - if (!buf->data) { - buf->data = MALLOC(size); - if (!buf->data) - return FALSE; - } - if (nouveau_bo_map_range(bo, offset, size, NOUVEAU_BO_RD)) - return FALSE; - memcpy(buf->data, bo->map, size); - nouveau_bo_unmap(bo); - - return TRUE; -} - -/* Migrate a linear buffer (vertex, index, constants) USER -> GART -> VRAM. */ -boolean -nv50_buffer_migrate(struct nv50_context *nv50, - struct nv50_resource *buf, const unsigned new_domain) -{ - struct nv50_screen *screen = nv50_screen(buf->base.screen); - struct nouveau_bo *bo; - const unsigned old_domain = buf->domain; - unsigned size = buf->base.width0; - unsigned offset; - int ret; - - assert(new_domain != old_domain); - - if (new_domain == NOUVEAU_BO_GART && old_domain == 0) { - if (!nv50_buffer_allocate(screen, buf, new_domain)) - return FALSE; - ret = nouveau_bo_map_range(buf->bo, buf->offset, size, NOUVEAU_BO_WR | - NOUVEAU_BO_NOSYNC); - if (ret) - return ret; - memcpy(buf->bo->map, buf->data, size); - nouveau_bo_unmap(buf->bo); - FREE(buf->data); - } else - if (old_domain != 0 && new_domain != 0) { - struct nouveau_mm_allocation *mm = buf->mm; - - if (new_domain == NOUVEAU_BO_VRAM) { - /* keep a system memory copy of our data in case we hit a fallback */ - if (!nv50_buffer_data_fetch(buf, buf->bo, buf->offset, size)) - return FALSE; - debug_printf("migrating %u KiB to VRAM\n", size / 1024); - } - - offset = buf->offset; - bo = buf->bo; - buf->bo = NULL; - buf->mm = NULL; - nv50_buffer_allocate(screen, buf, new_domain); - - nv50_m2mf_copy_linear(nv50, buf->bo, buf->offset, new_domain, - bo, offset, old_domain, buf->base.width0); - - nouveau_bo_ref(NULL, &bo); - if (mm) - 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)) - return FALSE; - if (!nv50_buffer_upload(nv50, buf, 0, buf->base.width0)) - return FALSE; - } else - return FALSE; - - assert(buf->domain == new_domain); - return TRUE; -} - -/* Migrate data from glVertexAttribPointer(non-VBO) user buffers to GART. - * We'd like to only allocate @size bytes here, but then we'd have to rebase - * the vertex indices ... - */ -boolean -nv50_user_buffer_upload(struct nv50_resource *buf, unsigned base, unsigned size) -{ - struct nv50_screen *screen = nv50_screen(buf->base.screen); - int ret; - - assert(buf->status & NV50_BUFFER_STATUS_USER_MEMORY); - - buf->base.width0 = base + size; - if (!nv50_buffer_reallocate(screen, buf, NOUVEAU_BO_GART)) - return FALSE; - - ret = nouveau_bo_map_range(buf->bo, buf->offset + base, size, - NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC); - if (ret) - return FALSE; - memcpy(buf->bo->map, buf->data + base, size); - nouveau_bo_unmap(buf->bo); - - return TRUE; -} diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 4380945a1e..03a5c3d2d9 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -119,13 +119,13 @@ nv50_create(struct pipe_screen *pscreen, void *priv) } struct resident { - struct nv50_resource *res; + struct nv04_resource *res; uint32_t flags; }; void nv50_bufctx_add_resident(struct nv50_context *nv50, int ctx, - struct nv50_resource *resource, uint32_t flags) + struct nv04_resource *resource, uint32_t flags) { struct resident rsd = { resource, flags }; @@ -140,7 +140,7 @@ nv50_bufctx_add_resident(struct nv50_context *nv50, int ctx, void nv50_bufctx_del_resident(struct nv50_context *nv50, int ctx, - struct nv50_resource *resource) + struct nv04_resource *resource) { struct resident *rsd, *top; unsigned i; diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index a6275d7958..55d996da27 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -155,9 +155,9 @@ void nv50_default_flush_notify(struct nouveau_channel *); void nv50_bufctx_emit_relocs(struct nv50_context *); void nv50_bufctx_add_resident(struct nv50_context *, int ctx, - struct nv50_resource *, uint32_t flags); + struct nv04_resource *, uint32_t flags); void nv50_bufctx_del_resident(struct nv50_context *, int ctx, - struct nv50_resource *); + struct nv04_resource *); static INLINE void nv50_bufctx_reset(struct nv50_context *nv50, int ctx) { @@ -204,11 +204,11 @@ nv50_create_sampler_view(struct pipe_context *, /* nv50_transfer.c */ void -nv50_sifc_linear_u8(struct nv50_context *nv50, - struct nouveau_bo *dst, unsigned domain, int offset, +nv50_sifc_linear_u8(struct pipe_context *pipe, + struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, void *data); void -nv50_m2mf_copy_linear(struct nv50_context *nv50, +nv50_m2mf_copy_linear(struct pipe_context *pipe, struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, unsigned size); diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c index 51ada6d749..07034bdcf6 100644 --- a/src/gallium/drivers/nv50/nv50_push.c +++ b/src/gallium/drivers/nv50/nv50_push.c @@ -227,10 +227,10 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info) for (i = 0; i < nv50->num_vtxbufs; ++i) { uint8_t *data; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - struct nv50_resource *res = nv50_resource(vb->buffer); + struct nv04_resource *res = nv04_resource(vb->buffer); - data = nv50_resource_map_offset(nv50, res, - vb->buffer_offset, NOUVEAU_BO_RD); + data = nouveau_resource_map_offset(&nv50->pipe, res, + vb->buffer_offset, NOUVEAU_BO_RD); if (apply_bias && likely(!(nv50->vertex->instance_bufs & (1 << i)))) data += info->index_bias * vb->stride; @@ -239,9 +239,9 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info) } if (info->indexed) { - ctx.idxbuf = nv50_resource_map_offset(nv50, - nv50_resource(nv50->idxbuf.buffer), - nv50->idxbuf.offset, NOUVEAU_BO_RD); + ctx.idxbuf = nouveau_resource_map_offset(&nv50->pipe, + nv04_resource(nv50->idxbuf.buffer), + nv50->idxbuf.offset, NOUVEAU_BO_RD); if (!ctx.idxbuf) return; index_size = nv50->idxbuf.index_size; @@ -285,8 +285,8 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info) } if (info->indexed) - nv50_resource_unmap(nv50_resource(nv50->idxbuf.buffer)); + nouveau_resource_unmap(nv04_resource(nv50->idxbuf.buffer)); for (i = 0; i < nv50->num_vtxbufs; ++i) - nv50_resource_unmap(nv50_resource(nv50->vtxbuf[i].buffer)); + nouveau_resource_unmap(nv04_resource(nv50->vtxbuf[i].buffer)); } diff --git a/src/gallium/drivers/nv50/nv50_resource.c b/src/gallium/drivers/nv50/nv50_resource.c index ae1a2bf55d..2a2fb0e32b 100644 --- a/src/gallium/drivers/nv50/nv50_resource.c +++ b/src/gallium/drivers/nv50/nv50_resource.c @@ -8,7 +8,7 @@ nv50_resource_is_referenced(struct pipe_context *pipe, struct pipe_resource *resource, unsigned face, int layer) { - struct nv50_resource *res = nv50_resource(resource); + struct nv04_resource *res = nv04_resource(resource); unsigned flags = 0; unsigned bo_flags = nouveau_bo_pending(res->bo); @@ -26,7 +26,7 @@ nv50_resource_create(struct pipe_screen *screen, { switch (templ->target) { case PIPE_BUFFER: - return nv50_buffer_create(screen, templ); + return nouveau_buffer_create(screen, templ); default: return nv50_miptree_create(screen, templ); } @@ -64,5 +64,5 @@ nv50_screen_init_resource_functions(struct pipe_screen *pscreen) pscreen->resource_from_handle = nv50_resource_from_handle; pscreen->resource_get_handle = u_resource_get_handle_vtbl; pscreen->resource_destroy = u_resource_destroy_vtbl; - pscreen->user_buffer_create = nv50_user_buffer_create; + pscreen->user_buffer_create = nouveau_user_buffer_create; } diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h index 64563421fd..76229298f7 100644 --- a/src/gallium/drivers/nv50/nv50_resource.h +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -6,112 +6,14 @@ #include "util/u_double_list.h" #define NOUVEAU_NVC0 #include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_buffer.h" #undef NOUVEAU_NVC0 -struct pipe_resource; -struct nouveau_bo; -struct nv50_context; - -#define NV50_BUFFER_SCORE_MIN -25000 -#define NV50_BUFFER_SCORE_MAX 25000 -#define NV50_BUFFER_SCORE_VRAM_THRESHOLD 20000 - -/* DIRTY: buffer was (or will be after the next flush) written to by GPU and - * resource->data has not been updated to reflect modified VRAM contents - * - * USER_MEMORY: resource->data is a pointer to client memory and may change - * between GL calls - */ -#define NV50_BUFFER_STATUS_DIRTY (1 << 0) -#define NV50_BUFFER_STATUS_USER_MEMORY (1 << 7) - -/* Resources, if mapped into the GPU's address space, are guaranteed to - * have constant virtual addresses. - * The address of a resource will lie within the nouveau_bo referenced, - * and this bo should be added to the memory manager's validation list. - */ -struct nv50_resource { - struct pipe_resource base; - const struct u_resource_vtbl *vtbl; - - uint8_t *data; - struct nouveau_bo *bo; - uint32_t offset; - - uint8_t status; - uint8_t domain; - - int16_t score; /* low if mapped very often, if high can move to VRAM */ - - struct nouveau_fence *fence; - struct nouveau_fence *fence_wr; - - struct nouveau_mm_allocation *mm; -}; - void -nv50_buffer_release_gpu_storage(struct nv50_resource *); - -boolean -nv50_buffer_download(struct nv50_context *, struct nv50_resource *, - unsigned start, unsigned size); - -boolean -nv50_buffer_migrate(struct nv50_context *, - struct nv50_resource *, unsigned domain); - -static INLINE void -nv50_buffer_adjust_score(struct nv50_context *nv50, struct nv50_resource *res, - int16_t score) -{ - if (score < 0) { - if (res->score > NV50_BUFFER_SCORE_MIN) - res->score += score; - } else - if (score > 0){ - if (res->score < NV50_BUFFER_SCORE_MAX) - res->score += score; - if (res->domain == NOUVEAU_BO_GART && - res->score > NV50_BUFFER_SCORE_VRAM_THRESHOLD) - nv50_buffer_migrate(nv50, res, NOUVEAU_BO_VRAM); - } -} - -/* XXX: wait for fence (atm only using this for vertex push) */ -static INLINE void * -nv50_resource_map_offset(struct nv50_context *nv50, - struct nv50_resource *res, uint32_t offset, - uint32_t flags) -{ - void *map; - - nv50_buffer_adjust_score(nv50, res, -250); - - if ((res->domain == NOUVEAU_BO_VRAM) && - (res->status & NV50_BUFFER_STATUS_DIRTY)) - nv50_buffer_download(nv50, res, 0, res->base.width0); - - if ((res->domain != NOUVEAU_BO_GART) || - (res->status & NV50_BUFFER_STATUS_USER_MEMORY)) - return res->data + offset; - - if (res->mm) - flags |= NOUVEAU_BO_NOSYNC; - - if (nouveau_bo_map_range(res->bo, res->offset + offset, - res->base.width0, flags)) - return NULL; - - map = res->bo->map; - nouveau_bo_unmap(res->bo); - return map; -} +nv50_init_resource_functions(struct pipe_context *pcontext); -static INLINE void -nv50_resource_unmap(struct nv50_resource *res) -{ - /* no-op */ -} +void +nv50_screen_init_resource_functions(struct pipe_screen *pscreen); #define NV50_TILE_DIM_SHIFT(m, d) (((m) >> (d * 4)) & 0xf) @@ -133,7 +35,7 @@ struct nv50_miptree_level { #define NV50_MAX_TEXTURE_LEVELS 16 struct nv50_miptree { - struct nv50_resource base; + struct nv04_resource base; struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS]; uint32_t total_size; uint32_t layer_stride; @@ -146,25 +48,6 @@ nv50_miptree(struct pipe_resource *pt) return (struct nv50_miptree *)pt; } -static INLINE struct nv50_resource * -nv50_resource(struct pipe_resource *resource) -{ - return (struct nv50_resource *)resource; -} - -/* is resource mapped into the GPU's address space (i.e. VRAM or GART) ? */ -static INLINE boolean -nv50_resource_mapped_by_gpu(struct pipe_resource *resource) -{ - return nv50_resource(resource)->domain != 0; -} - -void -nv50_init_resource_functions(struct pipe_context *pcontext); - -void -nv50_screen_init_resource_functions(struct pipe_screen *pscreen); - /* Internal functions: */ struct pipe_resource * @@ -176,17 +59,6 @@ nv50_miptree_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *template, struct winsys_handle *whandle); -struct pipe_resource * -nv50_buffer_create(struct pipe_screen *pscreen, - const struct pipe_resource *templ); - -struct pipe_resource * -nv50_user_buffer_create(struct pipe_screen *screen, - void *ptr, - unsigned bytes, - unsigned usage); - - struct pipe_surface * nv50_miptree_surface_new(struct pipe_context *, struct pipe_resource *, @@ -195,7 +67,4 @@ nv50_miptree_surface_new(struct pipe_context *, void nv50_miptree_surface_del(struct pipe_context *, struct pipe_surface *); -boolean -nv50_user_buffer_upload(struct nv50_resource *, unsigned base, unsigned size); - #endif diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index f2b03e8156..13c03b1a7e 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -310,6 +310,8 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) screen->base.vertex_buffer_flags = screen->base.index_buffer_flags = NOUVEAU_BO_GART; + screen->base.copy_data = nv50_m2mf_copy_linear; + screen->base.push_data = nv50_sifc_linear_u8; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, &screen->fence.bo); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 3bf67eb656..eb9743a05d 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -73,7 +73,7 @@ int nv50_screen_tic_alloc(struct nv50_screen *, void *); int nv50_screen_tsc_alloc(struct nv50_screen *, void *); static INLINE void -nv50_resource_fence(struct nv50_resource *res, uint32_t flags) +nv50_resource_fence(struct nv04_resource *res, uint32_t flags) { struct nv50_screen *screen = nv50_screen(res->base.screen); @@ -86,7 +86,7 @@ nv50_resource_fence(struct nv50_resource *res, uint32_t flags) } static INLINE void -nv50_resource_validate(struct nv50_resource *res, uint32_t flags) +nv50_resource_validate(struct nv04_resource *res, uint32_t flags) { struct nv50_screen *screen = nv50_screen(res->base.screen); diff --git a/src/gallium/drivers/nv50/nv50_shader_state.c b/src/gallium/drivers/nv50/nv50_shader_state.c index e530b3390a..2d7572820f 100644 --- a/src/gallium/drivers/nv50/nv50_shader_state.c +++ b/src/gallium/drivers/nv50/nv50_shader_state.c @@ -35,7 +35,7 @@ nv50_constbufs_validate(struct nv50_context *nv50) unsigned s; for (s = 0; s < 3; ++s) { - struct nv50_resource *res; + struct nv04_resource *res; int i; unsigned p, b; @@ -55,7 +55,7 @@ nv50_constbufs_validate(struct nv50_context *nv50) i = ffs(nv50->constbuf_dirty[s]) - 1; nv50->constbuf_dirty[s] &= ~(1 << i); - res = nv50_resource(nv50->constbuf[s][i]); + res = nv04_resource(nv50->constbuf[s][i]); if (!res) { if (i != 0) { BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1); @@ -75,8 +75,8 @@ nv50_constbufs_validate(struct nv50_context *nv50) assert(0); - if (!nv50_resource_mapped_by_gpu(&res->base)) { - nv50_buffer_migrate(nv50, res, NOUVEAU_BO_VRAM); + if (!nouveau_resource_mapped_by_gpu(&res->base)) { + nouveau_buffer_migrate(&nv50->pipe, res, NOUVEAU_BO_VRAM); BEGIN_RING(chan, RING_3D(CODE_CB_FLUSH), 1); OUT_RING (chan, 0); @@ -149,9 +149,9 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog) return FALSE; prog->code_base = prog->res->start; - nv50_sifc_linear_u8(nv50, nv50->screen->code, NOUVEAU_BO_VRAM, - (prog->type << 16) + prog->code_base, prog->code_size, - prog->code); + nv50_sifc_linear_u8(&nv50->pipe, nv50->screen->code, + (prog->type << 16) + prog->code_base, + NOUVEAU_BO_VRAM, prog->code_size, prog->code); BEGIN_RING(nv50->screen->base.channel, RING_3D(CODE_CB_FLUSH), 1); OUT_RING (nv50->screen->base.channel, 0); diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 5e1fff46e4..ed2fd3b0f8 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -651,8 +651,7 @@ nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, if (nv50->constbuf[shader][index]) nv50_bufctx_del_resident(nv50, NV50_BUFCTX_CONSTANT, - nv50_resource( - nv50->constbuf[shader][index])); + nv04_resource(nv50->constbuf[shader][index])); pipe_resource_reference(&nv50->constbuf[shader][index], res); diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 93e74ca059..eaee0a1107 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -168,7 +168,7 @@ nv50_validate_tic(struct nv50_context *nv50, int s) for (i = 0; i < nv50->num_textures[s]; ++i) { struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); - struct nv50_resource *res; + struct nv04_resource *res; if (!tic) { BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1); @@ -261,8 +261,9 @@ nv50_validate_tsc(struct nv50_context *nv50, int s) if (tsc->id < 0) { tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc); - nv50_sifc_linear_u8(nv50, nv50->screen->txc, NOUVEAU_BO_VRAM, - 65536 + tsc->id * 32, 32, tsc->tsc); + nv50_sifc_linear_u8(&nv50->pipe, nv50->screen->txc, + 65536 + tsc->id * 32, + NOUVEAU_BO_VRAM, 32, tsc->tsc); need_flush = TRUE; } nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index 696350d10c..d80a535490 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -102,10 +102,11 @@ nv50_m2mf_transfer_rect(struct pipe_screen *pscreen, } void -nv50_sifc_linear_u8(struct nv50_context *nv50, - struct nouveau_bo *dst, unsigned domain, int offset, +nv50_sifc_linear_u8(struct pipe_context *pipe, + struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, void *data) { + struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->base.channel; uint32_t *src = (uint32_t *)data; unsigned count = (size + 3) / 4; @@ -158,11 +159,12 @@ nv50_sifc_linear_u8(struct nv50_context *nv50, } void -nv50_m2mf_copy_linear(struct nv50_context *nv50, +nv50_m2mf_copy_linear(struct pipe_context *pipe, struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, unsigned size) { + struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->base.channel; BEGIN_RING(chan, RING_MF(LINEAR_IN), 1); diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index d18b2dffd1..1f0d34ed79 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -127,12 +127,12 @@ nv50_emit_vtxattr(struct nv50_context *nv50, struct pipe_vertex_buffer *vb, { const void *data; struct nouveau_channel *chan = nv50->screen->base.channel; - struct nv50_resource *res = nv50_resource(vb->buffer); + struct nv04_resource *res = nv04_resource(vb->buffer); float v[4]; const unsigned nc = util_format_get_nr_components(ve->src_format); - data = nv50_resource_map_offset(nv50, res, vb->buffer_offset + - ve->src_offset, NOUVEAU_BO_RD); + data = nouveau_resource_map_offset(&nv50->pipe, res, vb->buffer_offset + + ve->src_offset, NOUVEAU_BO_RD); util_format_read_4f(ve->src_format, v, 0, data, 0, 0, 0, 1, 1); @@ -189,7 +189,7 @@ static void nv50_prevalidate_vbufs(struct nv50_context *nv50) { struct pipe_vertex_buffer *vb; - struct nv50_resource *buf; + struct nv04_resource *buf; int i; uint32_t base, size; @@ -201,27 +201,27 @@ nv50_prevalidate_vbufs(struct nv50_context *nv50) vb = &nv50->vtxbuf[i]; if (!vb->stride) continue; - buf = nv50_resource(vb->buffer); + buf = nv04_resource(vb->buffer); /* NOTE: user buffers with temporary storage count as mapped by GPU */ - if (!nv50_resource_mapped_by_gpu(vb->buffer)) { + if (!nouveau_resource_mapped_by_gpu(vb->buffer)) { if (nv50->vbo_push_hint) { nv50->vbo_fifo = ~0; continue; } else { - if (buf->status & NV50_BUFFER_STATUS_USER_MEMORY) { + if (buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY) { nv50->vbo_user |= 1 << i; assert(vb->stride > vb->buffer_offset); nv50_vbuf_range(nv50, i, &base, &size); - nv50_user_buffer_upload(buf, base, size); + nouveau_user_buffer_upload(buf, base, size); } else { - nv50_buffer_migrate(nv50, buf, NOUVEAU_BO_GART); + nouveau_buffer_migrate(&nv50->pipe, buf, NOUVEAU_BO_GART); } nv50->vbo_dirty = TRUE; } } nv50_bufctx_add_resident(nv50, NV50_BUFCTX_VERTEX, buf, NOUVEAU_BO_RD); - nv50_buffer_adjust_score(nv50, buf, 1); + nouveau_buffer_adjust_score(&nv50->pipe, buf, 1); } } @@ -237,7 +237,7 @@ nv50_update_user_vbufs(struct nv50_context *nv50) struct pipe_vertex_element *ve = &nv50->vertex->element[i].pipe; const int b = ve->vertex_buffer_index; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[b]; - struct nv50_resource *buf = nv50_resource(vb->buffer); + struct nv04_resource *buf = nv04_resource(vb->buffer); if (!(nv50->vbo_user & (1 << b))) continue; @@ -250,7 +250,7 @@ nv50_update_user_vbufs(struct nv50_context *nv50) if (!(written & (1 << b))) { written |= 1 << b; - nv50_user_buffer_upload(buf, base, size); + nouveau_user_buffer_upload(buf, base, size); } offset = vb->buffer_offset + ve->src_offset; @@ -274,7 +274,7 @@ nv50_release_user_vbufs(struct nv50_context *nv50) int i = ffs(vbo_user) - 1; vbo_user &= ~(1 << i); - nv50_buffer_release_gpu_storage(nv50_resource(nv50->vtxbuf[i].buffer)); + nouveau_buffer_release_gpu_storage(nv04_resource(nv50->vtxbuf[i].buffer)); } } @@ -308,7 +308,7 @@ nv50_vertex_arrays_validate(struct nv50_context *nv50) } for (i = 0; i < vertex->num_elements; ++i) { - struct nv50_resource *res; + struct nv04_resource *res; unsigned size, offset; ve = &vertex->element[i]; @@ -327,7 +327,7 @@ nv50_vertex_arrays_validate(struct nv50_context *nv50) OUT_RING (chan, 0); } - res = nv50_resource(vb->buffer); + res = nv04_resource(vb->buffer); if (nv50->vbo_fifo || unlikely(vb->stride == 0)) { if (!nv50->vbo_fifo) @@ -536,11 +536,11 @@ nv50_draw_elements(struct nv50_context *nv50, boolean shorten, nv50->state.index_bias = index_bias; } - if (nv50_resource_mapped_by_gpu(nv50->idxbuf.buffer) && 0) { - struct nv50_resource *res = nv50_resource(nv50->idxbuf.buffer); + if (nouveau_resource_mapped_by_gpu(nv50->idxbuf.buffer) && 0) { + struct nv04_resource *res = nv04_resource(nv50->idxbuf.buffer); unsigned offset = res->offset + nv50->idxbuf.offset; - nv50_buffer_adjust_score(nv50, res, 1); + nouveau_buffer_adjust_score(&nv50->pipe, res, 1); while (instance_count--) { BEGIN_RING(chan, RING_3D(VERTEX_BEGIN_GL), 1); @@ -597,8 +597,9 @@ nv50_draw_elements(struct nv50_context *nv50, boolean shorten, mode |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; } } else { - data = nv50_resource_map_offset(nv50, nv50_resource(nv50->idxbuf.buffer), - nv50->idxbuf.offset, NOUVEAU_BO_RD); + data = nouveau_resource_map_offset(&nv50->pipe, + nv04_resource(nv50->idxbuf.buffer), + nv50->idxbuf.offset, NOUVEAU_BO_RD); if (!data) return; diff --git a/src/gallium/drivers/nv50/nv50_winsys.h b/src/gallium/drivers/nv50/nv50_winsys.h index 8aaf24c009..35e79210a6 100644 --- a/src/gallium/drivers/nv50/nv50_winsys.h +++ b/src/gallium/drivers/nv50/nv50_winsys.h @@ -4,6 +4,7 @@ #include #include + #include "pipe/p_defines.h" #include "nouveau/nouveau_bo.h" @@ -13,8 +14,9 @@ #include "nouveau/nouveau_resource.h" #include "nouveau/nouveau_pushbuf.h" #include "nouveau/nouveau_reloc.h" +#include "nouveau/nouveau_notifier.h" -#include "nv50_resource.h" /* OUT_RESRC */ +#include "nouveau/nouveau_buffer.h" #ifndef NV04_PFIFO_MAX_PACKET_LEN #define NV04_PFIFO_MAX_PACKET_LEN 2047 @@ -68,18 +70,18 @@ BEGIN_RING_NI(struct nouveau_channel *chan, uint32_t mthd, unsigned size) } static INLINE int -OUT_RESRCh(struct nouveau_channel *chan, struct nv50_resource *res, +OUT_RESRCh(struct nouveau_channel *chan, struct nv04_resource *res, unsigned delta, unsigned flags) { return OUT_RELOCh(chan, res->bo, res->offset + delta, res->domain | flags); } static INLINE int -OUT_RESRCl(struct nouveau_channel *chan, struct nv50_resource *res, +OUT_RESRCl(struct nouveau_channel *chan, struct nv04_resource *res, unsigned delta, unsigned flags) { if (flags & NOUVEAU_BO_WR) - res->status |= NV50_BUFFER_STATUS_DIRTY; + res->status |= NOUVEAU_BUFFER_STATUS_DIRTY; return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); } -- cgit v1.2.3 From be68782d9aebf6f6575bb8cc9cfc66b7bad79644 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Mar 2011 13:09:41 +1000 Subject: nv50: sync textures with render targets ourselves Port of the nvc0 commit doing the same. Signed-off-by: Ben Skeggs --- src/gallium/drivers/nouveau/nouveau_buffer.c | 6 +++--- src/gallium/drivers/nouveau/nouveau_buffer.h | 5 +++-- src/gallium/drivers/nv50/nv50_3d.xml.h | 2 +- src/gallium/drivers/nv50/nv50_screen.h | 5 +++++ src/gallium/drivers/nv50/nv50_state_validate.c | 16 ++++++++++++++++ src/gallium/drivers/nv50/nv50_tex.c | 8 ++++++++ src/gallium/drivers/nv50/nv50_winsys.h | 2 +- 7 files changed, 37 insertions(+), 7 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c index 4f4b24fdd2..efb16824e4 100644 --- a/src/gallium/drivers/nouveau/nouveau_buffer.c +++ b/src/gallium/drivers/nouveau/nouveau_buffer.c @@ -112,7 +112,7 @@ nouveau_buffer_download(struct pipe_context *pipe, struct nv04_resource *buf, memcpy(buf->data + start, bounce->map, size); nouveau_bo_unmap(bounce); - buf->status &= ~NOUVEAU_BUFFER_STATUS_DIRTY; + buf->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; nouveau_bo_ref(NULL, &bounce); if (mm) @@ -152,7 +152,7 @@ nouveau_buffer_upload(struct pipe_context *pipe, struct nv04_resource *buf, release_allocation(&mm, screen->fence.current); if (start == 0 && size == buf->base.width0) - buf->status &= ~NOUVEAU_BUFFER_STATUS_DIRTY; + buf->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; return TRUE; } @@ -174,7 +174,7 @@ nouveau_buffer_transfer_get(struct pipe_context *pipe, if (buf->domain == NOUVEAU_BO_VRAM) { if (usage & PIPE_TRANSFER_READ) { - if (buf->status & NOUVEAU_BUFFER_STATUS_DIRTY) + if (buf->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) nouveau_buffer_download(pipe, buf, 0, buf->base.width0); } } diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.h b/src/gallium/drivers/nouveau/nouveau_buffer.h index d75bc4e0c3..c3e0c2cf92 100644 --- a/src/gallium/drivers/nouveau/nouveau_buffer.h +++ b/src/gallium/drivers/nouveau/nouveau_buffer.h @@ -17,7 +17,8 @@ struct nouveau_bo; * USER_MEMORY: resource->data is a pointer to client memory and may change * between GL calls */ -#define NOUVEAU_BUFFER_STATUS_DIRTY (1 << 0) +#define NOUVEAU_BUFFER_STATUS_GPU_READING (1 << 0) +#define NOUVEAU_BUFFER_STATUS_GPU_WRITING (1 << 1) #define NOUVEAU_BUFFER_STATUS_USER_MEMORY (1 << 7) /* Resources, if mapped into the GPU's address space, are guaranteed to @@ -84,7 +85,7 @@ nouveau_resource_map_offset(struct pipe_context *pipe, nouveau_buffer_adjust_score(pipe, res, -250); if ((res->domain == NOUVEAU_BO_VRAM) && - (res->status & NOUVEAU_BUFFER_STATUS_DIRTY)) + (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING)) nouveau_buffer_download(pipe, res, 0, res->base.width0); if ((res->domain != NOUVEAU_BO_GART) || diff --git a/src/gallium/drivers/nv50/nv50_3d.xml.h b/src/gallium/drivers/nv50/nv50_3d.xml.h index eb05bd4095..9bb3211728 100644 --- a/src/gallium/drivers/nv50/nv50_3d.xml.h +++ b/src/gallium/drivers/nv50/nv50_3d.xml.h @@ -74,7 +74,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - +#define NV50_3D_SERIALIZE 0x00000110 #define NV50_3D_DMA_NOTIFY 0x00000180 diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index eb9743a05d..3886d8068c 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -93,6 +93,11 @@ nv50_resource_validate(struct nv04_resource *res, uint32_t flags) if (likely(res->bo)) { nouveau_bo_validate(screen->base.channel, res->bo, flags); + if (flags & NOUVEAU_BO_WR) + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + if (flags & NOUVEAU_BO_RD) + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + nv50_resource_fence(res, flags); } } diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index a8f48b2a28..c97927624e 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -8,6 +8,7 @@ nv50_validate_fb(struct nv50_context *nv50) struct nouveau_channel *chan = nv50->screen->base.channel; struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned i; + boolean serialize = FALSE; nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME); @@ -37,6 +38,11 @@ nv50_validate_fb(struct nv50_context *nv50) BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1); OUT_RING (chan, sf->depth); + if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) + serialize = TRUE; + mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING; + nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); } @@ -62,6 +68,11 @@ nv50_validate_fb(struct nv50_context *nv50) OUT_RING (chan, sf->height); OUT_RING (chan, (unk << 16) | sf->depth); + if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) + serialize = TRUE; + mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING; + nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); } else { @@ -72,6 +83,11 @@ nv50_validate_fb(struct nv50_context *nv50) BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); OUT_RING (chan, fb->width << 16); OUT_RING (chan, fb->height << 16); + + if (serialize) { + BEGIN_RING(chan, RING_3D(SERIALIZE), 1); + OUT_RING (chan, 0); + } } static void diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index eaee0a1107..a76139ad37 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -212,9 +212,17 @@ nv50_validate_tic(struct nv50_context *nv50, int s) OUT_RINGp (chan, &tic->tic[3], 5); need_flush = TRUE; + } else + if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { + BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1); + OUT_RING (chan, 0x20); //(tic->id << 4) | 1); } + nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); + res->status &= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; + nv50_bufctx_add_resident(nv50, NV50_BUFCTX_TEXTURES, res, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); diff --git a/src/gallium/drivers/nv50/nv50_winsys.h b/src/gallium/drivers/nv50/nv50_winsys.h index 35e79210a6..afa2a00c7a 100644 --- a/src/gallium/drivers/nv50/nv50_winsys.h +++ b/src/gallium/drivers/nv50/nv50_winsys.h @@ -81,7 +81,7 @@ OUT_RESRCl(struct nouveau_channel *chan, struct nv04_resource *res, unsigned delta, unsigned flags) { if (flags & NOUVEAU_BO_WR) - res->status |= NOUVEAU_BUFFER_STATUS_DIRTY; + res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; return OUT_RELOCl(chan, res->bo, res->offset + delta, res->domain | flags); } -- cgit v1.2.3 From 7048ad62f89289c9e642203c009dca38ce8753f8 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Thu, 3 Mar 2011 12:25:12 +0100 Subject: nv50: increase size of shader code bo 512 KiB should be quite enough, but dynamic resize might be nicer. --- src/gallium/drivers/nv50/nv50_pc_emit.c | 3 ++- src/gallium/drivers/nv50/nv50_screen.c | 25 ++++++++++++++----------- src/gallium/drivers/nv50/nv50_screen.h | 2 ++ src/gallium/drivers/nv50/nv50_shader_state.c | 7 +++++-- 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'src/gallium/drivers/nv50/nv50_screen.h') diff --git a/src/gallium/drivers/nv50/nv50_pc_emit.c b/src/gallium/drivers/nv50/nv50_pc_emit.c index f37dc51e6a..252c58dd8f 100644 --- a/src/gallium/drivers/nv50/nv50_pc_emit.c +++ b/src/gallium/drivers/nv50/nv50_pc_emit.c @@ -762,7 +762,8 @@ emit_flow(struct nv_pc *pc, struct nv_instruction *i, ubyte flow_op) new_fixup(pc, NV50_FIXUP_CODE_RELOC, 0, pos, 0xffff << 11, 9); new_fixup(pc, NV50_FIXUP_CODE_RELOC, 1, pos, 0x3f << 14, -4); - pc->emit[0] |= (pos / 4) << 11; + pc->emit[0] |= ((pos >> 2) & 0xffff) << 11; + pc->emit[1] |= ((pos >> 18) & 0x003f) << 14; } } diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 3f148436e8..3ccaff2838 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -286,7 +286,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) uint32_t tesla_class; unsigned stack_size, max_warps, tls_space; int ret; - unsigned i; + unsigned i, base; screen = CALLOC_STRUCT(nv50_screen); if (!screen) @@ -425,25 +425,28 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) BEGIN_RING(chan, RING_3D(ZCULL_REGION), 1); /* deactivate ZCULL */ OUT_RING (chan, 0x3f); - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, 3 << 16, &screen->code); + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 16, + 3 << NV50_CODE_BO_SIZE_LOG2, &screen->code); if (ret) goto fail; - nouveau_resource_init(&screen->vp_code_heap, 0, 1 << 16); - nouveau_resource_init(&screen->gp_code_heap, 0, 1 << 16); - nouveau_resource_init(&screen->fp_code_heap, 0, 1 << 16); + nouveau_resource_init(&screen->vp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2); + nouveau_resource_init(&screen->gp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2); + nouveau_resource_init(&screen->fp_code_heap, 0, 1 << NV50_CODE_BO_SIZE_LOG2); + + base = 1 << NV50_CODE_BO_SIZE_LOG2; BEGIN_RING(chan, RING_3D(VP_ADDRESS_HIGH), 2); - OUT_RELOCh(chan, screen->code, 0 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); - OUT_RELOCl(chan, screen->code, 0 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCh(chan, screen->code, base * 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->code, base * 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); BEGIN_RING(chan, RING_3D(FP_ADDRESS_HIGH), 2); - OUT_RELOCh(chan, screen->code, 1 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); - OUT_RELOCl(chan, screen->code, 1 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCh(chan, screen->code, base * 1, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->code, base * 1, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); BEGIN_RING(chan, RING_3D(GP_ADDRESS_HIGH), 2); - OUT_RELOCh(chan, screen->code, 2 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); - OUT_RELOCl(chan, screen->code, 2 << 16, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCh(chan, screen->code, base * 2, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->code, base * 2, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); nouveau_device_get_param(dev, NOUVEAU_GETPARAM_GRAPH_UNITS, &value); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 3886d8068c..aea434b867 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -14,6 +14,8 @@ struct nv50_context; +#define NV50_CODE_BO_SIZE_LOG2 19 + #define NV50_SCRATCH_SIZE (2 << 20) #define NV50_SCRATCH_NR_BUFFERS 2 diff --git a/src/gallium/drivers/nv50/nv50_shader_state.c b/src/gallium/drivers/nv50/nv50_shader_state.c index f7d78a3b11..bea9c095bb 100644 --- a/src/gallium/drivers/nv50/nv50_shader_state.c +++ b/src/gallium/drivers/nv50/nv50_shader_state.c @@ -138,6 +138,7 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog) return FALSE; if (prog->type == PIPE_SHADER_FRAGMENT) heap = nv50->screen->fp_code_heap; + else if (prog->type == PIPE_SHADER_GEOMETRY) heap = nv50->screen->gp_code_heap; else heap = nv50->screen->vp_code_heap; @@ -145,14 +146,16 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog) size = align(prog->code_size, 0x100); ret = nouveau_resource_alloc(heap, size, prog, &prog->res); - if (ret) + if (ret) { + NOUVEAU_ERR("out of code space for shader type %i\n", prog->type); return FALSE; + } prog->code_base = prog->res->start; nv50_relocate_program(prog, prog->code_base, 0); nv50_sifc_linear_u8(&nv50->base, nv50->screen->code, - (prog->type << 16) + prog->code_base, + (prog->type << NV50_CODE_BO_SIZE_LOG2) + prog->code_base, NOUVEAU_BO_VRAM, prog->code_size, prog->code); BEGIN_RING(nv50->screen->base.channel, RING_3D(CODE_CB_FLUSH), 1); -- cgit v1.2.3