Module: Mesa
Branch: master
Commit: d7a6c1a4769774a0a86cc75090d5d3089f248a7d
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=d7a6c1a4769774a0a86cc75090d5d3089f248a7d

Author: Charmaine Lee <charmai...@vmware.com>
Date:   Thu Apr 14 17:33:32 2016 -0700

svga: minimize surface flush

Currently, we always do a surface flush when we try to establish
a synchronized write transfer map. But if the subresource has not
been modified, we can skip the surface flush. In other words,
we only need to do a surface flush if the to-be-mapped subresource
has been modified in this command buffer.

With this patch, lightsmark2008 shows about 15% performance improvement.

Reviewed-by: Brian Paul <bri...@vmware.com>

---

 src/gallium/drivers/svga/svga_resource_texture.c | 71 +++++++++++++++++++-----
 src/gallium/drivers/svga/svga_resource_texture.h | 29 ++++++++++
 2 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/src/gallium/drivers/svga/svga_resource_texture.c 
b/src/gallium/drivers/svga/svga_resource_texture.c
index db73080..ae51228 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.c
+++ b/src/gallium/drivers/svga/svga_resource_texture.c
@@ -234,6 +234,7 @@ svga_texture_destroy(struct pipe_screen *screen,
 
    FREE(tex->defined);
    FREE(tex->rendered_to);
+   FREE(tex->dirty);
    FREE(tex);
 
    assert(ss->hud.num_resources > 0);
@@ -436,6 +437,13 @@ svga_texture_transfer_map(struct pipe_context *pipe,
          return NULL;
       }
 
+      /* If this is the first time mapping to the surface in this
+       * command buffer, clear the dirty masks of this surface.
+       */
+      if (sws->surface_is_flushed(sws, surf)) {
+         svga_clear_texture_dirty(tex);
+      }
+
       if (need_tex_readback(transfer)) {
         enum pipe_error ret;
 
@@ -464,13 +472,21 @@ svga_texture_transfer_map(struct pipe_context *pipe,
       else {
         assert(transfer->usage & PIPE_TRANSFER_WRITE);
         if ((transfer->usage & PIPE_TRANSFER_UNSYNCHRONIZED) == 0) {
-            svga_surfaces_flush(svga);
-            if (!sws->surface_is_flushed(sws, surf)) {
-               svga->hud.surface_write_flushes++;
-               svga_context_flush(svga, NULL);
+            if (svga_is_texture_dirty(tex, st->slice, transfer->level)) {
+               /*
+                * do a surface flush if the subresource has been modified
+                * in this command buffer.
+                */
+               svga_surfaces_flush(svga);
+               if (!sws->surface_is_flushed(sws, surf)) {
+                  svga->hud.surface_write_flushes++;
+                  svga_context_flush(svga, NULL);
+               }
             }
         }
       }
+      /* mark this texture level as dirty */
+      svga_set_texture_dirty(tex, st->slice, transfer->level);
    }
 
    st->use_direct_map = use_direct_map;
@@ -756,9 +772,13 @@ svga_texture_create(struct pipe_screen *screen,
    tex->rendered_to = CALLOC(template->depth0 * template->array_size,
                              sizeof(tex->rendered_to[0]));
    if (!tex->rendered_to) {
-      FREE(tex->defined);
-      FREE(tex);
-      return NULL;
+      goto fail;
+   }
+
+   tex->dirty = CALLOC(template->depth0 * template->array_size,
+                             sizeof(tex->dirty[0]));
+   if (!tex->dirty) {
+      goto fail;
    }
 
    tex->b.b = *template;
@@ -872,10 +892,7 @@ svga_texture_create(struct pipe_screen *screen,
    tex->key.format = svga_translate_format(svgascreen, template->format,
                                            bindings);
    if (tex->key.format == SVGA3D_FORMAT_INVALID) {
-      FREE(tex->defined);
-      FREE(tex->rendered_to);
-      FREE(tex);
-      return NULL;
+      goto fail;
    }
 
    /* Use typeless formats for sRGB and depth resources.  Typeless
@@ -900,10 +917,7 @@ svga_texture_create(struct pipe_screen *screen,
    tex->handle = svga_screen_surface_create(svgascreen, bindings,
                                             tex->b.b.usage, &tex->key);
    if (!tex->handle) {
-      FREE(tex->defined);
-      FREE(tex->rendered_to);
-      FREE(tex);
-      return NULL;
+      goto fail;
    }
 
    SVGA_DBG(DEBUG_DMA, "  --> got sid %p (texture)\n", tex->handle);
@@ -916,6 +930,16 @@ svga_texture_create(struct pipe_screen *screen,
    svgascreen->hud.num_resources++;
 
    return &tex->b.b;
+
+fail:
+   if (tex->dirty)
+      FREE(tex->dirty);
+   if (tex->rendered_to)
+      FREE(tex->rendered_to);
+   if (tex->defined)
+      FREE(tex->defined);
+   FREE(tex);
+   return NULL;
 }
 
 
@@ -993,11 +1017,28 @@ svga_texture_from_handle(struct pipe_screen *screen,
    tex->handle = srf;
 
    tex->rendered_to = CALLOC(1, sizeof(tex->rendered_to[0]));
+   if (!tex->rendered_to)
+      goto fail;
+
+   tex->dirty = CALLOC(1, sizeof(tex->dirty[0]));
+   if (!tex->dirty)
+      goto fail;
+
    tex->imported = TRUE;
 
    ss->hud.num_resources++;
 
    return &tex->b.b;
+
+fail:
+   if (tex->defined)
+      FREE(tex->defined);
+   if (tex->rendered_to)
+      FREE(tex->rendered_to);
+   if (tex->dirty)
+      FREE(tex->dirty);
+   FREE(tex);
+   return NULL;
 }
 
 boolean
diff --git a/src/gallium/drivers/svga/svga_resource_texture.h 
b/src/gallium/drivers/svga/svga_resource_texture.h
index 283b87f..e779f19 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.h
+++ b/src/gallium/drivers/svga/svga_resource_texture.h
@@ -87,6 +87,11 @@ struct svga_texture
 
    /** array indexed by cube face or 3D/array slice, one bit per mipmap level 
*/
    ushort *rendered_to;
+
+   /** array indexed by cube face or 3D/array slice, one bit per mipmap level.
+    *  Set if the level is marked as dirty.
+    */ 
+   ushort *dirty;
 };
 
 
@@ -207,6 +212,30 @@ svga_was_texture_rendered_to(const struct svga_texture 
*tex,
    return !!(tex->rendered_to[face] & (1 << level));
 }
 
+static inline void
+svga_set_texture_dirty(struct svga_texture *tex,
+                       unsigned face, unsigned level)
+{
+   check_face_level(tex, face, level);
+   tex->dirty[face] |= 1 << level;
+}
+
+static inline void
+svga_clear_texture_dirty(struct svga_texture *tex)
+{
+   unsigned i;
+   for (i = 0; i < tex->b.b.depth0 * tex->b.b.array_size; i++) {
+      tex->dirty[i] = 0;
+   }
+}
+
+static inline boolean
+svga_is_texture_dirty(const struct svga_texture *tex,
+                      unsigned face, unsigned level)
+{
+   check_face_level(tex, face, level);
+   return !!(tex->dirty[face] & (1 << level));
+}
 
 struct pipe_resource *
 svga_texture_create(struct pipe_screen *screen,

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to