From bde2045fa247b4d1de98a3bc7585d1b60f9b58b7 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 3 Apr 2015 02:15:17 -0400 Subject: [PATCH] freedreno: keep track of buffer valid ranges Copies nouveau_buffer and radeon_buffer. This allows a write to proceed to an uninitialized part of a buffer even when the GPU is using the previously-initialized portions. Signed-off-by: Ilia Mirkin --- src/gallium/drivers/freedreno/freedreno_resource.c | 24 ++++++++++++++++++++++ src/gallium/drivers/freedreno/freedreno_resource.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 000d1c21..6dc4a56 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -59,12 +59,19 @@ realloc_bo(struct fd_resource *rsc, uint32_t size) rsc->timestamp = 0; rsc->dirty = rsc->reading = false; list_delinit(&rsc->list); + util_range_set_empty(&rsc->valid_buffer_range); } static void fd_resource_transfer_flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, const struct pipe_box *box) { + struct fd_resource *rsc = fd_resource(ptrans->resource); + + if (ptrans->resource->target == PIPE_BUFFER) + util_range_add(&rsc->valid_buffer_range, + ptrans->box.x + box->x, + ptrans->box.x + box->x + box->width); } static void @@ -75,6 +82,11 @@ fd_resource_transfer_unmap(struct pipe_context *pctx, struct fd_resource *rsc = fd_resource(ptrans->resource); if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) fd_bo_cpu_fini(rsc->bo); + + util_range_add(&rsc->valid_buffer_range, + ptrans->box.x, + ptrans->box.x + ptrans->box.width); + pipe_resource_reference(&ptrans->resource, NULL); util_slab_free(&ctx->transfer_pool, ptrans); } @@ -120,6 +132,13 @@ fd_resource_transfer_map(struct pipe_context *pctx, if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { realloc_bo(rsc, fd_bo_size(rsc->bo)); + } else if ((usage & PIPE_TRANSFER_WRITE) && + prsc->target == PIPE_BUFFER && + !util_ranges_intersect(&rsc->valid_buffer_range, + box->x, box->x + box->width)) { + /* We are trying to write to a previously uninitialized range. No need + * to wait. + */ } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { /* If the GPU is writing to the resource, or if it is reading from the * resource and we're trying to write to it, flush the renders. @@ -172,6 +191,7 @@ fd_resource_destroy(struct pipe_screen *pscreen, if (rsc->bo) fd_bo_del(rsc->bo); list_delinit(&rsc->list); + util_range_destroy(&rsc->valid_buffer_range); FREE(rsc); } @@ -282,6 +302,8 @@ fd_resource_create(struct pipe_screen *pscreen, list_inithead(&rsc->list); prsc->screen = pscreen; + util_range_init(&rsc->valid_buffer_range); + rsc->base.vtbl = &fd_resource_vtbl; rsc->cpp = util_format_get_blocksize(tmpl->format); @@ -346,6 +368,8 @@ fd_resource_from_handle(struct pipe_screen *pscreen, list_inithead(&rsc->list); prsc->screen = pscreen; + util_range_init(&rsc->valid_buffer_range); + rsc->bo = fd_screen_bo_from_handle(pscreen, handle, &slice->pitch); if (!rsc->bo) goto fail; diff --git a/src/gallium/drivers/freedreno/freedreno_resource.h b/src/gallium/drivers/freedreno/freedreno_resource.h index 1539fc9..a2a540c 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.h +++ b/src/gallium/drivers/freedreno/freedreno_resource.h @@ -30,6 +30,7 @@ #define FREEDRENO_RESOURCE_H_ #include "util/u_double_list.h" +#include "util/u_range.h" #include "util/u_transfer.h" #include "freedreno_util.h" @@ -68,6 +69,8 @@ struct fd_resource { struct fd_resource_slice slices[MAX_MIP_LEVELS]; uint32_t timestamp; bool dirty, reading; + /* buffer range that has been initialized */ + struct util_range valid_buffer_range; struct list_head list; }; -- 2.7.4