diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index 35d635ff3dd..4a03d8294f5 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 7552a8f9d23..ce8a651982a 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 8582e305a07..88a093fd918 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 035ee86f4be..1fea2d1a48b 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 dfd9e1f73a6..d6734401029 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 b847b652d1d..9e00d34d23a 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 5035eaffde6..f46e339ad7a 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 9f26befc00c..e56f1fa9f53 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_shader.h +++ b/src/gallium/drivers/etnaviv/etnaviv_shader.h @@ -32,6 +32,23 @@ 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);