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 <olvaffe@gmail.com>
Reviewed-by: Alexandros Frantzis alexandros.frantzis@collabora.com
Fixes: a22c5df079 ("virgl: Use buffer copy transfers to avoid waiting when mapping")
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
This commit is contained in:
Chia-I Wu 2019-06-17 09:53:48 -07:00
parent 2a717f300b
commit 98eda99ab8

View file

@ -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);