0,0 → 1,427 |
#include <inttypes.h> /* for PRIu64 macro */ |
#include "util/u_math.h" |
#include "lp_rast_priv.h" |
#include "lp_state_fs.h" |
|
struct tile { |
int coverage; |
int overdraw; |
const struct lp_rast_state *state; |
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_4", |
"triangle_3_16", |
"triangle_4_16", |
"shade_tile", |
"shade_tile_opaque", |
"begin_query", |
"end_query", |
"set_state", |
}; |
|
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 lp_rast_state *state, |
const struct cmd_block *block, |
int k ) |
{ |
if (!state) |
return NULL; |
|
if (block->cmd[k] == LP_RAST_OP_SHADE_TILE || |
block->cmd[k] == LP_RAST_OP_SHADE_TILE_OPAQUE || |
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 state->variant; |
|
return NULL; |
} |
|
|
static boolean |
is_blend( const struct lp_rast_state *state, |
const struct cmd_block *block, |
int k ) |
{ |
const struct lp_fragment_shader_variant *variant = get_variant(state, block, k); |
|
if (variant) |
return variant->key.blend.rt[0].blend_enable; |
|
return FALSE; |
} |
|
|
|
static void |
debug_bin( const struct cmd_bin *bin, int x, int y ) |
{ |
const struct lp_rast_state *state = NULL; |
const struct cmd_block *head = bin->head; |
int i, j = 0; |
|
debug_printf("bin %d,%d:\n", x, y); |
|
while (head) { |
for (i = 0; i < head->count; i++, j++) { |
if (head->cmd[i] == LP_RAST_OP_SET_STATE) |
state = head->arg[i].state; |
|
debug_printf("%d: %s %s\n", j, |
cmd_name(head->cmd[i]), |
is_blend(state, 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; |
unsigned i,j; |
|
if (!tile->state) |
return 0; |
|
blend = tile->state->variant->key.blend.rt[0].blend_enable; |
|
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; |
const struct lp_rast_plane *tri_plane = GET_PLANES(tri); |
struct lp_rast_plane plane[8]; |
int x, y; |
int count = 0; |
unsigned i, nr_planes = 0; |
boolean blend = tile->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, |
int x, int y, |
boolean print_cmds) |
{ |
unsigned k, j = 0; |
const struct cmd_block *block; |
|
int tx = x * TILE_SIZE; |
int ty = y * TILE_SIZE; |
|
memset(tile->data, ' ', sizeof tile->data); |
tile->coverage = 0; |
tile->overdraw = 0; |
tile->state = NULL; |
|
for (block = bin->head; block; block = block->next) { |
for (k = 0; k < block->count; k++, j++) { |
boolean blend = is_blend(tile->state, 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_SET_STATE) |
tile->state = block->arg[k].state; |
|
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, int i, int j) |
{ |
struct tile tile; |
int x,y; |
|
if (bin->head) { |
do_debug_bin(&tile, bin, i, j, 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 uint64_t _total = 0; |
static uint64_t _possible = 0; |
|
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, x, y); |
|
do_debug_bin(&tile, bin, x, y, 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: %" PRIu64 |
" possible %" PRIu64 ": percentage: %f\n", |
_total, |
_possible, |
(double) _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"; |
unsigned sz = lp_scene_bin_size(scene, x, y); |
unsigned sz2 = util_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, x, y); |
} |
} |
} |
} |