{
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);
#include "etnaviv_context.h"
#include "etnaviv_debug.h"
#include "etnaviv_disasm.h"
-#include "etnaviv_shader.h"
#include "etnaviv_uniforms.h"
#include "etnaviv_util.h"
/* GPU hardware specs */
const struct etna_specs *specs;
+
+ const struct etna_shader_key *key;
};
static struct etna_reg_desc *
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) {
#include "etnaviv_context.h"
#include "etnaviv_internal.h"
+#include "etnaviv_shader.h"
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
/* replicated here to avoid passing extra ptrs everywhere */
struct etna_shader *shader;
+ struct etna_shader_key key;
};
struct etna_varying {
struct tgsi_token toks[65536];
struct tgsi_parse_context parse;
struct etna_shader s = {};
+ struct etna_shader_key key = {};
void *ptr;
size_t size;
s.tokens = toks;
v->shader = &s;
+ v->key = key;
if (!etna_compile_shader(v)) {
fprintf(stderr, "compiler failed!\n");
}
}
+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)
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;
};
struct etna_shader_state {
+ void *bind_vs, *bind_fs;
struct etna_shader_variant *vs, *fs;
};
}
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;
return NULL;
v->shader = shader;
+ v->key = key;
ret = etna_compile_shader(v);
if (!ret) {
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)
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
}
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;
}
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;
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);