From fba2eabe13b8a3f8c1396c5949db3daab0192156 Mon Sep 17 00:00:00 2001 From: Christoph Bumiller Date: Sat, 10 Oct 2009 13:13:16 +0200 Subject: [PATCH] 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. --- src/gallium/drivers/nv50/nv50_context.c | 7 --- src/gallium/drivers/nv50/nv50_context.h | 5 ++ src/gallium/drivers/nv50/nv50_screen.c | 25 ++------- .../drivers/nv50/nv50_state_validate.c | 54 ++++++++++++++++--- src/gallium/drivers/nv50/nv50_tex.c | 34 +++++++----- src/gallium/drivers/nv50/nv50_vbo.c | 4 -- 6 files changed, 77 insertions(+), 52 deletions(-) diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 7ef27bb671c..219e7a78623 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -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); diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index fd2dab856de..75cb65d9a28 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -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 *); diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index dd7baecba7c..66361dc3baf 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -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 */ diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index 9079de918d0..012911f41bd 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -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); +} diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 81e04327e80..e12a6ad648b 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -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; diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index eeed148c7b9..8b0fbf0e760 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -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)); -- 2.30.2