etnaviv: add etna_shader_key and generate variants if needed
authorChristian Gmeiner <christian.gmeiner@gmail.com>
Sun, 19 Mar 2017 16:19:10 +0000 (17:19 +0100)
committerChristian Gmeiner <christian.gmeiner@gmail.com>
Wed, 5 Apr 2017 17:58:10 +0000 (19:58 +0200)
Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
src/gallium/drivers/etnaviv/etnaviv_compiler.c
src/gallium/drivers/etnaviv/etnaviv_compiler.h
src/gallium/drivers/etnaviv/etnaviv_compiler_cmdline.c
src/gallium/drivers/etnaviv/etnaviv_context.c
src/gallium/drivers/etnaviv/etnaviv_context.h
src/gallium/drivers/etnaviv/etnaviv_shader.c
src/gallium/drivers/etnaviv/etnaviv_shader.h

index 35d635ff3ddf9ae9fc398a9a54005170b9f2e875..4a03d8294f541aa3db5a221f33ff2ea4fa68c0ce 100644 (file)
@@ -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);
index 7552a8f9d237b4260f71c5d957ea8f99ad2c2e30..ce8a651982a47d51961fff35a20c57f8aef50d9c 100644 (file)
@@ -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) {
index 8582e305a073cd170b20b5551ce267df7338a269..88a093fd918f8b8a8877ad6b149d57e78387ddaa 100644 (file)
@@ -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 {
index 035ee86f4beaad4d6d07b39ee03781d603e29041..1fea2d1a48b20ae4b446b48a17994116be1be039 100644 (file)
@@ -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");
index dfd9e1f73a6b294f7eaa1bd0d980470138b01aaf..d67344010295f3a42d8e86328d8c219b0932b517 100644 (file)
@@ -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;
index b847b652d1dc6afa7077f59a7b587ce7fcf95d92..9e00d34d23a2f822ba4835ab5c088a768a2b4a95 100644 (file)
@@ -80,6 +80,7 @@ struct etna_vertexbuf_state {
 };
 
 struct etna_shader_state {
+   void *bind_vs, *bind_fs;
    struct etna_shader_variant *vs, *fs;
 };
 
index 5035eaffde6e7750599a21e49b234b2773fe67a1..f46e339ad7a14e235f239da1504f2fb892d6e6d5 100644 (file)
@@ -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;
 }
 
index 9f26befc00c9dc603214dfec72ae8bced4282075..e56f1fa9f534369b5afe71368b675c3fa3fb0dc0 100644 (file)
 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)
+{
+   STATIC_ASSERT(sizeof(struct etna_shader_key) <= sizeof(a->global));
+
+   return a->global == b->global;
+}
+
 struct etna_shader {
     /* shader id (for debug): */
     uint32_t id;
@@ -49,6 +66,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);