svga: invalidate new surface before it is bound to a render target view
authorCharmaine Lee <charmainel@vmware.com>
Wed, 26 Oct 2016 23:15:23 +0000 (16:15 -0700)
committerBrian Paul <brianp@vmware.com>
Thu, 3 Nov 2016 20:29:23 +0000 (14:29 -0600)
Invalidate a "new" surface before it is bound to a render target view or
depth stencil view in order to avoid the unnecessary host side copy
of the surface data before it is rendered to.
Note that, recycled surface is already invalidated before it is reused.

Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/drivers/svga/svga_resource_buffer_upload.c
src/gallium/drivers/svga/svga_resource_texture.c
src/gallium/drivers/svga/svga_resource_texture.h
src/gallium/drivers/svga/svga_screen_cache.c
src/gallium/drivers/svga/svga_screen_cache.h
src/gallium/drivers/svga/svga_surface.c

index ac8cedfd3b791256c75ca0fbc1894f430efb4268..b327a1679e43675e725e4d8120aa7b4427cabaab 100644 (file)
@@ -146,6 +146,8 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
    assert(!sbuf->user);
 
    if (!sbuf->handle) {
+      boolean validated;
+
       sbuf->key.flags = 0;
 
       sbuf->key.format = SVGA3D_BUFFER;
@@ -187,7 +189,8 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
                sbuf->b.b.width0);
 
       sbuf->handle = svga_screen_surface_create(ss, sbuf->b.b.bind,
-                                                sbuf->b.b.usage, &sbuf->key);
+                                                sbuf->b.b.usage,
+                                                &validated, &sbuf->key);
       if (!sbuf->handle)
          return PIPE_ERROR_OUT_OF_MEMORY;
 
index 89909336e9136725de52c8af407300bd4bb8a6cc..20580e9dd9224476204b48e53d1548367769c314 100644 (file)
@@ -1102,7 +1102,8 @@ svga_texture_create(struct pipe_screen *screen,
 
    SVGA_DBG(DEBUG_DMA, "surface_create for texture\n", tex->handle);
    tex->handle = svga_screen_surface_create(svgascreen, bindings,
-                                            tex->b.b.usage, &tex->key);
+                                            tex->b.b.usage,
+                                            &tex->validated, &tex->key);
    if (!tex->handle) {
       goto fail;
    }
index 6347ef6352faaed6047beeb600bf5c051fe5a1cf..9f7b0c6e6596ed541ff61684f4d3a2eb75f974f2 100644 (file)
@@ -77,6 +77,13 @@ struct svga_texture
     */
    struct svga_winsys_surface *handle;
 
+   /**
+    * Whether the host side surface is validated, either through the
+    * InvalidateGBSurface command or after the surface is updated
+    * or rendered to.
+    */
+   boolean validated;
+
    /**
     * Whether the host side surface is imported and not created by this
     * driver.
@@ -195,6 +202,7 @@ svga_define_texture_level(struct svga_texture *tex,
 {
    check_face_level(tex, face, level);
    tex->defined[face] |= 1 << level;
+   tex->validated = TRUE;
 }
 
 
@@ -213,6 +221,7 @@ svga_set_texture_rendered_to(struct svga_texture *tex,
 {
    check_face_level(tex, face, level);
    tex->rendered_to[face] |= 1 << level;
+   tex->validated = TRUE;
 }
 
 
index 86a04136e6457a5e35d8bcf6dc1ef67a3be8d44f..76e34258f9ce91dc21494b51394f877245fcf738 100644 (file)
@@ -433,10 +433,12 @@ svga_screen_cache_init(struct svga_screen *svgascreen)
  * allocate a new surface.
  * \param bind_flags  bitmask of PIPE_BIND_x flags
  * \param usage  one of PIPE_USAGE_x values
+ * \param validated return True if the surface is a reused surface
  */
 struct svga_winsys_surface *
 svga_screen_surface_create(struct svga_screen *svgascreen,
                            unsigned bind_flags, enum pipe_resource_usage usage,
+                           boolean *validated,
                            struct svga_host_surface_cache_key *key)
 {
    struct svga_winsys_screen *sws = svgascreen->sws;
@@ -510,6 +512,7 @@ svga_screen_surface_create(struct svga_screen *svgascreen,
                      key->numMipLevels,
                      key->numFaces,
                      key->arraySize);
+         *validated = TRUE;
       }
    }
 
@@ -536,6 +539,8 @@ svga_screen_surface_create(struct svga_screen *svgascreen,
                   key->size.width,
                   key->size.height,
                   key->size.depth);
+
+      *validated = FALSE;
    }
 
    return handle;
index 9365f751f72c634adda37f676c07333ff02ab19d..619603a82385d502d490d068ff3e649509e12e7a 100644 (file)
@@ -145,6 +145,7 @@ svga_screen_cache_init(struct svga_screen *svgascreen);
 struct svga_winsys_surface *
 svga_screen_surface_create(struct svga_screen *svgascreen,
                            unsigned bind_flags, enum pipe_resource_usage usage,
+                           boolean *validated,
                            struct svga_host_surface_cache_key *key);
 
 void
index 2ffdce5e10cc3e34fb49e62bc2a847b109fa37f5..cf0052727dfdff11cb284cc43c99dc8d27b1de41 100644 (file)
@@ -120,6 +120,7 @@ svga_texture_view_surface(struct svga_context *svga,
    struct svga_winsys_surface *handle;
    uint32_t i, j;
    unsigned z_offset = 0;
+   boolean validated;
 
    SVGA_DBG(DEBUG_PERF,
             "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
@@ -156,7 +157,8 @@ svga_texture_view_surface(struct svga_context *svga,
    }
 
    SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
-   handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, key);
+   handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
+                                       &validated, key);
    if (!handle) {
       key->cachable = 0;
       return NULL;
@@ -434,6 +436,23 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
    if (s && s->view_id == SVGA3D_INVALID_ID) {
       SVGA3dResourceType resType;
       SVGA3dRenderTargetViewDesc desc;
+      struct svga_texture *stex = svga_texture(s->base.texture);
+
+      if (stex->validated == FALSE) {
+         assert(stex->handle);
+
+         /* We are about to render into a surface that has not been validated.
+          * First invalidate the surface so that the device does not
+          * need to update the host-side copy with the invalid
+          * content when the associated mob is first bound to the surface.
+          */
+         ret = SVGA3D_InvalidateGBSurface(svga->swc, stex->handle);
+         if (ret != PIPE_OK) {
+            s = NULL;
+            goto done;
+         }
+         stex->validated = TRUE;
+      }
 
       desc.tex.mipSlice = s->real_level;
       desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
@@ -481,6 +500,7 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
       }
    }
    
+done:
    SVGA_STATS_TIME_POP(svga_sws(svga));
 
    return s ? &s->base : NULL;