etnaviv: add basic shader variant support
This commit adds some basic infrastructure to handle shader
variants. We are still creating exactly one shader variant
for each shader.
Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler.h b/src/gallium/drivers/etnaviv/etnaviv_compiler.h
index 2a3b4f4..8de0126 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_compiler.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_compiler.h
@@ -92,6 +92,9 @@
/* unknown input property (XX_INPUT_COUNT, field UNK8) */
uint32_t input_count_unk8;
+
+ /* shader variants form a linked list */
+ struct etna_shader_variant *next;
};
struct etna_varying {
diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.c b/src/gallium/drivers/etnaviv/etnaviv_shader.c
index 35084e5..0ef611f 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_shader.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_shader.c
@@ -31,6 +31,7 @@
#include "etnaviv_debug.h"
#include "etnaviv_util.h"
+#include "tgsi/tgsi_parse.h"
#include "util/u_math.h"
#include "util/u_memory.h"
@@ -266,25 +267,65 @@
ctx->vertex_elements);
}
+static struct etna_shader_variant *
+create_variant(struct etna_shader *shader)
+{
+ struct etna_shader_variant *v;
+
+ v = etna_compile_shader(shader->specs, shader->tokens);
+ if (!v) {
+ debug_error("compile failed!");
+ return NULL;
+ }
+
+ v->id = ++shader->variant_count;
+
+ return v;
+}
+
static void *
etna_create_shader_state(struct pipe_context *pctx,
const struct pipe_shader_state *pss)
{
struct etna_context *ctx = etna_context(pctx);
- struct etna_shader_variant *shader = etna_compile_shader(&ctx->specs, pss->tokens);
+ struct etna_shader *shader = CALLOC_STRUCT(etna_shader);
+
+ if (!shader)
+ return NULL;
static uint32_t id;
shader->id = id++;
+ shader->specs = &ctx->specs;
+ shader->tokens = tgsi_dup_tokens(pss->tokens);
- dump_shader_info(shader, &ctx->debug);
+ /* compile new variant */
+ struct etna_shader_variant *v;
- return shader;
+ v = create_variant(shader);
+ if (v) {
+ v->next = shader->variants;
+ shader->variants = v;
+ dump_shader_info(v, &ctx->debug);
+ }
+
+ return v;
}
static void
etna_delete_shader_state(struct pipe_context *pctx, void *ss)
{
- etna_destroy_shader(ss);
+ struct etna_shader *shader = ss;
+ struct etna_shader_variant *v, *t;
+
+ v = shader->variants;
+ while (v) {
+ t = v;
+ v = v->next;
+ etna_destroy_shader(t);
+ }
+
+ FREE(shader->tokens);
+ FREE(shader);
}
static void
diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.h b/src/gallium/drivers/etnaviv/etnaviv_shader.h
index 1dbd200..c613c17 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_shader.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_shader.h
@@ -30,6 +30,18 @@
#include "pipe/p_state.h"
struct etna_context;
+struct etna_shader_variant;
+
+struct etna_shader {
+ /* shader id (for debug): */
+ uint32_t id;
+ uint32_t variant_count;
+
+ struct tgsi_token *tokens;
+ struct etna_specs *specs;
+
+ struct etna_shader_variant *variants;
+};
bool
etna_shader_link(struct etna_context *ctx);