From 0f55a95b2faa16cc008143c53a8b82b19c5d750a Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 17 Jul 2009 10:44:22 +0100 Subject: llvmpipe: make some small steps to flush texture cache less frequently No performance gain yet, but the code is a bit cleaner. --- src/gallium/drivers/llvmpipe/lp_context.h | 3 +- src/gallium/drivers/llvmpipe/lp_state_derived.c | 14 +++++ src/gallium/drivers/llvmpipe/lp_texture.c | 3 +- src/gallium/drivers/llvmpipe/lp_texture.h | 2 +- src/gallium/drivers/llvmpipe/lp_tile_cache.c | 80 +++++++++++++++---------- src/gallium/drivers/llvmpipe/lp_tile_cache.h | 3 + 6 files changed, 70 insertions(+), 35 deletions(-) (limited to 'src/gallium/drivers') diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 9bfae0aa7f8..ab88401c605 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -149,7 +149,8 @@ struct llvmpipe_context { struct llvmpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS]; struct llvmpipe_tile_cache *zsbuf_cache; - + + unsigned tex_timestamp; struct llvmpipe_tile_cache *tex_cache[PIPE_MAX_SAMPLERS]; unsigned use_sse : 1; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 16ae435d3aa..59b06f53361 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -32,6 +32,7 @@ #include "draw/draw_vertex.h" #include "draw/draw_private.h" #include "lp_context.h" +#include "lp_screen.h" #include "lp_state.h" @@ -200,6 +201,10 @@ update_tgsi_samplers( struct llvmpipe_context *llvmpipe ) llvmpipe->tgsi.frag_samplers[i].sampler = llvmpipe->sampler[i]; llvmpipe->tgsi.frag_samplers[i].texture = llvmpipe->texture[i]; } + + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + lp_tile_cache_validate_texture( llvmpipe->tex_cache[i] ); + } } /* Hopefully this will remain quite simple, otherwise need to pull in @@ -207,6 +212,15 @@ update_tgsi_samplers( struct llvmpipe_context *llvmpipe ) */ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) { + struct llvmpipe_screen *lp_screen = llvmpipe_screen(llvmpipe->pipe.screen); + + /* Check for updated textures. + */ + if (llvmpipe->tex_timestamp != lp_screen->timestamp) { + llvmpipe->tex_timestamp = lp_screen->timestamp; + llvmpipe->dirty |= LP_NEW_TEXTURE; + } + if (llvmpipe->dirty & (LP_NEW_SAMPLER | LP_NEW_TEXTURE)) update_tgsi_samplers( llvmpipe ); diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index fd9b5182ea6..542e3134457 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -227,7 +227,8 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE)) { /* Mark the surface as dirty. The tile cache will look for this. */ - lpt->modified = TRUE; + lpt->timestamp++; + llvmpipe_screen(screen)->timestamp++; } ps->face = face; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index dc688b238dd..a1ed6b0ac28 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -48,7 +48,7 @@ struct llvmpipe_texture */ struct pipe_buffer *buffer; - boolean modified; + unsigned timestamp; }; struct llvmpipe_transfer diff --git a/src/gallium/drivers/llvmpipe/lp_tile_cache.c b/src/gallium/drivers/llvmpipe/lp_tile_cache.c index 08c48e4d1c1..2bda88c9341 100644 --- a/src/gallium/drivers/llvmpipe/lp_tile_cache.c +++ b/src/gallium/drivers/llvmpipe/lp_tile_cache.c @@ -54,7 +54,10 @@ struct llvmpipe_tile_cache struct pipe_surface *surface; /**< the surface we're caching */ struct pipe_transfer *transfer; void *transfer_map; + struct pipe_texture *texture; /**< if caching a texture */ + unsigned timestamp; + struct llvmpipe_cached_tile entries[NUM_ENTRIES]; uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32]; float clear_color[4]; /**< for color bufs */ @@ -231,6 +234,23 @@ lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc) } } +void +lp_tile_cache_validate_texture(struct llvmpipe_tile_cache *tc) +{ + if (tc->texture) { + struct llvmpipe_texture *lpt = llvmpipe_texture(tc->texture); + if (lpt->timestamp != tc->timestamp) { + /* texture was modified, invalidate all cached tiles */ + uint i; + _debug_printf("INV %d %d\n", tc->timestamp, lpt->timestamp); + for (i = 0; i < NUM_ENTRIES; i++) { + tc->entries[i].x = -3; + } + + tc->timestamp = lpt->timestamp; + } + } +} /** * Specify the texture to cache. @@ -243,27 +263,29 @@ lp_tile_cache_set_texture(struct llvmpipe_tile_cache *tc, assert(!tc->transfer); - pipe_texture_reference(&tc->texture, texture); + if (tc->texture != texture) { + pipe_texture_reference(&tc->texture, texture); - if (tc->tex_trans) { - struct pipe_screen *screen = tc->tex_trans->texture->screen; + if (tc->tex_trans) { + struct pipe_screen *screen = tc->tex_trans->texture->screen; + + if (tc->tex_trans_map) { + screen->transfer_unmap(screen, tc->tex_trans); + tc->tex_trans_map = NULL; + } - if (tc->tex_trans_map) { - screen->transfer_unmap(screen, tc->tex_trans); - tc->tex_trans_map = NULL; + screen->tex_transfer_destroy(tc->tex_trans); + tc->tex_trans = NULL; } - screen->tex_transfer_destroy(tc->tex_trans); - tc->tex_trans = NULL; - } + /* mark as entries as invalid/empty */ + /* XXX we should try to avoid this when the teximage hasn't changed */ + for (i = 0; i < NUM_ENTRIES; i++) { + tc->entries[i].x = -1; + } - /* mark as entries as invalid/empty */ - /* XXX we should try to avoid this when the teximage hasn't changed */ - for (i = 0; i < NUM_ENTRIES; i++) { - tc->entries[i].x = -1; + tc->tex_face = -1; /* any invalid value here */ } - - tc->tex_face = -1; /* any invalid value here */ } @@ -443,7 +465,7 @@ lp_get_cached_tile(struct llvmpipe_tile_cache *tc, int x, int y) if (tile_x != tile->x || tile_y != tile->y) { - if (tile->x != -1) { + if (tile->x >= 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { pipe_put_tile_raw(pt, @@ -522,30 +544,24 @@ lp_get_cached_tile_tex(struct llvmpipe_tile_cache *tc, face, level); struct llvmpipe_cached_tile *tile = tc->entries + pos; - if (tc->texture) { - struct llvmpipe_texture *lpt = llvmpipe_texture(tc->texture); - if (lpt->modified) { - /* texture was modified, invalidate all cached tiles */ - uint p; - for (p = 0; p < NUM_ENTRIES; p++) { - tile = tc->entries + p; - tile->x = -1; - } - lpt->modified = FALSE; - } - } - if (tile_x != tile->x || tile_y != tile->y || z != tile->z || face != tile->face || level != tile->level) { - /* cache miss */ + /* cache miss. Most misses are because we've invaldiated the + * texture cache previously -- most commonly on binding a new + * texture. Currently we effectively flush the cache on texture + * bind. + */ #if 0 - printf("miss at %u x=%d y=%d z=%d face=%d level=%d\n", pos, - x/TILE_SIZE, y/TILE_SIZE, z, face, level); + _debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n" + " tile %u: x=%d y=%d z=%d face=%d level=%d\n", + pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level, + pos, tile->x, tile->y, tile->z, tile->face, tile->level); #endif + /* check if we need to get a new transfer */ if (!tc->tex_trans || tc->tex_face != face || diff --git a/src/gallium/drivers/llvmpipe/lp_tile_cache.h b/src/gallium/drivers/llvmpipe/lp_tile_cache.h index e82b4b856a3..9e830e9def2 100644 --- a/src/gallium/drivers/llvmpipe/lp_tile_cache.h +++ b/src/gallium/drivers/llvmpipe/lp_tile_cache.h @@ -83,6 +83,9 @@ extern void lp_tile_cache_set_texture(struct llvmpipe_tile_cache *tc, struct pipe_texture *texture); +void +lp_tile_cache_validate_texture(struct llvmpipe_tile_cache *tc); + extern void lp_flush_tile_cache(struct llvmpipe_tile_cache *tc); -- cgit v1.2.3