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

Christian Gmeiner christian.gmeiner at gmail.com
Sun Mar 26 14:13:11 UTC 2017


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;
+   };
+};
+
+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);
 
-- 
2.9.3



More information about the etnaviv mailing list