Mesa (master): svga: do not unconditionally enable streamout bind flag

Brian Paul brianp at kemper.freedesktop.org
Tue Jun 27 14:16:04 UTC 2017


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

Author: Charmaine Lee <charmainel at vmware.com>
Date:   Tue Nov 15 10:15:46 2016 -0800

svga: do not unconditionally enable streamout bind flag

Currently we unconditionally enable streamout bind flag at
buffer resource creation time. This is not necessary if the buffer
is never used as a streamout buffer. With this patch, we enable
streamout bind flag as indicated by the state tracker. If the buffer
is later bound to streamout and does not already has streamout bind
flag enabled, we will recreate the buffer with
the new set of bind flags. Buffer content will be copied
from the old buffer to the new one.

Tested with MTT piglit, Nature, Tropics, Lightsmark.

v2: Fix bind flags check as suggested by Brian.

Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: Jose Fonseca <jfonseca at vmware.com>

---

 src/gallium/drivers/svga/svga_pipe_streamout.c     |  8 +--
 src/gallium/drivers/svga/svga_resource_buffer.c    | 14 ++---
 .../drivers/svga/svga_resource_buffer_upload.c     | 62 +++++++++++++++++++++-
 .../drivers/svga/svga_resource_buffer_upload.h     |  5 ++
 4 files changed, 78 insertions(+), 11 deletions(-)

diff --git a/src/gallium/drivers/svga/svga_pipe_streamout.c b/src/gallium/drivers/svga/svga_pipe_streamout.c
index 18cc804d0c..4add087888 100644
--- a/src/gallium/drivers/svga/svga_pipe_streamout.c
+++ b/src/gallium/drivers/svga/svga_pipe_streamout.c
@@ -276,14 +276,14 @@ svga_set_stream_output_targets(struct pipe_context *pipe,
    for (i = 0; i < num_targets; i++) {
       struct svga_stream_output_target *sot
          = svga_stream_output_target(targets[i]);
-      struct svga_buffer *sbuf = svga_buffer(sot->base.buffer);
       unsigned size;
 
-      assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT);
-      (void) sbuf;
-
       svga->so_surfaces[i] = svga_buffer_handle(svga, sot->base.buffer,
                                                 PIPE_BIND_STREAM_OUTPUT);
+
+      assert(svga_buffer(sot->base.buffer)->key.flags
+             & SVGA3D_SURFACE_BIND_STREAM_OUTPUT);
+
       svga->so_targets[i] = &sot->base;
       soBindings[i].offset = sot->base.buffer_offset;
 
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c
index 4448b7d030..39aa530a67 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer.c
@@ -427,20 +427,22 @@ svga_buffer_create(struct pipe_screen *screen,
 
    if (svga_buffer_needs_hw_storage(bind_flags)) {
 
-      /* If the buffer will be used for vertex/index/stream data, set all
-       * the flags so that the buffer will be accepted for all those uses.
+      /* If the buffer will be used for vertex/index/stream data, set
+       * the vertex/index bind flags as well so that the buffer will be
+       * accepted for those uses.
        * Note that the PIPE_BIND_ flags we get from the state tracker are
        * just a hint about how the buffer may be used.  And OpenGL buffer
        * object may be used for many different things.
+       * Also note that we do not unconditionally set the streamout
+       * bind flag since streamout buffer is an output buffer and
+       * might have performance implication.
        */
       if (!(template->bind & PIPE_BIND_CONSTANT_BUFFER)) {
-         /* Not a constant buffer.  The buffer may be used for vertex data,
-          * indexes or stream-out.
+         /* Not a constant buffer.  The buffer may be used for vertex data
+          * or indexes.
           */
          bind_flags |= (PIPE_BIND_VERTEX_BUFFER |
                         PIPE_BIND_INDEX_BUFFER);
-         if (ss->sws->have_vgpu10)
-            bind_flags |= PIPE_BIND_STREAM_OUTPUT;
       }
 
       if (svga_buffer_create_host_surface(ss, sbuf, bind_flags) != PIPE_OK)
diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c
index 40429a8dc8..d18d026bfa 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c
@@ -213,6 +213,53 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
 }
 
 
+/**
+ * Recreates a host surface with the new bind flags.
+ */
+enum pipe_error
+svga_buffer_recreate_host_surface(struct svga_context *svga,
+                                  struct svga_buffer *sbuf,
+                                  unsigned bind_flags)
+{
+   struct svga_screen *ss = svga_screen(sbuf->b.b.screen);
+   struct svga_winsys_surface *old_handle;
+   struct svga_host_surface_cache_key old_key;
+   enum pipe_error ret = PIPE_OK;
+
+   assert(sbuf->bind_flags != bind_flags);
+
+   /* Flush any pending upload first */
+   svga_buffer_upload_flush(svga, sbuf);
+
+   /* Save the old resource handle and key */
+   old_handle = sbuf->handle;
+   old_key = sbuf->key;
+   sbuf->handle = NULL;
+ 
+   /* Create a new resource with the required bind_flags */
+   ret = svga_buffer_create_host_surface(ss, sbuf, bind_flags);
+   if (ret == PIPE_OK) {
+      /* Copy the surface data */
+      assert(sbuf->handle);
+      ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle,
+                                     0, 0, sbuf->b.b.width0);
+      if (ret != PIPE_OK) {
+         svga_context_flush(svga, NULL);
+         ret = SVGA3D_vgpu10_BufferCopy(svga->swc, old_handle, sbuf->handle,
+                                        0, 0, sbuf->b.b.width0);
+         assert(ret == PIPE_OK);
+      }
+   }
+
+   /* Set the new bind flags for this buffer resource */
+   sbuf->bind_flags = bind_flags;
+
+   /* Destroy the old resource handle */
+   svga_screen_surface_destroy(ss, &old_key, &old_handle);
+
+   return ret;
+}
+
 void
 svga_buffer_destroy_host_surface(struct svga_screen *ss,
                                  struct svga_buffer *sbuf)
@@ -791,7 +838,20 @@ svga_buffer_handle(struct svga_context *svga, struct pipe_resource *buf,
 
    assert(!sbuf->user);
 
-   if (!sbuf->handle) {
+   if (sbuf->handle) {
+      if ((sbuf->bind_flags & tobind_flags) != tobind_flags) {
+         /* If the allocated resource's bind flags do not include the
+          * requested bind flags, create a new resource to include the
+          * new bind flags, and do a BufferCopy from the old resource to
+          * the new one.
+          */
+         assert(svga_have_vgpu10(svga));
+         ret = svga_buffer_recreate_host_surface(svga, sbuf,
+                                                 sbuf->bind_flags|tobind_flags);
+         if (ret != PIPE_OK)
+            return NULL;
+      }
+   } else {
       /* This call will set sbuf->handle */
       if (svga_have_gb_objects(svga)) {
 	 ret = svga_buffer_update_hw(svga, sbuf, sbuf->bind_flags);
diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.h b/src/gallium/drivers/svga/svga_resource_buffer_upload.h
index f718f24c90..877ae5499a 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer_upload.h
+++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.h
@@ -50,6 +50,11 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
                                 struct svga_buffer *sbuf,
                                 unsigned bind_flags);
 
+enum pipe_error
+svga_buffer_recreate_host_surface(struct svga_context *svga,
+                                  struct svga_buffer *sbuf,
+                                  unsigned bind_flags);
+
 void
 svga_buffer_destroy_host_surface(struct svga_screen *ss,
                                  struct svga_buffer *sbuf);




More information about the mesa-commit mailing list