summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Gmeiner <[email protected]>2019-09-06 15:13:51 +0200
committerChristian Gmeiner <[email protected]>2019-10-20 09:03:06 +0000
commita6de05a968dafc2f677df86376deb78ddce421e3 (patch)
tree3000988d7c5d50e9ad8d08d3c19d24f617beed87 /src
parenteab6d75066463365fb89f99ad6185e462ecb33ea (diff)
etnaviv: keep track of buffer valid ranges for PIPE_BUFFER
This allows a write to proceed to an uninitialized part of a buffer even when the GPU is using the previously-initialized portions. Such a situation can be triggered with the following API usage example: glBufferSubData(..., offset, size, data1); glDrawArrays(...); // append new vertex data glBufferSubData(..., offset+size, size, data2); glDrawArrays(...); Same is done for freedreno, nouveau and radeon. Signed-off-by: Christian Gmeiner <[email protected]> Reviewed-by: Lucas Stach <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_resource.c4
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_resource.h4
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_transfer.c29
3 files changed, 35 insertions, 2 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index f1e314cb06f..cca8b64d7c6 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -300,6 +300,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
rsc->halign = halign;
pipe_reference_init(&rsc->base.reference, 1);
+ util_range_init(&rsc->valid_buffer_range);
size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale);
@@ -477,6 +478,8 @@ 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);
+
pipe_resource_reference(&rsc->texture, NULL);
pipe_resource_reference(&rsc->render, NULL);
@@ -513,6 +516,7 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
*prsc = *tmpl;
pipe_reference_init(&prsc->reference, 1);
+ 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 64aef18a016..226e444b02a 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -33,6 +33,7 @@
#include "util/list.h"
#include "util/set.h"
#include "util/u_helpers.h"
+#include "util/u_range.h"
struct etna_context;
struct pipe_screen;
@@ -84,6 +85,9 @@ struct etna_resource {
struct etna_resource_level levels[ETNA_NUM_LOD];
+ /* buffer range that has been initialized */
+ struct util_range valid_buffer_range;
+
/* for when TE doesn't support the base layout */
struct pipe_resource *texture;
/* for when PE doesn't support the base layout */
diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
index 62b876f2d99..77a9abafa99 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
@@ -174,6 +174,14 @@ 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);
+ if ((ptrans->resource->target == PIPE_BUFFER) &&
+ (ptrans->usage & PIPE_TRANSFER_WRITE)) {
+ util_range_add(&rsc->base,
+ &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);
@@ -199,6 +207,17 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
/* slab_alloc() doesn't zero */
memset(trans, 0, sizeof(*trans));
+ /*
+ * Upgrade to UNSYNCHRONIZED if target is PIPE_BUFFER and range is uninitialized.
+ */
+ if ((usage & PIPE_TRANSFER_WRITE) &&
+ (prsc->target == PIPE_BUFFER) &&
+ !util_ranges_intersect(&rsc->valid_buffer_range,
+ box->x,
+ box->x + box->width)) {
+ usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
+ }
+
/* Upgrade DISCARD_RANGE to WHOLE_RESOURCE if the whole resource is
* being mapped. If we add buffer reallocation to avoid CPU/GPU sync this
* check needs to be extended to coherent mappings and shared resources.
@@ -460,10 +479,16 @@ 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->base,
+ &rsc->valid_buffer_range,
+ ptrans->box.x + box->x,
+ ptrans->box.x + box->x + box->width);
}
void