From: Chia-I Wu Date: Mon, 17 Jun 2019 16:53:48 +0000 (-0700) Subject: virgl: fix sync issue regarding discard/unsync transfers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=98eda99ab88b8a5bcf5da5daa7ca4edbf34592fd;p=mesa.git virgl: fix sync issue regarding discard/unsync transfers GL_MAP_INVALIDATE_BUFFER_BIT cannot be treated as GL_MAP_INVALIDATE_RANGE_BIT naively. When we run into ptr = glMapBufferRange(buf, 0, size, GL_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT); memcpy(ptr, data1, size); glUnmapBuffer(buf); ptr = glMapBufferRange(buf, size, size, GL_WRITE_BIT|GL_MAP_UNSYNCHRONIZED_BIT); memcpy(ptr, data2, size); glUnmapBuffer(buf); we never want data1 to be copy_transfer'ed. Because that would mean that data2 might overwrite valid data. Signed-off-by: Chia-I Wu Reviewed-by: Alexandros Frantzis alexandros.frantzis@collabora.com Fixes: a22c5df0794 ("virgl: Use buffer copy transfers to avoid waiting when mapping") Reviewed-by: Emil Velikov --- diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 9b908afd852..4e585d72490 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -129,11 +129,21 @@ virgl_resource_transfer_prepare(struct virgl_context *vctx, */ if (wait && (xfer->base.usage & (PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE))) { - const bool can_realloc = - (xfer->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) && - virgl_can_rebind_resource(vctx, &res->u.b); - const bool can_staging = vctx->transfer_uploader && - !vctx->transfer_uploader_in_use; + bool can_realloc = false; + bool can_staging = false; + + /* A PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE transfer may be followed by + * PIPE_TRANSFER_UNSYNCHRONIZED transfers to non-overlapping regions. + * It cannot be treated as a PIPE_TRANSFER_DISCARD_RANGE transfer, + * otherwise those following unsynchronized transfers may overwrite + * valid data. + */ + if (xfer->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { + can_realloc = virgl_can_rebind_resource(vctx, &res->u.b); + } else { + can_staging = vctx->transfer_uploader && + !vctx->transfer_uploader_in_use; + } /* discard implies no readback */ assert(!readback);