nv50: use SIFC for TIC, TSC upload
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 10 Oct 2009 11:13:16 +0000 (13:13 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Mon, 19 Oct 2009 16:25:08 +0000 (18:25 +0200)
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
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_screen.c
src/gallium/drivers/nv50/nv50_state_validate.c
src/gallium/drivers/nv50/nv50_tex.c
src/gallium/drivers/nv50/nv50_vbo.c

index 7ef27bb671c2b1980202c379b63e462519a5a520..219e7a7862321f2ede5eeabbcbce52785b3d4b30 100644 (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);
index fd2dab856defe1543d55167c5aef3b2b3c54e767..75cb65d9a287d8b26d0053d4687628ae5656a045 100644 (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 *);
 
index dd7baecba7c3f42bfa0e4592e3f3ce5c4ea8781c..66361dc3bafdf403fc632903e233d41bf2f45fc2 100644 (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 */
index 9079de918d0086a4424c584e6bb6151354f0e305..012911f41bd437e57271b3589ce7b86945ea79fc 100644 (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);
+}
index 81e04327e808652597e64ad9c5005f74bf3e6901..e12a6ad648b2f726a44ec28067ebdddf82ca2f6b 100644 (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;
index eeed148c7b904bfd4b79c06ee846dd4359d47d3b..8b0fbf0e76034b8d3b1b290c46cbab0f5523c275 100644 (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));