summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2010-12-10 14:59:32 -0700
committerBrian Paul <brianp@vmware.com>2010-12-10 14:59:34 -0700
commit2cc926183f957f8abac18d71276dd5bbd1f27be2 (patch)
treec629d85a4cd3d3956e9a5e33eec09171a187d716
parentb3d2ec9942303d1d03e28a25b030eb060415abfb (diff)
st/mesa: make vertex shader variants per-context
Gallium shaders are per-context but OpenGL shaders aren't. So we need to make a different variant for each context. During context tear-down we need to walk over all shaders/programs and free all variants for the context being destroyed.
-rw-r--r--src/mesa/state_tracker/st_atom_shader.c1
-rw-r--r--src/mesa/state_tracker/st_context.c2
-rw-r--r--src/mesa/state_tracker/st_program.c155
-rw-r--r--src/mesa/state_tracker/st_program.h4
4 files changed, 148 insertions, 14 deletions
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 05442ef91b..f0981629b5 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -106,6 +106,7 @@ find_translated_vp(struct st_context *st,
st->ctx->Polygon.FrontMode != GL_FILL ||
st->ctx->Polygon.BackMode != GL_FILL));
+ key.st = st; /* variants are per-context */
/* Do we need to throw away old translations after a change in the
* GL program string?
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index 6ec9c699a2..21bb91f47a 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -252,6 +252,8 @@ void st_destroy_context( struct st_context *st )
_vbo_DestroyContext(st->ctx);
+ st_destroy_program_variants(st);
+
_mesa_free_context_data(ctx);
st_destroy_context_priv(st);
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index aae2913c20..d7d9e0e36f 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -32,6 +32,7 @@
#include "main/imports.h"
+#include "main/hash.h"
#include "main/mtypes.h"
#include "program/prog_print.h"
#include "program/programopt.h"
@@ -52,6 +53,29 @@
/**
+ * Delete a vertex program varient. Note the caller must unlink
+ * the varient from the linked list.
+ */
+static void
+delete_vp_varient(struct st_context *st, struct st_vp_varient *vpv)
+{
+ if (vpv->driver_shader)
+ cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
+
+#if FEATURE_feedback || FEATURE_rastpos
+ if (vpv->draw_shader)
+ draw_delete_vertex_shader( st->draw, vpv->draw_shader );
+#endif
+
+ if (vpv->tgsi.tokens)
+ st_free_tokens(vpv->tgsi.tokens);
+
+ FREE( vpv );
+}
+
+
+
+/**
* Clean out any old compilations:
*/
void
@@ -62,20 +86,7 @@ st_vp_release_varients( struct st_context *st,
for (vpv = stvp->varients; vpv; ) {
struct st_vp_varient *next = vpv->next;
-
- if (vpv->driver_shader)
- cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
-
-#if FEATURE_feedback || FEATURE_rastpos
- if (vpv->draw_shader)
- draw_delete_vertex_shader( st->draw, vpv->draw_shader );
-#endif
-
- if (vpv->tgsi.tokens)
- st_free_tokens(vpv->tgsi.tokens);
-
- FREE( vpv );
-
+ delete_vp_varient(st, vpv);
vpv = next;
}
@@ -759,3 +770,119 @@ st_print_shaders(struct gl_context *ctx)
}
}
}
+
+
+/**
+ * Vert/Geom/Frag programs have per-context variants. Free all the
+ * variants attached to the given program which match the given context.
+ */
+static void
+destroy_program_variants(struct st_context *st, struct gl_program *program)
+{
+ if (!program)
+ return;
+
+ switch (program->Target) {
+ case GL_VERTEX_PROGRAM_ARB:
+ {
+ struct st_vertex_program *stvp = (struct st_vertex_program *) program;
+ struct st_vp_varient *vpv, **prev = &stvp->varients;
+
+ for (vpv = stvp->varients; vpv; ) {
+ struct st_vp_varient *next = vpv->next;
+ if (vpv->key.st == st) {
+ /* unlink from list */
+ *prev = next;
+ /* destroy this variant */
+ delete_vp_varient(st, vpv);
+ }
+ else {
+ prev = &vpv;
+ }
+ vpv = next;
+ }
+ }
+ break;
+ case GL_FRAGMENT_PROGRAM_ARB:
+ {
+ struct st_fragment_program *stfp =
+ (struct st_fragment_program *) program;
+ }
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected program target in "
+ "destroy_program_variants_cb()");
+ }
+}
+
+
+/**
+ * Callback for _mesa_HashWalk. Free all the shader's program variants
+ * which match the given context.
+ */
+static void
+destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
+{
+ struct st_context *st = (struct st_context *) userData;
+ struct gl_shader *shader = (struct gl_shader *) data;
+
+ switch (shader->Type) {
+ case GL_SHADER_PROGRAM_MESA:
+ {
+ struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+ GLuint i;
+
+ for (i = 0; i < shProg->NumShaders; i++) {
+ destroy_program_variants(st, shProg->Shaders[i]->Program);
+ }
+
+ destroy_program_variants(st, (struct gl_program *)
+ shProg->VertexProgram);
+ destroy_program_variants(st, (struct gl_program *)
+ shProg->FragmentProgram);
+ destroy_program_variants(st, (struct gl_program *)
+ shProg->GeometryProgram);
+ }
+ break;
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ case GL_GEOMETRY_SHADER:
+ {
+ destroy_program_variants(st, shader->Program);
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+
+/**
+ * Callback for _mesa_HashWalk. Free all the program variants which match
+ * the given context.
+ */
+static void
+destroy_program_variants_cb(GLuint key, void *data, void *userData)
+{
+ struct st_context *st = (struct st_context *) userData;
+ struct gl_program *program = (struct gl_program *) data;
+ destroy_program_variants(st, program);
+}
+
+
+/**
+ * Walk over all shaders and programs to delete any variants which
+ * belong to the given context.
+ * This is called during context tear-down.
+ */
+void
+st_destroy_program_variants(struct st_context *st)
+{
+ /* ARB vert/frag program */
+ _mesa_HashWalk(st->ctx->Shared->Programs,
+ destroy_program_variants_cb, st);
+
+ /* GLSL vert/frag/geom shaders */
+ _mesa_HashWalk(st->ctx->Shared->ShaderObjects,
+ destroy_shader_program_variants_cb, st);
+}
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 72dbc715fe..10362ed93b 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -60,6 +60,7 @@ struct st_fragment_program
struct st_vp_varient_key
{
+ struct st_context *st; /**< variants are per-context */
boolean passthrough_edgeflags;
};
@@ -225,5 +226,8 @@ st_vp_release_varients( struct st_context *st,
extern void
st_print_shaders(struct gl_context *ctx);
+extern void
+st_destroy_program_variants(struct st_context *st);
+
#endif