r300g: Account for CS space used per atom.
authorCorbin Simpson <MostAwesomeDude@gmail.com>
Wed, 13 Jan 2010 09:41:31 +0000 (01:41 -0800)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Wed, 13 Jan 2010 09:44:58 +0000 (01:44 -0800)
Oh yeah, those atoms are startin' to pay off. The main obstacle now
for OA playability is the absurdly low default mouse sensitivity, IMO.
Not totally smooth yet, but getting there.

src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_state.c

index 98a5bb8e5fd1fd86d8e410f691123feea6bf6f68..5e4f6552c363e6862de561a910b7a3cab5846a3d 100644 (file)
@@ -110,23 +110,33 @@ static void r300_flush_cb(void *data)
     cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL);
 }
 
-#define R300_INIT_ATOM(name) \
-    r300->name##_state.state = NULL; \
-    r300->name##_state.emit = r300_emit_##name##_state; \
-    r300->name##_state.dirty = FALSE; \
-    insert_at_tail(&r300->atom_list, &r300->name##_state);
+#define R300_INIT_ATOM(atomname, atomsize) \
+    r300->atomname##_state.name = #atomname; \
+    r300->atomname##_state.state = NULL; \
+    r300->atomname##_state.size = atomsize; \
+    r300->atomname##_state.emit = r300_emit_##atomname##_state; \
+    r300->atomname##_state.dirty = FALSE; \
+    insert_at_tail(&r300->atom_list, &r300->atomname##_state);
 
 static void r300_setup_atoms(struct r300_context* r300)
 {
+    /* Create the actual atom list.
+     *
+     * Each atom is examined and emitted in the order it appears here, which
+     * can affect performance and conformance if not handled with care.
+     *
+     * Some atoms never change size, others change every emit. This is just
+     * an upper bound on each atom, to keep the emission machinery from
+     * underallocating space. */
     make_empty_list(&r300->atom_list);
-    R300_INIT_ATOM(ztop);
-    R300_INIT_ATOM(blend);
-    R300_INIT_ATOM(blend_color);
-    R300_INIT_ATOM(clip);
-    R300_INIT_ATOM(dsa);
-    R300_INIT_ATOM(rs);
-    R300_INIT_ATOM(scissor);
-    R300_INIT_ATOM(viewport);
+    R300_INIT_ATOM(ztop, 2);
+    R300_INIT_ATOM(blend, 8);
+    R300_INIT_ATOM(blend_color, 3);
+    R300_INIT_ATOM(clip, 29);
+    R300_INIT_ATOM(dsa, 8);
+    R300_INIT_ATOM(rs, 22);
+    R300_INIT_ATOM(scissor, 3);
+    R300_INIT_ATOM(viewport, 9);
 }
 
 struct pipe_context* r300_create_context(struct pipe_screen* screen,
index 7e5de40ded80e63a9fc2366a49785d010b3e21c8..682b9179c83f357b55ffed8ffd6d948577971493 100644 (file)
@@ -36,10 +36,19 @@ struct r300_fragment_shader;
 struct r300_vertex_shader;
 
 struct r300_atom {
+    /* List pointers. */
     struct r300_atom *prev, *next;
+    /* Name, for debugging. */
+    const char* name;
+    /* Opaque state. */
     void* state;
+    /* Emit the state to the context. */
     void (*emit)(struct r300_context*, void*);
+    /* Upper bound on number of dwords to emit. */
+    unsigned size;
+    /* Whether this atom should be emitted. */
     boolean dirty;
+    /* Another dirty flag that is never automatically cleared. */
     boolean always_dirty;
 };
 
index ba04bd07cc810638e747fd9f6ac4274d9cce66a6..9f93327e5981387331bd2d0521ddb8fea2bf6744 100644 (file)
@@ -41,6 +41,7 @@ void r300_emit_blend_state(struct r300_context* r300, void* state)
 {
     struct r300_blend_state* blend = (struct r300_blend_state*)state;
     CS_LOCALS(r300);
+
     BEGIN_CS(8);
     OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
     OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3);
@@ -992,14 +993,23 @@ void r300_emit_dirty_state(struct r300_context* r300)
     struct r300_screen* r300screen = r300_screen(r300->context.screen);
     struct r300_texture* tex;
     struct r300_atom* atom;
-    int i, dirty_tex = 0;
+    unsigned i, dwords = 1024;
+    int dirty_tex = 0;
     boolean invalid = FALSE;
 
-    /* Check size of CS. */
-    /* Make sure we have at least 8*1024 spare dwords. */
+    /* Check the required number of dwords against the space remaining in the
+     * current CS object. If we need more, then flush. */
+
+    foreach(atom, &r300->atom_list) {
+        if (atom->dirty || atom->always_dirty) {
+            dwords += atom->size;
+        }
+    }
+
+    /* Make sure we have at least 2*1024 spare dwords. */
     /* XXX It would be nice to know the number of dwords we really need to
      * XXX emit. */
-    if (!r300->winsys->check_cs(r300->winsys, 8*1024)) {
+    if (!r300->winsys->check_cs(r300->winsys, dwords)) {
         r300->context.flush(&r300->context, 0, NULL);
     }
 
index 00f1b23117508dde764d76879aea7ee8c0a9511d..281ff6844950a77d72e16f661231eacc8bd19d2e 100644 (file)
@@ -340,6 +340,7 @@ static void r300_set_blend_color(struct pipe_context* pipe,
                                  const struct pipe_blend_color* color)
 {
     struct r300_context* r300 = r300_context(pipe);
+    struct r300_screen* r300screen = r300_screen(pipe->screen);
     struct r300_blend_color_state* state =
         (struct r300_blend_color_state*)r300->blend_color_state.state;
     union util_color uc;
@@ -355,6 +356,7 @@ static void r300_set_blend_color(struct pipe_context* pipe,
         float_to_fixed10(color->color[2]) |
         (float_to_fixed10(color->color[1]) << 16);
 
+    r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2;
     r300->blend_color_state.dirty = TRUE;
 }
 
@@ -365,11 +367,14 @@ static void r300_set_clip_state(struct pipe_context* pipe,
 
     if (r300_screen(pipe->screen)->caps->has_tcl) {
         memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
-        r300->clip_state.dirty = TRUE;
+        r300->clip_state.size = 29;
     } else {
         draw_flush(r300->draw);
         draw_set_clip_state(r300->draw, state);
+        r300->clip_state.size = 2;
     }
+
+    r300->clip_state.dirty = TRUE;
 }
 
 /* Create a new depth, stencil, and alpha state based on the CSO dsa state.
@@ -462,8 +467,10 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
                                 void* state)
 {
     struct r300_context* r300 = r300_context(pipe);
+    struct r300_screen* r300screen = r300_screen(pipe->screen);
 
     r300->dsa_state.state = state;
+    r300->dsa_state.size = r300screen->caps->is_r500 ? 8 : 6;
     r300->dsa_state.dirty = TRUE;
 }
 
@@ -839,6 +846,7 @@ static void r300_set_scissor_state(struct pipe_context* pipe,
 
     memcpy(r300->scissor_state.state, state,
         sizeof(struct pipe_scissor_state));
+
     r300->scissor_state.dirty = TRUE;
 }