etnaviv: hook-up etc2 patching
Changes v1 -> v2: - Avoid the GPU sampling from the resource that gets mutated by the the transfer map by setting DRM_ETNA_PREP_WRITE. Changes v2 -> v3: - make use of likely(..) - drop minor optimization regarding rsc->layout == ETNA_LAYOUT_LINEAR - better documentation why DRM_ETNA_PREP_WRITE is needed Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
This commit is contained in:
parent
d8177f6233
commit
5d09325c1c
|
@ -478,6 +478,9 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
|
|||
pipe_resource_reference(&rsc->texture, NULL);
|
||||
pipe_resource_reference(&rsc->external, NULL);
|
||||
|
||||
for (unsigned i = 0; i < ETNA_NUM_LOD; i++)
|
||||
FREE(rsc->levels[i].patch_offsets);
|
||||
|
||||
FREE(rsc);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "util/list.h"
|
||||
|
||||
struct pipe_screen;
|
||||
struct util_dynarray;
|
||||
|
||||
struct etna_resource_level {
|
||||
unsigned width, padded_width; /* in pixels */
|
||||
|
@ -47,6 +48,10 @@ struct etna_resource_level {
|
|||
uint32_t ts_size;
|
||||
uint32_t clear_value; /* clear value of resource level (mainly for TS) */
|
||||
bool ts_valid;
|
||||
|
||||
/* keep track if we have done some per block patching */
|
||||
bool patched;
|
||||
struct util_dynarray *patch_offsets;
|
||||
};
|
||||
|
||||
enum etna_resource_addressing_mode {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "etnaviv_clear_blit.h"
|
||||
#include "etnaviv_context.h"
|
||||
#include "etnaviv_debug.h"
|
||||
#include "etnaviv_etc2.h"
|
||||
#include "etnaviv_screen.h"
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
|
@ -57,6 +58,46 @@ etna_compute_offset(enum pipe_format format, const struct pipe_box *box,
|
|||
util_format_get_blocksize(format);
|
||||
}
|
||||
|
||||
static void etna_patch_data(void *buffer, const struct pipe_transfer *ptrans)
|
||||
{
|
||||
struct pipe_resource *prsc = ptrans->resource;
|
||||
struct etna_resource *rsc = etna_resource(prsc);
|
||||
struct etna_resource_level *level = &rsc->levels[ptrans->level];
|
||||
|
||||
if (likely(!etna_etc2_needs_patching(prsc)))
|
||||
return;
|
||||
|
||||
if (level->patched)
|
||||
return;
|
||||
|
||||
/* do have the offsets of blocks to patch? */
|
||||
if (!level->patch_offsets) {
|
||||
level->patch_offsets = CALLOC_STRUCT(util_dynarray);
|
||||
|
||||
etna_etc2_calculate_blocks(buffer, ptrans->stride,
|
||||
ptrans->box.width, ptrans->box.height,
|
||||
prsc->format, level->patch_offsets);
|
||||
}
|
||||
|
||||
etna_etc2_patch(buffer, level->patch_offsets);
|
||||
|
||||
level->patched = true;
|
||||
}
|
||||
|
||||
static void etna_unpatch_data(void *buffer, const struct pipe_transfer *ptrans)
|
||||
{
|
||||
struct pipe_resource *prsc = ptrans->resource;
|
||||
struct etna_resource *rsc = etna_resource(prsc);
|
||||
struct etna_resource_level *level = &rsc->levels[ptrans->level];
|
||||
|
||||
if (!level->patched)
|
||||
return;
|
||||
|
||||
etna_etc2_patch(buffer, level->patch_offsets);
|
||||
|
||||
level->patched = false;
|
||||
}
|
||||
|
||||
static void
|
||||
etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans)
|
||||
{
|
||||
|
@ -119,6 +160,9 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans)
|
|||
}
|
||||
}
|
||||
|
||||
/* We need to have the patched data ready for the GPU. */
|
||||
etna_patch_data(trans->mapped, ptrans);
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -321,6 +365,14 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
|
|||
if (usage & PIPE_TRANSFER_WRITE)
|
||||
prep_flags |= DRM_ETNA_PREP_WRITE;
|
||||
|
||||
/*
|
||||
* The ETC2 patching operates in-place on the resource, so the resource will
|
||||
* get written even on read-only transfers. This blocks the GPU to sample
|
||||
* from this resource.
|
||||
*/
|
||||
if ((usage & PIPE_TRANSFER_READ) && etna_etc2_needs_patching(prsc))
|
||||
prep_flags |= DRM_ETNA_PREP_WRITE;
|
||||
|
||||
if (etna_bo_cpu_prep(rsc->bo, prep_flags))
|
||||
goto fail_prep;
|
||||
}
|
||||
|
@ -340,6 +392,10 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
|
|||
etna_compute_offset(prsc->format, box, res_level->stride,
|
||||
res_level->layer_stride);
|
||||
|
||||
/* We need to have the unpatched data ready for the gfx stack. */
|
||||
if (usage & PIPE_TRANSFER_READ)
|
||||
etna_unpatch_data(trans->mapped, ptrans);
|
||||
|
||||
return trans->mapped;
|
||||
} else {
|
||||
unsigned divSizeX = util_format_get_blockwidth(format);
|
||||
|
|
Loading…
Reference in New Issue