[PATCH 07/11] etnaviv: add etna_shader_key and generate variants if needed

Lucas Stach l.stach at pengutronix.de
Mon Mar 27 08:49:32 UTC 2017


Am Sonntag, den 26.03.2017, 16:13 +0200 schrieb Christian Gmeiner:
> Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
> ---
>  src/gallium/drivers/etnaviv/etnaviv_clear_blit.c   |  4 +-
>  src/gallium/drivers/etnaviv/etnaviv_compiler.c     |  4 +-
>  src/gallium/drivers/etnaviv/etnaviv_compiler.h     |  2 +
>  .../drivers/etnaviv/etnaviv_compiler_cmdline.c     |  2 +
>  src/gallium/drivers/etnaviv/etnaviv_context.c      | 38 +++++++++++++++
>  src/gallium/drivers/etnaviv/etnaviv_context.h      |  1 +
>  src/gallium/drivers/etnaviv/etnaviv_shader.c       | 54 +++++++++++-----------
>  src/gallium/drivers/etnaviv/etnaviv_shader.h       | 19 ++++++++
>  8 files changed, 95 insertions(+), 29 deletions(-)
> 
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
> index 35d635f..4a03d82 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
> @@ -49,11 +49,11 @@ etna_blit_save_state(struct etna_context *ctx)
>  {
>     util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer.vb);
>     util_blitter_save_vertex_elements(ctx->blitter, ctx->vertex_elements);
> -   util_blitter_save_vertex_shader(ctx->blitter, ctx->shader.vs);
> +   util_blitter_save_vertex_shader(ctx->blitter, ctx->shader.bind_vs);
>     util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
>     util_blitter_save_viewport(ctx->blitter, &ctx->viewport_s);
>     util_blitter_save_scissor(ctx->blitter, &ctx->scissor_s);
> -   util_blitter_save_fragment_shader(ctx->blitter, ctx->shader.fs);
> +   util_blitter_save_fragment_shader(ctx->blitter, ctx->shader.bind_fs);
>     util_blitter_save_blend(ctx->blitter, ctx->blend);
>     util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
>     util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref_s);
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.c b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
> index 7552a8f..ce8a651 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_compiler.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.c
> @@ -54,7 +54,6 @@
>  #include "etnaviv_context.h"
>  #include "etnaviv_debug.h"
>  #include "etnaviv_disasm.h"
> -#include "etnaviv_shader.h"
>  #include "etnaviv_uniforms.h"
>  #include "etnaviv_util.h"
>  
> @@ -197,6 +196,8 @@ struct etna_compile {
>  
>     /* GPU hardware specs */
>     const struct etna_specs *specs;
> +
> +   const struct etna_shader_key *key;
>  };
>  
>  static struct etna_reg_desc *
> @@ -2287,6 +2288,7 @@ etna_compile_shader(struct etna_shader_variant *v)
>     const struct tgsi_token *tokens = v->shader->tokens;
>  
>     c->specs = specs;
> +   c->key = &v->key;
>     c->tokens = tgsi_transform_lowering(&lconfig, tokens, &c->info);
>     c->free_tokens = !!c->tokens;
>     if (!c->tokens) {
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.h b/src/gallium/drivers/etnaviv/etnaviv_compiler.h
> index 8582e30..88a093f 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_compiler.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.h
> @@ -29,6 +29,7 @@
>  
>  #include "etnaviv_context.h"
>  #include "etnaviv_internal.h"
> +#include "etnaviv_shader.h"
>  #include "pipe/p_compiler.h"
>  #include "pipe/p_shader_tokens.h"
>  
> @@ -98,6 +99,7 @@ struct etna_shader_variant {
>  
>     /* replicated here to avoid passing extra ptrs everywhere */
>     struct etna_shader *shader;
> +   struct etna_shader_key key;
>  };
>  
>  struct etna_varying {
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c b/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c
> index 035ee86..1fea2d1 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c
> @@ -102,6 +102,7 @@ main(int argc, char **argv)
>     struct tgsi_token toks[65536];
>     struct tgsi_parse_context parse;
>     struct etna_shader s = {};
> +   struct etna_shader_key key = {};
>     void *ptr;
>     size_t size;
>  
> @@ -147,6 +148,7 @@ main(int argc, char **argv)
>     s.tokens = toks;
>  
>     v->shader = &s;
> +   v->key = key;
>  
>     if (!etna_compile_shader(v)) {
>        fprintf(stderr, "compiler failed!\n");
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
> index dfd9e1f..d673440 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_context.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
> @@ -106,6 +106,37 @@ etna_update_state_for_draw(struct etna_context *ctx, const struct pipe_draw_info
>     }
>  }
>  
> +static bool
> +etna_get_vs(struct etna_context *ctx, struct etna_shader_key key)
> +{
> +   const struct etna_shader_variant *old = ctx->shader.vs;
> +
> +   ctx->shader.vs = etna_shader_variant(ctx->shader.bind_vs, key, &ctx->debug);
> +
> +   if (!ctx->shader.vs)
> +      return false;
> +
> +   if (old != ctx->shader.vs)
> +      ctx->dirty |= ETNA_DIRTY_SHADER;
> +
> +   return true;
> +}
> +
> +static bool
> +etna_get_fs(struct etna_context *ctx, struct etna_shader_key key)
> +{
> +   const struct etna_shader_variant *old = ctx->shader.fs;
> +
> +   ctx->shader.fs = etna_shader_variant(ctx->shader.bind_fs, key, &ctx->debug);
> +
> +   if (!ctx->shader.fs)
> +      return false;
> +
> +   if (old != ctx->shader.fs)
> +      ctx->dirty |= ETNA_DIRTY_SHADER;
> +
> +   return true;
> +}
>  
>  static void
>  etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
> @@ -152,6 +183,13 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
>        return;
>     }
>  
> +   struct etna_shader_key key = {};
> +
> +   if (!etna_get_vs(ctx, key) || !etna_get_fs(ctx, key)) {
> +      BUG("compiled shaders are not okay");
> +      return;
> +   }
> +
>     /* Update any derived state */
>     if (!etna_state_update(ctx))
>        return;
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
> index b847b65..9e00d34 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_context.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
> @@ -80,6 +80,7 @@ struct etna_vertexbuf_state {
>  };
>  
>  struct etna_shader_state {
> +   void *bind_vs, *bind_fs;
>     struct etna_shader_variant *vs, *fs;
>  };
>  
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.c b/src/gallium/drivers/etnaviv/etnaviv_shader.c
> index 8132bc8..a5f9315 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_shader.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_shader.c
> @@ -268,7 +268,7 @@ etna_shader_update_vertex(struct etna_context *ctx)
>  }
>  
>  static struct etna_shader_variant *
> -create_variant(struct etna_shader *shader)
> +create_variant(struct etna_shader *shader, struct etna_shader_key key)
>  {
>     struct etna_shader_variant *v = CALLOC_STRUCT(etna_shader_variant);
>     int ret;
> @@ -277,6 +277,7 @@ create_variant(struct etna_shader *shader)
>        return NULL;
>  
>     v->shader = shader;
> +   v->key = key;
>  
>     ret = etna_compile_shader(v);
>     if (!ret) {
> @@ -293,6 +294,27 @@ fail:
>     return NULL;
>  }
>  
> +struct etna_shader_variant *
> +etna_shader_variant(struct etna_shader *shader, struct etna_shader_key key,
> +                   struct pipe_debug_callback *debug)
> +{
> +   struct etna_shader_variant *v;
> +
> +   for (v = shader->variants; v; v = v->next)
> +      if (etna_shader_key_equal(&key, &v->key))
> +         return v;
> +
> +   /* compile new variant if it doesn't exist already */
> +   v = create_variant(shader, key);
> +   if (v) {
> +      v->next = shader->variants;
> +      shader->variants = v;
> +      dump_shader_info(v, debug);
> +   }
> +
> +   return v;
> +}
> +
>  static void *
>  etna_create_shader_state(struct pipe_context *pctx,
>                           const struct pipe_shader_state *pss)
> @@ -308,17 +330,7 @@ etna_create_shader_state(struct pipe_context *pctx,
>     shader->specs = &ctx->specs;
>     shader->tokens = tgsi_dup_tokens(pss->tokens);
>  
> -   /* compile new variant */
> -   struct etna_shader_variant *v;
> -
> -   v = create_variant(shader);
> -   if (v) {
> -      v->next = shader->variants;
> -      shader->variants = v;
> -      dump_shader_info(v, &ctx->debug);
> -   }
> -
> -   return v;
> +   return shader;
>  }
>  
>  static void
> @@ -339,30 +351,20 @@ etna_delete_shader_state(struct pipe_context *pctx, void *ss)
>  }
>  
>  static void
> -etna_bind_fs_state(struct pipe_context *pctx, void *fss_)
> +etna_bind_fs_state(struct pipe_context *pctx, void *hwcso)
>  {
>     struct etna_context *ctx = etna_context(pctx);
> -   struct etna_shader_variant *fss = fss_;
> -
> -   if (ctx->shader.fs == fss) /* skip if already bound */
> -      return;
>  
> -   assert(fss == NULL || fss->processor == PIPE_SHADER_FRAGMENT);
> -   ctx->shader.fs = fss;
> +   ctx->shader.bind_fs = hwcso;
>     ctx->dirty |= ETNA_DIRTY_SHADER;
>  }
>  
>  static void
> -etna_bind_vs_state(struct pipe_context *pctx, void *vss_)
> +etna_bind_vs_state(struct pipe_context *pctx, void *hwcso)
>  {
>     struct etna_context *ctx = etna_context(pctx);
> -   struct etna_shader_variant *vss = vss_;
> -
> -   if (ctx->shader.vs == vss) /* skip if already bound */
> -      return;
>  
> -   assert(vss == NULL || vss->processor == PIPE_SHADER_VERTEX);
> -   ctx->shader.vs = vss;
> +   ctx->shader.bind_vs = hwcso;
>     ctx->dirty |= ETNA_DIRTY_SHADER;
>  }
>  
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.h b/src/gallium/drivers/etnaviv/etnaviv_shader.h
> index 9f26bef..b0d97a7 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_shader.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_shader.h
> @@ -32,6 +32,21 @@
>  struct etna_context;
>  struct etna_shader_variant;
>  
> +struct etna_shader_key
> +{
> +   union {
> +      struct {
> +      };
> +      uint32_t global;
> +   };
> +};

There should probably be an assert somewhere in the code, which checks
that sizeof(struct etna_shader_key) <= sizeof(etna_shader_key.global),
to avoid the key getting ambiguous by overflowing global size.

> +
> +static inline bool
> +etna_shader_key_equal(struct etna_shader_key *a, struct etna_shader_key *b)
> +{
> +   return a->global == b->global;
> +}
> +
>  struct etna_shader {
>      /* shader id (for debug): */
>      uint32_t id;
> @@ -49,6 +64,10 @@ etna_shader_link(struct etna_context *ctx);
>  bool
>  etna_shader_update_vertex(struct etna_context *ctx);
>  
> +struct etna_shader_variant *
> +etna_shader_variant(struct etna_shader *shader, struct etna_shader_key key,
> +                   struct pipe_debug_callback *debug);
> +
>  void
>  etna_shader_init(struct pipe_context *pctx);
>  




More information about the etnaviv mailing list