[Mesa-dev] [PATCH 5/5] svga: Add an environment variable to force coherent surface memory

Thomas Hellstrom thellstrom at vmware.com
Thu May 16 09:13:42 UTC 2019


The vmwgfx driver supports emulated coherent surface memory as of version
2.16. Add en environtment variable to enable this functionality for
texture- and buffer maps: SVGA_FORCE_COHERENT.
This environment variable should be used for testing only.

Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>
Reviewed-by: Brian Paul <brianp at vmware.com>
---
 .../drivers/svga/svga_resource_buffer.c       | 13 +++--
 .../drivers/svga/svga_resource_buffer.h       |  9 +++
 .../svga/svga_resource_buffer_upload.c        | 11 +++-
 .../drivers/svga/svga_resource_texture.c      | 58 ++++++++++++-------
 src/gallium/drivers/svga/svga_winsys.h        |  1 +
 src/gallium/winsys/svga/drm/vmw_context.c     |  1 +
 src/gallium/winsys/svga/drm/vmw_screen.c      |  6 +-
 src/gallium/winsys/svga/drm/vmw_screen.h      |  2 +
 .../winsys/svga/drm/vmw_screen_ioctl.c        | 12 ++++
 9 files changed, 82 insertions(+), 31 deletions(-)

diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c
index 3f37ef692fa..234d825d5a2 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer.c
@@ -310,16 +310,18 @@ svga_buffer_transfer_flush_region(struct pipe_context *pipe,
 {
    struct svga_screen *ss = svga_screen(pipe->screen);
    struct svga_buffer *sbuf = svga_buffer(transfer->resource);
-
+   struct svga_context *svga = svga_context(pipe);
    unsigned offset = transfer->box.x + box->x;
    unsigned length = box->width;
 
    assert(transfer->usage & PIPE_TRANSFER_WRITE);
    assert(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT);
 
-   mtx_lock(&ss->swc_mutex);
-   svga_buffer_add_range(sbuf, offset, offset + length);
-   mtx_unlock(&ss->swc_mutex);
+   if (!svga->swc->force_coherent || sbuf->swbuf) {
+      mtx_lock(&ss->swc_mutex);
+      svga_buffer_add_range(sbuf, offset, offset + length);
+      mtx_unlock(&ss->swc_mutex);
+   }
 }
 
 
@@ -359,7 +361,8 @@ svga_buffer_transfer_unmap(struct pipe_context *pipe,
 
          sbuf->dma.flags.discard = TRUE;
 
-         svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0);
+         if (!svga->swc->force_coherent || sbuf->swbuf)
+            svga_buffer_add_range(sbuf, 0, sbuf->b.b.width0);
       }
    }
 
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.h b/src/gallium/drivers/svga/svga_resource_buffer.h
index 464f073b34f..35ed35d61dd 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.h
+++ b/src/gallium/drivers/svga/svga_resource_buffer.h
@@ -314,6 +314,15 @@ svga_buffer_hw_storage_unmap(struct svga_context *svga,
             ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
             assert(ret == PIPE_OK);
          }
+         if (swc->force_coherent) {
+            ret = SVGA3D_UpdateGBSurface(swc, sbuf->handle);
+            if (ret != PIPE_OK) {
+               /* flush and retry */
+               svga_context_flush(svga, NULL);
+               ret = SVGA3D_UpdateGBSurface(swc, sbuf->handle);
+               assert(ret == PIPE_OK);
+            }
+         }
       }
    } else
       sws->buffer_unmap(sws, sbuf->hwbuf);
diff --git a/src/gallium/drivers/svga/svga_resource_buffer_upload.c b/src/gallium/drivers/svga/svga_resource_buffer_upload.c
index 74c3bc4ed61..64f75231a65 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer_upload.c
+++ b/src/gallium/drivers/svga/svga_resource_buffer_upload.c
@@ -448,6 +448,9 @@ svga_buffer_upload_gb_command(struct svga_context *svga,
    struct pipe_resource *dummy;
    unsigned i;
 
+   if (swc->force_coherent)
+      return PIPE_OK;
+
    assert(svga_have_gb_objects(svga));
    assert(numBoxes);
    assert(sbuf->dma.updates == NULL);
@@ -645,7 +648,7 @@ svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf)
    unsigned i;
    struct pipe_resource *dummy;
 
-   if (!sbuf->dma.pending) {
+   if (!sbuf->dma.pending || svga->swc->force_coherent) {
       //debug_printf("no dma pending on buffer\n");
       return;
    }
@@ -659,6 +662,7 @@ svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf)
     */
    if (svga_have_gb_objects(svga)) {
       struct svga_3d_update_gb_image *update = sbuf->dma.updates;
+
       assert(update);
 
       for (i = 0; i < sbuf->map.num_ranges; ++i, ++update) {
@@ -871,6 +875,9 @@ svga_buffer_update_hw(struct svga_context *svga, struct svga_buffer *sbuf,
          memcpy((uint8_t *) map + start, (uint8_t *) sbuf->swbuf + start, len);
       }
 
+      if (svga->swc->force_coherent)
+         sbuf->map.num_ranges = 0;
+
       svga_buffer_hw_storage_unmap(svga, sbuf);
 
       /* This user/malloc buffer is now indistinguishable from a gpu buffer */
@@ -1029,6 +1036,8 @@ svga_buffer_handle(struct svga_context *svga, struct pipe_resource *buf,
    }
 
    assert(sbuf->handle);
+   if (svga->swc->force_coherent)
+      return sbuf->handle;
 
    if (sbuf->map.num_ranges) {
       if (!sbuf->dma.pending) {
diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c
index 307b5ca4a10..0b872da3ed2 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.c
+++ b/src/gallium/drivers/svga/svga_resource_texture.c
@@ -401,21 +401,23 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
 
       svga_surfaces_flush(svga);
 
-      for (i = 0; i < st->box.d; i++) {
-         if (svga_have_vgpu10(svga)) {
-            ret = readback_image_vgpu10(svga, surf, st->slice + i, level,
-                                        tex->b.b.last_level + 1);
-         } else {
-            ret = readback_image_vgpu9(svga, surf, st->slice + i, level);
+      if (!svga->swc->force_coherent || tex->imported) {
+         for (i = 0; i < st->box.d; i++) {
+            if (svga_have_vgpu10(svga)) {
+               ret = readback_image_vgpu10(svga, surf, st->slice + i, level,
+                                           tex->b.b.last_level + 1);
+            } else {
+               ret = readback_image_vgpu9(svga, surf, st->slice + i, level);
+            }
          }
-      }
-      svga->hud.num_readbacks++;
-      SVGA_STATS_COUNT_INC(sws, SVGA_STATS_COUNT_TEXREADBACK);
+         svga->hud.num_readbacks++;
+         SVGA_STATS_COUNT_INC(sws, SVGA_STATS_COUNT_TEXREADBACK);
 
-      assert(ret == PIPE_OK);
-      (void) ret;
+         assert(ret == PIPE_OK);
+         (void) ret;
 
-      svga_context_flush(svga, NULL);
+         svga_context_flush(svga, NULL);
+      }
       /*
        * Note: if PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE were specified
        * we could potentially clear the flag for all faces/layers/mips.
@@ -694,6 +696,15 @@ svga_texture_surface_unmap(struct svga_context *svga,
          ret = SVGA3D_BindGBSurface(swc, surf);
          assert(ret == PIPE_OK);
       }
+      if (swc->force_coherent) {
+         ret = SVGA3D_UpdateGBSurface(swc, surf);
+         if (ret != PIPE_OK) {
+            /* flush and retry */
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_UpdateGBSurface(swc, surf);
+            assert(ret == PIPE_OK);
+         }
+      }
    }
 }
 
@@ -816,19 +827,22 @@ svga_texture_transfer_unmap_direct(struct svga_context *svga,
                       box.x, box.y, box.z,
                       box.w, box.h, box.d);
 
-      if (svga_have_vgpu10(svga)) {
-         unsigned i;
+      if (!svga->swc->force_coherent || tex->imported) {
+         if (svga_have_vgpu10(svga)) {
+            unsigned i;
 
-         for (i = 0; i < nlayers; i++) {
-            ret = update_image_vgpu10(svga, surf, &box,
-                                      st->slice + i, transfer->level,
-                                      tex->b.b.last_level + 1);
+            for (i = 0; i < nlayers; i++) {
+               ret = update_image_vgpu10(svga, surf, &box,
+                                         st->slice + i, transfer->level,
+                                         tex->b.b.last_level + 1);
+               assert(ret == PIPE_OK);
+            }
+         } else {
+            assert(nlayers == 1);
+            ret = update_image_vgpu9(svga, surf, &box, st->slice,
+                                     transfer->level);
             assert(ret == PIPE_OK);
          }
-      } else {
-         assert(nlayers == 1);
-         ret = update_image_vgpu9(svga, surf, &box, st->slice, transfer->level);
-         assert(ret == PIPE_OK);
       }
       (void) ret;
    }
diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h
index 174b5f3b78f..ee39db3bbbc 100644
--- a/src/gallium/drivers/svga/svga_winsys.h
+++ b/src/gallium/drivers/svga/svga_winsys.h
@@ -385,6 +385,7 @@ struct svga_winsys_context
     **/
 
    boolean have_gb_objects;
+   boolean force_coherent;
 
    /**
     * Map a guest-backed surface.
diff --git a/src/gallium/winsys/svga/drm/vmw_context.c b/src/gallium/winsys/svga/drm/vmw_context.c
index d073cd4859f..8b82a9f90d3 100644
--- a/src/gallium/winsys/svga/drm/vmw_context.c
+++ b/src/gallium/winsys/svga/drm/vmw_context.c
@@ -852,6 +852,7 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
    vswc->fctx = debug_flush_ctx_create(TRUE, VMW_DEBUG_FLUSH_STACK);
 #endif
 
+   vswc->base.force_coherent = vws->force_coherent;
    return &vswc->base;
 
 out_no_hash:
diff --git a/src/gallium/winsys/svga/drm/vmw_screen.c b/src/gallium/winsys/svga/drm/vmw_screen.c
index 56294fec60e..e3440bfd957 100644
--- a/src/gallium/winsys/svga/drm/vmw_screen.c
+++ b/src/gallium/winsys/svga/drm/vmw_screen.c
@@ -90,12 +90,12 @@ vmw_winsys_create( int fd )
    vws->device = stat_buf.st_rdev;
    vws->open_count = 1;
    vws->ioctl.drm_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
-   vws->base.have_gb_dma = TRUE;
-   vws->base.need_to_rebind_resources = FALSE;
-
+   vws->force_coherent = FALSE;
    if (!vmw_ioctl_init(vws))
       goto out_no_ioctl;
 
+   vws->base.have_gb_dma = !vws->force_coherent;
+   vws->base.need_to_rebind_resources = FALSE;
    vws->base.have_transfer_from_buffer_cmd = vws->base.have_vgpu10;
    vws->fence_ops = vmw_fence_ops_create(vws);
    if (!vws->fence_ops)
diff --git a/src/gallium/winsys/svga/drm/vmw_screen.h b/src/gallium/winsys/svga/drm/vmw_screen.h
index cb34fec48e7..e0b1bb33bc4 100644
--- a/src/gallium/winsys/svga/drm/vmw_screen.h
+++ b/src/gallium/winsys/svga/drm/vmw_screen.h
@@ -104,6 +104,8 @@ struct vmw_winsys_screen
 
    cnd_t cs_cond;
    mtx_t cs_mutex;
+
+   boolean force_coherent;
 };
 
 
diff --git a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c
index 3b14f1d3513..c7310dc7eb4 100644
--- a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c
+++ b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c
@@ -243,6 +243,9 @@ vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws,
       if (usage & SVGA_SURFACE_USAGE_SHARED)
          req->base.drm_surface_flags |= drm_vmw_surface_flag_shareable;
 
+      if (vws->force_coherent)
+         req->base.drm_surface_flags |= drm_vmw_surface_flag_coherent;
+
       req->base.drm_surface_flags |= drm_vmw_surface_flag_create_buffer;
       req->base.base_size.width = size.width;
       req->base.base_size.height = size.height;
@@ -969,6 +972,7 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
    drmVersionPtr version;
    boolean drm_gb_capable;
    boolean have_drm_2_5;
+   boolean have_drm_2_16;
    const char *getenv_val;
 
    VMW_FUNC;
@@ -985,6 +989,8 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
       (version->version_major == 2 && version->version_minor > 8);
    vws->ioctl.have_drm_2_15 = version->version_major > 2 ||
       (version->version_major == 2 && version->version_minor > 14);
+   have_drm_2_16 = version->version_major > 2 ||
+      (version->version_major == 2 && version->version_minor > 15);
 
    vws->ioctl.drm_execbuf_version = vws->ioctl.have_drm_2_9 ? 2 : 1;
 
@@ -1108,6 +1114,12 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
          vws->ioctl.num_cap_3d = size / sizeof(uint32_t);
       else
          vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
+
+      if (have_drm_2_16) {
+         getenv_val = getenv("SVGA_FORCE_COHERENT");
+         if (getenv_val && strcmp(getenv_val, "0") != 0)
+            vws->force_coherent = TRUE;
+      }
    } else {
       vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
 
-- 
2.20.1



More information about the mesa-dev mailing list