From b5d583efeff5f195bff48c95125a225c273189e2 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 17 Jul 2009 10:44:22 +0100 Subject: softpipe: make some small steps to flush texture cache less frequently No performance gain yet, but the code is a bit cleaner. --- src/gallium/drivers/softpipe/sp_context.h | 3 +- src/gallium/drivers/softpipe/sp_state_derived.c | 14 +++++ src/gallium/drivers/softpipe/sp_texture.c | 3 +- src/gallium/drivers/softpipe/sp_texture.h | 2 +- src/gallium/drivers/softpipe/sp_tile_cache.c | 80 +++++++++++++++---------- src/gallium/drivers/softpipe/sp_tile_cache.h | 3 + 6 files changed, 70 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 7888c2f644..f66f0b7849 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -149,7 +149,8 @@ struct softpipe_context { struct softpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS]; struct softpipe_tile_cache *zsbuf_cache; - + + unsigned tex_timestamp; struct softpipe_tile_cache *tex_cache[PIPE_MAX_SAMPLERS]; unsigned use_sse : 1; diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index 75be99768c..629a1f8e29 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -32,6 +32,7 @@ #include "draw/draw_vertex.h" #include "draw/draw_private.h" #include "sp_context.h" +#include "sp_screen.h" #include "sp_state.h" @@ -200,6 +201,10 @@ update_tgsi_samplers( struct softpipe_context *softpipe ) softpipe->tgsi.frag_samplers[i].sampler = softpipe->sampler[i]; softpipe->tgsi.frag_samplers[i].texture = softpipe->texture[i]; } + + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + sp_tile_cache_validate_texture( softpipe->tex_cache[i] ); + } } /* Hopefully this will remain quite simple, otherwise need to pull in @@ -207,6 +212,15 @@ update_tgsi_samplers( struct softpipe_context *softpipe ) */ void softpipe_update_derived( struct softpipe_context *softpipe ) { + struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen); + + /* Check for updated textures. + */ + if (softpipe->tex_timestamp != sp_screen->timestamp) { + softpipe->tex_timestamp = sp_screen->timestamp; + softpipe->dirty |= SP_NEW_TEXTURE; + } + if (softpipe->dirty & (SP_NEW_SAMPLER | SP_NEW_TEXTURE)) update_tgsi_samplers( softpipe ); diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 7a533dad9f..0c84375bf1 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -227,7 +227,8 @@ softpipe_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. */ - spt->modified = TRUE; + spt->timestamp++; + softpipe_screen(screen)->timestamp++; } ps->face = face; diff --git a/src/gallium/drivers/softpipe/sp_texture.h b/src/gallium/drivers/softpipe/sp_texture.h index 893aa7d11d..42df722a2d 100644 --- a/src/gallium/drivers/softpipe/sp_texture.h +++ b/src/gallium/drivers/softpipe/sp_texture.h @@ -48,7 +48,7 @@ struct softpipe_texture */ struct pipe_buffer *buffer; - boolean modified; + unsigned timestamp; }; struct softpipe_transfer diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index 306284808c..79b1e036be 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -54,7 +54,10 @@ struct softpipe_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 softpipe_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 @@ sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc) } } +void +sp_tile_cache_validate_texture(struct softpipe_tile_cache *tc) +{ + if (tc->texture) { + struct softpipe_texture *spt = softpipe_texture(tc->texture); + if (spt->timestamp != tc->timestamp) { + /* texture was modified, invalidate all cached tiles */ + uint i; + _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp); + for (i = 0; i < NUM_ENTRIES; i++) { + tc->entries[i].x = -3; + } + + tc->timestamp = spt->timestamp; + } + } +} /** * Specify the texture to cache. @@ -243,27 +263,29 @@ sp_tile_cache_set_texture(struct softpipe_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 @@ sp_get_cached_tile(struct softpipe_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 @@ sp_get_cached_tile_tex(struct softpipe_tile_cache *tc, face, level); struct softpipe_cached_tile *tile = tc->entries + pos; - if (tc->texture) { - struct softpipe_texture *spt = softpipe_texture(tc->texture); - if (spt->modified) { - /* texture was modified, invalidate all cached tiles */ - uint p; - for (p = 0; p < NUM_ENTRIES; p++) { - tile = tc->entries + p; - tile->x = -1; - } - spt->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/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index 639cde6705..0d165b4ad7 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -83,6 +83,9 @@ extern void sp_tile_cache_set_texture(struct softpipe_tile_cache *tc, struct pipe_texture *texture); +void +sp_tile_cache_validate_texture(struct softpipe_tile_cache *tc); + extern void sp_flush_tile_cache(struct softpipe_tile_cache *tc); -- cgit v1.2.3