svga, winsys/svga: Fix persistent memory discard maps
authorThomas Hellstrom <thellstrom@vmware.com>
Sat, 28 Mar 2020 17:02:25 +0000 (18:02 +0100)
committerThomas Hellstrom (VMware) <thomas_os@shipmail.org>
Wed, 1 Apr 2020 06:38:04 +0000 (08:38 +0200)
The kernel driver requires immediate notification using a
BindGBSurface command when a graphics coherent memory resource changes
backing MOB, so that it can start dirty-tracking the new MOB.
Since we always use graphics coherent memory for persistent memory, enqueue
and flush a BindGBSurface commmand at map time rather than at unmap time.
Since we're dealing with persistent memory, It's OK to flush while mapped.

This fixes an issue with gnome-shell / Wayland which uses persistent
memory together with discard maps when we advertise ARB_buffer_storage.
XWayland clients will render incorrectly.

Fixes: 71b43490dd ("svga: Support ARB_buffer_storage")
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Neha Bhende <bhenden@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4399>

src/gallium/drivers/svga/svga_resource_buffer.h
src/gallium/drivers/svga/svga_resource_texture.c
src/gallium/drivers/svga/svga_winsys.h
src/gallium/winsys/svga/drm/vmw_surface.c
src/gallium/winsys/svga/drm/vmw_surface.h

index 35ed35d61ddafaab62c79060416bdcbc4ebca78d..b3559446fa9cd6d01548c29967e3a2ed12fd3450 100644 (file)
@@ -285,7 +285,23 @@ svga_buffer_hw_storage_map(struct svga_context *svga,
    svga->hud.num_buffers_mapped++;
 
    if (sws->have_gb_objects) {
-      return svga->swc->surface_map(svga->swc, sbuf->handle, flags, retry);
+      struct svga_winsys_context *swc = svga->swc;
+      boolean rebind;
+      void *map;
+
+      map = swc->surface_map(swc, sbuf->handle, flags, retry, &rebind);
+      if (map && rebind) {
+         enum pipe_error ret;
+
+         ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_BindGBSurface(swc, sbuf->handle);
+            assert(ret == PIPE_OK);
+         }
+         svga_context_flush(svga, NULL);
+      }
+      return map;
    } else {
       *retry = FALSE;
       return sws->buffer_map(sws, sbuf->hwbuf, flags);
index 4cc58e001c0a0eab6b73f85f76ecb442dbc75219..58b2f64d0b7630eba4abdc661f3098fc5928469b 100644 (file)
@@ -458,10 +458,11 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
    {
       SVGA3dSize baseLevelSize;
       uint8_t *map;
-      boolean retry;
+      boolean retry, rebind;
       unsigned offset, mip_width, mip_height;
+      struct svga_winsys_context *swc = svga->swc;
 
-      map = svga->swc->surface_map(svga->swc, surf, usage, &retry);
+      map = swc->surface_map(swc, surf, usage, &retry, &rebind);
       if (map == NULL && retry) {
          /*
           * At this point, the svga_surfaces_flush() should already have
@@ -469,7 +470,18 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
           */
          svga->hud.surface_write_flushes++;
          svga_context_flush(svga, NULL);
-         map = svga->swc->surface_map(svga->swc, surf, usage, &retry);
+         map = swc->surface_map(swc, surf, usage, &retry, &rebind);
+      }
+      if (map && rebind) {
+         enum pipe_error ret;
+
+         ret = SVGA3D_BindGBSurface(swc, surf);
+         if (ret != PIPE_OK) {
+            svga_context_flush(svga, NULL);
+            ret = SVGA3D_BindGBSurface(swc, surf);
+            assert(ret == PIPE_OK);
+         }
+         svga_context_flush(svga, NULL);
       }
 
       /*
index 30d3f8776d935741277436f79cbb93b471296f27..20096c036c91fa5bc4c7a3a1e2473d732a006f82 100644 (file)
@@ -390,7 +390,11 @@ struct svga_winsys_context
 
    /**
     * Map a guest-backed surface.
+    * \param swc The winsys context
+    * \param surface The surface to map
     * \param flags  bitmaks of PIPE_TRANSFER_x flags
+    * \param retry Whether to flush and retry the map
+    * \param rebind Whether to issue an immediate rebind and flush.
     *
     * The surface_map() member is allowed to fail due to a
     * shortage of command buffer space, if the
@@ -401,7 +405,8 @@ struct svga_winsys_context
    void *
    (*surface_map)(struct svga_winsys_context *swc,
                   struct svga_winsys_surface *surface,
-                  unsigned flags, boolean *retry);
+                  unsigned flags, boolean *retry,
+                  boolean *rebind);
 
    /**
     * Unmap a guest-backed surface.
index 6aa09e11b76762ff582728c47900aa5dcc03b406..698cd11a28e58a0a4a56b98cfc82d94a31146674 100644 (file)
@@ -38,7 +38,8 @@
 void *
 vmw_svga_winsys_surface_map(struct svga_winsys_context *swc,
                             struct svga_winsys_surface *srf,
-                            unsigned flags, boolean *retry)
+                            unsigned flags, boolean *retry,
+                            boolean *rebind)
 {
    struct vmw_svga_winsys_surface *vsrf = vmw_svga_winsys_surface(srf);
    void *data = NULL;
@@ -47,6 +48,7 @@ vmw_svga_winsys_surface_map(struct svga_winsys_context *swc,
    struct vmw_winsys_screen *vws = vsrf->screen;
 
    *retry = FALSE;
+   *rebind = FALSE;
    assert((flags & (PIPE_TRANSFER_READ | PIPE_TRANSFER_WRITE)) != 0);
    mtx_lock(&vsrf->mutex);
 
@@ -121,6 +123,12 @@ vmw_svga_winsys_surface_map(struct svga_winsys_context *swc,
             if (vsrf->buf)
                vmw_svga_winsys_buffer_destroy(&vws->base, vsrf->buf);
             vsrf->buf = vbuf;
+
+            /* Rebind persistent maps immediately */
+            if (flags & PIPE_TRANSFER_PERSISTENT) {
+               *rebind = TRUE;
+               vsrf->rebind = FALSE;
+            }
             goto out_mapped;
          } else
             vmw_svga_winsys_buffer_destroy(&vws->base, vbuf);
index b1a1ce746b32b13d0e3921d1d253bb529dc6d478..ab75fed5f97151a7a9b2b30668e7b430d5b8bdd5 100644 (file)
@@ -88,8 +88,9 @@ vmw_svga_winsys_surface_reference(struct vmw_svga_winsys_surface **pdst,
                                   struct vmw_svga_winsys_surface *src);
 void *
 vmw_svga_winsys_surface_map(struct svga_winsys_context *swc,
-                           struct svga_winsys_surface *srf,
-                           unsigned flags, boolean *retry);
+                            struct svga_winsys_surface *srf,
+                            unsigned flags, boolean *retry,
+                            boolean *rebind);
 void
 vmw_svga_winsys_surface_unmap(struct svga_winsys_context *swc,
                               struct svga_winsys_surface *srf,