diff options
author | Thomas Hellstrom <[email protected]> | 2020-03-28 18:02:25 +0100 |
---|---|---|
committer | Eric Engestrom <[email protected]> | 2020-04-01 18:05:29 +0200 |
commit | 5e85ed86eb72c45741bd3f0ae32c04e8bd54b381 (patch) | |
tree | 3375f179ccb797b1ed9ba88b822facba5bfc9d49 | |
parent | 9c8dab082f8564ce643104287a4533a2f470069b (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 <[email protected]>
Reviewed-by: Neha Bhende <[email protected]>
Reviewed-by: Brian Paul <[email protected]>
Reviewed-by: Reviewed-by: Roland Scheidegger <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4399>
(cherry picked from commit 46fdc288fb52345134fd9aacd6d7ff71c7b747bb)
-rw-r--r-- | .pick_status.json | 2 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_buffer.h | 18 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_resource_texture.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_winsys.h | 7 | ||||
-rw-r--r-- | src/gallium/winsys/svga/drm/vmw_surface.c | 10 | ||||
-rw-r--r-- | src/gallium/winsys/svga/drm/vmw_surface.h | 5 |
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, |