[Mesa-dev] [PATCH] etnaviv: keep track of buffer valid ranges

Christian Gmeiner christian.gmeiner at gmail.com
Thu Oct 19 05:59:27 UTC 2017


This allows a write to proceed to an uninitialized part of a buffer
even when the GPU is using the previously-initialized portions.
Same is done for freedreno, nouveau and radeon.

Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
---
 src/gallium/drivers/etnaviv/etnaviv_resource.c |  3 +++
 src/gallium/drivers/etnaviv/etnaviv_resource.h |  4 ++++
 src/gallium/drivers/etnaviv/etnaviv_transfer.c | 22 +++++++++++++++++++---
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index d6cccd2dbb..4eb49bf936 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -268,6 +268,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
 
    pipe_reference_init(&rsc->base.reference, 1);
    list_inithead(&rsc->list);
+   util_range_init(&rsc->valid_buffer_range);
 
    size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale);
 
@@ -458,6 +459,7 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
    if (rsc->scanout)
       renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro);
 
+   util_range_destroy(&rsc->valid_buffer_range);
    list_delinit(&rsc->list);
 
    pipe_resource_reference(&rsc->texture, NULL);
@@ -494,6 +496,7 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
 
    pipe_reference_init(&prsc->reference, 1);
    list_inithead(&rsc->list);
+   util_range_init(&rsc->valid_buffer_range);
    prsc->screen = pscreen;
 
    rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
index 0b135e2373..705c1d1af6 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -31,6 +31,7 @@
 #include "etnaviv_tiling.h"
 #include "pipe/p_state.h"
 #include "util/list.h"
+#include "util/u_range.h"
 
 struct pipe_screen;
 
@@ -73,6 +74,9 @@ struct etna_resource {
 
    struct etna_resource_level levels[ETNA_NUM_LOD];
 
+   /* buffer range that has been initialized */
+   struct util_range valid_buffer_range;
+
    /* When we are rendering to a texture, we need a differently tiled resource */
    struct pipe_resource *texture;
    /*
diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
index 6c1edd4835..33f3b058fa 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
@@ -126,6 +126,10 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans)
    if (!trans->rsc && !(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED))
       etna_bo_cpu_fini(rsc->bo);
 
+   util_range_add(&rsc->valid_buffer_range,
+                  ptrans->box.x,
+                  ptrans->box.x + ptrans->box.width);
+
    pipe_resource_reference(&trans->rsc, NULL);
    pipe_resource_reference(&ptrans->resource, NULL);
    slab_free(&ctx->transfer_pool, trans);
@@ -283,7 +287,14 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
     * Pull resources into the CPU domain. Only skipped for unsynchronized
     * transfers without a temporary resource.
     */
-   if (trans->rsc || !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
+   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 (trans->rsc || !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
       uint32_t prep_flags = 0;
 
       if (usage & PIPE_TRANSFER_READ)
@@ -360,10 +371,15 @@ fail_prep:
 
 static void
 etna_transfer_flush_region(struct pipe_context *pctx,
-                           struct pipe_transfer *transfer,
+                           struct pipe_transfer *ptrans,
                            const struct pipe_box *box)
 {
-   /* NOOP for now */
+   struct etna_resource *rsc = etna_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);
 }
 
 void
-- 
2.13.6



More information about the mesa-dev mailing list