summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0/nvc0_shader_state.c
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2011-12-09 18:46:09 +0100
committerChristoph Bumiller <[email protected]>2011-12-15 18:51:48 +0100
commit14bd9d764802b5fedb652c791faafe4d13b65262 (patch)
tree4dba8e6abb0d7d6914fa7f265b5f81127c86c262 /src/gallium/drivers/nvc0/nvc0_shader_state.c
parent14193da589275969be31dbdb3280bb48cd24d0c0 (diff)
nvc0: implement new stream output interface
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_shader_state.c')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_shader_state.c104
1 files changed, 63 insertions, 41 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nvc0/nvc0_shader_state.c
index f4a12fbee11..446bd948a53 100644
--- a/src/gallium/drivers/nvc0/nvc0_shader_state.c
+++ b/src/gallium/drivers/nvc0/nvc0_shader_state.c
@@ -90,7 +90,9 @@ nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
return FALSE;
}
- return nvc0_program_upload_code(nvc0, prog);
+ if (likely(prog->code_size))
+ return nvc0_program_upload_code(nvc0, prog);
+ return TRUE; /* stream output info only */
}
void
@@ -212,14 +214,15 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
struct nouveau_channel *chan = nvc0->screen->base.channel;
struct nvc0_program *gp = nvc0->gmtyprog;
- if (!gp) {
+ if (gp)
+ nvc0_program_validate(nvc0, gp);
+ /* we allow GPs with no code for specifying stream output state only */
+ if (!gp || !gp->code_size) {
BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
OUT_RING (chan, 0x40);
IMMED_RING(chan, RING_3D(LAYER), 0);
return;
}
- if (!nvc0_program_validate(nvc0, gp))
- return;
nvc0_program_update_context_state(nvc0, gp, 3);
BEGIN_RING(chan, RING_3D(GP_SELECT), 1);
@@ -234,57 +237,76 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
nvc0_program_validate_clip(nvc0, gp);
}
-/* It's *is* kind of shader related. We need to inspect the program
- * to get the output locations right.
- */
void
nvc0_tfb_validate(struct nvc0_context *nvc0)
{
struct nouveau_channel *chan = nvc0->screen->base.channel;
- struct nvc0_program *vp;
- struct nvc0_transform_feedback_state *tfb = nvc0->tfb;
- int b;
+ struct nvc0_transform_feedback_state *tfb;
+ unsigned b, n, i;
- BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
- if (!tfb) {
- OUT_RING(chan, 0);
- return;
+ if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb;
+ else
+ if (nvc0->tevlprog) tfb = nvc0->tevlprog->tfb;
+ else
+ tfb = nvc0->vertprog->tfb;
+
+ IMMED_RING(chan, RING_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0);
+
+ if (tfb && tfb != nvc0->state.tfb) {
+ uint8_t var[128];
+
+ for (n = 0, b = 0; b < 4; n += tfb->varying_count[b++]) {
+ if (tfb->varying_count[b]) {
+ BEGIN_RING(chan, RING_3D(TFB_STREAM(b)), 3);
+ OUT_RING (chan, 0);
+ OUT_RING (chan, tfb->varying_count[b]);
+ OUT_RING (chan, tfb->stride[b]);
+
+ for (i = 0; i < tfb->varying_count[b]; ++i)
+ var[i] = tfb->varying_index[n + i];
+ for (; i & 3; ++i)
+ var[i] = 0; /* zero rest of method word bits */
+
+ BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), i / 4);
+ OUT_RINGp (chan, var, i / 4);
+
+ if (nvc0->tfbbuf[b])
+ nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b];
+ } else {
+ IMMED_RING(chan, RING_3D(TFB_VARYING_COUNT(b)), 0);
+ }
+ }
}
- OUT_RING(chan, 1);
+ nvc0->state.tfb = tfb;
- vp = nvc0->vertprog ? nvc0->vertprog : nvc0->gmtyprog;
+ if (!(nvc0->dirty & NVC0_NEW_TFB_TARGETS))
+ return;
+ nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_TFB);
for (b = 0; b < nvc0->num_tfbbufs; ++b) {
- uint8_t idx, var[128];
- int i, n;
- struct nv04_resource *buf = nv04_resource(nvc0->tfbbuf[b]);
+ struct nvc0_so_target *targ = nvc0_so_target(nvc0->tfbbuf[b]);
+ struct nv04_resource *buf = nv04_resource(targ->pipe.buffer);
- BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 5);
- OUT_RING (chan, 1);
- OUT_RESRCh(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR);
- OUT_RESRCl(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR);
- OUT_RING (chan, buf->base.width0 - nvc0->tfb_offset[b]);
- OUT_RING (chan, 0); /* TFB_PRIMITIVE_ID <- offset ? */
+ if (tfb)
+ targ->stride = tfb->stride[b];
- if (!(nvc0->dirty & NVC0_NEW_TFB))
+ if (!(nvc0->tfbbuf_dirty & (1 << b)))
continue;
- BEGIN_RING(chan, RING_3D(TFB_UNK07X0(b)), 3);
- OUT_RING (chan, 0);
- OUT_RING (chan, tfb->varying_count[b]);
- OUT_RING (chan, tfb->stride[b]);
-
- n = b ? tfb->varying_count[b - 1] : 0;
- i = 0;
- for (; i < tfb->varying_count[b]; ++i) {
- idx = tfb->varying_index[n + i];
- var[i] = vp->vp.out_pos[idx >> 2] + (idx & 3);
+ if (!targ->clean)
+ nvc0_query_fifo_wait(chan, targ->pq);
+ BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 5);
+ OUT_RING (chan, 1);
+ OUT_RESRCh(chan, buf, targ->pipe.buffer_offset, NOUVEAU_BO_WR);
+ OUT_RESRCl(chan, buf, targ->pipe.buffer_offset, NOUVEAU_BO_WR);
+ OUT_RING (chan, targ->pipe.buffer_size);
+ if (!targ->clean) {
+ nvc0_query_pushbuf_submit(chan, targ->pq, 0x4);
+ } else {
+ OUT_RING(chan, 0); /* TFB_BUFFER_OFFSET */
+ targ->clean = FALSE;
}
- for (; i & 3; ++i)
- var[i] = 0;
-
- BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), i / 4);
- OUT_RINGp (chan, var, i / 4);
+ nvc0_bufctx_add_resident(nvc0, NVC0_BUFCTX_TFB, buf, NOUVEAU_BO_WR);
}
for (; b < 4; ++b)
IMMED_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 0);