nv50: use SIFC for TIC, TSC upload

Add proper flushes for TIC and TSC and remove
the costly 2D.0110 flush in nv50_flush.

Correct TIC and TSC bo sizes.
This commit is contained in:
Christoph Bumiller 2009-10-10 13:13:16 +02:00
parent 6ab2fcca9d
commit fba2eabe13
6 changed files with 77 additions and 52 deletions

View file

@ -33,13 +33,6 @@ nv50_flush(struct pipe_context *pipe, unsigned flags,
{
struct nv50_context *nv50 = nv50_context(pipe);
struct nouveau_channel *chan = nv50->screen->base.channel;
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
/* We need this in the ddx for reliable composite, not sure what we're
* actually flushing. We generate all our own flushes with flags = 0. */
WAIT_RING(chan, 2);
BEGIN_RING(chan, eng2d, 0x0110, 1);
OUT_RING (chan, 0);
if (flags & PIPE_FLUSH_FRAME)
FIRE_RING(chan);

View file

@ -199,6 +199,11 @@ extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program
extern boolean nv50_state_validate(struct nv50_context *nv50);
extern void nv50_state_flush_notify(struct nouveau_channel *chan);
extern void nv50_so_init_sifc(struct nv50_context *nv50,
struct nouveau_stateobj *so,
struct nouveau_bo *bo, unsigned reloc,
unsigned size);
/* nv50_tex.c */
extern void nv50_tex_validate(struct nv50_context *);

View file

@ -364,48 +364,31 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000131 | (NV50_CB_PFP << 12));
/* Texture sampler/image unit setup - we abuse the constant buffer
* upload mechanism for the moment to upload data to the tex config
* blocks. At some point we *may* want to go the NVIDIA way of doing
* things?
*/
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tic);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 64*8*4, &screen->tic);
if (ret) {
nv50_screen_destroy(pscreen);
return NULL;
}
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_TIC << 16) | 0x0800);
so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, 0x00000800);
so_data (so, 0x000007ff);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tsc);
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 64*8*4, &screen->tsc);
if (ret) {
nv50_screen_destroy(pscreen);
return NULL;
}
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_TSC << 16) | 0x0800);
so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM |
NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, 0x00000800);
so_data (so, 0x00000000);
/* Vertex array limits - max them out */

View file

@ -222,6 +222,9 @@ nv50_state_flush_notify(struct nouveau_channel *chan)
{
struct nv50_context *nv50 = chan->user_private;
if (nv50->state.tic_upload && !(nv50->dirty & NV50_NEW_TEXTURE))
so_emit(chan, nv50->state.tic_upload);
so_emit_reloc_markers(chan, nv50->state.fb);
so_emit_reloc_markers(chan, nv50->state.vertprog);
so_emit_reloc_markers(chan, nv50->state.fragprog);
@ -233,6 +236,7 @@ boolean
nv50_state_validate(struct nv50_context *nv50)
{
struct nouveau_grobj *tesla = nv50->screen->tesla;
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
struct nouveau_stateobj *so;
unsigned i;
@ -354,19 +358,25 @@ scissor_uptodate:
viewport_uptodate:
if (nv50->dirty & NV50_NEW_SAMPLER) {
int i;
unsigned i;
so = so_new(nv50->sampler_nr * 9 + 23 + 4, 2);
nv50_so_init_sifc(nv50, so, nv50->screen->tsc, NOUVEAU_BO_VRAM,
nv50->sampler_nr * 8 * 4);
so = so_new(nv50->sampler_nr * 11, 0);
for (i = 0; i < nv50->sampler_nr; i++) {
if (!nv50->sampler[i])
continue;
so_method(so, tesla, NV50TCL_CB_ADDR, 1);
so_data (so, ((i * 8) << NV50TCL_CB_ADDR_ID_SHIFT) |
NV50_CB_TSC);
so_method(so, tesla, NV50TCL_CB_DATA(0) | (2<<29), 8);
so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
so_datap (so, nv50->sampler[i]->tsc, 8);
}
so_method(so, tesla, 0x1440, 1); /* sync SIFC */
so_data (so, 0);
so_method(so, tesla, 0x1334, 1); /* flush TSC */
so_data (so, 0);
so_ref(so, &nv50->state.tsc_upload);
so_ref(NULL, &so);
}
@ -384,3 +394,33 @@ viewport_uptodate:
return TRUE;
}
void nv50_so_init_sifc(struct nv50_context *nv50,
struct nouveau_stateobj *so,
struct nouveau_bo *bo, unsigned reloc, unsigned size)
{
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
so_method(so, eng2d, NV50_2D_DST_FORMAT, 2);
so_data (so, NV50_2D_DST_FORMAT_R8_UNORM);
so_data (so, 1);
so_method(so, eng2d, NV50_2D_DST_PITCH, 5);
so_data (so, 262144);
so_data (so, 65536);
so_data (so, 1);
so_reloc (so, bo, 0, reloc | NOUVEAU_BO_WR | NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, bo, 0, reloc | NOUVEAU_BO_WR | NOUVEAU_BO_LOW, 0, 0);
so_method(so, eng2d, NV50_2D_SIFC_UNK0800, 2);
so_data (so, 0);
so_data (so, NV50_2D_SIFC_FORMAT_R8_UNORM);
so_method(so, eng2d, NV50_2D_SIFC_WIDTH, 10);
so_data (so, size);
so_data (so, 1);
so_data (so, 0);
so_data (so, 1);
so_data (so, 0);
so_data (so, 1);
so_data (so, 0);
so_data (so, 0);
so_data (so, 0);
so_data (so, 0);
}

View file

@ -98,24 +98,24 @@ nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so,
void
nv50_tex_validate(struct nv50_context *nv50)
{
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
struct nouveau_grobj *tesla = nv50->screen->tesla;
struct nouveau_stateobj *so;
int unit, push;
unsigned i, unit, push;
push = nv50->miptree_nr * 11;
push += MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2;
push = MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2 + 23 + 6;
so = so_new(nv50->miptree_nr * 9 + push, nv50->miptree_nr + 2);
so = so_new(push, nv50->miptree_nr * 2);
for (unit = 0; unit < nv50->miptree_nr; unit++) {
nv50_so_init_sifc(nv50, so, nv50->screen->tic, NOUVEAU_BO_VRAM,
nv50->miptree_nr * 8 * 4);
for (i = 0, unit = 0; unit < nv50->miptree_nr; ++unit) {
struct nv50_miptree *mt = nv50->miptree[unit];
if (!mt)
continue;
so_method(so, tesla, NV50TCL_CB_ADDR, 1);
so_data (so, ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT) |
NV50_CB_TIC);
so_method(so, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
so_method(so, eng2d, NV50_2D_SIFC_DATA | (2 << 29), 8);
if (nv50_tex_construct(nv50, so, mt, unit)) {
NOUVEAU_ERR("failed tex validate\n");
so_ref(NULL, &so);
@ -123,17 +123,25 @@ nv50_tex_validate(struct nv50_context *nv50)
}
so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
so_data (so, (unit << NV50TCL_SET_SAMPLER_TEX_TIC_SHIFT) |
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) |
NV50TCL_SET_SAMPLER_TEX_VALID);
so_data (so, (i++ << NV50TCL_SET_SAMPLER_TEX_TIC_SHIFT) |
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) |
NV50TCL_SET_SAMPLER_TEX_VALID);
}
for (; unit < nv50->state.miptree_nr; unit++) {
so_method(so, tesla, NV50TCL_SET_SAMPLER_TEX, 1);
so_data (so,
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) | 0);
(unit << NV50TCL_SET_SAMPLER_TEX_SAMPLER_SHIFT) | 0);
}
/* not sure if the following really do what I think: */
so_method(so, tesla, 0x1440, 1); /* sync SIFC */
so_data (so, 0);
so_method(so, tesla, 0x1330, 1); /* flush TIC */
so_data (so, 0);
so_method(so, tesla, 0x1338, 1); /* flush texture caches */
so_data (so, 0x20);
so_ref(so, &nv50->state.tic_upload);
so_ref(NULL, &so);
nv50->state.miptree_nr = nv50->miptree_nr;

View file

@ -139,10 +139,6 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
OUT_RING (chan, 0);
BEGIN_RING(chan, tesla, 0x142c, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, tesla, 0x1440, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, tesla, 0x1334, 1);
OUT_RING (chan, 0);
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
OUT_RING (chan, nv50_prim(mode));