summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2010-12-13 13:38:12 -0700
committerBrian Paul <brianp@vmware.com>2010-12-13 13:38:16 -0700
commite12d6791c5e4bff60bb2e6c04414b1b4d1325f3e (patch)
treee242f038a77902b93f9964740d064f341c1ab3ae
parentc5751c673644808ab069259a852f24c4c0e92b9d (diff)
st/mesa: implement geometry shader varients
Only needed in order to support per-context gallium shaders.
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c39
-rw-r--r--src/mesa/state_tracker/st_cb_program.c28
-rw-r--r--src/mesa/state_tracker/st_context.h1
-rw-r--r--src/mesa/state_tracker/st_program.c132
-rw-r--r--src/mesa/state_tracker/st_program.h50
5 files changed, 165 insertions, 85 deletions
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 94890e9fea..a0e8565bdb 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -50,21 +50,6 @@
#include "st_program.h"
-
-/*
- * Translate geometry program if needed.
- */
-static void
-translate_gp(struct st_context *st,
- struct st_geometry_program *stgp)
-{
- if (!stgp->tgsi.tokens) {
- assert(stgp->Base.Base.NumInstructions > 1);
-
- st_translate_geometry_program(st, stgp);
- }
-}
-
/**
* Find a translated vertex program that corresponds to stvp and
* has outputs matched to stfp's inputs.
@@ -224,14 +209,16 @@ const struct st_tracked_state st_update_vp = {
_NEW_POLYGON, /* mesa */
ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */
},
- update_vp /* update */
+ update_vp /* update */
};
+
+
static void
update_gp( struct st_context *st )
{
-
struct st_geometry_program *stgp;
+ struct st_gp_varient_key key;
if (!st->ctx->GeometryProgram._Current) {
cso_set_geometry_shader_handle(st->cso_context, NULL);
@@ -241,18 +228,22 @@ update_gp( struct st_context *st )
stgp = st_geometry_program(st->ctx->GeometryProgram._Current);
assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM);
- translate_gp(st, stgp);
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+
+ st->gp_varient = st_get_gp_varient(st, stgp, &key);
st_reference_geomprog(st, &st->gp, stgp);
- cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader);
+ cso_set_geometry_shader_handle(st->cso_context,
+ st->gp_varient->driver_shader);
}
const struct st_tracked_state st_update_gp = {
- "st_update_gp", /* name */
- { /* dirty */
- 0, /* mesa */
- ST_NEW_GEOMETRY_PROGRAM /* st */
+ "st_update_gp", /* name */
+ { /* dirty */
+ 0, /* mesa */
+ ST_NEW_GEOMETRY_PROGRAM /* st */
},
- update_gp /* update */
+ update_gp /* update */
};
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index 25a135a05d..08d29ae11b 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -150,12 +150,10 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
break;
case MESA_GEOMETRY_PROGRAM:
{
- struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
+ struct st_geometry_program *stgp =
+ (struct st_geometry_program *) prog;
- if (stgp->driver_shader) {
- cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
- stgp->driver_shader = NULL;
- }
+ st_gp_release_varients(st, stgp);
if (stgp->tgsi.tokens) {
st_free_tokens((void *) stgp->tgsi.tokens);
@@ -167,26 +165,13 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
{
struct st_fragment_program *stfp =
(struct st_fragment_program *) prog;
- st_fp_release_varients(st, stfp);
-#if 0
- if (stfp->driver_shader) {
- cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
- stfp->driver_shader = NULL;
- }
+ st_fp_release_varients(st, stfp);
if (stfp->tgsi.tokens) {
st_free_tokens(stfp->tgsi.tokens);
stfp->tgsi.tokens = NULL;
}
-
- if (stfp->bitmap_program) {
- struct gl_program *prg = &stfp->bitmap_program->Base.Base;
- _mesa_reference_program(ctx, &prg, NULL);
- stfp->bitmap_program = NULL;
- }
-#endif
-
}
break;
default:
@@ -230,10 +215,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx,
stgp->serialNo++;
- if (stgp->driver_shader) {
- cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
- stgp->driver_shader = NULL;
- }
+ st_gp_release_varients(st, stgp);
if (stgp->tgsi.tokens) {
st_free_tokens((void *) stgp->tgsi.tokens);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 45597696ff..26565225e3 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -132,6 +132,7 @@ struct st_context
struct st_vp_varient *vp_varient;
struct st_fp_varient *fp_varient;
+ struct st_gp_varient *gp_varient;
struct gl_texture_object *default_texture;
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 795d8757ae..18c90b7fa4 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -130,6 +130,38 @@ st_fp_release_varients(struct st_context *st, struct st_fragment_program *stfp)
}
+/**
+ * Delete a geometry program varient. Note the caller must unlink
+ * the varient from the linked list.
+ */
+static void
+delete_gp_varient(struct st_context *st, struct st_gp_varient *gpv)
+{
+ if (gpv->driver_shader)
+ cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
+
+ FREE(gpv);
+}
+
+
+/**
+ * Free all varients of a geometry program.
+ */
+void
+st_gp_release_varients(struct st_context *st, struct st_geometry_program *stgp)
+{
+ struct st_gp_varient *gpv;
+
+ for (gpv = stgp->varients; gpv; ) {
+ struct st_gp_varient *next = gpv->next;
+ delete_gp_varient(st, gpv);
+ gpv = next;
+ }
+
+ stgp->varients = NULL;
+}
+
+
/**
@@ -330,7 +362,7 @@ fail:
* the key.
* \return new fragment program variant
*/
-struct st_fp_varient *
+static struct st_fp_varient *
st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *stfp,
const struct st_fp_varient_key *key)
@@ -591,10 +623,13 @@ st_get_fp_varient(struct st_context *st,
}
-
-void
+/**
+ * Translate a geometry program to create a new varient.
+ */
+static struct st_gp_varient *
st_translate_geometry_program(struct st_context *st,
- struct st_geometry_program *stgp)
+ struct st_geometry_program *stgp,
+ const struct st_gp_varient_key *key)
{
GLuint inputMapping[GEOM_ATTRIB_MAX];
GLuint outputMapping[GEOM_RESULT_MAX];
@@ -617,12 +652,19 @@ st_translate_geometry_program(struct st_context *st,
GLuint maxSlot = 0;
struct ureg_program *ureg;
+ struct st_gp_varient *gpv;
+
+ gpv = CALLOC_STRUCT(st_gp_varient);
+ if (!gpv)
+ return NULL;
+
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
if (ureg == NULL) {
- return;
+ FREE(gpv);
+ return NULL;
}
/* which vertex output goes to the first geometry input */
@@ -652,7 +694,7 @@ st_translate_geometry_program(struct st_context *st,
} else
++gs_builtin_inputs;
-#if 1
+#if 0
debug_printf("input map at %d = %d\n",
slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
#endif
@@ -794,37 +836,35 @@ st_translate_geometry_program(struct st_context *st,
st_free_tokens(stgp->tgsi.tokens);
stgp->tgsi.tokens = NULL;
}
- if (stgp->driver_shader) {
- cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
- stgp->driver_shader = NULL;
- }
ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
- error = st_translate_mesa_program(st->ctx,
- TGSI_PROCESSOR_GEOMETRY,
- ureg,
- &stgp->Base.Base,
- /* inputs */
- gs_num_inputs,
- inputMapping,
- stgp->input_semantic_name,
- stgp->input_semantic_index,
- NULL,
- /* outputs */
- gs_num_outputs,
- outputMapping,
- gs_output_semantic_name,
- gs_output_semantic_index,
- FALSE);
-
+ error = st_translate_mesa_program(st->ctx,
+ TGSI_PROCESSOR_GEOMETRY,
+ ureg,
+ &stgp->Base.Base,
+ /* inputs */
+ gs_num_inputs,
+ inputMapping,
+ stgp->input_semantic_name,
+ stgp->input_semantic_index,
+ NULL,
+ /* outputs */
+ gs_num_outputs,
+ outputMapping,
+ gs_output_semantic_name,
+ gs_output_semantic_index,
+ FALSE);
stgp->num_inputs = gs_num_inputs;
stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
ureg_destroy( ureg );
- stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
+
+ /* fill in new varient */
+ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
+ gpv->key = *key;
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
_mesa_print_program(&stgp->Base.Base);
@@ -835,8 +875,44 @@ st_translate_geometry_program(struct st_context *st,
tgsi_dump(stgp->tgsi.tokens, 0);
debug_printf("\n");
}
+
+ return gpv;
+}
+
+
+/**
+ * Get/create geometry program variant.
+ */
+struct st_gp_varient *
+st_get_gp_varient(struct st_context *st,
+ struct st_geometry_program *stgp,
+ const struct st_gp_varient_key *key)
+{
+ struct st_gp_varient *gpv;
+
+ /* Search for existing varient */
+ for (gpv = stgp->varients; gpv; gpv = gpv->next) {
+ if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
+ break;
+ }
+ }
+
+ if (!gpv) {
+ /* create new */
+ gpv = st_translate_geometry_program(st, stgp, key);
+ if (gpv) {
+ /* insert into list */
+ gpv->next = stgp->varients;
+ stgp->varients = gpv;
+ }
+ }
+
+ return gpv;
}
+
+
+
/**
* Debug- print current shader text
*/
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index acbecc924a..245866bf65 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -154,6 +154,29 @@ struct st_vertex_program
struct st_vp_varient *varients;
};
+
+
+struct st_gp_varient_key
+{
+ struct st_context *st; /**< variants are per-context */
+ /* no other fields yet */
+};
+
+
+/**
+ * Geometry program variant.
+ */
+struct st_gp_varient
+{
+ /* Parameters which generated this translated version of a vertex */
+ struct st_gp_varient_key key;
+
+ void *driver_shader;
+
+ struct st_gp_varient *next;
+};
+
+
/**
* Derived from Mesa gl_geometry_program:
*/
@@ -179,9 +202,12 @@ struct st_geometry_program
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
struct pipe_shader_state tgsi;
- void *driver_shader;
+
+ struct st_gp_varient *varients;
};
+
+
static INLINE struct st_fragment_program *
st_fragment_program( struct gl_fragment_program *fp )
{
@@ -233,19 +259,17 @@ st_reference_fragprog(struct st_context *st,
extern struct st_fp_varient *
-st_translate_fragment_program(struct st_context *st,
- struct st_fragment_program *fp,
- const struct st_fp_varient_key *key);
-
-extern struct st_fp_varient *
st_get_fp_varient(struct st_context *st,
struct st_fragment_program *stfp,
const struct st_fp_varient_key *key);
-extern void
-st_translate_geometry_program(struct st_context *st,
- struct st_geometry_program *stgp);
+extern struct st_gp_varient *
+st_get_gp_varient(struct st_context *st,
+ struct st_geometry_program *stgp,
+ const struct st_gp_varient_key *key);
+
+
/* Called after program string change, discard all previous
* compilation results.
@@ -259,7 +283,8 @@ st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp,
const struct st_vp_varient_key *key);
-void
+
+extern void
st_vp_release_varients( struct st_context *st,
struct st_vertex_program *stvp );
@@ -268,6 +293,11 @@ st_fp_release_varients( struct st_context *st,
struct st_fragment_program *stfp );
extern void
+st_gp_release_varients(struct st_context *st,
+ struct st_geometry_program *stgp);
+
+
+extern void
st_print_shaders(struct gl_context *ctx);
extern void