r600g: simplify dirty atom tracking
authorGrazvydas Ignotas <notasas@gmail.com>
Wed, 2 Sep 2015 22:54:31 +0000 (01:54 +0300)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 3 Sep 2015 16:06:42 +0000 (18:06 +0200)
Now that R600_NUM_ATOMS is below 64, dirty atom tracking can be
simplified.

Signed-off-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/r600/r600_hw_context.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_state_common.c

index 092f261700c4315b6f1b8c872da72ac847cb7081..cf715976ab2406f578fed6ce99f74084f699e876 100644 (file)
@@ -48,16 +48,15 @@ void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw,
        num_dw += ctx->b.rings.gfx.cs->cdw;
 
        if (count_draw_in) {
-               unsigned i;
+               uint64_t mask;
 
                /* The number of dwords all the dirty states would take. */
-               i = r600_next_dirty_atom(ctx, 0);
-               while (i < R600_NUM_ATOMS) {
-                       num_dw += ctx->atoms[i]->num_dw;
+               mask = ctx->dirty_atoms;
+               while (mask != 0) {
+                       num_dw += ctx->atoms[u_bit_scan64(&mask)]->num_dw;
                        if (ctx->screen->b.trace_bo) {
                                num_dw += R600_TRACE_CS_DWORDS;
                        }
-                       i = r600_next_dirty_atom(ctx, i + 1);
                }
 
                /* The upper-bound of how much space a draw command would take. */
index 9860eff35a503a3cc22ee4ea1731766d8402f671..76539d66ec6e13a7031b1f3c2a654f0e08e03c41 100644 (file)
@@ -87,9 +87,6 @@
 #define R600_BIG_ENDIAN 0
 #endif
 
-#define R600_DIRTY_ATOM_WORD_BITS (sizeof(unsigned long) * 8)
-#define R600_DIRTY_ATOM_ARRAY_LEN DIV_ROUND_UP(R600_NUM_ATOMS, R600_DIRTY_ATOM_WORD_BITS)
-
 struct r600_context;
 struct r600_bytecode;
 union  r600_shader_key;
@@ -438,7 +435,7 @@ struct r600_context {
        /* State binding slots are here. */
        struct r600_atom                *atoms[R600_NUM_ATOMS];
        /* Dirty atom bitmask for fast tests */
-       unsigned long                   dirty_atoms[R600_DIRTY_ATOM_ARRAY_LEN];
+       uint64_t                        dirty_atoms;
        /* States for CS initialization. */
        struct r600_command_buffer      start_cs_cmd; /* invariant state mostly */
        /** Compute specific registers initializations.  The start_cs_cmd atom
@@ -515,18 +512,17 @@ static inline void r600_set_atom_dirty(struct r600_context *rctx,
                                       struct r600_atom *atom,
                                       bool dirty)
 {
-       unsigned long mask;
-       unsigned int w;
+       uint64_t mask;
 
        atom->dirty = dirty;
 
        assert(atom->id != 0);
-       w = atom->id / R600_DIRTY_ATOM_WORD_BITS;
-       mask = 1ul << (atom->id % R600_DIRTY_ATOM_WORD_BITS);
+       assert(atom->id < sizeof(mask) * 8);
+       mask = 1ull << atom->id;
        if (dirty)
-               rctx->dirty_atoms[w] |= mask;
+               rctx->dirty_atoms |= mask;
        else
-               rctx->dirty_atoms[w] &= ~mask;
+               rctx->dirty_atoms &= ~mask;
 }
 
 static inline void r600_mark_atom_dirty(struct r600_context *rctx,
@@ -535,35 +531,6 @@ static inline void r600_mark_atom_dirty(struct r600_context *rctx,
        r600_set_atom_dirty(rctx, atom, true);
 }
 
-static inline unsigned int r600_next_dirty_atom(struct r600_context *rctx,
-                                               unsigned int id)
-{
-#if !defined(DEBUG) && defined(HAVE___BUILTIN_CTZ)
-       unsigned int w = id / R600_DIRTY_ATOM_WORD_BITS;
-       unsigned int bit = id % R600_DIRTY_ATOM_WORD_BITS;
-       unsigned long bits, mask = (1ul << bit) - 1;
-
-       for (; w < R600_DIRTY_ATOM_ARRAY_LEN; w++, mask = 0ul) {
-               bits = rctx->dirty_atoms[w] & ~mask;
-               if (bits == 0)
-                       continue;
-               return w * R600_DIRTY_ATOM_WORD_BITS + __builtin_ctzl(bits);
-       }
-
-       return R600_NUM_ATOMS;
-#else
-       for (; id < R600_NUM_ATOMS; id++) {
-               bool dirty = !!(rctx->dirty_atoms[id / R600_DIRTY_ATOM_WORD_BITS] &
-                       (1ul << (id % R600_DIRTY_ATOM_WORD_BITS)));
-               assert(dirty == (rctx->atoms[id] && rctx->atoms[id]->dirty));
-               if (dirty)
-                       break;
-       }
-
-       return id;
-#endif
-}
-
 void r600_trace_emit(struct r600_context *rctx);
 
 static inline void r600_emit_atom(struct r600_context *rctx, struct r600_atom *atom)
index 1f96ed6e12c04c6f673162d90da199357a73d53b..39c65ae45c385ac0021f816eede51e7c38a7a74b 100644 (file)
@@ -1427,8 +1427,8 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct pipe_draw_info info = *dinfo;
        struct pipe_index_buffer ib = {};
-       unsigned i;
        struct radeon_winsys_cs *cs = rctx->b.rings.gfx.cs;
+       uint64_t mask;
 
        if (!info.indirect && !info.count && (info.indexed || !info.count_from_stream_output)) {
                return;
@@ -1538,10 +1538,9 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
        r600_need_cs_space(rctx, ib.user_buffer ? 5 : 0, TRUE);
        r600_flush_emit(rctx);
 
-       i = r600_next_dirty_atom(rctx, 0);
-       while (i < R600_NUM_ATOMS) {
-               r600_emit_atom(rctx, rctx->atoms[i]);
-               i = r600_next_dirty_atom(rctx, i + 1);
+       mask = rctx->dirty_atoms;
+       while (mask != 0) {
+               r600_emit_atom(rctx, rctx->atoms[u_bit_scan64(&mask)]);
        }
 
        if (rctx->b.chip_class == CAYMAN) {