[Mesa-dev] [PATCH 3/3] etnaviv: SINGLE_BUFFER support on GC3000

Christian Gmeiner christian.gmeiner at gmail.com
Thu Apr 13 14:29:36 UTC 2017


And you forgot your Signed-off-by line!

greets
--
Christian Gmeiner, MSc

https://www.youtube.com/user/AloryOFFICIAL
https://soundcloud.com/christian-gmeiner


2017-04-13 16:25 GMT+02:00 Christian Gmeiner <christian.gmeiner at gmail.com>:
>  Hi
>
> 2017-04-13 16:05 GMT+02:00 Wladimir J. van der Laan <laanwj at gmail.com>:
>> This patch adds support for the SINGLE_BUFFER feature on GC3000
>> GPUs, which allows rendering to a single buffer using multiple pixel
>> pipes.
>>
>> This feature is always used when it is available, which means that
>> multi-tiled formats are no longer being used in that case, and all
>> buffers will be normal (super)tiled. This mimics the behavior of the
>> blob on GC3000.
>>
>> - Because the same format can be used to render to and texture from,
>>   this avoids an extra resolve pass when rendering to texture.
>>
>> - i.MX6qp includes a PRE which can scan-out directly from tiled formats,
>>   avoiding untiling overhead.
>
> Just some small nitpicks else
>
> Series is:
> Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>
>
> Btw.. we could land this for 17.0.1 if this lands before 00:00 GMT tomorrow.
>
>> ---
>>  src/gallium/drivers/etnaviv/etnaviv_context.c  |  3 +++
>>  src/gallium/drivers/etnaviv/etnaviv_emit.c     |  6 ++++--
>>  src/gallium/drivers/etnaviv/etnaviv_internal.h |  3 +++
>>  src/gallium/drivers/etnaviv/etnaviv_resource.c |  9 +++++++-
>>  src/gallium/drivers/etnaviv/etnaviv_rs.c       | 29 ++++++++++++++++++--------
>>  src/gallium/drivers/etnaviv/etnaviv_screen.c   |  5 +++++
>>  src/gallium/drivers/etnaviv/etnaviv_state.c    | 10 +++++++--
>>  src/gallium/drivers/etnaviv/etnaviv_surface.c  | 21 +++++++++++++------
>>  8 files changed, 66 insertions(+), 20 deletions(-)
>>
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
>> index 555aa12..f2f709c 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_context.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
>> @@ -293,6 +293,9 @@ etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
>>     etna_set_state(stream, VIVS_RA_EARLY_DEPTH, 0x00000031);
>>     etna_set_state(stream, VIVS_PA_W_CLIP_LIMIT, 0x34000001);
>>
>> +   /* Enable SINGLE_BUFFER for resolve, if supported */
>> +   etna_set_state(stream, VIVS_RS_SINGLE_BUFFER, COND(ctx->specs.single_buffer, VIVS_RS_SINGLE_BUFFER_ENABLE));
>> +
>>     ctx->dirty = ~0L;
>>
>>     /* go through all the used resources and clear their status flag */
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c
>> index af74cbb..7ced5fc 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_emit.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c
>> @@ -603,10 +603,12 @@ etna_emit_state(struct etna_context *ctx)
>>     if (unlikely(dirty & (ETNA_DIRTY_STENCIL_REF))) {
>>        /*014A0*/ EMIT_STATE(PE_STENCIL_CONFIG_EXT, ctx->stencil_ref.PE_STENCIL_CONFIG_EXT);
>>     }
>> +   if (unlikely(dirty & (ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER))) {
>> +      struct etna_blend_state *blend = etna_blend_state(ctx->blend);
>> +      /*014A4*/ EMIT_STATE(PE_LOGIC_OP, blend->PE_LOGIC_OP | ctx->framebuffer.PE_LOGIC_OP);
>> +   }
>>     if (unlikely(dirty & (ETNA_DIRTY_BLEND))) {
>>        struct etna_blend_state *blend = etna_blend_state(ctx->blend);
>> -
>> -      /*014A4*/ EMIT_STATE(PE_LOGIC_OP, blend->PE_LOGIC_OP);
>>        for (int x = 0; x < 2; ++x) {
>>           /*014A8*/ EMIT_STATE(PE_DITHER(x), blend->PE_DITHER[x]);
>>        }
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h
>> index 2f09d55..2f8dacb 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_internal.h
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h
>> @@ -72,6 +72,8 @@ struct etna_specs {
>>     unsigned has_shader_range_registers : 1;
>>     /* has the new sin/cos functions */
>>     unsigned has_new_sin_cos : 1;
>> +   /* supports single-buffer rendering with multiple pixel pipes */
>> +   unsigned single_buffer : 1;
>>     /* can use any kind of wrapping mode on npot textures */
>>     unsigned npot_tex_any_wrap;
>>     /* number of bits per TS tile */
>> @@ -191,6 +193,7 @@ struct compiled_framebuffer_state {
>>     uint32_t TS_COLOR_CLEAR_VALUE;
>>     struct etna_reloc TS_COLOR_STATUS_BASE;
>>     struct etna_reloc TS_COLOR_SURFACE_BASE;
>> +   uint32_t PE_LOGIC_OP;
>>     bool msaa_mode; /* adds input (and possible temp) to PS */
>>  };
>>
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
>> index 1f0582c..b4e853f 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
>> @@ -248,9 +248,16 @@ etna_resource_create(struct pipe_screen *pscreen,
>>        if (util_format_is_compressed(templat->format))
>>           layout = ETNA_LAYOUT_LINEAR;
>>     } else if (templat->target != PIPE_BUFFER) {
>> -      bool want_multitiled = screen->specs.pixel_pipes > 1;
>> +      bool want_multitiled = false;
>>        bool want_supertiled = screen->specs.can_supertile && !DBG_ENABLED(ETNA_DBG_NO_SUPERTILE);
>>
>> +      /* When this GPU supports single-buffer rendering, don't ever enable
>> +       * multi-tiling. This replicates the blob behavior on GC3000.
>> +       */
>> +      if (!screen->specs.single_buffer) {
>> +         want_multitiled = screen->specs.pixel_pipes > 1;
>> +      }
>> +
>
> Kick not needed { }
>
>>        /* Keep single byte blocksized resources as tiled, since we
>>         * are unable to use the RS blit to de-tile them. However,
>>         * if they're used as a render target or depth/stencil, they
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c
>> index 295ca10..e133ac6 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c
>> @@ -70,19 +70,27 @@ etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs,
>>                            COND(rs->source_tiling & 2, VIVS_RS_SOURCE_STRIDE_TILING) |
>>                            COND(source_multi, VIVS_RS_SOURCE_STRIDE_MULTI);
>>
>> -   cs->source[0].bo = rs->source;
>> -   cs->source[0].offset = rs->source_offset;
>> -   cs->source[0].flags = ETNA_RELOC_READ;
>> +   /* Initially all pipes to the source and destination buffer
>> +    * This will be overridden below as necessary for the multi-pipe,
>> +    * multi-tiled case.
>> +    */
>> +   for (unsigned pipe = 0; pipe < ctx->specs.pixel_pipes; ++pipe) {
>> +      cs->source[pipe].bo = rs->source;
>> +      cs->source[pipe].offset = rs->source_offset;
>> +      cs->source[pipe].flags = ETNA_RELOC_READ;
>> +
>> +      cs->dest[pipe].bo = rs->dest;
>> +      cs->dest[pipe].offset = rs->dest_offset;
>> +      cs->dest[pipe].flags = ETNA_RELOC_WRITE;
>>
>> -   cs->dest[0].bo = rs->dest;
>> -   cs->dest[0].offset = rs->dest_offset;
>> -   cs->dest[0].flags = ETNA_RELOC_WRITE;
>> +      cs->RS_PIPE_OFFSET[pipe] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(0);
>> +   }
>>
>>     cs->RS_DEST_STRIDE = (rs->dest_stride << dest_stride_shift) |
>>                          COND(rs->dest_tiling & 2, VIVS_RS_DEST_STRIDE_TILING) |
>>                          COND(dest_multi, VIVS_RS_DEST_STRIDE_MULTI);
>>
>> -   if (ctx->specs.pixel_pipes == 1) {
>> +   if (ctx->specs.pixel_pipes == 1 || ctx->specs.single_buffer) {
>>        cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) |
>>                             VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height);
>>     } else if (ctx->specs.pixel_pipes == 2) {
>> @@ -102,12 +110,11 @@ etna_compile_rs_state(struct etna_context *ctx, struct compiled_rs_state *cs,
>>
>>        cs->RS_WINDOW_SIZE = VIVS_RS_WINDOW_SIZE_WIDTH(rs->width) |
>>                             VIVS_RS_WINDOW_SIZE_HEIGHT(rs->height / 2);
>> +      cs->RS_PIPE_OFFSET[1] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(rs->height / 2);
>>     } else {
>>        abort();
>>     }
>>
>> -   cs->RS_PIPE_OFFSET[0] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(0);
>> -   cs->RS_PIPE_OFFSET[1] = VIVS_RS_PIPE_OFFSET_X(0) | VIVS_RS_PIPE_OFFSET_Y(rs->height / 2);
>>     cs->RS_DITHER[0] = rs->dither[0];
>>     cs->RS_DITHER[1] = rs->dither[1];
>>     cs->RS_CLEAR_CONTROL = VIVS_RS_CLEAR_CONTROL_BITS(rs->clear_bits) | rs->clear_mode;
>> @@ -117,6 +124,10 @@ 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.
>> +    */
>>  }
>>
>>  void
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c
>> index 41bacbc..9f3104f 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c
>> @@ -675,6 +675,11 @@ etna_get_specs(struct etna_screen *screen)
>>     screen->specs.max_rendertarget_size =
>>        VIV_FEATURE(screen, chipMinorFeatures0, RENDERTARGET_8K) ? 8192 : 2048;
>>
>> +   screen->specs.single_buffer = VIV_FEATURE(screen, chipMinorFeatures4, SINGLE_BUFFER);
>> +   if (screen->specs.single_buffer) {
>> +      DBG("etnaviv: Single buffer mode enabled with %i pixel pipes\n", screen->specs.pixel_pipes);
>> +   }
>> +
>
> Kick not needed { }
>
>>     return true;
>>
>>  fail:
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c
>> index dbb6c54..d96b445 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_state.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_state.c
>> @@ -168,8 +168,8 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
>>           cs->PE_COLOR_ADDR = cbuf->reloc[0];
>>           cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
>>        } else {
>> -         /* Rendered textures must always be multi-tiled */
>> -         assert(res->layout & ETNA_LAYOUT_BIT_MULTI);
>> +         /* Rendered textures must always be multi-tiled, or single-buffer mode must be supported */
>> +         assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || ctx->specs.single_buffer);
>>           for (int i = 0; i < ctx->specs.pixel_pipes; i++) {
>>              cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i];
>>              cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
>> @@ -331,6 +331,12 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
>>
>>     cs->TS_MEM_CONFIG = ts_mem_config;
>>
>> +   /* Single buffer setup. There is only one switch for this, not a separate
>> +    * one per color buffer / depth buffer. To keep the logic simple always use
>> +    * single buffer when this feature is available.
>> +    */
>> +   cs->PE_LOGIC_OP = VIVS_PE_LOGIC_OP_SINGLE_BUFFER(ctx->specs.single_buffer ? 2 : 0);
>> +
>>     ctx->framebuffer_s = *sv; /* keep copy of original structure */
>>     ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER;
>>  }
>> diff --git a/src/gallium/drivers/etnaviv/etnaviv_surface.c b/src/gallium/drivers/etnaviv/etnaviv_surface.c
>> index a0013a4..d19f493 100644
>> --- a/src/gallium/drivers/etnaviv/etnaviv_surface.c
>> +++ b/src/gallium/drivers/etnaviv/etnaviv_surface.c
>> @@ -94,12 +94,21 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
>>     struct etna_resource_level *lev = &rsc->levels[level];
>>
>>     /* Setup template relocations for this surface */
>> -   surf->reloc[0].bo = rsc->bo;
>> -   surf->reloc[0].offset = surf->surf.offset;
>> -   surf->reloc[0].flags = 0;
>> -   surf->reloc[1].bo = rsc->bo;
>> -   surf->reloc[1].offset = surf->surf.offset + lev->stride * lev->padded_height / 2;
>> -   surf->reloc[1].flags = 0;
>> +   for (unsigned pipe = 0; pipe < ctx->specs.pixel_pipes; ++pipe) {
>> +      surf->reloc[pipe].bo = rsc->bo;
>> +      surf->reloc[pipe].offset = surf->surf.offset;
>> +      surf->reloc[pipe].flags = 0;
>> +   }
>> +
>> +   /* In single buffer mode, both pixel pipes must point to the same address,
>> +    * for multi-tiled surfaces on the other hand the second pipe is expected to
>> +    * point halfway the image vertically.
>> +    */
>> +   if (rsc->layout & ETNA_LAYOUT_BIT_MULTI) {
>> +      surf->reloc[1].bo = rsc->bo;
>> +      surf->reloc[1].offset = surf->surf.offset + lev->stride * lev->padded_height / 2;
>> +      surf->reloc[1].flags = 0;
>> +   }
>>
>>     if (surf->surf.ts_size) {
>>        unsigned int layer_offset = layer * surf->surf.ts_layer_stride;
>> --
>> 2.7.4
>>


More information about the mesa-dev mailing list