diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c index f955b7c624b..2b559e58468 100644 --- a/src/gallium/drivers/virgl/virgl_buffer.c +++ b/src/gallium/drivers/virgl/virgl_buffer.c @@ -38,33 +38,11 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx, struct virgl_screen *vs = virgl_screen(ctx->screen); struct virgl_resource *vbuf = virgl_resource(resource); struct virgl_transfer *trans; - bool readback; - bool flush = false; trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource, &vbuf->metadata, level, usage, box); - flush = virgl_res_needs_flush(vctx, trans); - if (flush) - ctx->flush(ctx, NULL, 0); - - readback = virgl_res_needs_readback(vctx, vbuf, usage, 0); - if (readback) - vs->vws->transfer_get(vs->vws, vbuf->hw_res, box, trans->base.stride, - trans->l_stride, trans->offset, level); - - /* XXX Consider - * - * glBufferSubData(GL_ARRAY_BUFFER, 0, 12, data1); - * glDrawArrays(..); - * glFlush(); - * glBufferSubData(GL_ARRAY_BUFFER, 0, 12, data2) - * - * readback and flush are both false in the second glBufferSubData call. - * The draw call might end up seeing data2. - */ - if (readback || flush) - vs->vws->resource_wait(vs->vws, vbuf->hw_res); + virgl_resource_transfer_prepare(vctx, trans); trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res); if (!trans->hw_res_map) { diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index 5d1ee234ea2..07ae20177bf 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -38,8 +38,8 @@ * cmdbuf has no command that accesses the region (XXX we cannot just check * for overlapping transfers) */ -bool virgl_res_needs_flush(struct virgl_context *vctx, - struct virgl_transfer *trans) +static bool virgl_res_needs_flush(struct virgl_context *vctx, + struct virgl_transfer *trans) { struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; struct virgl_resource *res = virgl_resource(trans->base.resource); @@ -89,9 +89,9 @@ bool virgl_res_needs_flush(struct virgl_context *vctx, * PIPE_TRANSFER_READ becomes irrelevant. PIPE_TRANSFER_UNSYNCHRONIZED and * PIPE_TRANSFER_FLUSH_EXPLICIT are also irrelevant. */ -bool virgl_res_needs_readback(struct virgl_context *vctx, - struct virgl_resource *res, - unsigned usage, unsigned level) +static bool virgl_res_needs_readback(struct virgl_context *vctx, + struct virgl_resource *res, + unsigned usage, unsigned level) { if (usage & (PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)) @@ -103,6 +103,45 @@ bool virgl_res_needs_readback(struct virgl_context *vctx, return true; } +void +virgl_resource_transfer_prepare(struct virgl_context *vctx, + struct virgl_transfer *xfer) +{ + struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; + struct virgl_resource *res = virgl_resource(xfer->base.resource); + bool flush; + bool readback; + bool wait; + + flush = virgl_res_needs_flush(vctx, xfer); + readback = virgl_res_needs_readback(vctx, res, xfer->base.usage, + xfer->base.level); + + /* XXX This is incorrect. Consider + * + * glTexImage2D(..., data1); + * glDrawArrays(); + * glFlush(); + * glTexImage2D(..., data2); + * + * readback and flush are both false in the second glTexImage2D call. The + * draw call might end up seeing data2. Same applies to buffers with + * glBufferSubData. + */ + wait = flush || readback; + + if (flush) + vctx->base.flush(&vctx->base, NULL, 0); + + if (readback) { + vws->transfer_get(vws, res->hw_res, &xfer->base.box, xfer->base.stride, + xfer->l_stride, xfer->offset, xfer->base.level); + } + + if (wait) + vws->resource_wait(vws, res->hw_res); +} + static struct pipe_resource *virgl_resource_create(struct pipe_screen *screen, const struct pipe_resource *templ) { diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h index 380e145564a..fda795b6b5e 100644 --- a/src/gallium/drivers/virgl/virgl_resource.h +++ b/src/gallium/drivers/virgl/virgl_resource.h @@ -117,11 +117,9 @@ static inline unsigned pipe_to_virgl_bind(const struct virgl_screen *vs, unsigne return outbind; } -bool virgl_res_needs_flush(struct virgl_context *vctx, - struct virgl_transfer *transfer); -bool virgl_res_needs_readback(struct virgl_context *vctx, - struct virgl_resource *res, - unsigned usage, unsigned level); +void +virgl_resource_transfer_prepare(struct virgl_context *vctx, + struct virgl_transfer *xfer); void virgl_resource_layout(struct pipe_resource *pt, struct virgl_resource_metadata *metadata); diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c index 53cd038e500..c2bdc3ef9e2 100644 --- a/src/gallium/drivers/virgl/virgl_texture.c +++ b/src/gallium/drivers/virgl/virgl_texture.c @@ -126,7 +126,6 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx, struct virgl_winsys *vws = virgl_screen(ctx->screen)->vws; struct virgl_resource *vtex = virgl_resource(resource); struct virgl_transfer *trans; - bool flush, readback; trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource, &vtex->metadata, level, usage, box); @@ -134,27 +133,7 @@ static void *texture_transfer_map_plain(struct pipe_context *ctx, assert(resource->nr_samples <= 1); - flush = virgl_res_needs_flush(vctx, trans); - if (flush) - ctx->flush(ctx, NULL, 0); - - readback = virgl_res_needs_readback(vctx, vtex, usage, level); - if (readback) - vws->transfer_get(vws, vtex->hw_res, box, trans->base.stride, - trans->l_stride, trans->offset, level); - - /* XXX Consider - * - * glTexImage2D(..., data1); - * glDrawArrays(); - * glFlush(); - * glTexImage2D(..., data2); - * - * readback and flush are both false in the second glTexImage2D call. The - * draw call might end up seeing data2. - */ - if (readback || flush) - vws->resource_wait(vws, vtex->hw_res); + virgl_resource_transfer_prepare(vctx, trans); trans->hw_res_map = vws->resource_map(vws, vtex->hw_res); if (!trans->hw_res_map) {