nv40: delay all state emit until before draw
authorBen Skeggs <skeggsb@gmail.com>
Sat, 9 Feb 2008 03:08:54 +0000 (14:08 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Fri, 15 Feb 2008 02:50:33 +0000 (13:50 +1100)
src/mesa/pipe/nouveau/nouveau_stateobj.h
src/mesa/pipe/nv40/nv40_context.h
src/mesa/pipe/nv40/nv40_state.c
src/mesa/pipe/nv40/nv40_state_emit.c
src/mesa/pipe/nv40/nv40_vbo.c

index 8dfc0e9..58167a2 100644 (file)
@@ -30,7 +30,7 @@ so_new(unsigned push, unsigned reloc)
        struct nouveau_stateobj *so;
 
        so = malloc(sizeof(struct nouveau_stateobj));
-       so->refcount = 0;
+       so->refcount = 1;
        so->push = malloc(sizeof(unsigned) * push);
        so->reloc = malloc(sizeof(struct nouveau_stateobj_reloc) * reloc);
 
index 1a31f00..4aa3484 100644 (file)
 #define NOUVEAU_MSG(fmt, args...) \
        fprintf(stderr, "nouveau: "fmt, ##args);
 
-#define NV40_NEW_VERTPROG      (1 << 1)
-#define NV40_NEW_FRAGPROG      (1 << 2)
-#define NV40_NEW_ARRAYS                (1 << 3)
+#define NV40_NEW_BLEND         (1 <<  0)
+#define NV40_NEW_RAST          (1 <<  1)
+#define NV40_NEW_ZSA           (1 <<  2)
+#define NV40_NEW_SAMPLER       (1 <<  3)
+#define NV40_NEW_FB            (1 <<  4)
+#define NV40_NEW_STIPPLE       (1 <<  5)
+#define NV40_NEW_SCISSOR       (1 <<  6)
+#define NV40_NEW_VIEWPORT      (1 <<  7)
+#define NV40_NEW_BCOL          (1 <<  8)
+#define NV40_NEW_VERTPROG      (1 <<  9)
+#define NV40_NEW_FRAGPROG      (1 << 10)
+#define NV40_NEW_ARRAYS                (1 << 11)
 
 struct nv40_context {
        struct pipe_context pipe;
@@ -51,6 +60,13 @@ struct nv40_context {
        struct nouveau_stateobj *so_framebuffer;
        struct nouveau_stateobj *so_fragtex[16];
        struct nouveau_stateobj *so_vtxbuf;
+       struct nouveau_stateobj *so_blend;
+       struct nouveau_stateobj *so_rast;
+       struct nouveau_stateobj *so_zsa;
+       struct nouveau_stateobj *so_bcol;
+       struct nouveau_stateobj *so_scissor;
+       struct nouveau_stateobj *so_viewport;
+       struct nouveau_stateobj *so_stipple;
 
        struct {
                struct nouveau_resource *exec_heap;
index 125134a..ab53b03 100644 (file)
@@ -53,7 +53,8 @@ nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv40_context *nv40 = nv40_context(pipe);
 
-       so_emit(nv40->nvws, hwcso);
+       so_ref(hwcso, &nv40->so_blend);
+       nv40->dirty |= NV40_NEW_BLEND;
 }
 
 static void
@@ -354,7 +355,8 @@ nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv40_context *nv40 = nv40_context(pipe);
 
-       so_emit(nv40->nvws, hwcso);
+       so_ref(hwcso, &nv40->so_rast);
+       nv40->dirty |= NV40_NEW_RAST;
 }
 
 static void
@@ -420,7 +422,8 @@ nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv40_context *nv40 = nv40_context(pipe);
 
-       so_emit(nv40->nvws, hwcso);
+       so_ref(hwcso, &nv40->so_zsa);
+       nv40->dirty |= NV40_NEW_ZSA;
 }
 
 static void
@@ -508,8 +511,9 @@ nv40_set_blend_color(struct pipe_context *pipe,
                       (float_to_ubyte(bcol->color[1]) <<  8) |
                       (float_to_ubyte(bcol->color[2]) <<  0)));
 
-       so_emit(nv40->nvws, so);
+       so_ref(so, &nv40->so_bcol);
        so_ref(NULL, &so);
+       nv40->dirty |= NV40_NEW_BCOL;
 }
 
 static void
@@ -677,8 +681,9 @@ nv40_set_framebuffer_state(struct pipe_context *pipe,
        so_data  (so, ((w - 1) << 16) | 0);
        so_data  (so, ((h - 1) << 16) | 0);
 
-       so_emit(nv40->nvws, so);
-       so_ref (so, &nv40->so_framebuffer);
+       so_ref(so, &nv40->so_framebuffer);
+       so_ref(NULL, &so);
+       nv40->dirty |= NV40_NEW_FB;
 }
 
 static void
@@ -693,8 +698,9 @@ nv40_set_polygon_stipple(struct pipe_context *pipe,
        for (i = 0; i < 32; i++)
                so_data(so, stipple->stipple[i]);
 
-       so_emit(nv40->nvws, so);
+       so_ref(so, &nv40->so_stipple);
        so_ref(NULL, &so);
+       nv40->dirty |= NV40_NEW_STIPPLE;
 }
 
 static void
@@ -708,8 +714,9 @@ nv40_set_scissor_state(struct pipe_context *pipe,
        so_data  (so, ((s->maxx - s->minx) << 16) | s->minx);
        so_data  (so, ((s->maxy - s->miny) << 16) | s->miny);
 
-       so_emit(nv40->nvws, so);
+       so_ref(so, &nv40->so_scissor);
        so_ref(NULL, &so);
+       nv40->dirty |= NV40_NEW_SCISSOR;
 }
 
 static void
@@ -729,8 +736,9 @@ nv40_set_viewport_state(struct pipe_context *pipe,
        so_data  (so, fui(vpt->scale[2]));
        so_data  (so, fui(vpt->scale[3]));
 
-       so_emit(nv40->nvws, so);
+       so_ref(so, &nv40->so_viewport);
        so_ref(NULL, &so);
+       nv40->dirty |= NV40_NEW_VIEWPORT;
 }
 
 static void
index 3a22cd4..a10c995 100644 (file)
@@ -25,6 +25,30 @@ nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
 void
 nv40_emit_hw_state(struct nv40_context *nv40)
 {
+       if (nv40->dirty & NV40_NEW_FB)
+               so_emit(nv40->nvws, nv40->so_framebuffer);
+
+       if (nv40->dirty & NV40_NEW_BLEND)
+               so_emit(nv40->nvws, nv40->so_blend);
+
+       if (nv40->dirty & NV40_NEW_RAST)
+               so_emit(nv40->nvws, nv40->so_rast);
+
+       if (nv40->dirty & NV40_NEW_ZSA)
+               so_emit(nv40->nvws, nv40->so_zsa);
+
+       if (nv40->dirty & NV40_NEW_BCOL)
+               so_emit(nv40->nvws, nv40->so_bcol);
+
+       if (nv40->dirty & NV40_NEW_SCISSOR)
+               so_emit(nv40->nvws, nv40->so_scissor);
+
+       if (nv40->dirty & NV40_NEW_VIEWPORT)
+               so_emit(nv40->nvws, nv40->so_viewport);
+
+       if (nv40->dirty & NV40_NEW_STIPPLE)
+               so_emit(nv40->nvws, nv40->so_stipple);
+
        if (nv40->dirty & NV40_NEW_FRAGPROG) {
                nv40_fragprog_bind(nv40, nv40->fragprog.current);
                /*XXX: clear NV40_NEW_FRAGPROG if no new program uploaded */
@@ -46,6 +70,7 @@ nv40_emit_hw_state(struct nv40_context *nv40)
        }
 
        nv40->dirty_samplers = 0;
+       nv40->dirty = 0;
 
        nv40_state_emit_dummy_relocs(nv40);
 }
index e2cb3fd..fd1d884 100644 (file)
@@ -158,6 +158,7 @@ nv40_vbo_arrays_update(struct nv40_context *nv40, struct pipe_buffer *ib,
        so_emit(nv40->nvws, vtxfmt);
        so_emit(nv40->nvws, vtxbuf);
        so_ref (vtxbuf, &nv40->so_vtxbuf);
+       so_ref (NULL, &vtxbuf);
        so_ref (NULL, &vtxfmt);
 }
 
@@ -165,8 +166,10 @@ static boolean
 nv40_vbo_validate_state(struct nv40_context *nv40,
                        struct pipe_buffer *ib, unsigned ib_format)
 {
+       unsigned vdn = nv40->dirty & NV40_NEW_ARRAYS;
+
        nv40_emit_hw_state(nv40);
-       if (nv40->dirty & NV40_NEW_ARRAYS || ib) {
+       if (vdn || ib) {
                nv40_vbo_arrays_update(nv40, ib, ib_format);
                nv40->dirty &= ~NV40_NEW_ARRAYS;
        }