diff options
| author | Keith Whitwell <keithw@vmware.com> | 2010-08-27 19:24:51 +0100 | 
|---|---|---|
| committer | Keith Whitwell <keithw@vmware.com> | 2010-09-07 14:02:29 +0100 | 
| commit | f25836d7b2c21e046a725cf13c8649d3981693b7 (patch) | |
| tree | fd0e6a664b460685b6afceac386dfe3a6d131ed9 | |
| parent | 9f6e8e1d6b8696a3ee96cba01b2466ba7a1a8ef6 (diff) | |
llvmpipe: rasterization debugging helpers
| -rw-r--r-- | src/gallium/drivers/llvmpipe/SConscript | 1 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.c | 3 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.h | 7 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast_debug.c | 409 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast_priv.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_scene.c | 3 | ||||
| -rw-r--r-- | 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 8d57db72cf..650435f0f1 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 6a610aaf29..36068d74be 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 5f3059e794..3c8dae6b01 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 0000000000..f2ef21f2a9 --- /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 b1b4546bb8..3bcdfd6074 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 2a26896e62..54880f2f10 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 f653dd5f0b..28157bd6e9 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 | 
