From db77573d7bae90e77cfffde7c5bc9b65dc8b7fc2 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Mon, 3 Dec 2018 08:50:48 -0800 Subject: [PATCH] virgl: modify how we handle GL_MAP_FLUSH_EXPLICIT_BIT Previously, we ignored the the glUnmap(..) operation and flushed before we flush the cbuf. Now, let's just flush the data when we unmap. Neither method is optimal, for example: glMapBufferRange(.., 0, 100, GL_MAP_FLUSH_EXPLICIT_BIT) glFlushMappedBufferRange(.., 25, 30) glFlushMappedBufferRange(.., 65, 70) We'll end up flushing 25 --> 70. Maybe we can fix this later. v2: Add fixme comment in the code (Elie) Reviewed-by: Elie Tournier --- src/gallium/drivers/virgl/virgl_buffer.c | 46 +++++++++++----------- src/gallium/drivers/virgl/virgl_context.c | 34 +--------------- src/gallium/drivers/virgl/virgl_context.h | 1 - src/gallium/drivers/virgl/virgl_resource.h | 13 ------ 4 files changed, 25 insertions(+), 69 deletions(-) diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c index 54a82964691..bdbb3517826 100644 --- a/src/gallium/drivers/virgl/virgl_buffer.c +++ b/src/gallium/drivers/virgl/virgl_buffer.c @@ -33,7 +33,6 @@ static void virgl_buffer_destroy(struct pipe_screen *screen, struct virgl_screen *vs = virgl_screen(screen); struct virgl_buffer *vbuf = virgl_buffer(buf); - util_range_destroy(&vbuf->valid_buffer_range); vs->vws->resource_unref(vs->vws, vbuf->base.hw_res); FREE(vbuf); } @@ -53,7 +52,7 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx, bool readback; bool doflushwait = false; - if ((usage & PIPE_TRANSFER_READ) && (vbuf->on_list == TRUE)) + if (usage & PIPE_TRANSFER_READ) doflushwait = true; else doflushwait = virgl_res_needs_flush_wait(vctx, &vbuf->base, usage); @@ -92,13 +91,19 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx, struct virgl_buffer *vbuf = virgl_buffer(transfer->resource); if (trans->base.usage & PIPE_TRANSFER_WRITE) { - if (!(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { - struct virgl_screen *vs = virgl_screen(ctx->screen); - vctx->num_transfers++; - vs->vws->transfer_put(vs->vws, vbuf->base.hw_res, - &transfer->box, trans->base.stride, trans->l_stride, trans->offset, transfer->level); - + struct virgl_screen *vs = virgl_screen(ctx->screen); + if (transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) { + transfer->box.x += trans->range.start; + transfer->box.width = trans->range.end - trans->range.start; + trans->offset = transfer->box.x; } + + vctx->num_transfers++; + vs->vws->transfer_put(vs->vws, vbuf->base.hw_res, + &transfer->box, trans->base.stride, + trans->l_stride, trans->offset, + transfer->level); + } virgl_resource_destroy_transfer(vctx, trans); @@ -108,20 +113,19 @@ static void virgl_buffer_transfer_flush_region(struct pipe_context *ctx, struct pipe_transfer *transfer, const struct pipe_box *box) { - struct virgl_context *vctx = virgl_context(ctx); struct virgl_buffer *vbuf = virgl_buffer(transfer->resource); + struct virgl_transfer *trans = virgl_transfer(transfer); - if (!vbuf->on_list) { - struct pipe_resource *res = NULL; - - list_addtail(&vbuf->flush_list, &vctx->to_flush_bufs); - vbuf->on_list = TRUE; - pipe_resource_reference(&res, &vbuf->base.u.b); - } - - util_range_add(&vbuf->valid_buffer_range, transfer->box.x + box->x, - transfer->box.x + box->x + box->width); - + /* + * FIXME: This is not optimal. For example, + * + * glMapBufferRange(.., 0, 100, GL_MAP_FLUSH_EXPLICIT_BIT) + * glFlushMappedBufferRange(.., 25, 30) + * glFlushMappedBufferRange(.., 65, 70) + * + * We'll end up flushing 25 --> 70. + */ + util_range_add(&trans->range, box->x, box->x + box->width); vbuf->base.clean = FALSE; } @@ -145,7 +149,6 @@ struct pipe_resource *virgl_buffer_create(struct virgl_screen *vs, buf->base.u.b.screen = &vs->base; buf->base.u.vtbl = &virgl_buffer_vtbl; pipe_reference_init(&buf->base.u.b.reference, 1); - util_range_init(&buf->valid_buffer_range); virgl_resource_layout(&buf->base.u.b, &buf->metadata); vbind = pipe_to_virgl_bind(template->bind); @@ -155,6 +158,5 @@ struct pipe_resource *virgl_buffer_create(struct virgl_screen *vs, template->width0, 1, 1, 1, 0, 0, buf->metadata.total_size); - util_range_set_empty(&buf->valid_buffer_range); return &buf->base.u.b; } diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index 7b6845df1d8..bafec289cc7 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -60,29 +60,6 @@ uint32_t virgl_object_assign_handle(void) return ++next_handle; } -static void virgl_buffer_flush(struct virgl_context *vctx, - struct virgl_buffer *vbuf) -{ - struct virgl_screen *rs = virgl_screen(vctx->base.screen); - struct pipe_box box; - - assert(vbuf->on_list); - - box.height = 1; - box.depth = 1; - box.y = 0; - box.z = 0; - - box.x = vbuf->valid_buffer_range.start; - box.width = MIN2(vbuf->valid_buffer_range.end - vbuf->valid_buffer_range.start, vbuf->base.u.b.width0); - - vctx->num_transfers++; - rs->vws->transfer_put(rs->vws, vbuf->base.hw_res, - &box, 0, 0, box.x, 0); - - util_range_set_empty(&vbuf->valid_buffer_range); -} - static void virgl_attach_res_framebuffer(struct virgl_context *vctx) { struct virgl_winsys *vws = virgl_screen(vctx->base.screen)->vws; @@ -774,19 +751,11 @@ static void virgl_flush_from_st(struct pipe_context *ctx, enum pipe_flush_flags flags) { struct virgl_context *vctx = virgl_context(ctx); - struct virgl_buffer *buf, *tmp; + struct virgl_screen *rs = virgl_screen(ctx->screen); if (flags & PIPE_FLUSH_FENCE_FD) vctx->cbuf->needs_out_fence_fd = true; - LIST_FOR_EACH_ENTRY_SAFE(buf, tmp, &vctx->to_flush_bufs, flush_list) { - struct pipe_resource *res = &buf->base.u.b; - virgl_buffer_flush(vctx, buf); - list_del(&buf->flush_list); - buf->on_list = FALSE; - pipe_resource_reference(&res, NULL); - - } virgl_flush_eq(vctx, vctx, fence); if (vctx->cbuf->in_fence_fd != -1) { @@ -1329,7 +1298,6 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen, virgl_init_query_functions(vctx); virgl_init_so_functions(vctx); - list_inithead(&vctx->to_flush_bufs); slab_create_child(&vctx->transfer_pool, &rs->transfer_pool); vctx->primconvert = util_primconvert_create(&vctx->base, rs->caps.caps.v1.prim_mask); diff --git a/src/gallium/drivers/virgl/virgl_context.h b/src/gallium/drivers/virgl/virgl_context.h index 829258d1801..0f51d730985 100644 --- a/src/gallium/drivers/virgl/virgl_context.h +++ b/src/gallium/drivers/virgl/virgl_context.h @@ -75,7 +75,6 @@ struct virgl_context { struct pipe_resource *images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS]; int num_transfers; int num_draws; - struct list_head to_flush_bufs; struct pipe_resource *atomic_buffers[PIPE_MAX_HW_ATOMIC_BUFFERS]; diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h index bc90d3ef82f..6b76bc26d32 100644 --- a/src/gallium/drivers/virgl/virgl_resource.h +++ b/src/gallium/drivers/virgl/virgl_resource.h @@ -52,19 +52,6 @@ struct virgl_resource { struct virgl_buffer { struct virgl_resource base; - - struct list_head flush_list; - boolean on_list; - - /* The buffer range which is initialized (with a write transfer, - * streamout, DMA, or as a random access target). The rest of - * the buffer is considered invalid and can be mapped unsynchronized. - * - * This allows unsychronized mapping of a buffer range which hasn't - * been used yet. It's for applications which forget to use - * the unsynchronized map flag and expect the driver to figure it out. - */ - struct util_range valid_buffer_range; struct virgl_resource_metadata metadata; };