X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fetnaviv%2Fetnaviv_transfer.c;h=6c1edd483541d5417e03b0f13e4cc1947842ae3f;hp=1a5aa7fc043cebaf90e2a589a2991330abdbee88;hb=58c3ce071c28b2d132cb15e309b3168953d957bd;hpb=c9e8b49b885242d84ba031dacef5aa4a5ac1e5b6 diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c index 1a5aa7fc043..6c1edd48354 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -39,6 +39,8 @@ #include "util/u_surface.h" #include "util/u_transfer.h" +#include + /* Compute offset into a 1D/2D/3D buffer of a certain box. * This box must be aligned to the block width and height of the * underlying format. */ @@ -70,6 +72,13 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) if (rsc->texture && !etna_resource_newer(rsc, etna_resource(rsc->texture))) rsc = etna_resource(rsc->texture); /* switch to using the texture resource */ + /* + * Temporary resources are always pulled into the CPU domain, must push them + * back into GPU domain before the RS execs the blit to the base resource. + */ + if (trans->rsc) + etna_bo_cpu_fini(etna_resource(trans->rsc)->bo); + if (ptrans->usage & PIPE_TRANSFER_WRITE) { if (trans->rsc) { /* We have a temporary resource due to either tile status or @@ -82,21 +91,19 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) struct etna_resource_level *res_level = &rsc->levels[ptrans->level]; void *mapped = etna_bo_map(rsc->bo) + res_level->offset; - if (rsc->layout == ETNA_LAYOUT_LINEAR || rsc->layout == ETNA_LAYOUT_TILED) { - if (rsc->layout == ETNA_LAYOUT_TILED && !util_format_is_compressed(rsc->base.format)) { - etna_texture_tile( - mapped + ptrans->box.z * res_level->layer_stride, - trans->staging, ptrans->box.x, ptrans->box.y, - res_level->stride, ptrans->box.width, ptrans->box.height, - ptrans->stride, util_format_get_blocksize(rsc->base.format)); - } else { /* non-tiled or compressed format */ - util_copy_box(mapped, rsc->base.format, res_level->stride, - res_level->layer_stride, ptrans->box.x, - ptrans->box.y, ptrans->box.z, ptrans->box.width, - ptrans->box.height, ptrans->box.depth, - trans->staging, ptrans->stride, - ptrans->layer_stride, 0, 0, 0 /* src x,y,z */); - } + if (rsc->layout == ETNA_LAYOUT_TILED) { + etna_texture_tile( + mapped + ptrans->box.z * res_level->layer_stride, + trans->staging, ptrans->box.x, ptrans->box.y, + res_level->stride, ptrans->box.width, ptrans->box.height, + ptrans->stride, util_format_get_blocksize(rsc->base.format)); + } else if (rsc->layout == ETNA_LAYOUT_LINEAR) { + util_copy_box(mapped, rsc->base.format, res_level->stride, + res_level->layer_stride, ptrans->box.x, + ptrans->box.y, ptrans->box.z, ptrans->box.width, + ptrans->box.height, ptrans->box.depth, + trans->staging, ptrans->stride, + ptrans->layer_stride, 0, 0, 0 /* src x,y,z */); } else { BUG("unsupported tiling %i", rsc->layout); } @@ -105,15 +112,20 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) } rsc->seqno++; - etna_bo_cpu_fini(rsc->bo); if (rsc->base.bind & PIPE_BIND_SAMPLER_VIEW) { - /* XXX do we need to flush the CPU cache too or start a write barrier - * to make sure the GPU sees it? */ ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES; } } + /* + * Transfers without a temporary are only pulled into the CPU domain if they + * are not mapped unsynchronized. If they are, must push them back into GPU + * domain after CPU access is finished. + */ + if (!trans->rsc && !(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) + etna_bo_cpu_fini(rsc->bo); + pipe_resource_reference(&trans->rsc, NULL); pipe_resource_reference(&ptrans->resource, NULL); slab_free(&ctx->transfer_pool, trans); @@ -147,6 +159,20 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, assert(level <= prsc->last_level); + /* 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. + */ + if ((usage & PIPE_TRANSFER_DISCARD_RANGE) && + !(usage & PIPE_TRANSFER_UNSYNCHRONIZED) && + prsc->last_level == 0 && + prsc->width0 == box->width && + prsc->height0 == box->height && + prsc->depth0 == box->depth && + prsc->array_size == 1) { + usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; + } + if (rsc->texture && !etna_resource_newer(rsc, etna_resource(rsc->texture))) { /* We have a texture resource which is the same age or newer than the * render resource. Use the texture resource, which avoids bouncing @@ -179,13 +205,16 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, templ.nr_samples = 0; templ.bind = PIPE_BIND_RENDER_TARGET; - trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, &templ); + trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, + DRM_FORMAT_MOD_LINEAR, &templ); if (!trans->rsc) { slab_free(&ctx->transfer_pool, trans); return NULL; } - etna_copy_resource(pctx, trans->rsc, prsc, level, trans->rsc->last_level); + if (!(usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)) + etna_copy_resource(pctx, trans->rsc, prsc, level, + trans->rsc->last_level); /* Switch to using the temporary resource instead */ rsc = etna_resource(trans->rsc); @@ -196,8 +225,9 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, /* Always sync if we have the temporary resource. The PIPE_TRANSFER_READ * case could be optimised if we knew whether the resource has outstanding * rendering. */ - if (usage & PIPE_TRANSFER_READ || trans->rsc) - etna_resource_wait(pctx, rsc); + if ((usage & PIPE_TRANSFER_READ || trans->rsc) && + rsc->status & ETNA_PENDING_WRITE) + pctx->flush(pctx, NULL, 0); /* XXX we don't handle PIPE_TRANSFER_FLUSH_EXPLICIT; this flag can be ignored * when mapping in-place, @@ -249,26 +279,21 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE is set. */ - /* No need to allocate a buffer for copying if the resource is not in use, - * and no tiling is needed, can just return a direct pointer. + /* + * Pull resources into the CPU domain. Only skipped for unsynchronized + * transfers without a temporary resource. */ - bool in_place = rsc->layout == ETNA_LAYOUT_LINEAR || - (rsc->layout == ETNA_LAYOUT_TILED && - util_format_is_compressed(prsc->format)); + if (trans->rsc || !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { + uint32_t prep_flags = 0; - /* Ignore PIPE_TRANSFER_UNSYNCHRONIZED and PIPE_TRANSFER_DONTBLOCK here. - * It appears that Gallium operates the index/vertex buffers in a - * circular fashion, and the CPU can catch up with the GPU and starts - * overwriting yet-to-be-processed entries, causing rendering corruption. */ - uint32_t prep_flags = 0; + if (usage & PIPE_TRANSFER_READ) + prep_flags |= DRM_ETNA_PREP_READ; + if (usage & PIPE_TRANSFER_WRITE) + prep_flags |= DRM_ETNA_PREP_WRITE; - if (usage & PIPE_TRANSFER_READ) - prep_flags |= DRM_ETNA_PREP_READ; - if (usage & PIPE_TRANSFER_WRITE) - prep_flags |= DRM_ETNA_PREP_WRITE; - - if (etna_bo_cpu_prep(rsc->bo, prep_flags)) - goto fail_prep; + if (etna_bo_cpu_prep(rsc->bo, prep_flags)) + goto fail_prep; + } /* map buffer object */ void *mapped = etna_bo_map(rsc->bo); @@ -277,7 +302,7 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, *out_transfer = ptrans; - if (in_place) { + if (rsc->layout == ETNA_LAYOUT_LINEAR) { ptrans->stride = res_level->stride; ptrans->layer_stride = res_level->layer_stride; @@ -304,24 +329,21 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, goto fail; if (usage & PIPE_TRANSFER_READ) { - /* untile or copy resource for reading */ - if (rsc->layout == ETNA_LAYOUT_LINEAR || rsc->layout == ETNA_LAYOUT_TILED) { - if (rsc->layout == ETNA_LAYOUT_TILED && !util_format_is_compressed(rsc->base.format)) { - etna_texture_untile(trans->staging, - mapped + ptrans->box.z * res_level->layer_stride, - ptrans->box.x, ptrans->box.y, res_level->stride, - ptrans->box.width, ptrans->box.height, ptrans->stride, - util_format_get_blocksize(rsc->base.format)); - } else { /* non-tiled or compressed format */ - util_copy_box(trans->staging, rsc->base.format, ptrans->stride, - ptrans->layer_stride, 0, 0, 0, /* dst x,y,z */ - ptrans->box.width, ptrans->box.height, - ptrans->box.depth, mapped, res_level->stride, - res_level->layer_stride, ptrans->box.x, - ptrans->box.y, ptrans->box.z); - } - } else /* TODO supertiling */ - { + if (rsc->layout == ETNA_LAYOUT_TILED) { + etna_texture_untile(trans->staging, + mapped + ptrans->box.z * res_level->layer_stride, + ptrans->box.x, ptrans->box.y, res_level->stride, + ptrans->box.width, ptrans->box.height, ptrans->stride, + util_format_get_blocksize(rsc->base.format)); + } else if (rsc->layout == ETNA_LAYOUT_LINEAR) { + util_copy_box(trans->staging, rsc->base.format, ptrans->stride, + ptrans->layer_stride, 0, 0, 0, /* dst x,y,z */ + ptrans->box.width, ptrans->box.height, + ptrans->box.depth, mapped, res_level->stride, + res_level->layer_stride, ptrans->box.x, + ptrans->box.y, ptrans->box.z); + } else { + /* TODO supertiling */ BUG("unsupported tiling %i for reading", rsc->layout); } }