Mesa (master): llvmpipe: rasterization debugging helpers

Keith Whitwell keithw at kemper.freedesktop.org
Tue Sep 7 06:03:40 PDT 2010


Module: Mesa
Branch: master
Commit: f25836d7b2c21e046a725cf13c8649d3981693b7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f25836d7b2c21e046a725cf13c8649d3981693b7

Author: Keith Whitwell <keithw at vmware.com>
Date:   Fri Aug 27 19:24:51 2010 +0100

llvmpipe: rasterization debugging helpers

---

 src/gallium/drivers/llvmpipe/SConscript      |    1 +
 src/gallium/drivers/llvmpipe/lp_rast.c       |    3 +
 src/gallium/drivers/llvmpipe/lp_rast.h       |    7 +
 src/gallium/drivers/llvmpipe/lp_rast_debug.c |  409 ++++++++++++++++++++++++++
 src/gallium/drivers/llvmpipe/lp_rast_priv.h  |    2 +
 src/gallium/drivers/llvmpipe/lp_scene.c      |    3 +
 src/gallium/drivers/llvmpipe/lp_setup.c      |    3 +
 7 files changed, 428 insertions(+), 0 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript
index 8d57db7..650435f 100644
--- a/src/gallium/drivers/llvmpipe/SConscript
+++ b/src/gallium/drivers/llvmpipe/SConscript
@@ -55,6 +55,7 @@ llvmpipe = env.ConvenienceLibrary(
 		'lp_perf.c',
 		'lp_query.c',
 		'lp_rast.c',
+		'lp_rast_debug.c',
 		'lp_rast_tri.c',
 		'lp_scene.c',
 		'lp_scene_queue.c',
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 6a610aa..36068d7 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -594,6 +594,9 @@ do_rasterize_bin(struct lp_rasterizer_task *task,
    const struct cmd_block *block;
    unsigned k;
 
+   if (0)
+      lp_debug_bin(bin);
+
    for (block = bin->head; block; block = block->next) {
       for (k = 0; k < block->count; k++) {
          dispatch[block->cmd[k]]( task, block->arg[k] );
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 5f3059e..3c8dae6 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -245,4 +245,11 @@ lp_rast_arg_null( void )
 #define LP_RAST_OP_MAX               0xf
 #define LP_RAST_OP_MASK              0xff
 
+void
+lp_debug_bins( struct lp_scene *scene );
+void
+lp_debug_draw_bins_by_cmd_length( struct lp_scene *scene );
+void
+lp_debug_draw_bins_by_coverage( struct lp_scene *scene );
+
 #endif
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_debug.c b/src/gallium/drivers/llvmpipe/lp_rast_debug.c
new file mode 100644
index 0000000..f2ef21f
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_rast_debug.c
@@ -0,0 +1,409 @@
+#include "util/u_math.h"
+#include "lp_rast_priv.h"
+#include "lp_state_fs.h"
+
+static INLINE int u_bit_scan(unsigned *mask)
+{
+   int i = ffs(*mask) - 1;
+   *mask &= ~(1 << i);
+   return i;
+}
+
+struct tile {
+   int coverage;
+   int overdraw;
+   char data[TILE_SIZE][TILE_SIZE];
+};
+
+static char get_label( int i )
+{
+   static const char *cmd_labels = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+   unsigned max_label = (2*26+10);
+
+   if (i < max_label)
+      return cmd_labels[i];
+   else
+      return '?';
+}
+
+
+
+static const char *cmd_names[LP_RAST_OP_MAX] = 
+{
+   "clear_color",
+   "clear_zstencil",
+   "triangle_1",
+   "triangle_2",
+   "triangle_3",
+   "triangle_4",
+   "triangle_5",
+   "triangle_6",
+   "triangle_7",
+   "triangle_8",
+   "triangle_3_16",
+   "shade_tile",
+   "shade_tile_opaque",
+   "begin_query",
+   "end_query",
+};
+
+static const char *cmd_name(unsigned cmd)
+{
+   assert(Elements(cmd_names) > cmd);
+   return cmd_names[cmd];
+}
+
+static const struct lp_fragment_shader_variant *
+get_variant(  const struct cmd_block *block,
+              int k )
+{
+   if (block->cmd[k] == LP_RAST_OP_SHADE_TILE ||
+       block->cmd[k] == LP_RAST_OP_SHADE_TILE_OPAQUE)
+      return  block->arg[k].shade_tile->state->variant;
+
+   if (block->cmd[k] == LP_RAST_OP_TRIANGLE_1 ||
+       block->cmd[k] == LP_RAST_OP_TRIANGLE_2 ||
+       block->cmd[k] == LP_RAST_OP_TRIANGLE_3 ||
+       block->cmd[k] == LP_RAST_OP_TRIANGLE_4 ||
+       block->cmd[k] == LP_RAST_OP_TRIANGLE_5 ||
+       block->cmd[k] == LP_RAST_OP_TRIANGLE_6 ||
+       block->cmd[k] == LP_RAST_OP_TRIANGLE_7)
+      return block->arg[k].triangle.tri->inputs.state->variant;
+
+   return NULL;
+}
+
+
+static boolean
+is_blend( const struct cmd_block *block,
+          int k )
+{
+   const struct lp_fragment_shader_variant *variant = get_variant(block, k);
+
+   if (variant)
+      return  variant->key.blend.rt[0].blend_enable;
+
+   return FALSE;
+}
+
+
+
+static void
+debug_bin( const struct cmd_bin *bin )
+{
+   const struct cmd_block *head = bin->head;
+   int i, j = 0;
+
+   debug_printf("bin %d,%d:\n", bin->x, bin->y);
+                
+   while (head) {
+      for (i = 0; i < head->count; i++, j++) {
+         debug_printf("%d: %s %s\n", j,
+                      cmd_name(head->cmd[i]),
+                      is_blend(head, i) ? "blended" : "");
+      }
+      head = head->next;
+   }
+}
+
+
+static void plot(struct tile *tile,
+                 int x, int y,
+                 char val,
+                 boolean blend)
+{
+   if (tile->data[x][y] == ' ')
+      tile->coverage++;
+   else
+      tile->overdraw++;
+
+   tile->data[x][y] = val;
+}
+
+
+
+
+
+
+static int
+debug_shade_tile(int x, int y,
+                 const union lp_rast_cmd_arg arg,
+                 struct tile *tile,
+                 char val)
+{
+   const struct lp_rast_shader_inputs *inputs = arg.shade_tile;
+   boolean blend = inputs->state->variant->key.blend.rt[0].blend_enable;
+   unsigned i,j;
+
+   if (inputs->disable)
+      return 0;
+
+   for (i = 0; i < TILE_SIZE; i++)
+      for (j = 0; j < TILE_SIZE; j++)
+         plot(tile, i, j, val, blend);
+
+   return TILE_SIZE * TILE_SIZE;
+}
+
+static int
+debug_clear_tile(int x, int y,
+                 const union lp_rast_cmd_arg arg,
+                 struct tile *tile,
+                 char val)
+{
+   unsigned i,j;
+
+   for (i = 0; i < TILE_SIZE; i++)
+      for (j = 0; j < TILE_SIZE; j++)
+         plot(tile, i, j, val, FALSE);
+
+   return TILE_SIZE * TILE_SIZE;
+
+}
+
+
+static int
+debug_triangle(int tilex, int tiley,
+               const union lp_rast_cmd_arg arg,
+               struct tile *tile,
+               char val)
+{
+   const struct lp_rast_triangle *tri = arg.triangle.tri;
+   unsigned plane_mask = arg.triangle.plane_mask;
+   struct lp_rast_plane plane[8];
+   int x, y;
+   int count = 0;
+   unsigned i, nr_planes = 0;
+   boolean blend = tri->inputs.state->variant->key.blend.rt[0].blend_enable;
+
+   if (tri->inputs.disable) {
+      /* This triangle was partially binned and has been disabled */
+      return 0;
+   }
+
+   while (plane_mask) {
+      plane[nr_planes] = tri->plane[u_bit_scan(&plane_mask)];
+      plane[nr_planes].c = (plane[nr_planes].c +
+                            plane[nr_planes].dcdy * tiley -
+                            plane[nr_planes].dcdx * tilex);
+      nr_planes++;
+   }
+
+   for(y = 0; y < TILE_SIZE; y++)
+   {
+      for(x = 0; x < TILE_SIZE; x++)
+      {
+         for (i = 0; i < nr_planes; i++)
+            if (plane[i].c <= 0)
+               goto out;
+         
+         plot(tile, x, y, val, blend);
+         count++;
+
+      out:
+         for (i = 0; i < nr_planes; i++)
+            plane[i].c -= plane[i].dcdx;
+      }
+
+      for (i = 0; i < nr_planes; i++) {
+         plane[i].c += plane[i].dcdx * TILE_SIZE;
+         plane[i].c += plane[i].dcdy;
+      }
+   }
+   return count;
+}
+
+
+
+
+
+static void
+do_debug_bin( struct tile *tile,
+              const struct cmd_bin *bin,
+              boolean print_cmds)
+{
+   unsigned k, j = 0;
+   const struct cmd_block *block;
+
+   int tx = bin->x * TILE_SIZE;
+   int ty = bin->y * TILE_SIZE;
+
+   memset(tile->data, ' ', sizeof tile->data);
+   tile->coverage = 0;
+   tile->overdraw = 0;
+
+   for (block = bin->head; block; block = block->next) {
+      for (k = 0; k < block->count; k++, j++) {
+         boolean blend = is_blend(block, k);
+         char val = get_label(j);
+         int count = 0;
+            
+         if (print_cmds)
+            debug_printf("%c: %15s", val, cmd_name(block->cmd[k]));
+         
+         if (block->cmd[k] == LP_RAST_OP_CLEAR_COLOR ||
+             block->cmd[k] == LP_RAST_OP_CLEAR_ZSTENCIL)
+            count = debug_clear_tile(tx, ty, block->arg[k], tile, val);
+
+         if (block->cmd[k] == LP_RAST_OP_SHADE_TILE ||
+             block->cmd[k] == LP_RAST_OP_SHADE_TILE_OPAQUE)
+            count = debug_shade_tile(tx, ty, block->arg[k], tile, val);
+
+         if (block->cmd[k] == LP_RAST_OP_TRIANGLE_1 ||
+             block->cmd[k] == LP_RAST_OP_TRIANGLE_2 ||
+             block->cmd[k] == LP_RAST_OP_TRIANGLE_3 ||
+             block->cmd[k] == LP_RAST_OP_TRIANGLE_4 ||
+             block->cmd[k] == LP_RAST_OP_TRIANGLE_5 ||
+             block->cmd[k] == LP_RAST_OP_TRIANGLE_6 ||
+             block->cmd[k] == LP_RAST_OP_TRIANGLE_7)
+            count = debug_triangle(tx, ty, block->arg[k], tile, val);
+
+         if (print_cmds) {
+            debug_printf(" % 5d", count);
+
+            if (blend)
+               debug_printf(" blended");
+            
+            debug_printf("\n");
+         }
+      }
+   }
+}
+
+void
+lp_debug_bin( const struct cmd_bin *bin)
+{
+   struct tile tile;
+   int x,y;
+
+   if (bin->head) {
+      do_debug_bin(&tile, bin, TRUE);
+
+      debug_printf("------------------------------------------------------------------\n");
+      for (y = 0; y < TILE_SIZE; y++) {
+         for (x = 0; x < TILE_SIZE; x++) {
+            debug_printf("%c", tile.data[y][x]);
+         }
+         debug_printf("|\n");
+      }
+      debug_printf("------------------------------------------------------------------\n");
+
+      debug_printf("each pixel drawn avg %f times\n",
+                   ((float)tile.overdraw + tile.coverage)/(float)tile.coverage);
+   }
+}
+
+
+
+
+
+
+/** Return number of bytes used for a single bin */
+static unsigned
+lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y )
+{
+   struct cmd_bin *bin = lp_scene_get_bin((struct lp_scene *) scene, x, y);
+   const struct cmd_block *cmd;
+   unsigned size = 0;
+   for (cmd = bin->head; cmd; cmd = cmd->next) {
+      size += (cmd->count *
+               (sizeof(uint8_t) + sizeof(union lp_rast_cmd_arg)));
+   }
+   return size;
+}
+
+
+
+void
+lp_debug_draw_bins_by_coverage( struct lp_scene *scene )
+{
+   unsigned x, y;
+   unsigned total = 0;
+   unsigned possible = 0;
+   static unsigned long long _total;
+   static unsigned long long _possible;
+
+   for (x = 0; x < scene->tiles_x; x++)
+      debug_printf("-");
+   debug_printf("\n");
+
+   for (y = 0; y < scene->tiles_y; y++) {
+      for (x = 0; x < scene->tiles_x; x++) {
+         struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
+         const char *bits = "0123456789";
+         struct tile tile;
+
+         if (bin->head) {
+            //lp_debug_bin(bin);
+
+            do_debug_bin(&tile, bin, FALSE);
+
+            total += tile.coverage;
+            possible += 64*64;
+
+            if (tile.coverage == 64*64)
+               debug_printf("*");
+            else if (tile.coverage) {
+               int bit = tile.coverage/(64.0*64.0)*10;
+               debug_printf("%c", bits[MIN2(bit,10)]);
+            }
+            else
+               debug_printf("?");
+         }
+         else {
+            debug_printf(" ");
+         }
+      }
+      debug_printf("|\n");
+   }
+
+   for (x = 0; x < scene->tiles_x; x++)
+      debug_printf("-");
+   debug_printf("\n");
+
+   debug_printf("this tile total: %u possible %u: percentage: %f\n",
+                total,
+                possible,
+                total * 100.0 / (float)possible);
+
+   _total += total;
+   _possible += possible;
+
+   debug_printf("overall   total: %llu possible %llu: percentage: %f\n",
+                _total,
+                _possible,
+                _total * 100.0 / (double)_possible);
+}
+
+
+void
+lp_debug_draw_bins_by_cmd_length( struct lp_scene *scene )
+{
+   unsigned x, y;
+
+   for (y = 0; y < scene->tiles_y; y++) {
+      for (x = 0; x < scene->tiles_x; x++) {
+         const char *bits = " ...,-~:;=o+xaw*#XAWWWWWWWWWWWWWWWW";
+         int sz = lp_scene_bin_size(scene, x, y);
+         int sz2 = util_unsigned_logbase2(sz);
+         debug_printf("%c", bits[MIN2(sz2,32)]);
+      }
+      debug_printf("\n");
+   }
+}
+
+
+void
+lp_debug_bins( struct lp_scene *scene )
+{
+   unsigned x, y;
+
+   for (y = 0; y < scene->tiles_y; y++) {
+      for (x = 0; x < scene->tiles_x; x++) {
+         struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
+         if (bin->head) {
+            debug_bin(bin);
+         }
+      }
+   }
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index b1b4546..3bcdfd6 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -291,5 +291,7 @@ void lp_rast_triangle_8( struct lp_rasterizer_task *,
 void lp_rast_triangle_3_16( struct lp_rasterizer_task *, 
                             const union lp_rast_cmd_arg );
 
+void
+lp_debug_bin( const struct cmd_bin *bin );
 
 #endif
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index 2a26896..54880f2 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -489,5 +489,8 @@ void lp_scene_end_binning( struct lp_scene *scene )
                    scene->scene_size);
       debug_printf("  data size: %u\n",
                    lp_scene_data_size(scene));
+
+      if (0)
+         lp_debug_bins( scene );
    }
 }
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index f653dd5..28157bd 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -279,6 +279,9 @@ set_scene_state( struct lp_setup_context *setup,
                    states[new_state],
                    (new_state == SETUP_FLUSHED) ? ": " : "",
                    (new_state == SETUP_FLUSHED) ? reason : "");
+
+      if (new_state == SETUP_FLUSHED && setup->scene)
+         lp_debug_draw_bins_by_coverage(setup->scene);
    }
 
    /* wait for a free/empty scene



More information about the mesa-commit mailing list