etnaviv: Do GC3000 resolve-in-place when possible
authorWladimir J. van der Laan <laanwj@gmail.com>
Sat, 30 Sep 2017 08:11:32 +0000 (10:11 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Thu, 12 Oct 2017 14:03:26 +0000 (16:03 +0200)
If an RS blit is done with source exactly the same as destination, and
the hardware supports this, do an in-place resolve. This only fills in
tiles that have not been rendered to using information from the TS.

This is the same as the blob does and potentially saves significant
bandwidth when doing i.MX6qp scanout using PRE, and when rendering to
textures (though here using sampler TS would be even better).

Signed-off-by: Wladimir J. van der Laan <laanwj@gmail.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
src/gallium/drivers/etnaviv/etnaviv_emit.c
src/gallium/drivers/etnaviv/etnaviv_rs.c
src/gallium/drivers/etnaviv/etnaviv_rs.h

index c85ada926699acdde864360cf785947ac89a1d6f..c62287b1339a0b6fbfdfe90cba5f8d146084e973 100644 (file)
@@ -591,6 +591,7 @@ etna_try_rs_blit(struct pipe_context *pctx,
       .source = src->bo,
       .source_offset = src_offset,
       .source_stride = src_lev->stride,
+      .source_padded_width = src_lev->padded_width,
       .source_padded_height = src_lev->padded_height,
       .dest_format = translate_rs_format(dst_format),
       .dest_tiling = dst->layout,
index c2117d563d1d95961d5b8ff2cd8d1cedda7e6d74..707b1e7349148a0823776b12da20c0d5591076b2 100644 (file)
@@ -173,7 +173,14 @@ etna_submit_rs_state(struct etna_context *ctx,
 
    ctx->stats.rs_operations++;
 
-   if (screen->specs.pixel_pipes == 1) {
+   if (cs->RS_KICKER_INPLACE) {
+      etna_cmd_stream_reserve(stream, 6);
+      etna_coalesce_start(stream, &coalesce);
+      /* 0/1 */ EMIT_STATE(RS_EXTRA_CONFIG, cs->RS_EXTRA_CONFIG);
+      /* 2/3 */ EMIT_STATE(RS_SOURCE_STRIDE, cs->RS_SOURCE_STRIDE);
+      /* 4/5 */ EMIT_STATE(RS_KICKER_INPLACE, cs->RS_KICKER_INPLACE);
+      etna_coalesce_end(stream, &coalesce);
+   } else if (screen->specs.pixel_pipes == 1) {
       etna_cmd_stream_reserve(stream, 22);
       etna_coalesce_start(stream, &coalesce);
       /* 0/1 */ EMIT_STATE(RS_CONFIG, cs->RS_CONFIG);
index 5c108a6c7a289c548e272922fa95e25285d81112..c9072c2645ea6ddd21c8d38728774fb4327b308d 100644 (file)
@@ -118,10 +118,21 @@ etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs,
    cs->RS_FILL_VALUE[3] = rs->clear_value[3];
    cs->RS_EXTRA_CONFIG = VIVS_RS_EXTRA_CONFIG_AA(rs->aa) |
                          VIVS_RS_EXTRA_CONFIG_ENDIAN(rs->endian_mode);
-   /* TODO: cs->RS_UNK016B0 = s->size / 64 ?
-    * The blob does this consistently but there seems to be no currently supported
-    * model that needs it.
+
+   /* If source the same as destination, and the hardware supports this,
+    * do an in-place resolve to fill in unrendered tiles.
     */
+   if (ctx->specs.single_buffer && rs->source == rs->dest &&
+         rs->source_offset == rs->dest_offset &&
+         rs->source_format == rs->dest_format &&
+         rs->source_tiling == rs->dest_tiling &&
+         rs->source_stride == rs->dest_stride &&
+         !rs->downsample_x && !rs->downsample_y &&
+         !rs->swap_rb && !rs->flip &&
+         !rs->clear_mode && rs->source_padded_width) {
+      /* Total number of tiles (same as for autodisable) */
+      cs->RS_KICKER_INPLACE = rs->source_padded_width * rs->source_padded_height / 16;
+   }
 }
 
 void
index ec5b659ccd46378926eaad91fc10e43dee69ed0b..171d3fa0095f1bd1e028e8115995e4f154ba83ea 100644 (file)
@@ -43,6 +43,7 @@ struct rs_state {
    struct etna_bo *source;
    uint32_t source_offset;
    uint32_t source_stride;
+   uint32_t source_padded_width; /* total padded width (only needed for source) */
    uint32_t source_padded_height; /* total padded height */
    struct etna_bo *dest;
    uint32_t dest_offset;
@@ -69,6 +70,7 @@ struct compiled_rs_state {
    uint32_t RS_FILL_VALUE[4];
    uint32_t RS_EXTRA_CONFIG;
    uint32_t RS_PIPE_OFFSET[2];
+   uint32_t RS_KICKER_INPLACE; /* Set if source is destination */
 
    struct etna_reloc source[2];
    struct etna_reloc dest[2];