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 <christian.gmeiner@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
This commit is contained in:
parent
eab6d75066
commit
a6de05a968
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue