[PATCH 1/7] nv50: support conditional rendering
Christoph Bumiller
e0425955 at student.tuwien.ac.at
Tue Jan 5 05:22:06 PST 2010
On get_query_result with wait == TRUE, we now flush
and then busy wait for the result to be written.
---
src/gallium/drivers/nv50/nv50_query.c | 94 +++++++++++++++++++++++---------
src/gallium/drivers/nv50/nv50_screen.c | 6 ++-
src/gallium/drivers/nv50/nv50_screen.h | 1 +
3 files changed, 75 insertions(+), 26 deletions(-)
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 5d9e182..e320cc6 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -27,6 +27,7 @@
struct nv50_query {
struct nouveau_bo *bo;
+ int slot;
unsigned type;
boolean ready;
uint64_t result;
@@ -41,19 +42,23 @@ nv50_query(struct pipe_query *pipe)
static struct pipe_query *
nv50_query_create(struct pipe_context *pipe, unsigned type)
{
- struct nouveau_device *dev = nouveau_screen(pipe->screen)->device;
- struct nv50_query *q = CALLOC_STRUCT(nv50_query);
- int ret;
+ struct nv50_screen *screen = nv50_context(pipe)->screen;
+ struct nv50_query *q;
+ int slot;
- assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER);
- q->type = type;
+ assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
- ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 256,
- 16, &q->bo);
- if (ret) {
- FREE(q);
+ slot = ffs(screen->notifier_slots) - 1;
+ if (slot < 0)
return NULL;
- }
+
+ q = CALLOC_STRUCT(nv50_query);
+ if (!q)
+ return NULL;
+
+ screen->notifier_slots |= 1 << slot;
+ q->slot = slot;
+ q->type = type;
return (struct pipe_query *)q;
}
@@ -61,10 +66,11 @@ nv50_query_create(struct pipe_context *pipe, unsigned type)
static void
nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
{
+ struct nv50_screen *screen = nv50_context(pipe)->screen;
struct nv50_query *q = nv50_query(pq);
if (q) {
- nouveau_bo_ref(NULL, &q->bo);
+ screen->notifier_slots &= ~(1 << q->slot);
FREE(q);
}
}
@@ -72,11 +78,14 @@ nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq)
static void
nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
{
- struct nv50_context *nv50 = nv50_context(pipe);
- struct nouveau_channel *chan = nv50->screen->base.channel;
- struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_screen *screen = nv50_context(pipe)->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *tesla = screen->tesla;
struct nv50_query *q = nv50_query(pq);
+ nouveau_notifier_wr32(screen->sync, q->slot * 4 + 0, 0xff);
+ nouveau_notifier_wr32(screen->sync, q->slot * 4 + 1, 0xff);
+
BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_RESET, 1);
OUT_RING (chan, 1);
BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1);
@@ -93,36 +102,70 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
struct nouveau_grobj *tesla = nv50->screen->tesla;
struct nv50_query *q = nv50_query(pq);
- MARK_RING (chan, 5, 2); /* flush on lack of space or relocs */
BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4);
- OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, q->slot * 16);
OUT_RING (chan, 0x00000000);
OUT_RING (chan, 0x0100f002);
- FIRE_RING (chan);
+
+ BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1);
+ OUT_RING (chan, 0);
}
static boolean
nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
boolean wait, uint64_t *result)
{
+ struct nv50_screen *screen = nv50_context(pipe)->screen;
+ struct nouveau_channel *chan = screen->base.channel;
struct nv50_query *q = nv50_query(pq);
- int ret;
if (!q->ready) {
- ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD |
- wait ? 0 : NOUVEAU_BO_NOWAIT);
- if (ret)
- return false;
- q->result = ((uint32_t *)q->bo->map)[1];
+ int pos = q->slot * 16;
+
+ if (nouveau_notifier_rd32(screen->sync, pos)) {
+ if (!wait)
+ return false;
+ FIRE_RING(chan);
+ }
+ while (nouveau_notifier_rd32(screen->sync, pos));
+
+ q->result = nouveau_notifier_rd32(screen->sync, pos + 1);
q->ready = TRUE;
- nouveau_bo_unmap(q->bo);
}
*result = q->result;
return q->ready;
}
+static void
+nv50_render_condition(struct pipe_context *pipe,
+ struct pipe_query *pq, uint mode)
+{
+ struct nv50_screen *screen = nv50_context(pipe)->screen;
+ struct nouveau_channel *chan = screen->base.channel;
+ struct nouveau_grobj *tesla = screen->tesla;
+ struct nv50_query *q = nv50_query(pq);
+
+ if (q) {
+ if (mode == PIPE_RENDER_COND_WAIT ||
+ mode == PIPE_RENDER_COND_BY_REGION_WAIT) {
+ BEGIN_RING(chan, tesla, 0x60, 3);
+ OUT_RING (chan, screen->sync->handle);
+ OUT_RING (chan, q->slot * 16);
+ OUT_RING (chan, 0);
+ }
+
+ BEGIN_RING(chan, tesla, NV50TCL_COND_ADDRESS_HIGH, 3);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, q->slot * 16);
+ OUT_RING (chan, NV50TCL_COND_MODE_RES);
+ } else {
+ BEGIN_RING(chan, tesla, NV50TCL_COND_MODE, 1);
+ OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS);
+ }
+}
+
void
nv50_init_query_functions(struct nv50_context *nv50)
{
@@ -131,4 +174,5 @@ nv50_init_query_functions(struct nv50_context *nv50)
nv50->pipe.begin_query = nv50_query_begin;
nv50->pipe.end_query = nv50_query_end;
nv50->pipe.get_query_result = nv50_query_result;
+ nv50->pipe.render_condition = nv50_render_condition;
}
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 7e039ea..d7bc3cd 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -276,12 +276,13 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
BIND_RING(chan, screen->tesla, 3);
/* Sync notifier */
- ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync);
+ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 16, &screen->sync);
if (ret) {
NOUVEAU_ERR("Error creating notifier object: %d\n", ret);
nv50_screen_destroy(pscreen);
return NULL;
}
+ screen->notifier_slots = 0x3; /* mark first 2 slots as reserved */
/* Static M2MF init */
so = so_new(32, 0);
@@ -322,6 +323,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
NV50TCL_DMA_COLOR__SIZE);
for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++)
so_data(so, chan->vram->handle);
+ so_method(so, screen->tesla, NV50TCL_DMA_QUERY, 1);
+ so_data (so, screen->sync->handle);
+
so_method(so, screen->tesla, NV50TCL_RT_CONTROL, 1);
so_data (so, 1);
diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
index 61e24a5..7a66e11 100644
--- a/src/gallium/drivers/nv50/nv50_screen.h
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -14,6 +14,7 @@ struct nv50_screen {
struct nouveau_grobj *eng2d;
struct nouveau_grobj *m2mf;
struct nouveau_notifier *sync;
+ uint32_t notifier_slots;
struct nouveau_bo *constbuf_misc[1];
struct nouveau_bo *constbuf_parm[2];
--
1.6.4.4
--------------060703070100030003060000
Content-Type: text/plain;
name="0001-nouveau-add-nouveau_notifier_rd32-wr32.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0001-nouveau-add-nouveau_notifier_rd32-wr32.patch"
More information about the Nouveau
mailing list