[Nouveau] [PATCH try 2 2/2] gallium/nouveau: move pushbuf and fences to context
Maarten Lankhorst
maarten.lankhorst at canonical.com
Mon Jun 16 23:34:24 PDT 2014
nv30 seems to not support dma objects with offset, so simply extend the query_heap to cover the
entire notifier, and use a offset in nv30_context_kick_notify.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at canonical.com>
---
src/gallium/drivers/nouveau/nouveau_buffer.c | 14 +-
src/gallium/drivers/nouveau/nouveau_context.h | 5 +
src/gallium/drivers/nouveau/nouveau_fence.c | 10 +
src/gallium/drivers/nouveau/nouveau_fence.h | 6 +-
src/gallium/drivers/nouveau/nouveau_screen.c | 16 --
src/gallium/drivers/nouveau/nouveau_screen.h | 5 -
src/gallium/drivers/nouveau/nv30/nv30_context.c | 104 +++++++--
src/gallium/drivers/nouveau/nv30/nv30_context.h | 2 +
src/gallium/drivers/nouveau/nv30/nv30_draw.c | 4 +-
src/gallium/drivers/nouveau/nv30/nv30_query.c | 6 +-
src/gallium/drivers/nouveau/nv30/nv30_screen.c | 160 ++++---------
src/gallium/drivers/nouveau/nv30/nv30_screen.h | 4 +-
.../drivers/nouveau/nv30/nv30_state_validate.c | 9 +-
src/gallium/drivers/nouveau/nv50/nv50_context.c | 128 ++++++++---
src/gallium/drivers/nouveau/nv50/nv50_context.h | 33 ++-
src/gallium/drivers/nouveau/nv50/nv50_program.c | 2 +-
src/gallium/drivers/nouveau/nv50/nv50_query.c | 2 +-
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 79 +------
src/gallium/drivers/nouveau/nv50/nv50_screen.h | 35 +--
.../drivers/nouveau/nv50/nv50_state_validate.c | 8 +-
src/gallium/drivers/nouveau/nv50/nv50_surface.c | 6 +-
src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 6 +-
src/gallium/drivers/nouveau/nv50/nv84_video.c | 16 +-
src/gallium/drivers/nouveau/nvc0/nvc0_compute.c | 20 +-
src/gallium/drivers/nouveau/nvc0/nvc0_compute.h | 4 +
src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 133 ++++++++---
src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 32 +++
src/gallium/drivers/nouveau/nvc0/nvc0_query.c | 4 +-
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 253 +++++++++------------
src/gallium/drivers/nouveau/nvc0/nvc0_screen.h | 35 +--
.../drivers/nouveau/nvc0/nvc0_state_validate.c | 6 +-
src/gallium/drivers/nouveau/nvc0/nvc0_surface.c | 10 +-
src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 6 +-
src/gallium/drivers/nouveau/nvc0/nve4_compute.c | 22 +-
src/gallium/drivers/nouveau/nvc0/nve4_compute.h | 3 +
35 files changed, 625 insertions(+), 563 deletions(-)
diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c
index 49ff100..8affb0e 100644
--- a/src/gallium/drivers/nouveau/nouveau_buffer.c
+++ b/src/gallium/drivers/nouveau/nouveau_buffer.c
@@ -217,8 +217,8 @@ nouveau_transfer_write(struct nouveau_context *nv, struct nouveau_transfer *tx,
else
nv->push_data(nv, buf->bo, buf->offset + base, buf->domain, size, data);
- nouveau_fence_ref(nv->screen->fence.current, &buf->fence);
- nouveau_fence_ref(nv->screen->fence.current, &buf->fence_wr);
+ nouveau_fence_ref(nv->fence.current, &buf->fence);
+ nouveau_fence_ref(nv->fence.current, &buf->fence_wr);
}
/* Does a CPU wait for the buffer's backing data to become reliably accessible
@@ -288,7 +288,7 @@ nouveau_buffer_transfer_del(struct nouveau_context *nv,
if (likely(tx->bo)) {
nouveau_bo_ref(NULL, &tx->bo);
if (tx->mm)
- release_allocation(&tx->mm, nv->screen->fence.current);
+ release_allocation(&tx->mm, nv->fence.current);
} else {
align_free(tx->map -
(tx->base.box.x & NOUVEAU_MIN_BUFFER_MAP_ALIGN_MASK));
@@ -572,11 +572,11 @@ nouveau_copy_buffer(struct nouveau_context *nv,
src->bo, src->offset + srcx, src->domain, size);
dst->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
- nouveau_fence_ref(nv->screen->fence.current, &dst->fence);
- nouveau_fence_ref(nv->screen->fence.current, &dst->fence_wr);
+ nouveau_fence_ref(nv->fence.current, &dst->fence);
+ nouveau_fence_ref(nv->fence.current, &dst->fence_wr);
src->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
- nouveau_fence_ref(nv->screen->fence.current, &src->fence);
+ nouveau_fence_ref(nv->fence.current, &src->fence);
} else {
struct pipe_box src_box;
src_box.x = srcx;
@@ -787,7 +787,7 @@ nouveau_buffer_migrate(struct nouveau_context *nv,
nouveau_bo_ref(NULL, &bo);
if (mm)
- release_allocation(&mm, screen->fence.current);
+ release_allocation(&mm, nv->fence.current);
} else
if (new_domain == NOUVEAU_BO_VRAM && old_domain == 0) {
struct nouveau_transfer tx;
diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h
index 14608d3..48e2a66 100644
--- a/src/gallium/drivers/nouveau/nouveau_context.h
+++ b/src/gallium/drivers/nouveau/nouveau_context.h
@@ -49,6 +49,8 @@ struct nouveau_context {
uint32_t buf_cache_count;
uint32_t buf_cache_frame;
} stats;
+
+ struct nouveau_fence_mgr fence;
};
static INLINE struct nouveau_context *
@@ -91,6 +93,7 @@ nouveau_context_destroy(struct nouveau_context *ctx)
if (ctx->scratch.bo[i])
nouveau_bo_ref(NULL, &ctx->scratch.bo[i]);
+ nouveau_pushbuf_del(&ctx->pushbuf);
FREE(ctx);
}
@@ -106,4 +109,6 @@ nouveau_context_update_frame_stats(struct nouveau_context *nv)
}
}
+int nouveau_context_fence_kick(struct nouveau_fence_mgr *);
+
#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.c b/src/gallium/drivers/nouveau/nouveau_fence.c
index 09b3b1e..b751971 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.c
+++ b/src/gallium/drivers/nouveau/nouveau_fence.c
@@ -23,6 +23,7 @@
#include "util/u_double_list.h"
#include "nouveau_screen.h"
+#include "nouveau_context.h"
#include "nouveau_winsys.h"
#include "nouveau_fence.h"
@@ -30,6 +31,15 @@
#include <sched.h>
#endif
+int nouveau_context_fence_kick(struct nouveau_fence_mgr *mgr)
+{
+ struct nouveau_context *context = NULL;
+
+ context = container_of(mgr, context, fence);
+
+ return nouveau_pushbuf_kick(context->pushbuf, context->pushbuf->channel);
+}
+
boolean
nouveau_fence_new(struct nouveau_fence_mgr *mgr, struct nouveau_fence **fence,
boolean emit)
diff --git a/src/gallium/drivers/nouveau/nouveau_fence.h b/src/gallium/drivers/nouveau/nouveau_fence.h
index cb44dd3..cdc60ed 100644
--- a/src/gallium/drivers/nouveau/nouveau_fence.h
+++ b/src/gallium/drivers/nouveau/nouveau_fence.h
@@ -32,10 +32,10 @@ struct nouveau_fence_work {
};
struct nouveau_fence {
+ int32_t ref;
struct nouveau_fence *next;
struct nouveau_fence_mgr *mgr;
int state;
- int ref;
uint32_t sequence;
struct list_head work;
};
@@ -55,10 +55,10 @@ static INLINE void
nouveau_fence_ref(struct nouveau_fence *fence, struct nouveau_fence **ref)
{
if (fence)
- ++fence->ref;
+ p_atomic_inc(&fence->ref);
if (*ref) {
- if (--(*ref)->ref == 0)
+ if (p_atomic_dec_zero(&(*ref)->ref))
nouveau_fence_del(*ref);
}
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index 9ea3a46..f78b6e1 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -167,11 +167,6 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
ret = nouveau_client_new(screen->device, &screen->client);
if (ret)
return ret;
- ret = nouveau_pushbuf_new(screen->client, screen->channel,
- 4, 512 * 1024, 1,
- &screen->pushbuf);
- if (ret)
- return ret;
/* getting CPU time first appears to be more accurate */
screen->cpu_gpu_time_delta = os_time_get();
@@ -216,19 +211,8 @@ nouveau_screen_fini(struct nouveau_screen *screen)
nouveau_mm_destroy(screen->mm_GART);
nouveau_mm_destroy(screen->mm_VRAM);
- nouveau_pushbuf_del(&screen->pushbuf);
-
nouveau_client_del(&screen->client);
nouveau_object_del(&screen->channel);
nouveau_device_del(&screen->device);
}
-
-int nouveau_screen_fence_kick(struct nouveau_fence_mgr *mgr)
-{
- struct nouveau_screen *screen = NULL;
-
- screen = container_of(mgr, screen, fence);
-
- return nouveau_pushbuf_kick(screen->pushbuf, screen->pushbuf->channel);
-}
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
index 7682214..c1e9bc3 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -22,7 +22,6 @@ struct nouveau_screen {
struct nouveau_device *device;
struct nouveau_object *channel;
struct nouveau_client *client;
- struct nouveau_pushbuf *pushbuf;
int refcount;
@@ -36,8 +35,6 @@ struct nouveau_screen {
uint16_t class_3d;
- struct nouveau_fence_mgr fence;
-
struct nouveau_mman *mm_VRAM;
struct nouveau_mman *mm_GART;
@@ -126,6 +123,4 @@ void nouveau_screen_fini(struct nouveau_screen *);
void nouveau_screen_init_vdec(struct nouveau_screen *);
-int nouveau_screen_fence_kick(struct nouveau_fence_mgr *);
-
#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c
index 35c66f1..5cb75b8 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_context.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c
@@ -36,29 +36,27 @@
static void
nv30_context_kick_notify(struct nouveau_pushbuf *push)
{
- struct nouveau_screen *screen;
struct nv30_context *nv30;
if (!push->user_priv)
return;
nv30 = container_of(push->user_priv, nv30, bufctx);
- screen = &nv30->screen->base;
- nouveau_fence_next(&screen->fence);
- nouveau_fence_update(&screen->fence, TRUE);
+ nouveau_fence_next(&nv30->base.fence);
+ nouveau_fence_update(&nv30->base.fence, TRUE);
if (push->bufctx) {
struct nouveau_bufref *bref;
LIST_FOR_EACH_ENTRY(bref, &push->bufctx->current, thead) {
struct nv04_resource *res = bref->priv;
if (res && res->mm) {
- nouveau_fence_ref(screen->fence.current, &res->fence);
+ nouveau_fence_ref(nv30->base.fence.current, &res->fence);
if (bref->flags & NOUVEAU_BO_RD)
res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
if (bref->flags & NOUVEAU_BO_WR) {
- nouveau_fence_ref(screen->fence.current, &res->fence_wr);
+ nouveau_fence_ref(nv30->base.fence.current, &res->fence_wr);
res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
NOUVEAU_BUFFER_STATUS_DIRTY;
}
@@ -75,7 +73,7 @@ nv30_context_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence,
struct nouveau_pushbuf *push = nv30->base.pushbuf;
if (fence)
- nouveau_fence_ref(nv30->screen->base.fence.current,
+ nouveau_fence_ref(nv30->base.fence.current,
(struct nouveau_fence **)fence);
PUSH_KICK(push);
@@ -159,6 +157,22 @@ nv30_context_destroy(struct pipe_context *pipe)
{
struct nv30_context *nv30 = nv30_context(pipe);
+ /* need to flush before destroying the bufctx */
+ nouveau_pushbuf_kick(nv30->base.pushbuf, nv30->base.pushbuf->channel);
+
+ if (nv30->base.fence.current) {
+ struct nouveau_fence *current = NULL;
+
+ /* nouveau_fence_wait will create a new current fence, so wait on the
+ * _current_ one, and remove both.
+ */
+ nouveau_fence_ref(nv30->base.fence.current, ¤t);
+ nouveau_fence_wait(current);
+ nouveau_fence_ref(NULL, ¤t);
+ nouveau_fence_ref(NULL, &nv30->base.fence.current);
+ }
+ nouveau_heap_free(&nv30->fence);
+
if (nv30->blitter)
util_blitter_destroy(nv30->blitter);
@@ -173,6 +187,33 @@ nv30_context_destroy(struct pipe_context *pipe)
nouveau_context_destroy(&nv30->base);
}
+static void
+nv30_context_fence_emit(struct nouveau_fence_mgr *mgr, uint32_t *sequence)
+{
+ struct nv30_context *nv30 = NULL;
+ struct nouveau_pushbuf *push;
+
+ nv30 = container_of(mgr, nv30, base.fence);
+ push = nv30->base.pushbuf;
+
+ *sequence = ++nv30->base.fence.sequence;
+
+ BEGIN_NV04(push, NV30_3D(FENCE_OFFSET), 2);
+ PUSH_DATA (push, nv30->fence->start);
+ PUSH_DATA (push, *sequence);
+}
+
+static uint32_t
+nv30_context_fence_update(struct nouveau_fence_mgr *mgr)
+{
+ struct nv30_context *nv30 = NULL;
+
+ nv30 = container_of(mgr, nv30, base.fence);
+
+ return *(uint32_t *)((char *)nv30->screen->notify->map + nv30->fence->start);
+}
+
+
#define FAIL_CONTEXT_INIT(str, err) \
do { \
NOUVEAU_ERR(str, err); \
@@ -185,7 +226,6 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv)
{
struct nv30_screen *screen = nv30_screen(pscreen);
struct nv30_context *nv30 = CALLOC_STRUCT(nv30_context);
- struct nouveau_pushbuf *push;
struct pipe_context *pipe;
int ret;
@@ -202,23 +242,37 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv)
pipe->destroy = nv30_context_destroy;
pipe->flush = nv30_context_flush;
- /*XXX: *cough* per-context client */
nv30->base.client = screen->base.client;
- /*XXX: *cough* per-context pushbufs */
- push = screen->base.pushbuf;
- nv30->base.pushbuf = push;
+ ret = nouveau_pushbuf_new(screen->base.client, screen->base.channel,
+ 4, 512 * 1024, 1, &nv30->base.pushbuf);
+ if (ret)
+ goto err;
+
+ /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in,
+ * this means that the address pointed at by the DMA object must
+ * be 4KiB aligned, which means this object needs to be the first
+ * one allocated on the channel.
+ */
+ ret = nouveau_heap_alloc(screen->query_heap, 32, NULL, &nv30->fence);
+
+ if (ret)
+ goto err;
+
nv30->base.pushbuf->user_priv = &nv30->bufctx; /* hack at validate time */
nv30->base.pushbuf->rsvd_kick = 16; /* hack in screen before first space */
nv30->base.pushbuf->kick_notify = nv30_context_kick_notify;
+ nv30->base.fence.screen = &screen->base;
+ nv30->base.fence.flush = nouveau_context_fence_kick;
+ nv30->base.fence.emit = nv30_context_fence_emit;
+ nv30->base.fence.update = nv30_context_fence_update;
+
nv30->base.invalidate_resource_storage = nv30_invalidate_resource_storage;
ret = nouveau_bufctx_new(nv30->base.client, 64, &nv30->bufctx);
- if (ret) {
- nv30_context_destroy(pipe);
- return NULL;
- }
+ if (ret)
+ goto err;
/*XXX: make configurable with performance vs quality, these defaults
* match the binary driver's defaults
@@ -233,6 +287,14 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv)
if (debug_get_bool_option("NV30_SWTNL", FALSE))
nv30->draw_flags |= NV30_NEW_SWTNL;
+ nouveau_fence_new(&nv30->base.fence, &nv30->base.fence.current, FALSE);
+
+ if (!screen->cur_ctx) {
+ nv30_screen_init_hwctx(screen, nv30->base.pushbuf);
+ screen->cur_ctx = nv30;
+ }
+ nouveau_pushbuf_bufctx(nv30->base.pushbuf, nv30->bufctx);
+
nv30->sample_mask = 0xffff;
nv30_vbo_init(pipe);
nv30_query_init(pipe);
@@ -247,12 +309,14 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv)
nv30_draw_init(pipe);
nv30->blitter = util_blitter_create(pipe);
- if (!nv30->blitter) {
- nv30_context_destroy(pipe);
- return NULL;
- }
+ if (!nv30->blitter)
+ goto err;
nouveau_context_init_vdec(&nv30->base);
return pipe;
+
+err:
+ nv30_context_destroy(pipe);
+ return NULL;
}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.h b/src/gallium/drivers/nouveau/nv30/nv30_context.h
index 7b32aae..e9180a5 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_context.h
+++ b/src/gallium/drivers/nouveau/nv30/nv30_context.h
@@ -97,6 +97,8 @@ struct nv30_context {
unsigned dirty_samplers;
} fragprog;
+ struct nouveau_heap *fence;
+
struct pipe_framebuffer_state framebuffer;
struct pipe_blend_color blend_colour;
struct pipe_stencil_ref stencil_ref;
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_draw.c b/src/gallium/drivers/nouveau/nv30/nv30_draw.c
index 3575c3d..2ee5e58 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_draw.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_draw.c
@@ -119,7 +119,7 @@ nv30_render_draw_elements(struct vbuf_render *render,
{
struct nv30_render *r = nv30_render(render);
struct nv30_context *nv30 = r->nv30;
- struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
unsigned i;
BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs);
@@ -269,7 +269,7 @@ nv30_render_validate(struct nv30_context *nv30)
struct nv30_render *r = nv30_render(nv30->draw->render);
struct nv30_rasterizer_stateobj *rast = nv30->rast;
struct pipe_screen *pscreen = &nv30->screen->base.base;
- struct nouveau_pushbuf *push = nv30->screen->base.pushbuf;
+ struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_object *eng3d = nv30->screen->eng3d;
struct nv30_vertprog *vp = nv30->vertprog.program;
struct vertex_info *vinfo = &r->vertex_info;
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_query.c b/src/gallium/drivers/nouveau/nv30/nv30_query.c
index 01b3817..6b27267 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_query.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_query.c
@@ -39,7 +39,7 @@ struct nv30_query_object {
static volatile void *
nv30_ntfy(struct nv30_screen *screen, struct nv30_query_object *qo)
{
- struct nv04_notify *query = screen->query->data;
+ struct nv04_notify *query = screen->ntfy->data;
struct nouveau_bo *notify = screen->notify;
volatile void *ntfy = NULL;
@@ -76,6 +76,10 @@ nv30_query_object_new(struct nv30_screen *screen)
* spin waiting for one to become free
*/
while (nouveau_heap_alloc(screen->query_heap, 32, NULL, &qo->hw)) {
+ if (&screen->queries == screen->queries.next) {
+ FREE(qo);
+ return NULL;
+ }
oq = LIST_FIRST_ENTRY(struct nv30_query_object, &screen->queries, list);
nv30_query_object_del(screen, &oq);
}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
index a0518c3..3e86470 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
@@ -287,34 +287,6 @@ nv30_screen_is_format_supported(struct pipe_screen *pscreen,
}
static void
-nv30_screen_fence_emit(struct nouveau_fence_mgr *mgr, uint32_t *sequence)
-{
- struct nv30_screen *screen = NULL;
- struct nouveau_pushbuf *push;
-
- screen = container_of(mgr, screen, base.fence);
- push = screen->base.pushbuf;
-
- *sequence = ++screen->base.fence.sequence;
-
- BEGIN_NV04(push, NV30_3D(FENCE_OFFSET), 2);
- PUSH_DATA (push, 0);
- PUSH_DATA (push, *sequence);
-}
-
-static uint32_t
-nv30_screen_fence_update(struct nouveau_fence_mgr *mgr)
-{
- struct nv30_screen *screen = NULL;
- struct nv04_notify *fence;
-
- screen = container_of(mgr, screen, base.fence);
- fence = screen->fence->data;
-
- return *(uint32_t *)((char *)screen->notify->map + fence->offset);
-}
-
-static void
nv30_screen_destroy(struct pipe_screen *pscreen)
{
struct nv30_screen *screen = nv30_screen(pscreen);
@@ -322,20 +294,6 @@ nv30_screen_destroy(struct pipe_screen *pscreen)
if (!nouveau_drm_screen_unref(&screen->base))
return;
- if (screen->base.fence.current) {
- struct nouveau_fence *current = NULL;
-
- /* nouveau_fence_wait will create a new current fence, so wait on the
- * _current_ one, and remove both.
- */
- nouveau_fence_ref(screen->base.fence.current, ¤t);
- nouveau_fence_wait(current);
- nouveau_fence_ref(NULL, ¤t);
- nouveau_fence_ref(NULL, &screen->base.fence.current);
- }
-
- nouveau_object_del(&screen->query);
- nouveau_object_del(&screen->fence);
nouveau_object_del(&screen->ntfy);
nouveau_object_del(&screen->sifm);
@@ -361,10 +319,9 @@ nv30_screen_create(struct nouveau_device *dev)
{
struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
struct pipe_screen *pscreen;
- struct nouveau_pushbuf *push;
struct nv04_fifo *fifo;
unsigned oclass = 0;
- int ret, i;
+ int ret;
if (!screen)
return NULL;
@@ -411,11 +368,6 @@ nv30_screen_create(struct nouveau_device *dev)
nv30_resource_screen_init(pscreen);
nouveau_screen_init_vdec(&screen->base);
- screen->base.fence.screen = &screen->base;
- screen->base.fence.flush = nouveau_screen_fence_kick;
- screen->base.fence.emit = nv30_screen_fence_emit;
- screen->base.fence.update = nv30_screen_fence_update;
-
ret = nouveau_screen_init(&screen->base, dev);
if (ret)
FAIL_SCREEN_INIT("nv30_screen_init failed: %d\n", ret);
@@ -428,46 +380,25 @@ nv30_screen_create(struct nouveau_device *dev)
}
fifo = screen->base.channel->data;
- push = screen->base.pushbuf;
- push->rsvd_kick = 16;
ret = nouveau_object_new(screen->base.channel, 0x00000000, NV01_NULL_CLASS,
NULL, 0, &screen->null);
if (ret)
FAIL_SCREEN_INIT("error allocating null object: %d\n", ret);
- /* DMA_FENCE refuses to accept DMA objects with "adjust" filled in,
- * this means that the address pointed at by the DMA object must
- * be 4KiB aligned, which means this object needs to be the first
- * one allocated on the channel.
+ /*
+ * DMA_NOTIFY object, we don't actually use this but M2MF fails without
+ *
+ * suballocations are also used for queries and fences.
*/
- ret = nouveau_object_new(screen->base.channel, 0xbeef1e00,
- NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
- .length = 32 }, sizeof(struct nv04_notify),
- &screen->fence);
- if (ret)
- FAIL_SCREEN_INIT("error allocating fence notifier: %d\n", ret);
-
- /* DMA_NOTIFY object, we don't actually use this but M2MF fails without */
ret = nouveau_object_new(screen->base.channel, 0xbeef0301,
NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
- .length = 32 }, sizeof(struct nv04_notify),
+ .length = 4096 }, sizeof(struct nv04_notify),
&screen->ntfy);
if (ret)
FAIL_SCREEN_INIT("error allocating sync notifier: %d\n", ret);
- /* DMA_QUERY, used to implement occlusion queries, we attempt to allocate
- * the remainder of the "notifier block" assigned by the kernel for
- * use as query objects
- */
- ret = nouveau_object_new(screen->base.channel, 0xbeef0351,
- NOUVEAU_NOTIFIER_CLASS, &(struct nv04_notify) {
- .length = 4096 - 128 }, sizeof(struct nv04_notify),
- &screen->query);
- if (ret)
- FAIL_SCREEN_INIT("error allocating query notifier: %d\n", ret);
-
- ret = nouveau_heap_init(&screen->query_heap, 0, 4096 - 128);
+ ret = nouveau_heap_init(&screen->query_heap, 32, 4096 - 32);
if (ret)
FAIL_SCREEN_INIT("error creating query heap: %d\n", ret);
@@ -495,6 +426,44 @@ nv30_screen_create(struct nouveau_device *dev)
if (ret)
FAIL_SCREEN_INIT("error allocating 3d object: %d\n", ret);
+ ret = nouveau_object_new(screen->base.channel, 0xbeef3901, NV03_M2MF_CLASS,
+ NULL, 0, &screen->m2mf);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating m2mf object: %d\n", ret);
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef6201,
+ NV10_SURFACE_2D_CLASS, NULL, 0, &screen->surf2d);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating surf2d object: %d\n", ret);
+
+ if (dev->chipset < 0x40)
+ oclass = NV30_SURFACE_SWZ_CLASS;
+ else
+ oclass = NV40_SURFACE_SWZ_CLASS;
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef5201, oclass,
+ NULL, 0, &screen->swzsurf);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating swizzled surface object: %d\n", ret);
+
+ if (dev->chipset < 0x40)
+ oclass = NV30_SIFM_CLASS;
+ else
+ oclass = NV40_SIFM_CLASS;
+
+ ret = nouveau_object_new(screen->base.channel, 0xbeef7701, oclass,
+ NULL, 0, &screen->sifm);
+ if (ret)
+ FAIL_SCREEN_INIT("error allocating scaled image object: %d\n", ret);
+
+ return pscreen;
+}
+
+void nv30_screen_init_hwctx(struct nv30_screen *screen, struct nouveau_pushbuf *push)
+{
+ struct nv04_fifo *fifo = screen->base.channel->data;
+ int i;
+
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
PUSH_DATA (push, screen->eng3d->handle);
BEGIN_NV04(push, NV30_3D(DMA_NOTIFY), 13);
@@ -507,8 +476,8 @@ nv30_screen_create(struct nouveau_device *dev)
PUSH_DATA (push, fifo->vram); /* ZETA */
PUSH_DATA (push, fifo->vram); /* VTXBUF0 */
PUSH_DATA (push, fifo->gart); /* VTXBUF1 */
- PUSH_DATA (push, screen->fence->handle); /* FENCE */
- PUSH_DATA (push, screen->query->handle); /* QUERY - intr 0x80 if nullobj */
+ PUSH_DATA (push, screen->ntfy->handle); /* FENCE */
+ PUSH_DATA (push, screen->ntfy->handle); /* QUERY - intr 0x80 if nullobj */
PUSH_DATA (push, screen->null->handle); /* UNK1AC */
PUSH_DATA (push, screen->null->handle); /* UNK1B0 */
if (screen->eng3d->oclass < NV40_3D_CLASS) {
@@ -562,51 +531,21 @@ nv30_screen_create(struct nouveau_device *dev)
PUSH_DATA (push, NV40_3D_MIPMAP_ROUNDING_MODE_DOWN);
}
- ret = nouveau_object_new(screen->base.channel, 0xbeef3901, NV03_M2MF_CLASS,
- NULL, 0, &screen->m2mf);
- if (ret)
- FAIL_SCREEN_INIT("error allocating m2mf object: %d\n", ret);
-
BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
PUSH_DATA (push, screen->m2mf->handle);
BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
- ret = nouveau_object_new(screen->base.channel, 0xbeef6201,
- NV10_SURFACE_2D_CLASS, NULL, 0, &screen->surf2d);
- if (ret)
- FAIL_SCREEN_INIT("error allocating surf2d object: %d\n", ret);
-
BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
PUSH_DATA (push, screen->surf2d->handle);
BEGIN_NV04(push, NV04_SF2D(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
- if (dev->chipset < 0x40)
- oclass = NV30_SURFACE_SWZ_CLASS;
- else
- oclass = NV40_SURFACE_SWZ_CLASS;
-
- ret = nouveau_object_new(screen->base.channel, 0xbeef5201, oclass,
- NULL, 0, &screen->swzsurf);
- if (ret)
- FAIL_SCREEN_INIT("error allocating swizzled surface object: %d\n", ret);
-
BEGIN_NV04(push, NV01_SUBC(SSWZ, OBJECT), 1);
PUSH_DATA (push, screen->swzsurf->handle);
BEGIN_NV04(push, NV04_SSWZ(DMA_NOTIFY), 1);
PUSH_DATA (push, screen->ntfy->handle);
- if (dev->chipset < 0x40)
- oclass = NV30_SIFM_CLASS;
- else
- oclass = NV40_SIFM_CLASS;
-
- ret = nouveau_object_new(screen->base.channel, 0xbeef7701, oclass,
- NULL, 0, &screen->sifm);
- if (ret)
- FAIL_SCREEN_INIT("error allocating scaled image object: %d\n", ret);
-
BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
PUSH_DATA (push, screen->sifm->handle);
BEGIN_NV04(push, NV03_SIFM(DMA_NOTIFY), 1);
@@ -614,8 +553,5 @@ nv30_screen_create(struct nouveau_device *dev)
BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
PUSH_DATA (push, NV05_SIFM_COLOR_CONVERSION_TRUNCATE);
- nouveau_pushbuf_kick(push, push->channel);
-
- nouveau_fence_new(&screen->base.fence, &screen->base.fence.current, FALSE);
- return pscreen;
+ PUSH_KICK (push);
}
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.h b/src/gallium/drivers/nouveau/nv30/nv30_screen.h
index 0b3bbbb..7a8c339 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.h
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.h
@@ -22,9 +22,7 @@ struct nv30_screen {
struct nouveau_bo *notify;
struct nouveau_object *ntfy;
- struct nouveau_object *fence;
- struct nouveau_object *query;
struct nouveau_heap *query_heap;
struct list_head queries;
@@ -46,4 +44,6 @@ nv30_screen(struct pipe_screen *pscreen)
return (struct nv30_screen *)pscreen;
}
+extern void nv30_screen_init_hwctx(struct nv30_screen *screen, struct nouveau_pushbuf *push);
+
#endif
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c
index f227559..0daab1b 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_state_validate.c
@@ -432,8 +432,10 @@ nv30_state_context_switch(struct nv30_context *nv30)
{
struct nv30_context *prev = nv30->screen->cur_ctx;
- if (prev)
+ if (prev) {
+ PUSH_KICK(prev->base.pushbuf);
nv30->state = prev->state;
+ }
nv30->dirty = NV30_NEW_ALL;
if (!nv30->vertex)
@@ -458,7 +460,6 @@ nv30_state_context_switch(struct nv30_context *nv30)
boolean
nv30_state_validate(struct nv30_context *nv30, boolean hwtnl)
{
- struct nouveau_screen *screen = &nv30->screen->base;
struct nouveau_pushbuf *push = nv30->base.pushbuf;
struct nouveau_bufctx *bctx = nv30->bufctx;
struct nouveau_bufref *bref;
@@ -516,13 +517,13 @@ nv30_state_validate(struct nv30_context *nv30, boolean hwtnl)
LIST_FOR_EACH_ENTRY(bref, &bctx->current, thead) {
struct nv04_resource *res = bref->priv;
if (res && res->mm) {
- nouveau_fence_ref(screen->fence.current, &res->fence);
+ nouveau_fence_ref(nv30->base.fence.current, &res->fence);
if (bref->flags & NOUVEAU_BO_RD)
res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
if (bref->flags & NOUVEAU_BO_WR) {
- nouveau_fence_ref(screen->fence.current, &res->fence_wr);
+ nouveau_fence_ref(nv30->base.fence.current, &res->fence_wr);
res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
}
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c
index af1e436..526f6e0 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c
@@ -36,14 +36,14 @@ nv50_flush(struct pipe_context *pipe,
struct pipe_fence_handle **fence,
unsigned flags)
{
- struct nouveau_screen *screen = nouveau_screen(pipe->screen);
+ struct nv50_context *nv50 = nv50_context(pipe);
if (fence)
- nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
+ nouveau_fence_ref(nv50->base.fence.current, (struct nouveau_fence **)fence);
- PUSH_KICK(screen->pushbuf);
+ PUSH_KICK(nv50->base.pushbuf);
- nouveau_context_update_frame_stats(nouveau_context(pipe));
+ nouveau_context_update_frame_stats(&nv50->base);
}
static void
@@ -80,14 +80,11 @@ nv50_memory_barrier(struct pipe_context *pipe, unsigned flags)
void
nv50_default_kick_notify(struct nouveau_pushbuf *push)
{
- struct nv50_screen *screen = push->user_priv;
+ struct nv50_context *nv50 = push->user_priv;
- if (screen) {
- nouveau_fence_next(&screen->base.fence);
- nouveau_fence_update(&screen->base.fence, TRUE);
- if (screen->cur_ctx)
- screen->cur_ctx->state.flushed = TRUE;
- }
+ nouveau_fence_next(&nv50->base.fence);
+ nouveau_fence_update(&nv50->base.fence, TRUE);
+ nv50->state.flushed = TRUE;
}
static void
@@ -124,8 +121,27 @@ nv50_destroy(struct pipe_context *pipe)
if (nv50_context_screen(nv50)->cur_ctx == nv50)
nv50_context_screen(nv50)->cur_ctx = NULL;
- nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
- nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
+
+ if (nv50->base.pushbuf) {
+ nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL);
+ nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel);
+ }
+
+ if (nv50->base.fence.current) {
+ struct nouveau_fence *current = NULL;
+
+ /* nouveau_fence_wait will create a new current fence, so wait on the
+ * _current_ one, and remove both.
+ */
+ nouveau_fence_ref(nv50->base.fence.current, ¤t);
+ nouveau_fence_wait(current);
+ nouveau_fence_ref(NULL, ¤t);
+ nouveau_fence_ref(NULL, &nv50->base.fence.current);
+ }
+ if (nv50->fence.mm) {
+ nouveau_mm_free(nv50->fence.mm);
+ nouveau_bo_ref(NULL, &nv50->fence.bo);
+ }
nv50_context_unreference_resources(nv50);
@@ -138,6 +154,40 @@ nv50_destroy(struct pipe_context *pipe)
nouveau_context_destroy(&nv50->base);
}
+
+static void
+nv50_context_fence_emit(struct nouveau_fence_mgr *mgr, u32 *sequence)
+{
+ struct nv50_context *nv50 = NULL;
+ struct nouveau_pushbuf *push;
+
+ nv50 = container_of(mgr, nv50, base.fence);
+ push = nv50->base.pushbuf;
+
+ /* we need to do it after possible flush in MARK_RING */
+ *sequence = ++nv50->base.fence.sequence;
+
+ PUSH_DATA (push, NV50_FIFO_PKHDR(NV50_3D(QUERY_ADDRESS_HIGH), 4));
+ PUSH_DATAh(push, nv50->fence.bo->offset + nv50->fence.ofs);
+ PUSH_DATA (push, nv50->fence.bo->offset + nv50->fence.ofs);
+ PUSH_DATA (push, *sequence);
+ PUSH_DATA (push, 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 u32
+nv50_context_fence_update(struct nouveau_fence_mgr *mgr)
+{
+ struct nv50_context *nv50 = NULL;
+
+ nv50 = container_of(mgr, nv50, base.fence);
+ return nv50->fence.map[0];
+}
+
static int
nv50_invalidate_resource_storage(struct nouveau_context *ctx,
struct pipe_resource *res,
@@ -240,9 +290,29 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
if (!nv50_blitctx_create(nv50))
goto out_err;
- nv50->base.pushbuf = screen->base.pushbuf;
nv50->base.client = screen->base.client;
+ ret = nouveau_pushbuf_new(screen->base.client, screen->base.channel,
+ 4, 512 * 1024, 1, &nv50->base.pushbuf);
+ if (ret)
+ goto out_err;
+
+ nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;
+ nv50->base.pushbuf->user_priv = nv50;
+ nv50->base.pushbuf->rsvd_kick = 5;
+
+ nv50->base.fence.screen = &screen->base;
+ nv50->base.fence.flush = nouveau_context_fence_kick;
+ nv50->base.fence.emit = nv50_context_fence_emit;
+ nv50->base.fence.update = nv50_context_fence_update;
+
+ nv50->fence.mm = nouveau_mm_allocate(screen->base.mm_GART, 16, &nv50->fence.bo, &nv50->fence.ofs);
+ if (!nv50->fence.bo)
+ goto out_err;
+
+ nouveau_bo_map(nv50->fence.bo, NOUVEAU_BO_RD, screen->base.client);
+ nv50->fence.map = (u32 *)((char *)nv50->fence.bo->map + nv50->fence.ofs);
+
ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT,
&nv50->bufctx_3d);
if (!ret)
@@ -250,6 +320,14 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
if (ret)
goto out_err;
+ nouveau_fence_new(&nv50->base.fence, &nv50->base.fence.current, FALSE);
+
+ if (!screen->cur_ctx) {
+ nv50_screen_init_hwctx(screen, nv50->base.pushbuf);
+ screen->cur_ctx = nv50;
+ }
+ nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx);
+
nv50->base.screen = &screen->base;
nv50->base.copy_data = nv50_m2mf_copy_linear;
nv50->base.push_data = nv50_sifc_linear_u8;
@@ -269,12 +347,6 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
pipe->memory_barrier = nv50_memory_barrier;
pipe->get_sample_position = nv50_context_get_sample_position;
- if (!screen->cur_ctx) {
- screen->cur_ctx = nv50;
- nouveau_pushbuf_bufctx(screen->base.pushbuf, nv50->bufctx);
- }
- nv50->base.pushbuf->kick_notify = nv50_default_kick_notify;
-
nv50_init_query_functions(nv50);
nv50_init_surface_functions(nv50);
nv50_init_state_functions(nv50);
@@ -313,26 +385,20 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
- BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, screen->fence.bo);
- BCTX_REFN_bo(nv50->bufctx, FENCE, flags, screen->fence.bo);
+ BCTX_REFN_bo(nv50->bufctx_3d, SCREEN, flags, nv50->fence.bo);
+ BCTX_REFN_bo(nv50->bufctx, FENCE, flags, nv50->fence.bo);
nv50->base.scratch.bo_size = 2 << 20;
return pipe;
out_err:
- if (nv50->bufctx_3d)
- nouveau_bufctx_del(&nv50->bufctx_3d);
- if (nv50->bufctx)
- nouveau_bufctx_del(&nv50->bufctx);
- if (nv50->blit)
- FREE(nv50->blit);
- FREE(nv50);
+ nv50_destroy(pipe);
return NULL;
}
void
-nv50_bufctx_fence(struct nouveau_bufctx *bufctx, boolean on_flush)
+nv50_bufctx_fence(struct nv50_context *nv50, struct nouveau_bufctx *bufctx, boolean on_flush)
{
struct nouveau_list *list = on_flush ? &bufctx->current : &bufctx->pending;
struct nouveau_list *it;
@@ -341,7 +407,7 @@ nv50_bufctx_fence(struct nouveau_bufctx *bufctx, boolean on_flush)
struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
struct nv04_resource *res = ref->priv;
if (res)
- nv50_resource_validate(res, (unsigned)ref->priv_data);
+ nv50_resource_validate(nv50, res, (unsigned)ref->priv_data);
}
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h
index 3b7cb18..529a6da 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.h
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h
@@ -186,6 +186,13 @@ struct nv50_context {
struct nv50_blitctx *blit;
+ struct {
+ struct nouveau_mm_allocation *mm;
+ struct nouveau_bo *bo;
+ unsigned ofs;
+ u32 *map;
+ } fence;
+
#ifdef NV50_WITH_DRAW_MODULE
struct draw_context *draw;
#endif
@@ -218,10 +225,34 @@ nv50_context_shader_stage(unsigned pipe)
}
}
+static INLINE void
+nv50_resource_fence(struct nv50_context *nv50, struct nv04_resource *res, uint32_t flags)
+{
+ if (res->mm) {
+ nouveau_fence_ref(nv50->base.fence.current, &res->fence);
+ if (flags & NOUVEAU_BO_WR)
+ nouveau_fence_ref(nv50->base.fence.current, &res->fence_wr);
+ }
+}
+
+static INLINE void
+nv50_resource_validate(struct nv50_context *nv50, struct nv04_resource *res, uint32_t flags)
+{
+ if (likely(res->bo)) {
+ if (flags & NOUVEAU_BO_WR)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
+ NOUVEAU_BUFFER_STATUS_DIRTY;
+ if (flags & NOUVEAU_BO_RD)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
+
+ nv50_resource_fence(nv50, res, flags);
+ }
+}
+
/* nv50_context.c */
struct pipe_context *nv50_create(struct pipe_screen *, void *);
-void nv50_bufctx_fence(struct nouveau_bufctx *, boolean on_flush);
+void nv50_bufctx_fence(struct nv50_context *nv50, struct nouveau_bufctx *, boolean on_flush);
void nv50_default_kick_notify(struct nouveau_pushbuf *);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c
index 4744a3c..c489a0d 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_program.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c
@@ -445,7 +445,7 @@ nv50_program_upload_code(struct nv50_context *nv50, struct nv50_program *prog)
}
prog->code_base = prog->mem->start;
- ret = nv50_tls_realloc(nv50->screen, prog->tls_space);
+ ret = nv50_tls_realloc(nv50, prog->tls_space);
if (ret < 0) {
nouveau_heap_free(&prog->mem);
return FALSE;
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_query.c b/src/gallium/drivers/nouveau/nv50/nv50_query.c
index 6a17139..44ac2e1 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_query.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_query.c
@@ -68,7 +68,7 @@ nv50_query_allocate(struct nv50_context *nv50, struct nv50_query *q, int size)
if (q->ready)
nouveau_mm_free(q->mm);
else
- nouveau_fence_work(screen->base.fence.current, nouveau_mm_free_work,
+ nouveau_fence_work(nv50->base.fence.current, nouveau_mm_free_work,
q->mm);
}
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index 8195650..4efcac6 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -307,20 +307,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
if (!nouveau_drm_screen_unref(&screen->base))
return;
- if (screen->base.fence.current) {
- struct nouveau_fence *current = NULL;
-
- /* nouveau_fence_wait will create a new current fence, so wait on the
- * _current_ one, and remove both.
- */
- nouveau_fence_ref(screen->base.fence.current, ¤t);
- nouveau_fence_wait(current);
- nouveau_fence_ref(NULL, ¤t);
- nouveau_fence_ref(NULL, &screen->base.fence.current);
- }
- if (screen->base.pushbuf)
- screen->base.pushbuf->user_priv = NULL;
-
if (screen->blitter)
nv50_blitter_destroy(screen);
@@ -329,7 +315,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
nouveau_bo_ref(NULL, &screen->stack_bo);
nouveau_bo_ref(NULL, &screen->txc);
nouveau_bo_ref(NULL, &screen->uniforms);
- nouveau_bo_ref(NULL, &screen->fence.bo);
nouveau_heap_destroy(&screen->vp_code_heap);
nouveau_heap_destroy(&screen->gp_code_heap);
@@ -347,43 +332,9 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
FREE(screen);
}
-static void
-nv50_screen_fence_emit(struct nouveau_fence_mgr *mgr, u32 *sequence)
-{
- struct nv50_screen *screen = NULL;
- struct nouveau_pushbuf *push;
-
- screen = container_of(mgr, screen, base.fence);
- push = screen->base.pushbuf;
-
- /* we need to do it after possible flush in MARK_RING */
- *sequence = ++screen->base.fence.sequence;
-
- PUSH_DATA (push, NV50_FIFO_PKHDR(NV50_3D(QUERY_ADDRESS_HIGH), 4));
- PUSH_DATAh(push, screen->fence.bo->offset);
- PUSH_DATA (push, screen->fence.bo->offset);
- PUSH_DATA (push, *sequence);
- PUSH_DATA (push, 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 u32
-nv50_screen_fence_update(struct nouveau_fence_mgr *mgr)
+void
+nv50_screen_init_hwctx(struct nv50_screen *screen, struct nouveau_pushbuf *push)
{
- struct nv50_screen *screen = NULL;
-
- screen = container_of(mgr, screen, base.fence);
- return screen->fence.map[0];
-}
-
-static void
-nv50_screen_init_hwctx(struct nv50_screen *screen)
-{
- struct nouveau_pushbuf *push = screen->base.pushbuf;
struct nv04_fifo *fifo;
unsigned i;
@@ -625,9 +576,10 @@ static int nv50_tls_alloc(struct nv50_screen *screen, unsigned tls_space,
return 0;
}
-int nv50_tls_realloc(struct nv50_screen *screen, unsigned tls_space)
+int nv50_tls_realloc(struct nv50_context *nv50, unsigned tls_space)
{
- struct nouveau_pushbuf *push = screen->base.pushbuf;
+ struct nouveau_pushbuf *push = nv50->base.pushbuf;
+ struct nv50_screen *screen = nv50->screen;
int ret;
uint64_t tls_size;
@@ -685,9 +637,6 @@ nv50_screen_create(struct nouveau_device *dev)
screen->base.sysmem_bindings |=
PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER;
- screen->base.pushbuf->user_priv = screen;
- screen->base.pushbuf->rsvd_kick = 5;
-
chan = screen->base.channel;
pscreen->destroy = nv50_screen_destroy;
@@ -714,20 +663,6 @@ nv50_screen_create(struct nouveau_device *dev)
screen->base.base.is_video_format_supported = nouveau_vp3_screen_video_supported;
}
- ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096,
- NULL, &screen->fence.bo);
- if (ret) {
- NOUVEAU_ERR("Failed to allocate fence bo: %d\n", ret);
- goto fail;
- }
-
- nouveau_bo_map(screen->fence.bo, 0, NULL);
- screen->fence.map = screen->fence.bo->map;
- screen->base.fence.screen = &screen->base;
- screen->base.fence.flush = nouveau_screen_fence_kick;
- screen->base.fence.emit = nv50_screen_fence_emit;
- screen->base.fence.update = nv50_screen_fence_update;
-
ret = nouveau_object_new(chan, 0xbeef0301, NOUVEAU_NOTIFIER_CLASS,
&(struct nv04_notify){ .length = 32 },
sizeof(struct nv04_notify), &screen->sync);
@@ -856,10 +791,6 @@ nv50_screen_create(struct nouveau_device *dev)
if (!nv50_blitter_create(screen))
goto fail;
- nv50_screen_init_hwctx(screen);
-
- nouveau_fence_new(&screen->base.fence, &screen->base.fence.current, FALSE);
-
return pscreen;
fail:
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.h b/src/gallium/drivers/nouveau/nv50/nv50_screen.h
index f8ce365..db69b67 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.h
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.h
@@ -59,11 +59,6 @@ struct nv50_screen {
uint32_t lock[NV50_TSC_MAX_ENTRIES / 32];
} tsc;
- struct {
- uint32_t *map;
- struct nouveau_bo *bo;
- } fence;
-
struct nouveau_object *sync;
struct nouveau_object *tesla;
@@ -83,32 +78,6 @@ void nv50_blitter_destroy(struct nv50_screen *);
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 nv04_resource *res, uint32_t flags)
-{
- struct nv50_screen *screen = nv50_screen(res->base.screen);
-
- if (res->mm) {
- nouveau_fence_ref(screen->base.fence.current, &res->fence);
- if (flags & NOUVEAU_BO_WR)
- nouveau_fence_ref(screen->base.fence.current, &res->fence_wr);
- }
-}
-
-static INLINE void
-nv50_resource_validate(struct nv04_resource *res, uint32_t flags)
-{
- if (likely(res->bo)) {
- if (flags & NOUVEAU_BO_WR)
- res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
- NOUVEAU_BUFFER_STATUS_DIRTY;
- if (flags & NOUVEAU_BO_RD)
- res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
-
- nv50_resource_fence(res, flags);
- }
-}
-
struct nv50_format {
uint32_t rt;
uint32_t tic;
@@ -150,6 +119,8 @@ nv50_screen_tsc_free(struct nv50_screen *screen, struct nv50_tsc_entry *tsc)
}
}
-extern int nv50_tls_realloc(struct nv50_screen *screen, unsigned tls_space);
+extern int nv50_tls_realloc(struct nv50_context *nv50, unsigned tls_space);
+
+extern void nv50_screen_init_hwctx(struct nv50_screen *screen, struct nouveau_pushbuf *push);
#endif
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
index 1dcb961..3c6acb3 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
@@ -393,8 +393,10 @@ nv50_switch_pipe_context(struct nv50_context *ctx_to)
{
struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
- if (ctx_from)
+ if (ctx_from) {
+ PUSH_KICK(ctx_from->base.pushbuf);
ctx_to->state = ctx_from->state;
+ }
ctx_to->dirty = ~0;
ctx_to->viewports_dirty = ~0;
@@ -494,14 +496,14 @@ nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words)
PUSH_DATA (nv50->base.pushbuf, 0);
}
- nv50_bufctx_fence(nv50->bufctx_3d, FALSE);
+ nv50_bufctx_fence(nv50, nv50->bufctx_3d, FALSE);
}
nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx_3d);
ret = nouveau_pushbuf_validate(nv50->base.pushbuf);
if (unlikely(nv50->state.flushed)) {
nv50->state.flushed = FALSE;
- nv50_bufctx_fence(nv50->bufctx_3d, TRUE);
+ nv50_bufctx_fence(nv50, nv50->bufctx_3d, TRUE);
}
return !ret;
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
index 6e68fb8..fd555d5 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
@@ -601,8 +601,8 @@ nv50_clear_buffer(struct pipe_context *pipe,
PUSH_DATA (push, 0x3c);
}
- nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence);
- nouveau_fence_ref(nv50->screen->base.fence.current, &buf->fence_wr);
+ nouveau_fence_ref(nv50->base.fence.current, &buf->fence);
+ nouveau_fence_ref(nv50->base.fence.current, &buf->fence_wr);
nv50->dirty |= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR;
}
@@ -1405,7 +1405,7 @@ nv50_blit_eng2d(struct nv50_context *nv50, const struct pipe_blit_info *info)
PUSH_DATA (push, srcy >> 32);
}
}
- nv50_bufctx_fence(nv50->bufctx, FALSE);
+ nv50_bufctx_fence(nv50, nv50->bufctx, FALSE);
nouveau_bufctx_reset(nv50->bufctx, NV50_BIND_2D);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
index 3fa2f05..9707a45 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
@@ -735,11 +735,11 @@ nva0_draw_stream_output(struct nv50_context *nv50,
static void
nv50_draw_vbo_kick_notify(struct nouveau_pushbuf *chan)
{
- struct nv50_screen *screen = chan->user_priv;
+ struct nv50_context *nv50 = chan->user_priv;
- nouveau_fence_update(&screen->base.fence, TRUE);
+ nouveau_fence_update(&nv50->base.fence, TRUE);
- nv50_bufctx_fence(screen->cur_ctx->bufctx_3d, TRUE);
+ nv50_bufctx_fence(nv50, nv50->bufctx_3d, TRUE);
}
void
diff --git a/src/gallium/drivers/nouveau/nv50/nv84_video.c b/src/gallium/drivers/nouveau/nv50/nv84_video.c
index a39f572..d5aa43b 100644
--- a/src/gallium/drivers/nouveau/nv50/nv84_video.c
+++ b/src/gallium/drivers/nouveau/nv50/nv84_video.c
@@ -492,17 +492,17 @@ nv84_create_decoder(struct pipe_context *context,
surf.offset = dec->vpring->size - 0x1000;
context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1);
- PUSH_SPACE(screen->pushbuf, 5);
- PUSH_REFN(screen->pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
+ PUSH_SPACE(nv50->base.pushbuf, 5);
+ PUSH_REFN(nv50->base.pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
/* The clear_render_target is done via 3D engine, so use it to write to a
* sempahore to indicate that it's done.
*/
- BEGIN_NV04(screen->pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4);
- PUSH_DATAh(screen->pushbuf, dec->fence->offset);
- PUSH_DATA (screen->pushbuf, dec->fence->offset);
- PUSH_DATA (screen->pushbuf, 1);
- PUSH_DATA (screen->pushbuf, 0xf010);
- PUSH_KICK (screen->pushbuf);
+ BEGIN_NV04(nv50->base.pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4);
+ PUSH_DATAh(nv50->base.pushbuf, dec->fence->offset);
+ PUSH_DATA (nv50->base.pushbuf, dec->fence->offset);
+ PUSH_DATA (nv50->base.pushbuf, 1);
+ PUSH_DATA (nv50->base.pushbuf, 0xf010);
+ PUSH_KICK (nv50->base.pushbuf);
PUSH_SPACE(bsp_push, 2 + 12 + 2 + 4 + 3);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
index ad287a2..f769e67 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
@@ -26,14 +26,12 @@
#include "nvc0/nvc0_compute.h"
int
-nvc0_screen_compute_setup(struct nvc0_screen *screen,
- struct nouveau_pushbuf *push)
+nvc0_screen_compute_setup(struct nvc0_screen *screen)
{
struct nouveau_object *chan = screen->base.channel;
struct nouveau_device *dev = screen->base.device;
uint32_t obj_class;
int ret;
- int i;
switch (dev->chipset & ~0xf) {
case 0xc0:
@@ -59,8 +57,18 @@ nvc0_screen_compute_setup(struct nvc0_screen *screen,
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 1 << 12, NULL,
&screen->parm);
- if (ret)
- return ret;
+ return ret;
+}
+
+void
+nvc0_context_compute_setup(struct nvc0_context *nvc0)
+{
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct nvc0_screen *screen = nvc0->screen;
+ int i;
+
+ if (!screen->parm)
+ return;
BEGIN_NVC0(push, SUBC_COMPUTE(NV01_SUBCHAN_OBJECT), 1);
PUSH_DATA (push, screen->compute->oclass);
@@ -117,8 +125,6 @@ nvc0_screen_compute_setup(struct nvc0_screen *screen,
PUSH_DATA (push, (0 << 8) | 1);
/* TODO: textures & samplers */
-
- return 0;
}
boolean
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.h b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.h
index 9a1a717..6364c3b 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.h
@@ -4,6 +4,10 @@
#include "nv50/nv50_defs.xml.h"
#include "nvc0/nvc0_compute.xml.h"
+void nvc0_context_compute_setup(struct nvc0_context *nvc0);
+
+int nvc0_screen_compute_setup(struct nvc0_screen *);
+
boolean
nvc0_compute_validate_program(struct nvc0_context *nvc0);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
index 52f8a57..1fd3091 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
@@ -37,10 +37,9 @@ nvc0_flush(struct pipe_context *pipe,
unsigned flags)
{
struct nvc0_context *nvc0 = nvc0_context(pipe);
- struct nouveau_screen *screen = &nvc0->screen->base;
if (fence)
- nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence);
+ nouveau_fence_ref(nvc0->base.fence.current, (struct nouveau_fence **)fence);
PUSH_KICK(nvc0->base.pushbuf); /* fencing handled in kick_notify */
@@ -50,7 +49,8 @@ nvc0_flush(struct pipe_context *pipe,
static void
nvc0_texture_barrier(struct pipe_context *pipe)
{
- struct nouveau_pushbuf *push = nvc0_context(pipe)->base.pushbuf;
+ struct nvc0_context *nvc0 = nvc0_context(pipe);
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0);
IMMED_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 0);
@@ -125,11 +125,27 @@ nvc0_destroy(struct pipe_context *pipe)
if (nvc0->screen->cur_ctx == nvc0)
nvc0->screen->cur_ctx = NULL;
- /* Unset bufctx, we don't want to revalidate any resources after the flush.
- * Other contexts will always set their bufctx again on action calls.
- */
- nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL);
- nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel);
+
+ if (nvc0->base.pushbuf) {
+ nouveau_pushbuf_bufctx(nvc0->base.pushbuf, NULL);
+ nouveau_pushbuf_kick(nvc0->base.pushbuf, nvc0->base.pushbuf->channel);
+ }
+
+ if (nvc0->base.fence.current) {
+ struct nouveau_fence *current = NULL;
+
+ /* nouveau_fence_wait will create a new current fence, so wait on the
+ * _current_ one, and remove both.
+ */
+ nouveau_fence_ref(nvc0->base.fence.current, ¤t);
+ nouveau_fence_wait(current);
+ nouveau_fence_ref(NULL, ¤t);
+ nouveau_fence_ref(NULL, &nvc0->base.fence.current);
+ }
+ if (nvc0->fence.mm) {
+ nouveau_mm_free(nvc0->fence.mm);
+ nouveau_bo_ref(NULL, &nvc0->fence.bo);
+ }
nvc0_context_unreference_resources(nvc0);
nvc0_blitctx_destroy(nvc0);
@@ -144,15 +160,14 @@ nvc0_destroy(struct pipe_context *pipe)
void
nvc0_default_kick_notify(struct nouveau_pushbuf *push)
{
- struct nvc0_screen *screen = push->user_priv;
+ struct nvc0_context *nvc0 = push->user_priv;
- if (screen) {
- nouveau_fence_next(&screen->base.fence);
- nouveau_fence_update(&screen->base.fence, TRUE);
- if (screen->cur_ctx)
- screen->cur_ctx->state.flushed = TRUE;
+ if (nvc0) {
+ nouveau_fence_next(&nvc0->base.fence);
+ nouveau_fence_update(&nvc0->base.fence, TRUE);
+ nvc0->state.flushed = TRUE;
}
- NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
+ NOUVEAU_DRV_STAT(&nvc0->screen->base, pushbuf_count, 1);
}
static int
@@ -240,6 +255,53 @@ static void
nvc0_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
float *);
+static void
+nvc0_context_fence_emit(struct nouveau_fence_mgr *mgr, u32 *sequence)
+{
+ struct nvc0_context *nvc0 = NULL;
+ struct nouveau_pushbuf *push;
+
+ nvc0 = container_of(mgr, nvc0, base.fence);
+ push = nvc0->base.pushbuf;
+
+ /* we need to do it after possible flush in MARK_RING */
+ *sequence = ++mgr->sequence;
+
+ BEGIN_NVC0(push, NVC0_3D(QUERY_ADDRESS_HIGH), 4);
+ PUSH_DATAh(push, nvc0->fence.bo->offset + nvc0->fence.ofs);
+ PUSH_DATA (push, nvc0->fence.bo->offset + nvc0->fence.ofs);
+ PUSH_DATA (push, *sequence);
+ PUSH_DATA (push, NVC0_3D_QUERY_GET_FENCE | NVC0_3D_QUERY_GET_SHORT |
+ (0xf << NVC0_3D_QUERY_GET_UNIT__SHIFT));
+}
+
+static u32
+nvc0_context_fence_update(struct nouveau_fence_mgr *mgr)
+{
+ struct nvc0_context *nvc0 = NULL;
+
+ nvc0 = container_of(mgr, nvc0, base.fence);
+ return nvc0->fence.map[0];
+}
+
+static void nvc0_init_fence_functions(struct nvc0_context *nvc0)
+{
+ struct nvc0_screen *screen = nvc0->screen;
+
+ nvc0->fence.mm = nouveau_mm_allocate(screen->base.mm_GART, 16, &nvc0->fence.bo, &nvc0->fence.ofs);
+ if (nvc0->fence.bo) {
+ nouveau_bo_map(nvc0->fence.bo, NOUVEAU_BO_RD, screen->base.client);
+ nvc0->fence.map = (u32 *)((char *)nvc0->fence.bo->map + nvc0->fence.ofs);
+
+ nouveau_fence_new(&nvc0->base.fence, &nvc0->base.fence.current, FALSE);
+ }
+
+ nvc0->base.fence.screen = &screen->base;
+ nvc0->base.fence.flush = nouveau_context_fence_kick;
+ nvc0->base.fence.emit = nvc0_context_fence_emit;
+ nvc0->base.fence.update = nvc0_context_fence_update;
+}
+
struct pipe_context *
nvc0_create(struct pipe_screen *pscreen, void *priv)
{
@@ -257,9 +319,17 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
if (!nvc0_blitctx_create(nvc0))
goto out_err;
- nvc0->base.pushbuf = screen->base.pushbuf;
nvc0->base.client = screen->base.client;
+ ret = nouveau_pushbuf_new(screen->base.client, screen->base.channel,
+ 4, 512 * 1024, 1, &nvc0->base.pushbuf);
+ if (ret)
+ goto out_err;
+
+ nvc0->base.pushbuf->kick_notify = nvc0_default_kick_notify;
+ nvc0->base.pushbuf->user_priv = nvc0;
+ nvc0->base.pushbuf->rsvd_kick = 5;
+
ret = nouveau_bufctx_new(screen->base.client, 2, &nvc0->bufctx);
if (!ret)
ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_3D_COUNT,
@@ -288,11 +358,12 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
pipe->memory_barrier = nvc0_memory_barrier;
pipe->get_sample_position = nvc0_context_get_sample_position;
+ nvc0_init_fence_functions(nvc0);
if (!screen->cur_ctx) {
screen->cur_ctx = nvc0;
- nouveau_pushbuf_bufctx(screen->base.pushbuf, nvc0->bufctx);
+ nvc0_screen_init_hwctx(nvc0);
}
- screen->base.pushbuf->kick_notify = nvc0_default_kick_notify;
+ nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
nvc0_init_query_functions(nvc0);
nvc0_init_surface_functions(nvc0);
@@ -337,10 +408,14 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
flags = NOUVEAU_BO_GART | NOUVEAU_BO_WR;
- BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->fence.bo);
- BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->fence.bo);
- if (screen->compute)
- BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, screen->fence.bo);
+ BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, screen->notify.bo);
+ BCTX_REFN_bo(nvc0->bufctx_3d, SCREEN, flags, nvc0->fence.bo);
+ BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, screen->notify.bo);
+ BCTX_REFN_bo(nvc0->bufctx, FENCE, flags, nvc0->fence.bo);
+ if (screen->compute) {
+ BCTX_REFN_bo(nvc0->bufctx_3d, CP_SCREEN, flags, screen->notify.bo);
+ BCTX_REFN_bo(nvc0->bufctx_cp, CP_SCREEN, flags, nvc0->fence.bo);
+ }
nvc0->base.scratch.bo_size = 2 << 20;
@@ -351,17 +426,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
return pipe;
out_err:
- if (nvc0) {
- if (nvc0->bufctx_3d)
- nouveau_bufctx_del(&nvc0->bufctx_3d);
- if (nvc0->bufctx_cp)
- nouveau_bufctx_del(&nvc0->bufctx_cp);
- if (nvc0->bufctx)
- nouveau_bufctx_del(&nvc0->bufctx);
- if (nvc0->blit)
- FREE(nvc0->blit);
- FREE(nvc0);
- }
+ nvc0_destroy(pipe);
return NULL;
}
@@ -377,7 +442,7 @@ nvc0_bufctx_fence(struct nvc0_context *nvc0, struct nouveau_bufctx *bufctx,
struct nouveau_bufref *ref = (struct nouveau_bufref *)it;
struct nv04_resource *res = ref->priv;
if (res)
- nvc0_resource_validate(res, (unsigned)ref->priv_data);
+ nvc0_resource_validate(nvc0, res, (unsigned)ref->priv_data);
NOUVEAU_DRV_STAT_IFD(count++);
}
NOUVEAU_DRV_STAT(&nvc0->screen->base, resource_validate_count, count);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
index 76416a0..823a181 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
@@ -140,6 +140,13 @@ struct nvc0_context {
struct nvc0_transform_feedback_state *tfb;
} state;
+ struct {
+ struct nouveau_mm_allocation *mm;
+ struct nouveau_bo *bo;
+ u32 ofs;
+ u32 *map;
+ } fence;
+
struct nvc0_blend_stateobj *blend;
struct nvc0_rasterizer_stateobj *rast;
struct nvc0_zsa_stateobj *zsa;
@@ -356,4 +363,29 @@ void nve4_launch_grid(struct pipe_context *,
void nvc0_launch_grid(struct pipe_context *,
const uint *, const uint *, uint32_t, const void *);
+
+static INLINE void
+nvc0_resource_fence(struct nvc0_context *nvc0, struct nv04_resource *res, uint32_t flags)
+{
+ if (res->mm) {
+ nouveau_fence_ref(nvc0->base.fence.current, &res->fence);
+ if (flags & NOUVEAU_BO_WR)
+ nouveau_fence_ref(nvc0->base.fence.current, &res->fence_wr);
+ }
+}
+
+static INLINE void
+nvc0_resource_validate(struct nvc0_context *nvc0, struct nv04_resource *res, uint32_t flags)
+{
+ if (likely(res->bo)) {
+ if (flags & NOUVEAU_BO_WR)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
+ NOUVEAU_BUFFER_STATUS_DIRTY;
+ if (flags & NOUVEAU_BO_RD)
+ res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
+
+ nvc0_resource_fence(nvc0, res, flags);
+ }
+}
+
#endif
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_query.c b/src/gallium/drivers/nouveau/nvc0/nvc0_query.c
index 856f685..7438d62 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_query.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_query.c
@@ -79,7 +79,7 @@ nvc0_query_allocate(struct nvc0_context *nvc0, struct nvc0_query *q, int size)
if (q->state == NVC0_QUERY_STATE_READY)
nouveau_mm_free(q->u.mm);
else
- nouveau_fence_work(screen->base.fence.current,
+ nouveau_fence_work(nvc0->base.fence.current,
nouveau_mm_free_work, q->u.mm);
}
}
@@ -411,7 +411,7 @@ nvc0_query_end(struct pipe_context *pipe, struct pipe_query *pq)
break;
}
if (q->is64bit)
- nouveau_fence_ref(nvc0->screen->base.fence.current, &q->fence);
+ nouveau_fence_ref(nvc0->base.fence.current, &q->fence);
}
static INLINE void
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index 2a317af..26ddbed 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -31,6 +31,8 @@
#include "nvc0/nvc0_context.h"
#include "nvc0/nvc0_screen.h"
+#include "nvc0/nvc0_compute.h"
+#include "nvc0/nve4_compute.h"
#include "nvc0/mme/com9097.mme.h"
@@ -357,20 +359,6 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
if (!nouveau_drm_screen_unref(&screen->base))
return;
- if (screen->base.fence.current) {
- struct nouveau_fence *current = NULL;
-
- /* nouveau_fence_wait will create a new current fence, so wait on the
- * _current_ one, and remove both.
- */
- nouveau_fence_ref(screen->base.fence.current, ¤t);
- nouveau_fence_wait(current);
- nouveau_fence_ref(NULL, ¤t);
- nouveau_fence_ref(NULL, &screen->base.fence.current);
- }
- if (screen->base.pushbuf)
- screen->base.pushbuf->user_priv = NULL;
-
if (screen->blitter)
nvc0_blitter_destroy(screen);
if (screen->pm.prog) {
@@ -382,9 +370,11 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
nouveau_bo_ref(NULL, &screen->uniform_bo);
nouveau_bo_ref(NULL, &screen->tls);
nouveau_bo_ref(NULL, &screen->txc);
- nouveau_bo_ref(NULL, &screen->fence.bo);
nouveau_bo_ref(NULL, &screen->poly_cache);
nouveau_bo_ref(NULL, &screen->parm);
+ nouveau_bo_ref(NULL, &screen->notify.bo);
+ if (screen->notify.mm)
+ nouveau_mm_free(screen->notify.mm);
nouveau_heap_destroy(&screen->lib_code);
nouveau_heap_destroy(&screen->text_heap);
@@ -405,11 +395,9 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
}
static int
-nvc0_graph_set_macro(struct nvc0_screen *screen, uint32_t m, unsigned pos,
+nvc0_graph_set_macro(struct nouveau_pushbuf *push, uint32_t m, unsigned pos,
unsigned size, const uint32_t *data)
{
- struct nouveau_pushbuf *push = screen->base.pushbuf;
-
size /= 4;
BEGIN_NVC0(push, SUBC_3D(NVC0_GRAPH_MACRO_ID), 2);
@@ -489,35 +477,6 @@ nvc0_magic_3d_init(struct nouveau_pushbuf *push, uint16_t obj_class)
* are supposed to do */
}
-static void
-nvc0_screen_fence_emit(struct nouveau_fence_mgr *mgr, u32 *sequence)
-{
- struct nvc0_screen *screen = NULL;
- struct nouveau_pushbuf *push;
-
- screen = container_of(mgr, screen, base.fence);
- push = screen->base.pushbuf;
-
- /* we need to do it after possible flush in MARK_RING */
- *sequence = ++screen->base.fence.sequence;
-
- BEGIN_NVC0(push, NVC0_3D(QUERY_ADDRESS_HIGH), 4);
- PUSH_DATAh(push, screen->fence.bo->offset);
- PUSH_DATA (push, screen->fence.bo->offset);
- PUSH_DATA (push, *sequence);
- PUSH_DATA (push, NVC0_3D_QUERY_GET_FENCE | NVC0_3D_QUERY_GET_SHORT |
- (0xf << NVC0_3D_QUERY_GET_UNIT__SHIFT));
-}
-
-static u32
-nvc0_screen_fence_update(struct nouveau_fence_mgr *mgr)
-{
- struct nvc0_screen *screen = NULL;
-
- screen = container_of(mgr, screen, base.fence);
- return screen->fence.map[0];
-}
-
static int
nvc0_screen_init_compute(struct nvc0_screen *screen)
{
@@ -530,10 +489,10 @@ nvc0_screen_init_compute(struct nvc0_screen *screen)
* investigate this further before enabling it by default.
*/
if (debug_get_bool_option("NVC0_COMPUTE", FALSE))
- return nvc0_screen_compute_setup(screen, screen->base.pushbuf);
+ return nvc0_screen_compute_setup(screen);
return 0;
case 0xe0:
- return nve4_screen_compute_setup(screen, screen->base.pushbuf);
+ return nve4_screen_compute_setup(screen);
case 0xf0:
case 0x100:
case 0x110:
@@ -586,11 +545,9 @@ nvc0_screen_create(struct nouveau_device *dev)
struct nvc0_screen *screen;
struct pipe_screen *pscreen;
struct nouveau_object *chan;
- struct nouveau_pushbuf *push;
uint64_t value;
uint32_t obj_class;
int ret;
- unsigned i;
union nouveau_bo_config mm_config;
switch (dev->chipset & ~0xf) {
@@ -616,9 +573,6 @@ nvc0_screen_create(struct nouveau_device *dev)
return NULL;
}
chan = screen->base.channel;
- push = screen->base.pushbuf;
- push->user_priv = screen;
- push->rsvd_kick = 5;
screen->base.vidmem_bindings |= PIPE_BIND_CONSTANT_BUFFER |
PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER;
@@ -638,16 +592,12 @@ nvc0_screen_create(struct nouveau_device *dev)
screen->base.base.get_video_param = nouveau_vp3_screen_get_video_param;
screen->base.base.is_video_format_supported = nouveau_vp3_screen_video_supported;
- ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, NULL,
- &screen->fence.bo);
- if (ret)
+
+ screen->notify.mm = nouveau_mm_allocate(screen->base.mm_GART, 16,
+ &screen->notify.bo,
+ &screen->notify.ofs);
+ if (!screen->notify.mm)
goto fail;
- nouveau_bo_map(screen->fence.bo, 0, NULL);
- screen->fence.map = screen->fence.bo->map;
- screen->base.fence.screen = &screen->base;
- screen->base.fence.flush = nouveau_screen_fence_kick;
- screen->base.fence.emit = nvc0_screen_fence_emit;
- screen->base.fence.update = nvc0_screen_fence_update;
ret = nouveau_object_new(chan,
@@ -675,39 +625,11 @@ nvc0_screen_create(struct nouveau_device *dev)
if (ret)
FAIL_SCREEN_INIT("Error allocating PGRAPH context for M2MF: %d\n", ret);
- BEGIN_NVC0(push, SUBC_M2MF(NV01_SUBCHAN_OBJECT), 1);
- PUSH_DATA (push, screen->m2mf->oclass);
- if (screen->m2mf->oclass == NVE4_P2MF_CLASS) {
- BEGIN_NVC0(push, SUBC_COPY(NV01_SUBCHAN_OBJECT), 1);
- PUSH_DATA (push, 0xa0b5);
- }
-
ret = nouveau_object_new(chan, 0xbeef902d, NVC0_2D_CLASS, NULL, 0,
&screen->eng2d);
if (ret)
FAIL_SCREEN_INIT("Error allocating PGRAPH context for 2D: %d\n", ret);
- BEGIN_NVC0(push, SUBC_2D(NV01_SUBCHAN_OBJECT), 1);
- PUSH_DATA (push, screen->eng2d->oclass);
- BEGIN_NVC0(push, NVC0_2D(SINGLE_GPC), 1);
- PUSH_DATA (push, 0);
- BEGIN_NVC0(push, NVC0_2D(OPERATION), 1);
- PUSH_DATA (push, NVC0_2D_OPERATION_SRCCOPY);
- BEGIN_NVC0(push, NVC0_2D(CLIP_ENABLE), 1);
- PUSH_DATA (push, 0);
- BEGIN_NVC0(push, NVC0_2D(COLOR_KEY_ENABLE), 1);
- PUSH_DATA (push, 0);
- BEGIN_NVC0(push, SUBC_2D(0x0884), 1);
- PUSH_DATA (push, 0x3f);
- BEGIN_NVC0(push, SUBC_2D(0x0888), 1);
- PUSH_DATA (push, 1);
- BEGIN_NVC0(push, NVC0_2D(COND_MODE), 1);
- PUSH_DATA (push, NVC0_2D_COND_MODE_ALWAYS);
-
- BEGIN_NVC0(push, SUBC_2D(NVC0_GRAPH_NOTIFY_ADDRESS_HIGH), 2);
- PUSH_DATAh(push, screen->fence.bo->offset + 16);
- PUSH_DATA (push, screen->fence.bo->offset + 16);
-
switch (dev->chipset & ~0xf) {
case 0x110:
obj_class = GM107_3D_CLASS;
@@ -750,6 +672,95 @@ nvc0_screen_create(struct nouveau_device *dev)
FAIL_SCREEN_INIT("Error allocating PGRAPH context for 3D: %d\n", ret);
screen->base.class_3d = obj_class;
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, NULL,
+ &screen->text);
+ if (ret)
+ goto fail;
+
+ /* XXX: getting a page fault at the end of the code buffer every few
+ * launches, don't use the last 256 bytes to work around them - prefetch ?
+ */
+ nouveau_heap_init(&screen->text_heap, 0, (1 << 20) - 0x100);
+
+ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 6 << 16, NULL,
+ &screen->uniform_bo);
+ if (ret)
+ goto fail;
+
+ if (dev->drm_version >= 0x01000101) {
+ ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_GRAPH_UNITS, &value);
+ if (ret) {
+ NOUVEAU_ERR("NOUVEAU_GETPARAM_GRAPH_UNITS failed.\n");
+ goto fail;
+ }
+ } else {
+ if (dev->chipset >= 0xe0 && dev->chipset < 0xf0)
+ value = (8 << 8) | 4;
+ else
+ value = (16 << 8) | 4;
+ }
+ screen->mp_count = value >> 8;
+ screen->mp_count_compute = screen->mp_count;
+
+ nvc0_screen_resize_tls_area(screen, 128 * 16, 0, 0x200);
+
+ screen->tic.entries = CALLOC(4096, sizeof(void *));
+ screen->tsc.entries = screen->tic.entries + 2048;
+
+ mm_config.nvc0.tile_mode = 0;
+ mm_config.nvc0.memtype = 0xfe0;
+ screen->mm_VRAM_fe0 = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config);
+
+ if (!nvc0_blitter_create(screen))
+ goto fail;
+
+ if (nvc0_screen_init_compute(screen))
+ goto fail;
+
+ return pscreen;
+
+fail:
+ nvc0_screen_destroy(pscreen);
+ return NULL;
+}
+
+int
+nvc0_screen_init_hwctx(struct nvc0_context *nvc0)
+{
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct nvc0_screen *screen = nvc0->screen;
+ struct nouveau_device *dev = screen->base.device;
+ unsigned i;
+ int ret;
+
+ BEGIN_NVC0(push, SUBC_M2MF(NV01_SUBCHAN_OBJECT), 1);
+ PUSH_DATA (push, screen->m2mf->oclass);
+ if (screen->m2mf->oclass == NVE4_P2MF_CLASS) {
+ BEGIN_NVC0(push, SUBC_COPY(NV01_SUBCHAN_OBJECT), 1);
+ PUSH_DATA (push, 0xa0b5);
+ }
+
+ BEGIN_NVC0(push, SUBC_2D(NV01_SUBCHAN_OBJECT), 1);
+ PUSH_DATA (push, screen->eng2d->oclass);
+ BEGIN_NVC0(push, NVC0_2D(SINGLE_GPC), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NVC0(push, NVC0_2D(OPERATION), 1);
+ PUSH_DATA (push, NVC0_2D_OPERATION_SRCCOPY);
+ BEGIN_NVC0(push, NVC0_2D(CLIP_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NVC0(push, NVC0_2D(COLOR_KEY_ENABLE), 1);
+ PUSH_DATA (push, 0);
+ BEGIN_NVC0(push, SUBC_2D(0x0884), 1);
+ PUSH_DATA (push, 0x3f);
+ BEGIN_NVC0(push, SUBC_2D(0x0888), 1);
+ PUSH_DATA (push, 1);
+ BEGIN_NVC0(push, NVC0_2D(COND_MODE), 1);
+ PUSH_DATA (push, NVC0_2D_COND_MODE_ALWAYS);
+
+ BEGIN_NVC0(push, SUBC_2D(NVC0_GRAPH_NOTIFY_ADDRESS_HIGH), 2);
+ PUSH_DATAh(push, screen->notify.bo->offset + screen->notify.ofs);
+ PUSH_DATA (push, screen->notify.bo->offset + screen->notify.ofs);
+
BEGIN_NVC0(push, SUBC_3D(NV01_SUBCHAN_OBJECT), 1);
PUSH_DATA (push, screen->eng3d->oclass);
@@ -804,21 +815,6 @@ nvc0_screen_create(struct nouveau_device *dev)
nvc0_magic_3d_init(push, screen->eng3d->oclass);
- ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 17, 1 << 20, NULL,
- &screen->text);
- if (ret)
- goto fail;
-
- /* XXX: getting a page fault at the end of the code buffer every few
- * launches, don't use the last 256 bytes to work around them - prefetch ?
- */
- nouveau_heap_init(&screen->text_heap, 0, (1 << 20) - 0x100);
-
- ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 1 << 12, 6 << 16, NULL,
- &screen->uniform_bo);
- if (ret)
- goto fail;
-
PUSH_REFN (push, screen->uniform_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
for (i = 0; i < 5; ++i) {
@@ -859,23 +855,6 @@ nvc0_screen_create(struct nouveau_device *dev)
PUSH_DATAh(push, screen->uniform_bo->offset + (5 << 16) + (6 << 9));
PUSH_DATA (push, screen->uniform_bo->offset + (5 << 16) + (6 << 9));
- if (dev->drm_version >= 0x01000101) {
- ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_GRAPH_UNITS, &value);
- if (ret) {
- NOUVEAU_ERR("NOUVEAU_GETPARAM_GRAPH_UNITS failed.\n");
- goto fail;
- }
- } else {
- if (dev->chipset >= 0xe0 && dev->chipset < 0xf0)
- value = (8 << 8) | 4;
- else
- value = (16 << 8) | 4;
- }
- screen->mp_count = value >> 8;
- screen->mp_count_compute = screen->mp_count;
-
- nvc0_screen_resize_tls_area(screen, 128 * 16, 0, 0x200);
-
BEGIN_NVC0(push, NVC0_3D(CODE_ADDRESS_HIGH), 2);
PUSH_DATAh(push, screen->text->offset);
PUSH_DATA (push, screen->text->offset);
@@ -954,7 +933,7 @@ nvc0_screen_create(struct nouveau_device *dev)
PUSH_DATA (push, 8192 << 16);
PUSH_DATA (push, 8192 << 16);
-#define MK_MACRO(m, n) i = nvc0_graph_set_macro(screen, m, i, sizeof(n), n);
+#define MK_MACRO(m, n) i = nvc0_graph_set_macro(push, m, i, sizeof(n), n);
i = 0;
MK_MACRO(NVC0_3D_MACRO_VERTEX_ARRAY_PER_INSTANCE, mme9097_per_instance_bf);
@@ -989,28 +968,14 @@ nvc0_screen_create(struct nouveau_device *dev)
IMMED_NVC0(push, NVC0_3D(EDGEFLAG), 1);
- if (nvc0_screen_init_compute(screen))
- goto fail;
-
- PUSH_KICK (push);
-
- screen->tic.entries = CALLOC(4096, sizeof(void *));
- screen->tsc.entries = screen->tic.entries + 2048;
-
- mm_config.nvc0.tile_mode = 0;
- mm_config.nvc0.memtype = 0xfe0;
- screen->mm_VRAM_fe0 = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config);
-
- if (!nvc0_blitter_create(screen))
- goto fail;
-
- nouveau_fence_new(&screen->base.fence, &screen->base.fence.current, FALSE);
-
- return pscreen;
+ if (dev->chipset < 0xe0)
+ nvc0_context_compute_setup(nvc0);
+ else
+ nve4_context_compute_setup(nvc0);
fail:
- nvc0_screen_destroy(pscreen);
- return NULL;
+ PUSH_KICK (push);
+ return ret;
}
int
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
index c58add5..95843c7 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
@@ -59,9 +59,11 @@ struct nvc0_screen {
} tsc;
struct {
+ struct nouveau_mm_allocation *mm;
struct nouveau_bo *bo;
- uint32_t *map;
- } fence;
+ u32 ofs;
+ u32 *map;
+ } notify;
struct {
struct nvc0_program *prog; /* compute state object to read MP counters */
@@ -250,37 +252,10 @@ void nvc0_screen_make_buffers_resident(struct nvc0_screen *);
int nvc0_screen_tic_alloc(struct nvc0_screen *, void *);
int nvc0_screen_tsc_alloc(struct nvc0_screen *, void *);
-int nve4_screen_compute_setup(struct nvc0_screen *, struct nouveau_pushbuf *);
-int nvc0_screen_compute_setup(struct nvc0_screen *, struct nouveau_pushbuf *);
-
boolean nvc0_screen_resize_tls_area(struct nvc0_screen *, uint32_t lpos,
uint32_t lneg, uint32_t cstack);
-static INLINE void
-nvc0_resource_fence(struct nv04_resource *res, uint32_t flags)
-{
- struct nvc0_screen *screen = nvc0_screen(res->base.screen);
-
- if (res->mm) {
- nouveau_fence_ref(screen->base.fence.current, &res->fence);
- if (flags & NOUVEAU_BO_WR)
- nouveau_fence_ref(screen->base.fence.current, &res->fence_wr);
- }
-}
-
-static INLINE void
-nvc0_resource_validate(struct nv04_resource *res, uint32_t flags)
-{
- if (likely(res->bo)) {
- if (flags & NOUVEAU_BO_WR)
- res->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING |
- NOUVEAU_BUFFER_STATUS_DIRTY;
- if (flags & NOUVEAU_BO_RD)
- res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING;
-
- nvc0_resource_fence(res, flags);
- }
-}
+int nvc0_screen_init_hwctx(struct nvc0_context *nvc0);
struct nvc0_format {
uint32_t rt;
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
index dcec910..e808082 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
@@ -130,7 +130,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
PUSH_DATA(push, 0);
PUSH_DATA(push, 0);
- nvc0_resource_fence(res, NOUVEAU_BO_WR);
+ nvc0_resource_fence(nvc0, res, NOUVEAU_BO_WR);
assert(!fb->zsbuf);
}
@@ -523,8 +523,10 @@ nvc0_switch_pipe_context(struct nvc0_context *ctx_to)
struct nvc0_context *ctx_from = ctx_to->screen->cur_ctx;
unsigned s;
- if (ctx_from)
+ if (ctx_from) {
+ PUSH_KICK(ctx_from->base.pushbuf);
ctx_to->state = ctx_from->state;
+ }
ctx_to->dirty = ~0;
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
index c28ec6d..6e4f68b 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
@@ -332,7 +332,7 @@ nvc0_clear_render_target(struct pipe_context *pipe,
IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);
/* tiled textures don't have to be fenced, they're not mapped directly */
- nvc0_resource_fence(res, NOUVEAU_BO_WR);
+ nvc0_resource_fence(nvc0, res, NOUVEAU_BO_WR);
}
BEGIN_NIC0(push, NVC0_3D(CLEAR_BUFFERS), sf->depth);
@@ -479,8 +479,8 @@ nvc0_clear_buffer(struct pipe_context *pipe,
IMMED_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 0x3c);
}
- nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence);
- nouveau_fence_ref(nvc0->screen->base.fence.current, &buf->fence_wr);
+ nouveau_fence_ref(nvc0->base.fence.current, &buf->fence);
+ nouveau_fence_ref(nvc0->base.fence.current, &buf->fence_wr);
nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
}
@@ -1354,8 +1354,8 @@ nvc0_blit_eng2d(struct nvc0_context *nvc0, const struct pipe_blit_info *info)
PUSH_DATA (push, srcy >> 32);
}
}
- nvc0_resource_validate(&dst->base, NOUVEAU_BO_WR);
- nvc0_resource_validate(&src->base, NOUVEAU_BO_RD);
+ nvc0_resource_validate(nvc0, &dst->base, NOUVEAU_BO_WR);
+ nvc0_resource_validate(nvc0, &src->base, NOUVEAU_BO_RD);
nouveau_bufctx_reset(nvc0->bufctx, NVC0_BIND_2D);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
index 6406cf5..fbb18cf 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
@@ -557,11 +557,11 @@ nvc0_prim_gl(unsigned prim)
static void
nvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push)
{
- struct nvc0_screen *screen = push->user_priv;
+ struct nvc0_context *nvc0 = push->user_priv;
- nouveau_fence_update(&screen->base.fence, TRUE);
+ nouveau_fence_update(&nvc0->base.fence, TRUE);
- NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1);
+ NOUVEAU_DRV_STAT(&nvc0->screen->base, pushbuf_count, 1);
}
static void
diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c
index f243316..90848b4 100644
--- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.c
+++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.c
@@ -34,12 +34,10 @@ static void nve4_compute_dump_launch_desc(const struct nve4_cp_launch_desc *);
int
-nve4_screen_compute_setup(struct nvc0_screen *screen,
- struct nouveau_pushbuf *push)
+nve4_screen_compute_setup(struct nvc0_screen *screen)
{
struct nouveau_device *dev = screen->base.device;
struct nouveau_object *chan = screen->base.channel;
- unsigned i;
int ret;
uint32_t obj_class;
@@ -65,9 +63,21 @@ nve4_screen_compute_setup(struct nvc0_screen *screen,
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, NVE4_CP_PARAM_SIZE, NULL,
&screen->parm);
- if (ret)
- return ret;
+ return ret;
+}
+
+void
+nve4_context_compute_setup(struct nvc0_context *nvc0)
+{
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct nvc0_screen *screen = nvc0->screen;
+ uint32_t obj_class;
+ unsigned i;
+ if (!screen->parm)
+ return;
+
+ obj_class = screen->compute->oclass;
BEGIN_NVC0(push, SUBC_COMPUTE(NV01_SUBCHAN_OBJECT), 1);
PUSH_DATA (push, screen->compute->oclass);
@@ -176,8 +186,6 @@ nve4_screen_compute_setup(struct nvc0_screen *screen,
BEGIN_NVC0(push, NVE4_COMPUTE(FLUSH), 1);
PUSH_DATA (push, NVE4_COMPUTE_FLUSH_CB);
-
- return 0;
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nve4_compute.h b/src/gallium/drivers/nouveau/nvc0/nve4_compute.h
index 79862b7..a4be963 100644
--- a/src/gallium/drivers/nouveau/nvc0/nve4_compute.h
+++ b/src/gallium/drivers/nouveau/nvc0/nve4_compute.h
@@ -5,6 +5,9 @@
#include "nv50/nv50_defs.xml.h"
#include "nvc0/nve4_compute.xml.h"
+void nve4_context_compute_setup(struct nvc0_context *nvc0);
+int nve4_screen_compute_setup(struct nvc0_screen *);
+
/* Input space is implemented as c0[], to which we bind the screen->parm bo.
*/
#define NVE4_CP_INPUT_USER 0x0000
--
2.0.0
More information about the Nouveau
mailing list