Discussion:
[Mesa-dev] [PATCH 10/12] virgl: modify how we handle GL_MAP_FLUSH_EXPLICIT_BIT
Gurchetan Singh
2018-12-07 01:20:42 UTC
Permalink
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.
---
src/gallium/drivers/virgl/virgl_buffer.c | 37 +++++++++-------------
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, 16 insertions(+), 69 deletions(-)

diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c
index d5d728735e..ae828446ec 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->base.layer_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->base.layer_stride, trans->offset,
+ transfer->level);
+
}

virgl_resource_destroy_transfer(vctx, trans);
@@ -108,20 +113,10 @@ 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);
-
+ util_range_add(&trans->range, box->x, box->x + box->width);
vbuf->base.clean = FALSE;
}

@@ -145,7 +140,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 +149,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 90a9429fa5..a92fd6115a 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -54,29 +54,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;
@@ -736,19 +713,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) {
@@ -1291,7 +1260,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 4a6cc09ee5..65166154e4 100644
--- a/src/gallium/drivers/virgl/virgl_context.h
+++ b/src/gallium/drivers/virgl/virgl_context.h
@@ -73,7 +73,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 fa985494a7..2e2fa186d1 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;
};
--
2.18.1
Gurchetan Singh
2018-12-07 01:20:43 UTC
Permalink
A resource is just a buffer with some metadata.
---
src/gallium/drivers/virgl/virgl_buffer.c | 51 +++++++------
src/gallium/drivers/virgl/virgl_context.c | 5 +-
src/gallium/drivers/virgl/virgl_resource.h | 21 +-----
src/gallium/drivers/virgl/virgl_texture.c | 85 +++++++++++-----------
4 files changed, 71 insertions(+), 91 deletions(-)

diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c
index ae828446ec..4c545be63a 100644
--- a/src/gallium/drivers/virgl/virgl_buffer.c
+++ b/src/gallium/drivers/virgl/virgl_buffer.c
@@ -31,9 +31,9 @@ static void virgl_buffer_destroy(struct pipe_screen *screen,
struct pipe_resource *buf)
{
struct virgl_screen *vs = virgl_screen(screen);
- struct virgl_buffer *vbuf = virgl_buffer(buf);
+ struct virgl_resource *vbuf = virgl_resource(buf);

- vs->vws->resource_unref(vs->vws, vbuf->base.hw_res);
+ vs->vws->resource_unref(vs->vws, vbuf->hw_res);
FREE(vbuf);
}

@@ -46,7 +46,7 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx,
{
struct virgl_context *vctx = virgl_context(ctx);
struct virgl_screen *vs = virgl_screen(ctx->screen);
- struct virgl_buffer *vbuf = virgl_buffer(resource);
+ struct virgl_resource *vbuf = virgl_resource(resource);
struct virgl_transfer *trans;
void *ptr;
bool readback;
@@ -55,7 +55,7 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx,
if (usage & PIPE_TRANSFER_READ)
doflushwait = true;
else
- doflushwait = virgl_res_needs_flush_wait(vctx, &vbuf->base, usage);
+ doflushwait = virgl_res_needs_flush_wait(vctx, vbuf, usage);

if (doflushwait)
ctx->flush(ctx, NULL, 0);
@@ -63,18 +63,18 @@ static void *virgl_buffer_transfer_map(struct pipe_context *ctx,
trans = virgl_resource_create_transfer(ctx, resource, &vbuf->metadata, level,
usage, box);

- readback = virgl_res_needs_readback(vctx, &vbuf->base, usage);
+ readback = virgl_res_needs_readback(vctx, vbuf, usage);
if (readback)
- vs->vws->transfer_get(vs->vws, vbuf->base.hw_res, box, trans->base.stride,
+ vs->vws->transfer_get(vs->vws, vbuf->hw_res, box, trans->base.stride,
trans->base.layer_stride, trans->offset, level);

if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED))
doflushwait = true;

if (doflushwait || readback)
- vs->vws->resource_wait(vs->vws, vbuf->base.hw_res);
+ vs->vws->resource_wait(vs->vws, vbuf->hw_res);

- ptr = vs->vws->resource_map(vs->vws, vbuf->base.hw_res);
+ ptr = vs->vws->resource_map(vs->vws, vbuf->hw_res);
if (!ptr) {
return NULL;
}
@@ -88,7 +88,7 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx,
{
struct virgl_context *vctx = virgl_context(ctx);
struct virgl_transfer *trans = virgl_transfer(transfer);
- struct virgl_buffer *vbuf = virgl_buffer(transfer->resource);
+ struct virgl_resource *vbuf = virgl_resource(transfer->resource);

if (trans->base.usage & PIPE_TRANSFER_WRITE) {
struct virgl_screen *vs = virgl_screen(ctx->screen);
@@ -99,7 +99,7 @@ static void virgl_buffer_transfer_unmap(struct pipe_context *ctx,
}

vctx->num_transfers++;
- vs->vws->transfer_put(vs->vws, vbuf->base.hw_res,
+ vs->vws->transfer_put(vs->vws, vbuf->hw_res,
&transfer->box, trans->base.stride,
trans->base.layer_stride, trans->offset,
transfer->level);
@@ -113,11 +113,11 @@ static void virgl_buffer_transfer_flush_region(struct pipe_context *ctx,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
- struct virgl_buffer *vbuf = virgl_buffer(transfer->resource);
+ struct virgl_resource *vbuf = virgl_resource(transfer->resource);
struct virgl_transfer *trans = virgl_transfer(transfer);

util_range_add(&trans->range, box->x, box->x + box->width);
- vbuf->base.clean = FALSE;
+ vbuf->clean = FALSE;
}

static const struct u_resource_vtbl virgl_buffer_vtbl =
@@ -132,22 +132,21 @@ static const struct u_resource_vtbl virgl_buffer_vtbl =
struct pipe_resource *virgl_buffer_create(struct virgl_screen *vs,
const struct pipe_resource *template)
{
- struct virgl_buffer *buf;
+ struct virgl_resource *buf;
uint32_t vbind;
- buf = CALLOC_STRUCT(virgl_buffer);
- buf->base.clean = TRUE;
- buf->base.u.b = *template;
- buf->base.u.b.screen = &vs->base;
- buf->base.u.vtbl = &virgl_buffer_vtbl;
- pipe_reference_init(&buf->base.u.b.reference, 1);
- virgl_resource_layout(&buf->base.u.b, &buf->metadata);
+ buf = CALLOC_STRUCT(virgl_resource);
+ buf->clean = TRUE;
+ buf->u.b = *template;
+ buf->u.b.screen = &vs->base;
+ buf->u.vtbl = &virgl_buffer_vtbl;
+ pipe_reference_init(&buf->u.b.reference, 1);
+ virgl_resource_layout(&buf->u.b, &buf->metadata);

vbind = pipe_to_virgl_bind(template->bind);

- buf->base.hw_res = vs->vws->resource_create(vs->vws, template->target,
- template->format, vbind,
- template->width0, 1, 1, 1, 0, 0,
- buf->metadata.total_size);
-
- return &buf->base.u.b;
+ buf->hw_res = vs->vws->resource_create(vs->vws, template->target,
+ template->format, vbind,
+ template->width0, 1, 1, 1, 0, 0,
+ buf->metadata.total_size);
+ return &buf->u.b;
}
diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c
index a92fd6115a..6263043b18 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -468,14 +468,13 @@ void virgl_transfer_inline_write(struct pipe_context *ctx,
struct virgl_context *vctx = virgl_context(ctx);
struct virgl_screen *vs = virgl_screen(ctx->screen);
struct virgl_resource *grres = virgl_resource(res);
- struct virgl_buffer *vbuf = virgl_buffer(res);

grres->clean = FALSE;

- if (virgl_res_needs_flush_wait(vctx, &vbuf->base, usage)) {
+ if (virgl_res_needs_flush_wait(vctx, grres, usage)) {
ctx->flush(ctx, NULL, 0);

- vs->vws->resource_wait(vs->vws, vbuf->base.hw_res);
+ vs->vws->resource_wait(vs->vws, grres->hw_res);
}

virgl_encoder_inline_write(vctx, grres, level, usage,
diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h
index 2e2fa186d1..54d01e7a07 100644
--- a/src/gallium/drivers/virgl/virgl_resource.h
+++ b/src/gallium/drivers/virgl/virgl_resource.h
@@ -46,17 +46,8 @@ struct virgl_resource_metadata

struct virgl_resource {
struct u_resource u;
- struct virgl_hw_res *hw_res;
boolean clean;
-};
-
-struct virgl_buffer {
- struct virgl_resource base;
- struct virgl_resource_metadata metadata;
-};
-
-struct virgl_texture {
- struct virgl_resource base;
+ struct virgl_hw_res *hw_res;
struct virgl_resource_metadata metadata;
};

@@ -86,16 +77,6 @@ static inline struct virgl_resource *virgl_resource(struct pipe_resource *r)
return (struct virgl_resource *)r;
}

-static inline struct virgl_buffer *virgl_buffer(struct pipe_resource *r)
-{
- return (struct virgl_buffer *)r;
-}
-
-static inline struct virgl_texture *virgl_texture(struct pipe_resource *r)
-{
- return (struct virgl_texture *)r;
-}
-
static inline struct virgl_transfer *virgl_transfer(struct pipe_transfer *trans)
{
return (struct virgl_transfer *)trans;
diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c
index c576807fd9..a6afeb2293 100644
--- a/src/gallium/drivers/virgl/virgl_texture.c
+++ b/src/gallium/drivers/virgl/virgl_texture.c
@@ -103,19 +103,19 @@ static void *virgl_texture_transfer_map(struct pipe_context *ctx,
{
struct virgl_context *vctx = virgl_context(ctx);
struct virgl_screen *vs = virgl_screen(ctx->screen);
- struct virgl_texture *vtex = virgl_texture(resource);
+ struct virgl_resource *vtex = virgl_resource(resource);
struct virgl_transfer *trans;
void *ptr;
boolean readback = TRUE;
struct virgl_hw_res *hw_res;
bool doflushwait;

- doflushwait = virgl_res_needs_flush_wait(vctx, &vtex->base, usage);
+ doflushwait = virgl_res_needs_flush_wait(vctx, vtex, usage);
if (doflushwait)
ctx->flush(ctx, NULL, 0);

- trans = virgl_resource_create_transfer(ctx, resource, &vtex->metadata, level,
- usage, box);
+ trans = virgl_resource_create_transfer(ctx, resource, &vtex->metadata,
+ level, usage, box);

if (resource->nr_samples > 1) {
struct pipe_resource tmp_resource;
@@ -128,22 +128,22 @@ static void *virgl_texture_transfer_map(struct pipe_context *ctx,
ctx->flush(ctx, NULL, 0);
/* we want to do a resolve blit into the temporary */
hw_res = trans->resolve_tmp->hw_res;
- struct virgl_resource_metadata *data = &((struct virgl_texture*)trans->resolve_tmp)->metadata;
+ struct virgl_resource_metadata *data = &trans->resolve_tmp->metadata;
trans->base.stride = data->stride[level];
trans->base.layer_stride = data->layer_stride[level];
trans->offset = 0;
} else {
- hw_res = vtex->base.hw_res;
+ hw_res = vtex->hw_res;
trans->resolve_tmp = NULL;
}

- readback = virgl_res_needs_readback(vctx, &vtex->base, usage);
+ readback = virgl_res_needs_readback(vctx, vtex, usage);
if (readback)
vs->vws->transfer_get(vs->vws, hw_res, box, trans->base.stride,
trans->base.layer_stride, trans->offset, level);

if (doflushwait || readback)
- vs->vws->resource_wait(vs->vws, vtex->base.hw_res);
+ vs->vws->resource_wait(vs->vws, vtex->hw_res);

ptr = vs->vws->resource_map(vs->vws, hw_res);
if (!ptr) {
@@ -160,14 +160,14 @@ static void virgl_texture_transfer_unmap(struct pipe_context *ctx,
{
struct virgl_context *vctx = virgl_context(ctx);
struct virgl_transfer *trans = virgl_transfer(transfer);
- struct virgl_texture *vtex = virgl_texture(transfer->resource);
+ struct virgl_resource *vtex = virgl_resource(transfer->resource);

if (trans->base.usage & PIPE_TRANSFER_WRITE) {
if (!(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
struct virgl_screen *vs = virgl_screen(ctx->screen);
- vtex->base.clean = FALSE;
+ vtex->clean = FALSE;
vctx->num_transfers++;
- vs->vws->transfer_put(vs->vws, vtex->base.hw_res,
+ vs->vws->transfer_put(vs->vws, vtex->hw_res,
&transfer->box, trans->base.stride,
trans->base.layer_stride, trans->offset,
transfer->level);
@@ -186,18 +186,19 @@ static boolean virgl_texture_get_handle(struct pipe_screen *screen,
struct winsys_handle *whandle)
{
struct virgl_screen *vs = virgl_screen(screen);
- struct virgl_texture *vtex = virgl_texture(ptex);
+ struct virgl_resource *vtex = virgl_resource(ptex);

- return vs->vws->resource_get_handle(vs->vws, vtex->base.hw_res,
- vtex->metadata.stride[0], whandle);
+ return vs->vws->resource_get_handle(vs->vws, vtex->hw_res,
+ vtex->metadata.stride[0],
+ whandle);
}

static void virgl_texture_destroy(struct pipe_screen *screen,
struct pipe_resource *res)
{
struct virgl_screen *vs = virgl_screen(screen);
- struct virgl_texture *vtex = virgl_texture(res);
- vs->vws->resource_unref(vs->vws, vtex->base.hw_res);
+ struct virgl_resource *vtex = virgl_resource(res);
+ vs->vws->resource_unref(vs->vws, vtex->hw_res);
FREE(vtex);
}

@@ -215,43 +216,43 @@ virgl_texture_from_handle(struct virgl_screen *vs,
const struct pipe_resource *template,
struct winsys_handle *whandle)
{
- struct virgl_texture *tex = CALLOC_STRUCT(virgl_texture);
- tex->base.u.b = *template;
- tex->base.u.b.screen = &vs->base;
- pipe_reference_init(&tex->base.u.b.reference, 1);
- tex->base.u.vtbl = &virgl_texture_vtbl;
+ struct virgl_resource *tex = CALLOC_STRUCT(virgl_resource);
+ tex->u.b = *template;
+ tex->u.b.screen = &vs->base;
+ pipe_reference_init(&tex->u.b.reference, 1);
+ tex->u.vtbl = &virgl_texture_vtbl;

- tex->base.hw_res = vs->vws->resource_create_from_handle(vs->vws, whandle);
- return &tex->base.u.b;
+ tex->hw_res = vs->vws->resource_create_from_handle(vs->vws, whandle);
+ return &tex->u.b;
}

struct pipe_resource *virgl_texture_create(struct virgl_screen *vs,
const struct pipe_resource *template)
{
- struct virgl_texture *tex;
+ struct virgl_resource *tex;
unsigned vbind;

- tex = CALLOC_STRUCT(virgl_texture);
- tex->base.clean = TRUE;
- tex->base.u.b = *template;
- tex->base.u.b.screen = &vs->base;
- pipe_reference_init(&tex->base.u.b.reference, 1);
- tex->base.u.vtbl = &virgl_texture_vtbl;
- virgl_resource_layout(&tex->base.u.b, &tex->metadata);
+ tex = CALLOC_STRUCT(virgl_resource);
+ tex->clean = TRUE;
+ tex->u.b = *template;
+ tex->u.b.screen = &vs->base;
+ pipe_reference_init(&tex->u.b.reference, 1);
+ tex->u.vtbl = &virgl_texture_vtbl;
+ virgl_resource_layout(&tex->u.b, &tex->metadata);

vbind = pipe_to_virgl_bind(template->bind);
- tex->base.hw_res = vs->vws->resource_create(vs->vws, template->target,
- template->format, vbind,
- template->width0,
- template->height0,
- template->depth0,
- template->array_size,
- template->last_level,
- template->nr_samples,
- tex->metadata.total_size);
- if (!tex->base.hw_res) {
+ tex->hw_res = vs->vws->resource_create(vs->vws, template->target,
+ template->format, vbind,
+ template->width0,
+ template->height0,
+ template->depth0,
+ template->array_size,
+ template->last_level,
+ template->nr_samples,
+ tex->metadata.total_size);
+ if (!tex->hw_res) {
FREE(tex);
return NULL;
}
- return &tex->base.u.b;
+ return &tex->u.b;
}
--
2.18.1
Gurchetan Singh
2018-12-07 01:20:44 UTC
Permalink
We can remove some duplicated code.
---
src/gallium/drivers/virgl/virgl_buffer.c | 33 +--------
src/gallium/drivers/virgl/virgl_resource.c | 84 +++++++++++++++++++---
src/gallium/drivers/virgl/virgl_resource.h | 16 ++---
src/gallium/drivers/virgl/virgl_texture.c | 70 ++----------------
4 files changed, 89 insertions(+), 114 deletions(-)

diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c
index 4c545be63a..5d446907c3 100644
--- a/src/gallium/drivers/virgl/virgl_buffer.c
+++ b/src/gallium/drivers/virgl/virgl_buffer.c
@@ -27,16 +27,6 @@
#include "virgl_resource.h"
#include "virgl_screen.h"

-static void virgl_buffer_destroy(struct pipe_screen *screen,
- struct pipe_resource *buf)
-{
- struct virgl_screen *vs = virgl_screen(screen);
- struct virgl_resource *vbuf = virgl_resource(buf);
-
- vs->vws->resource_unref(vs->vws, vbuf->hw_res);
- FREE(vbuf);
-}
-
static void *virgl_buffer_transfer_map(struct pipe_context *ctx,
struct pipe_resource *resource,
unsigned level,
@@ -123,30 +113,13 @@ static void virgl_buffer_transfer_flush_region(struct pipe_context *ctx,
static const struct u_resource_vtbl virgl_buffer_vtbl =
{
u_default_resource_get_handle, /* get_handle */
- virgl_buffer_destroy, /* resource_destroy */
+ virgl_resource_destroy, /* resource_destroy */
virgl_buffer_transfer_map, /* transfer_map */
virgl_buffer_transfer_flush_region, /* transfer_flush_region */
virgl_buffer_transfer_unmap, /* transfer_unmap */
};

-struct pipe_resource *virgl_buffer_create(struct virgl_screen *vs,
- const struct pipe_resource *template)
+void virgl_buffer_init(struct virgl_resource *res)
{
- struct virgl_resource *buf;
- uint32_t vbind;
- buf = CALLOC_STRUCT(virgl_resource);
- buf->clean = TRUE;
- buf->u.b = *template;
- buf->u.b.screen = &vs->base;
- buf->u.vtbl = &virgl_buffer_vtbl;
- pipe_reference_init(&buf->u.b.reference, 1);
- virgl_resource_layout(&buf->u.b, &buf->metadata);
-
- vbind = pipe_to_virgl_bind(template->bind);
-
- buf->hw_res = vs->vws->resource_create(vs->vws, template->target,
- template->format, vbind,
- template->width0, 1, 1, 1, 0, 0,
- buf->metadata.total_size);
- return &buf->u.b;
+ res->u.vtbl = &virgl_buffer_vtbl;
}
diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c
index a0b28e1d02..bcfd527abf 100644
--- a/src/gallium/drivers/virgl/virgl_resource.c
+++ b/src/gallium/drivers/virgl/virgl_resource.c
@@ -22,6 +22,7 @@
*/
#include "util/u_format.h"
#include "util/u_inlines.h"
+#include "util/u_memory.h"
#include "virgl_context.h"
#include "virgl_resource.h"
#include "virgl_screen.h"
@@ -56,11 +57,37 @@ bool virgl_res_needs_readback(struct virgl_context *vctx,
static struct pipe_resource *virgl_resource_create(struct pipe_screen *screen,
const struct pipe_resource *templ)
{
- struct virgl_screen *vs = virgl_screen(screen);
- if (templ->target == PIPE_BUFFER)
- return virgl_buffer_create(vs, templ);
- else
- return virgl_texture_create(vs, templ);
+ unsigned vbind;
+ struct virgl_screen *vs = virgl_screen(screen);
+ struct virgl_resource *res = CALLOC_STRUCT(virgl_resource);
+
+ res->clean = TRUE;
+ res->u.b = *templ;
+ res->u.b.screen = &vs->base;
+ pipe_reference_init(&res->u.b.reference, 1);
+ vbind = pipe_to_virgl_bind(templ->bind);
+ virgl_resource_layout(&res->u.b, &res->metadata);
+ res->hw_res = vs->vws->resource_create(vs->vws, templ->target,
+ templ->format, vbind,
+ templ->width0,
+ templ->height0,
+ templ->depth0,
+ templ->array_size,
+ templ->last_level,
+ templ->nr_samples,
+ res->metadata.total_size);
+ if (!res->hw_res) {
+ FREE(res);
+ return NULL;
+ }
+
+ if (templ->target == PIPE_BUFFER)
+ virgl_buffer_init(res);
+ else
+ virgl_texture_init(res);
+
+ return &res->u.b;
+
}

static struct pipe_resource *virgl_resource_from_handle(struct pipe_screen *screen,
@@ -68,11 +95,24 @@ static struct pipe_resource *virgl_resource_from_handle(struct pipe_screen *scre
struct winsys_handle *whandle,
unsigned usage)
{
- struct virgl_screen *vs = virgl_screen(screen);
- if (templ->target == PIPE_BUFFER)
- return NULL;
- else
- return virgl_texture_from_handle(vs, templ, whandle);
+ struct virgl_screen *vs = virgl_screen(screen);
+ if (templ->target == PIPE_BUFFER)
+ return NULL;
+
+ struct virgl_resource *res = CALLOC_STRUCT(virgl_resource);
+ res->u.b = *templ;
+ res->u.b.screen = &vs->base;
+ pipe_reference_init(&res->u.b.reference, 1);
+
+ res->hw_res = vs->vws->resource_create_from_handle(vs->vws, whandle);
+ if (!res->hw_res) {
+ FREE(res);
+ return NULL;
+ }
+
+ virgl_texture_init(res);
+
+ return &res->u.b;
}

void virgl_init_screen_resource_functions(struct pipe_screen *screen)
@@ -203,3 +243,27 @@ void virgl_resource_destroy_transfer(struct virgl_context *vctx,
util_range_destroy(&trans->range);
slab_free(&vctx->transfer_pool, trans);
}
+
+void virgl_resource_destroy(struct pipe_screen *screen,
+ struct pipe_resource *resource)
+{
+ struct virgl_screen *vs = virgl_screen(screen);
+ struct virgl_resource *res = virgl_resource(resource);
+ vs->vws->resource_unref(vs->vws, res->hw_res);
+ FREE(res);
+}
+
+boolean virgl_resource_get_handle(struct pipe_screen *screen,
+ struct pipe_resource *resource,
+ struct winsys_handle *whandle)
+{
+ struct virgl_screen *vs = virgl_screen(screen);
+ struct virgl_resource *res = virgl_resource(resource);
+
+ if (res->u.b.target == PIPE_BUFFER)
+ return FALSE;
+
+ return vs->vws->resource_get_handle(vs->vws, res->hw_res,
+ res->metadata.stride[0],
+ whandle);
+}
diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h
index 54d01e7a07..62e5e22ae8 100644
--- a/src/gallium/drivers/virgl/virgl_resource.h
+++ b/src/gallium/drivers/virgl/virgl_resource.h
@@ -65,12 +65,7 @@ void virgl_init_screen_resource_functions(struct pipe_screen *screen);

void virgl_init_context_resource_functions(struct pipe_context *ctx);

-struct pipe_resource *virgl_texture_create(struct virgl_screen *vs,
- const struct pipe_resource *templ);
-
-struct pipe_resource *virgl_texture_from_handle(struct virgl_screen *vs,
- const struct pipe_resource *templ,
- struct winsys_handle *whandle);
+void virgl_texture_init(struct virgl_resource *res);

static inline struct virgl_resource *virgl_resource(struct pipe_resource *r)
{
@@ -82,8 +77,7 @@ static inline struct virgl_transfer *virgl_transfer(struct pipe_transfer *trans)
return (struct virgl_transfer *)trans;
}

-struct pipe_resource *virgl_buffer_create(struct virgl_screen *vs,
- const struct pipe_resource *templ);
+void virgl_buffer_init(struct virgl_resource *res);

static inline unsigned pipe_to_virgl_bind(unsigned pbind)
{
@@ -135,4 +129,10 @@ virgl_resource_create_transfer(struct pipe_context *ctx,
void virgl_resource_destroy_transfer(struct virgl_context *vctx,
struct virgl_transfer *trans);

+void virgl_resource_destroy(struct pipe_screen *screen,
+ struct pipe_resource *resource);
+
+boolean virgl_resource_get_handle(struct pipe_screen *screen,
+ struct pipe_resource *resource,
+ struct winsys_handle *whandle);
#endif
diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c
index a6afeb2293..0c1a1f8197 100644
--- a/src/gallium/drivers/virgl/virgl_texture.c
+++ b/src/gallium/drivers/virgl/virgl_texture.c
@@ -181,78 +181,16 @@ static void virgl_texture_transfer_unmap(struct pipe_context *ctx,
virgl_resource_destroy_transfer(vctx, trans);
}

-static boolean virgl_texture_get_handle(struct pipe_screen *screen,
- struct pipe_resource *ptex,
- struct winsys_handle *whandle)
-{
- struct virgl_screen *vs = virgl_screen(screen);
- struct virgl_resource *vtex = virgl_resource(ptex);
-
- return vs->vws->resource_get_handle(vs->vws, vtex->hw_res,
- vtex->metadata.stride[0],
- whandle);
-}
-
-static void virgl_texture_destroy(struct pipe_screen *screen,
- struct pipe_resource *res)
-{
- struct virgl_screen *vs = virgl_screen(screen);
- struct virgl_resource *vtex = virgl_resource(res);
- vs->vws->resource_unref(vs->vws, vtex->hw_res);
- FREE(vtex);
-}
-
static const struct u_resource_vtbl virgl_texture_vtbl =
{
- virgl_texture_get_handle, /* get_handle */
- virgl_texture_destroy, /* resource_destroy */
+ virgl_resource_get_handle, /* get_handle */
+ virgl_resource_destroy, /* resource_destroy */
virgl_texture_transfer_map, /* transfer_map */
NULL, /* transfer_flush_region */
virgl_texture_transfer_unmap, /* transfer_unmap */
};

-struct pipe_resource *
-virgl_texture_from_handle(struct virgl_screen *vs,
- const struct pipe_resource *template,
- struct winsys_handle *whandle)
+void virgl_texture_init(struct virgl_resource *res)
{
- struct virgl_resource *tex = CALLOC_STRUCT(virgl_resource);
- tex->u.b = *template;
- tex->u.b.screen = &vs->base;
- pipe_reference_init(&tex->u.b.reference, 1);
- tex->u.vtbl = &virgl_texture_vtbl;
-
- tex->hw_res = vs->vws->resource_create_from_handle(vs->vws, whandle);
- return &tex->u.b;
-}
-
-struct pipe_resource *virgl_texture_create(struct virgl_screen *vs,
- const struct pipe_resource *template)
-{
- struct virgl_resource *tex;
- unsigned vbind;
-
- tex = CALLOC_STRUCT(virgl_resource);
- tex->clean = TRUE;
- tex->u.b = *template;
- tex->u.b.screen = &vs->base;
- pipe_reference_init(&tex->u.b.reference, 1);
- tex->u.vtbl = &virgl_texture_vtbl;
- virgl_resource_layout(&tex->u.b, &tex->metadata);
-
- vbind = pipe_to_virgl_bind(template->bind);
- tex->hw_res = vs->vws->resource_create(vs->vws, template->target,
- template->format, vbind,
- template->width0,
- template->height0,
- template->depth0,
- template->array_size,
- template->last_level,
- template->nr_samples,
- tex->metadata.total_size);
- if (!tex->hw_res) {
- FREE(tex);
- return NULL;
- }
- return &tex->u.b;
+ res->u.vtbl = &virgl_texture_vtbl;
}
--
2.18.1
Gurchetan Singh
2018-12-10 18:17:24 UTC
Permalink
Post by Gurchetan Singh
Previously, we ignored the the glUnmap(..) operation and
flushed before we flush the cbuf. Now, let's just flush
the data when we unmap.
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.
I don't know how to feel about that.
We clearly go against the spec.
We currently know the behavor of this piece of code but in few
months, someone will facing the issue and loose lots of time.
I agree, the problem is the kernel transfer API
(drm_virtgpu_3d_transfer_to_host) doesn't pass usage flags
(PIPE_TRANSFER_FLUSH_EXPLICIT) such that the host can use
GL_MAP_FLUSH_EXPLICIT_BIT. The best method is to use the virgl protocol to
encode the transfer. This series is a self-contained cleanup for that:

https://gitlab.freedesktop.org/gurchetansingh/mesa/tree/optimize-transfers

In the meantime, I'll add big comment.
I would prefer that we fix it now.
If we decide to still upstream that code, we should at least add
a big warning.
Post by Gurchetan Singh
---
src/gallium/drivers/virgl/virgl_buffer.c | 37 +++++++++-------------
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, 16 insertions(+), 69 deletions(-)
diff --git a/src/gallium/drivers/virgl/virgl_buffer.c
b/src/gallium/drivers/virgl/virgl_buffer.c
Post by Gurchetan Singh
index d5d728735e..ae828446ec 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,
Post by Gurchetan Singh
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,
Post by Gurchetan Singh
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);
Post by Gurchetan Singh
@@ -92,13 +91,19 @@ static void virgl_buffer_transfer_unmap(struct
pipe_context *ctx,
Post by Gurchetan Singh
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->base.layer_stride, trans->offset, transfer->level);
Post by Gurchetan Singh
-
+ 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->base.layer_stride, trans->offset,
+ transfer->level);
+
}
virgl_resource_destroy_transfer(vctx, trans);
@@ -108,20 +113,10 @@ static void
virgl_buffer_transfer_flush_region(struct pipe_context *ctx,
Post by Gurchetan Singh
struct pipe_transfer
*transfer,
Post by Gurchetan Singh
const struct pipe_box
*box)
Post by Gurchetan Singh
{
- 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);
-
+ util_range_add(&trans->range, box->x, box->x + box->width);
vbuf->base.clean = FALSE;
}
@@ -145,7 +140,6 @@ struct pipe_resource *virgl_buffer_create(struct
virgl_screen *vs,
Post by Gurchetan Singh
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 +149,5 @@ struct pipe_resource *virgl_buffer_create(struct
virgl_screen *vs,
Post by Gurchetan Singh
template->width0, 1, 1,
1, 0, 0,
buf->metadata.total_size);
Post by Gurchetan Singh
- 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
Post by Gurchetan Singh
index 90a9429fa5..a92fd6115a 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -54,29 +54,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);
Post by Gurchetan Singh
-
- 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;
@@ -736,19 +713,11 @@ static void virgl_flush_from_st(struct
pipe_context *ctx,
Post by Gurchetan Singh
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)
{
Post by Gurchetan Singh
- 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) {
@@ -1291,7 +1260,6 @@ struct pipe_context *virgl_context_create(struct
pipe_screen *pscreen,
Post by Gurchetan Singh
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);
Post by Gurchetan Singh
diff --git a/src/gallium/drivers/virgl/virgl_context.h
b/src/gallium/drivers/virgl/virgl_context.h
Post by Gurchetan Singh
index 4a6cc09ee5..65166154e4 100644
--- a/src/gallium/drivers/virgl/virgl_context.h
+++ b/src/gallium/drivers/virgl/virgl_context.h
@@ -73,7 +73,6 @@ struct virgl_context {
struct pipe_resource
*images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
Post by Gurchetan Singh
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
Post by Gurchetan Singh
index fa985494a7..2e2fa186d1 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.
Post by Gurchetan Singh
- */
- struct util_range valid_buffer_range;
struct virgl_resource_metadata metadata;
};
--
2.18.1
_______________________________________________
mesa-dev mailing list
https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Gurchetan Singh
2018-12-10 18:20:36 UTC
Permalink
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)
---
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 d5d728735e..a20deab549 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->base.layer_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->base.layer_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 90a9429fa5..a92fd6115a 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -54,29 +54,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;
@@ -736,19 +713,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) {
@@ -1291,7 +1260,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 4a6cc09ee5..65166154e4 100644
--- a/src/gallium/drivers/virgl/virgl_context.h
+++ b/src/gallium/drivers/virgl/virgl_context.h
@@ -73,7 +73,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 fa985494a7..2e2fa186d1 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;
};
--
2.18.1
Loading...