diff options
author | Christoph Bumiller <[email protected]> | 2011-12-09 18:46:09 +0100 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2011-12-15 18:51:48 +0100 |
commit | 14bd9d764802b5fedb652c791faafe4d13b65262 (patch) | |
tree | 4dba8e6abb0d7d6914fa7f265b5f81127c86c262 /src/gallium/drivers/nvc0/nvc0_shader_state.c | |
parent | 14193da589275969be31dbdb3280bb48cd24d0c0 (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.c | 104 |
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); |