freedreno: keep track of buffer valid ranges
authorIlia Mirkin <imirkin@alum.mit.edu>
Fri, 3 Apr 2015 06:15:17 +0000 (02:15 -0400)
committerRob Clark <robclark@freedesktop.org>
Sun, 5 Apr 2015 20:36:35 +0000 (16:36 -0400)
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 <imirkin@alum.mit.edu>
src/gallium/drivers/freedreno/freedreno_resource.c
src/gallium/drivers/freedreno/freedreno_resource.h

index 000d1c210af47b92c3fe774a3207a5494a3be14b..6dc4a5635652ca20a4132b2f5947ae99d313bf70 100644 (file)
@@ -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;
index 1539fc9ad1a86e2169a7af9e72e571348e4bc4ad..a2a540ce5069cf31824857a66d62beaa66953094 100644 (file)
@@ -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;
 };