summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2020-03-28 18:02:25 +0100
committerEric Engestrom <eric@engestrom.ch>2020-04-01 18:05:29 +0200
commit5e85ed86eb72c45741bd3f0ae32c04e8bd54b381 (patch)
tree3375f179ccb797b1ed9ba88b822facba5bfc9d49
parent9c8dab082f8564ce643104287a4533a2f470069b (diff)
svga, winsys/svga: Fix persistent memory discard maps
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> (cherry picked from commit 46fdc288fb52345134fd9aacd6d7ff71c7b747bb)
-rw-r--r--.pick_status.json2
-rw-r--r--src/gallium/drivers/svga/svga_resource_buffer.h18
-rw-r--r--src/gallium/drivers/svga/svga_resource_texture.c18
-rw-r--r--src/gallium/drivers/svga/svga_winsys.h7
-rw-r--r--src/gallium/winsys/svga/drm/vmw_surface.c10
-rw-r--r--src/gallium/winsys/svga/drm/vmw_surface.h5
6 files changed, 51 insertions, 9 deletions
diff --git a/.pick_status.json b/.pick_status.json
index e8d093daf1e..f48b048960e 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -148,7 +148,7 @@
"description": "svga, winsys/svga: Fix persistent memory discard maps",
"nominated": true,
"nomination_type": 1,
- "resolution": 0,
+ "resolution": 1,
"master_sha": null,
"because_sha": "71b43490dd04c03d4027230b0939b81ab91650ca"
},
diff --git a/src/gallium/drivers/svga/svga_resource_buffer.h b/src/gallium/drivers/svga/svga_resource_buffer.h
index 35ed35d61dd..b3559446fa9 100644
--- a/src/gallium/drivers/svga/svga_resource_buffer.h
+++ b/src/gallium/drivers/svga/svga_resource_buffer.h
@@ -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);
diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c
index 4cc58e001c0..58b2f64d0b7 100644
--- a/src/gallium/drivers/svga/svga_resource_texture.c
+++ b/src/gallium/drivers/svga/svga_resource_texture.c
@@ -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);
}
/*
diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h
index 30d3f8776d9..20096c036c9 100644
--- a/src/gallium/drivers/svga/svga_winsys.h
+++ b/src/gallium/drivers/svga/svga_winsys.h
@@ -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.
diff --git a/src/gallium/winsys/svga/drm/vmw_surface.c b/src/gallium/winsys/svga/drm/vmw_surface.c
index 6aa09e11b76..698cd11a28e 100644
--- a/src/gallium/winsys/svga/drm/vmw_surface.c
+++ b/src/gallium/winsys/svga/drm/vmw_surface.c
@@ -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);
diff --git a/src/gallium/winsys/svga/drm/vmw_surface.h b/src/gallium/winsys/svga/drm/vmw_surface.h
index b1a1ce746b3..ab75fed5f97 100644
--- a/src/gallium/winsys/svga/drm/vmw_surface.h
+++ b/src/gallium/winsys/svga/drm/vmw_surface.h
@@ -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,