From 127a493fe2a2f7fd8515b278185322dfacdad357 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 7 Dec 2007 20:13:10 -0700 Subject: Tile clearing optimizations. Clear using int values rather than floats when possible. Better performance now. --- src/mesa/pipe/softpipe/sp_clear.c | 42 +----- src/mesa/pipe/softpipe/sp_tile_cache.c | 252 ++++++++++++++++++--------------- src/mesa/pipe/softpipe/sp_tile_cache.h | 4 +- 3 files changed, 147 insertions(+), 151 deletions(-) diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c index a6352e0616..bfe4a29144 100644 --- a/src/mesa/pipe/softpipe/sp_clear.c +++ b/src/mesa/pipe/softpipe/sp_clear.c @@ -51,49 +51,15 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, softpipe_update_derived(softpipe); /* not needed?? */ if (ps == sp_tile_cache_get_surface(softpipe->zbuf_cache)) { - float clear[4]; - clear[0] = 1.0; /* XXX hack */ - sp_tile_cache_clear(softpipe->zbuf_cache, clear); + sp_tile_cache_clear(softpipe->zbuf_cache, clearValue); } else if (ps == sp_tile_cache_get_surface(softpipe->cbuf_cache[0])) { - float clear[4]; - /* XXX it sure would be nice if the clear color was passed to - * this function as float[4].... - */ - uint r, g, b, a; - switch (ps->format) { - case PIPE_FORMAT_R8G8B8A8_UNORM: - r = (clearValue >> 24) & 0xff; - g = (clearValue >> 16) & 0xff; - g = (clearValue >> 8) & 0xff; - a = (clearValue ) & 0xff; - break; - case PIPE_FORMAT_A8R8G8B8_UNORM: - r = (clearValue >> 16) & 0xff; - g = (clearValue >> 8) & 0xff; - b = (clearValue ) & 0xff; - a = (clearValue >> 24) & 0xff; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - r = (clearValue >> 8) & 0xff; - g = (clearValue >> 16) & 0xff; - b = (clearValue >> 24) & 0xff; - a = (clearValue ) & 0xff; - break; - default: - assert(0); - } - - clear[0] = r / 255.0; - clear[1] = g / 255.0; - clear[2] = b / 255.0; - clear[3] = a / 255.0; - - sp_tile_cache_clear(softpipe->cbuf_cache[0], clear); + sp_tile_cache_clear(softpipe->cbuf_cache[0], clearValue); } +#if !TILE_CLEAR_OPTIMIZATION pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); - +#endif #if 0 sp_clear_tile_cache(ps, clearValue); diff --git a/src/mesa/pipe/softpipe/sp_tile_cache.c b/src/mesa/pipe/softpipe/sp_tile_cache.c index 602b78ebe6..13774e6c8f 100644 --- a/src/mesa/pipe/softpipe/sp_tile_cache.c +++ b/src/mesa/pipe/softpipe/sp_tile_cache.c @@ -52,7 +52,9 @@ struct softpipe_tile_cache struct pipe_texture *texture; /**< if caching a texture */ struct softpipe_cached_tile entries[NUM_ENTRIES]; uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32]; - float clear_value[4]; + float clear_color[4]; + uint clear_val; + boolean depth_stencil; /** Is the surface a depth/stencil format? */ }; @@ -67,6 +69,9 @@ struct softpipe_tile_cache +/** + * Is the tile at (x,y) in cleared state? + */ static INLINE uint is_clear_flag_set(const uint *bitvec, int x, int y) { @@ -80,6 +85,9 @@ is_clear_flag_set(const uint *bitvec, int x, int y) } +/** + * Mark the tile at (x,y) as not cleared. + */ static INLINE void clear_clear_flag(uint *bitvec, int x, int y) { @@ -120,10 +128,15 @@ sp_destroy_tile_cache(struct softpipe_tile_cache *tc) } +/** + * Specify the surface to cache. + */ void sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { + assert(!tc->texture); + if (tc->surface && tc->surface->map) { assert(tc->surface != ps); pipe_surface_unmap(tc->surface); @@ -133,9 +146,19 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, if (!ps->map) pipe_surface_map(ps); + + if (ps) { + tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM || + ps->format == PIPE_FORMAT_Z16_UNORM || + ps->format == PIPE_FORMAT_Z32_UNORM || + ps->format == PIPE_FORMAT_U_S8); + } } +/** + * Return the surface being cached. + */ struct pipe_surface * sp_tile_cache_get_surface(struct softpipe_tile_cache *tc) { @@ -143,12 +166,17 @@ sp_tile_cache_get_surface(struct softpipe_tile_cache *tc) } +/** + * Specify the texture to cache. + */ void sp_tile_cache_set_texture(struct softpipe_tile_cache *tc, struct pipe_texture *texture) { uint i; + assert(!tc->surface); + tc->texture = texture; /* mark as entries as invalid/empty */ @@ -159,84 +187,71 @@ sp_tile_cache_set_texture(struct softpipe_tile_cache *tc, } -static INLINE boolean -is_depth_stencil_surface(struct pipe_surface *ps) +/** + * Set pixels in a tile to the given clear color/value, float. + */ +static void +clear_tile_rgba(struct softpipe_cached_tile *tile, + enum pipe_format format, + const float clear_value[4]) { - return (ps && - (ps->format == PIPE_FORMAT_S8Z24_UNORM || - ps->format == PIPE_FORMAT_Z16_UNORM || - ps->format == PIPE_FORMAT_Z32_UNORM || - ps->format == PIPE_FORMAT_U_S8)); + if (clear_value[0] == 0.0 && + clear_value[1] == 0.0 && + clear_value[2] == 0.0 && + clear_value[3] == 0.0) { + memset(tile->data.color, 0, sizeof(tile->data.color)); + } + else { + uint i, j; + for (i = 0; i < TILE_SIZE; i++) { + for (j = 0; j < TILE_SIZE; j++) { + tile->data.color[i][j][0] = clear_value[0]; + tile->data.color[i][j][1] = clear_value[1]; + tile->data.color[i][j][2] = clear_value[2]; + tile->data.color[i][j][3] = clear_value[3]; + } + } + } } /** - * Set pixels in a tile to the given clear color/value. + * Set a tile to a solid value/color. */ static void clear_tile(struct softpipe_cached_tile *tile, enum pipe_format format, - const float clear_value[4]) + uint clear_value) { uint i, j; switch (format) { - case PIPE_FORMAT_Z16_UNORM: - { - ushort clear_val = (ushort) (clear_value[0] * 0xffff); - for (i = 0; i < TILE_SIZE; i++) { - for (j = 0; j < TILE_SIZE; j++) { - tile->data.depth16[i][j] = clear_val; - } - } - } - break; - case PIPE_FORMAT_Z32_UNORM: - { - uint clear_val = (uint) (clear_value[0] * 0xffffffff); - for (i = 0; i < TILE_SIZE; i++) { - for (j = 0; j < TILE_SIZE; j++) { - tile->data.depth32[i][j] = clear_val; - } - } - } + case PIPE_FORMAT_U_S8: + /* 8 bpp */ + memset(tile->data.any, 0, TILE_SIZE * TILE_SIZE); break; - case PIPE_FORMAT_S8Z24_UNORM: - { - uint clear_val = (uint) (clear_value[0] * 0xffffff); - clear_val |= ((uint) clear_value[1]) << 24; - for (i = 0; i < TILE_SIZE; i++) { - for (j = 0; j < TILE_SIZE; j++) { - tile->data.depth32[i][j] = clear_val; - } - } + case PIPE_FORMAT_Z16_UNORM: + /* 16 bpp */ + if (clear_value == 0) { + memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE); } - break; - case PIPE_FORMAT_U_S8: - { - ubyte clear_val = (uint) clear_value[0]; + else { for (i = 0; i < TILE_SIZE; i++) { for (j = 0; j < TILE_SIZE; j++) { - tile->data.stencil8[i][j] = clear_val; + tile->data.depth16[i][j] = clear_value; } } } break; default: - /* color */ - if (clear_value[0] == 0.0 && - clear_value[1] == 0.0 && - clear_value[2] == 0.0 && - clear_value[3] == 0.0) { - memset(tile->data.color, 0, sizeof(tile->data.color)); + /* 32 bpp */ + if (clear_value == 0) { + memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE); } else { for (i = 0; i < TILE_SIZE; i++) { for (j = 0; j < TILE_SIZE; j++) { - tile->data.color[i][j][0] = clear_value[0]; - tile->data.color[i][j][1] = clear_value[1]; - tile->data.color[i][j][2] = clear_value[2]; - tile->data.color[i][j][3] = clear_value[3]; + tile->data.color32[i][j] = clear_value; } } } @@ -244,52 +259,6 @@ clear_tile(struct softpipe_cached_tile *tile, } -static INLINE void -put_tile(struct pipe_context *pipe, - struct pipe_surface *ps, - struct softpipe_cached_tile *tile) -{ - assert(tile->x >= 0); - assert(tile->x % TILE_SIZE == 0); - assert(tile->y >= 0); - assert(tile->y % TILE_SIZE == 0); - - if (is_depth_stencil_surface(ps)) { - pipe->put_tile(pipe, ps, - tile->x, tile->y, TILE_SIZE, TILE_SIZE, - tile->data.depth32, 0/*STRIDE*/); - } - else { - pipe->put_tile_rgba(pipe, ps, - tile->x, tile->y, TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); - } -} - - -static INLINE void -get_tile(struct pipe_context *pipe, - struct pipe_surface *ps, - struct softpipe_cached_tile *tile) -{ - assert(tile->x >= 0); - assert(tile->x % TILE_SIZE == 0); - assert(tile->y >= 0); - assert(tile->y % TILE_SIZE == 0); - - if (is_depth_stencil_surface(ps)) { - pipe->get_tile(pipe, ps, - tile->x, tile->y, TILE_SIZE, TILE_SIZE, - tile->data.depth32, 0/*STRIDE*/); - } - else { - pipe->get_tile_rgba(pipe, ps, - tile->x, tile->y, TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); - } -} - - /** * Actually clear the tiles which were flagged as being in a clear state. */ @@ -305,15 +274,15 @@ sp_tile_cache_flush_clear(struct pipe_context *pipe, uint numCleared = 0; /* clear one tile to the clear value */ - clear_tile(&tile, ps->format, tc->clear_value); + clear_tile(&tile, ps->format, tc->clear_val); /* push the tile to all positions marked as clear */ for (y = 0; y < h; y += TILE_SIZE) { for (x = 0; x < w; x += TILE_SIZE) { if (is_clear_flag_set(tc->clear_flags, x, y)) { - tile.x = x; - tile.y = y; - put_tile(pipe, ps, &tile); + pipe->put_tile(pipe, ps, + x, y, TILE_SIZE, TILE_SIZE, + tile.data.color32, 0/*STRIDE*/); /* do this? */ clear_clear_flag(tc->clear_flags, x, y); @@ -349,7 +318,16 @@ sp_flush_tile_cache(struct softpipe_context *softpipe, for (pos = 0; pos < NUM_ENTRIES; pos++) { struct softpipe_cached_tile *tile = tc->entries + pos; if (tile->x >= 0) { - put_tile(pipe, ps, tile); + if (tc->depth_stencil) { + pipe->put_tile(pipe, ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + tile->data.depth32, 0/*STRIDE*/); + } + else { + pipe->put_tile_rgba(pipe, ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + (float *) tile->data.color); + } tile->x = tile->y = -1; /* mark as empty */ inuse++; } @@ -389,7 +367,16 @@ sp_get_cached_tile(struct softpipe_context *softpipe, if (tile->x != -1) { /* put dirty tile back in framebuffer */ - put_tile(pipe, ps, tile); + if (tc->depth_stencil) { + pipe->put_tile(pipe, ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + tile->data.depth32, 0/*STRIDE*/); + } + else { + pipe->put_tile_rgba(pipe, ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + (float *) tile->data.color); + } } tile->x = tile_x; @@ -397,12 +384,26 @@ sp_get_cached_tile(struct softpipe_context *softpipe, if (is_clear_flag_set(tc->clear_flags, x, y)) { /* don't get tile from framebuffer, just clear it */ - clear_tile(tile, ps->format, tc->clear_value); + if (tc->depth_stencil) { + clear_tile(tile, ps->format, tc->clear_val); + } + else { + clear_tile_rgba(tile, ps->format, tc->clear_color); + } clear_clear_flag(tc->clear_flags, x, y); } else { /* get new tile data from surface */ - get_tile(pipe, ps, tile); + if (tc->depth_stencil) { + pipe->get_tile(pipe, ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + tile->data.depth32, 0/*STRIDE*/); + } + else { + pipe->get_tile_rgba(pipe, ps, + tile->x, tile->y, TILE_SIZE, TILE_SIZE, + (float *) tile->data.color); + } } } @@ -477,12 +478,39 @@ sp_get_cached_tile_tex(struct pipe_context *pipe, * Save the color and set a 'clearflag' for each tile of the screen. */ void -sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float value[4]) +sp_tile_cache_clear(struct softpipe_tile_cache *tc, uint clearValue) { - tc->clear_value[0] = value[0]; - tc->clear_value[1] = value[1]; - tc->clear_value[2] = value[2]; - tc->clear_value[3] = value[3]; + uint r, g, b, a; + + tc->clear_val = clearValue; + + switch (tc->surface->format) { + case PIPE_FORMAT_R8G8B8A8_UNORM: + r = (clearValue >> 24) & 0xff; + g = (clearValue >> 16) & 0xff; + b = (clearValue >> 8) & 0xff; + a = (clearValue ) & 0xff; + break; + case PIPE_FORMAT_A8R8G8B8_UNORM: + r = (clearValue >> 16) & 0xff; + g = (clearValue >> 8) & 0xff; + b = (clearValue ) & 0xff; + a = (clearValue >> 24) & 0xff; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + r = (clearValue >> 8) & 0xff; + g = (clearValue >> 16) & 0xff; + b = (clearValue >> 24) & 0xff; + a = (clearValue ) & 0xff; + break; + default: + r = g = b = a = 0; + } + + tc->clear_color[0] = r / 255.0; + tc->clear_color[1] = g / 255.0; + tc->clear_color[2] = b / 255.0; + tc->clear_color[3] = a / 255.0; #if TILE_CLEAR_OPTIMIZATION /* set flags to indicate all the tiles are cleared */ diff --git a/src/mesa/pipe/softpipe/sp_tile_cache.h b/src/mesa/pipe/softpipe/sp_tile_cache.h index c4f2e0f184..91fb2795a2 100644 --- a/src/mesa/pipe/softpipe/sp_tile_cache.h +++ b/src/mesa/pipe/softpipe/sp_tile_cache.h @@ -51,9 +51,11 @@ struct softpipe_cached_tile int z, face, level; /**< Extra texture indexes */ union { float color[TILE_SIZE][TILE_SIZE][4]; + uint color32[TILE_SIZE][TILE_SIZE]; uint depth32[TILE_SIZE][TILE_SIZE]; ushort depth16[TILE_SIZE][TILE_SIZE]; ubyte stencil8[TILE_SIZE][TILE_SIZE]; + ubyte any[1]; } data; }; @@ -80,7 +82,7 @@ sp_flush_tile_cache(struct softpipe_context *softpipe, struct softpipe_tile_cache *tc); extern void -sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float value[4]); +sp_tile_cache_clear(struct softpipe_tile_cache *tc, uint clearValue); extern struct softpipe_cached_tile * sp_get_cached_tile(struct softpipe_context *softpipe, -- cgit v1.2.3