llvmpipe: make some small steps to flush texture cache less frequently
authorKeith Whitwell <keithw@vmware.com>
Fri, 17 Jul 2009 09:44:22 +0000 (10:44 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Sat, 29 Aug 2009 08:21:16 +0000 (09:21 +0100)
No performance gain yet, but the code is a bit cleaner.

src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_texture.c
src/gallium/drivers/llvmpipe/lp_texture.h
src/gallium/drivers/llvmpipe/lp_tile_cache.c
src/gallium/drivers/llvmpipe/lp_tile_cache.h

index 9bfae0a..ab88401 100644 (file)
@@ -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;
index 16ae435..59b06f5 100644 (file)
@@ -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 );
index fd9b518..542e313 100644 (file)
@@ -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;
index dc688b2..a1ed6b0 100644 (file)
@@ -48,7 +48,7 @@ struct llvmpipe_texture
     */
    struct pipe_buffer *buffer;
 
-   boolean modified;
+   unsigned timestamp;
 };
 
 struct llvmpipe_transfer
index 08c48e4..2bda88c 100644 (file)
@@ -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 ||
index e82b4b8..9e830e9 100644 (file)
@@ -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);