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