radeonsi: use a bitmask for tracking dirty atoms
authorMarek Olšák <marek.olsak@amd.com>
Fri, 28 Aug 2015 22:49:40 +0000 (00:49 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 1 Sep 2015 19:51:14 +0000 (21:51 +0200)
This mainly removes the cache misses when checking the dirty flags.
Not much else though.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
src/gallium/drivers/radeonsi/si_hw_context.c
src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_state_draw.c

index f821ad33ff3da3b3efb81d7e7b7b63d0d813e080..2381b6c0004b465fb2f1073d93c45654af0a4a47 100644 (file)
@@ -31,7 +31,6 @@ void si_need_cs_space(struct si_context *ctx, unsigned num_dw,
                        boolean count_draw_in)
 {
        struct radeon_winsys_cs *cs = ctx->b.rings.gfx.cs;
-       int i;
 
        /* There are two memory usage counters in the winsys for all buffers
         * that have been added (cs_add_reloc) and two counters in the pipe
@@ -59,11 +58,10 @@ void si_need_cs_space(struct si_context *ctx, unsigned num_dw,
        num_dw += cs->cdw;
 
        if (count_draw_in) {
-               for (i = 0; i < SI_NUM_ATOMS; i++) {
-                       if (ctx->atoms.array[i]->dirty) {
-                               num_dw += ctx->atoms.array[i]->num_dw;
-                       }
-               }
+               unsigned mask = ctx->dirty_atoms;
+
+               while (mask)
+                       num_dw += ctx->atoms.array[u_bit_scan(&mask)]->num_dw;
 
                /* The number of dwords all the dirty states would take. */
                num_dw += si_pm4_dirty_dw(ctx);
index 5ca83e7a2d207cafa53e1702e259d28de4abdedf..35104cf78483816cea96729a76ba37877ad01696 100644 (file)
@@ -155,6 +155,7 @@ struct si_context {
        struct si_shader_selector       *fixed_func_tcs_shader;
 
        union si_state_atoms            atoms;
+       unsigned                        dirty_atoms; /* mask */
 
        struct si_framebuffer           framebuffer;
        struct si_vertex_element        *vertex_elements;
@@ -339,7 +340,12 @@ static inline void
 si_set_atom_dirty(struct si_context *sctx,
                  struct r600_atom *atom, bool dirty)
 {
-       atom->dirty = dirty;
+       unsigned bit = 1 << (atom->id - 1);
+
+       if (dirty)
+               sctx->dirty_atoms |= bit;
+       else
+               sctx->dirty_atoms &= ~bit;
 }
 
 static inline void
index 2ff58d1f33262532e4845c8896d787630c54de5f..81575b53dd84fdf40f038833fdfde2f8aa7a8b64 100644 (file)
@@ -729,7 +729,7 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
        struct si_context *sctx = (struct si_context *)ctx;
        struct pipe_index_buffer ib = {};
-       unsigned i;
+       unsigned mask;
 
        if (!info->count && !info->indirect &&
            (info->indexed || !info->count_from_stream_output))
@@ -821,12 +821,13 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
        si_need_cs_space(sctx, 0, TRUE);
 
        /* Emit states. */
-       for (i = 0; i < SI_NUM_ATOMS; i++) {
-               if (sctx->atoms.array[i]->dirty) {
-                       sctx->atoms.array[i]->emit(&sctx->b, sctx->atoms.array[i]);
-                       sctx->atoms.array[i]->dirty = false;
-               }
+       mask = sctx->dirty_atoms;
+       while (mask) {
+               struct r600_atom *atom = sctx->atoms.array[u_bit_scan(&mask)];
+
+               atom->emit(&sctx->b, atom);
        }
+       sctx->dirty_atoms = 0;
 
        si_pm4_emit_dirty(sctx);
        si_emit_scratch_reloc(sctx);