From 47afc5eed76f12ec38f94f0069c4695c9fe78889 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 4 Apr 2019 10:58:19 +0200 Subject: [PATCH] svga: Add an environment variable to force coherent surface memory 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 Reviewed-by: Brian Paul --- .../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.30.2