From f25836d7b2c21e046a725cf13c8649d3981693b7 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 27 Aug 2010 19:24:51 +0100 Subject: 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(+) create mode 100644 src/gallium/drivers/llvmpipe/lp_rast_debug.c 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 -- cgit v1.2.3