[Mesa-dev] [PATCH 02/14] st/mesa: add tessellation shader states
Marek Olšák
maraeo at gmail.com
Tue Jun 16 16:04:43 PDT 2015
From: Ilia Mirkin <imirkin at alum.mit.edu>
additional fixes by Marek
---
src/mesa/state_tracker/st_atom.c | 2 +
src/mesa/state_tracker/st_atom.h | 2 +
src/mesa/state_tracker/st_atom_shader.c | 72 +++++++++++
src/mesa/state_tracker/st_cb_program.c | 58 +++++++++
src/mesa/state_tracker/st_context.c | 2 +
src/mesa/state_tracker/st_context.h | 6 +
src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 4 +
src/mesa/state_tracker/st_program.c | 192 +++++++++++++++++++++++++++++
src/mesa/state_tracker/st_program.h | 122 +++++++++++++++++-
9 files changed, 459 insertions(+), 1 deletion(-)
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c
index 428f2d9..1c3eb7e 100644
--- a/src/mesa/state_tracker/st_atom.c
+++ b/src/mesa/state_tracker/st_atom.c
@@ -49,6 +49,8 @@ static const struct st_tracked_state *atoms[] =
&st_finalize_textures,
&st_update_fp,
&st_update_gp,
+ &st_update_tep,
+ &st_update_tcp,
&st_update_vp,
&st_update_rasterizer,
diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h
index c50111d..bec4a81 100644
--- a/src/mesa/state_tracker/st_atom.h
+++ b/src/mesa/state_tracker/st_atom.h
@@ -52,6 +52,8 @@ extern const struct st_tracked_state st_update_clip;
extern const struct st_tracked_state st_update_depth_stencil_alpha;
extern const struct st_tracked_state st_update_fp;
extern const struct st_tracked_state st_update_gp;
+extern const struct st_tracked_state st_update_tep;
+extern const struct st_tracked_state st_update_tcp;
extern const struct st_tracked_state st_update_vp;
extern const struct st_tracked_state st_update_rasterizer;
extern const struct st_tracked_state st_update_polygon_stipple;
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index ad8d262..d27882d 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -210,3 +210,75 @@ const struct st_tracked_state st_update_gp = {
},
update_gp /* update */
};
+
+
+
+static void
+update_tcp( struct st_context *st )
+{
+ struct st_tessctrl_program *sttcp;
+ struct st_tcp_variant_key key;
+
+ if (!st->ctx->TessCtrlProgram._Current) {
+ cso_set_tessctrl_shader_handle(st->cso_context, NULL);
+ return;
+ }
+
+ sttcp = st_tessctrl_program(st->ctx->TessCtrlProgram._Current);
+ assert(sttcp->Base.Base.Target == GL_TESS_CONTROL_PROGRAM_NV);
+
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+
+ st->tcp_variant = st_get_tcp_variant(st, sttcp, &key);
+
+ st_reference_tesscprog(st, &st->tcp, sttcp);
+
+ cso_set_tessctrl_shader_handle(st->cso_context,
+ st->tcp_variant->driver_shader);
+}
+
+const struct st_tracked_state st_update_tcp = {
+ "st_update_tcp", /* name */
+ { /* dirty */
+ 0, /* mesa */
+ ST_NEW_TESSCTRL_PROGRAM /* st */
+ },
+ update_tcp /* update */
+};
+
+
+
+static void
+update_tep( struct st_context *st )
+{
+ struct st_tesseval_program *sttep;
+ struct st_tep_variant_key key;
+
+ if (!st->ctx->TessEvalProgram._Current) {
+ cso_set_tesseval_shader_handle(st->cso_context, NULL);
+ return;
+ }
+
+ sttep = st_tesseval_program(st->ctx->TessEvalProgram._Current);
+ assert(sttep->Base.Base.Target == GL_TESS_EVALUATION_PROGRAM_NV);
+
+ memset(&key, 0, sizeof(key));
+ key.st = st;
+
+ st->tep_variant = st_get_tep_variant(st, sttep, &key);
+
+ st_reference_tesseprog(st, &st->tep, sttep);
+
+ cso_set_tesseval_shader_handle(st->cso_context,
+ st->tep_variant->driver_shader);
+}
+
+const struct st_tracked_state st_update_tep = {
+ "st_update_tep", /* name */
+ { /* dirty */
+ 0, /* mesa */
+ ST_NEW_TESSEVAL_PROGRAM /* st */
+ },
+ update_tep /* update */
+};
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index 6aa7d57..3029909 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -68,6 +68,12 @@ st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog)
case GL_GEOMETRY_PROGRAM_NV:
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
break;
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ st->dirty.st |= ST_NEW_TESSCTRL_PROGRAM;
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM;
+ break;
}
}
@@ -84,6 +90,8 @@ st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
+ st->dirty.st |= ST_NEW_TESSCTRL_PROGRAM;
+ st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM;
}
@@ -110,6 +118,16 @@ st_new_program(struct gl_context *ctx, GLenum target, GLuint id)
return _mesa_init_geometry_program(ctx, &prog->Base, target, id);
}
+ case GL_TESS_CONTROL_PROGRAM_NV: {
+ struct st_tessctrl_program *prog = ST_CALLOC_STRUCT(st_tessctrl_program);
+ return _mesa_init_tess_ctrl_program(ctx, &prog->Base, target, id);
+ }
+
+ case GL_TESS_EVALUATION_PROGRAM_NV: {
+ struct st_tesseval_program *prog = ST_CALLOC_STRUCT(st_tesseval_program);
+ return _mesa_init_tess_eval_program(ctx, &prog->Base, target, id);
+ }
+
default:
assert(0);
return NULL;
@@ -157,6 +175,28 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi);
}
break;
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ {
+ struct st_tessctrl_program *sttcp =
+ (struct st_tessctrl_program *) prog;
+
+ st_release_tcp_variants(st, sttcp);
+
+ if (sttcp->glsl_to_tgsi)
+ free_glsl_to_tgsi_visitor(sttcp->glsl_to_tgsi);
+ }
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ {
+ struct st_tesseval_program *sttep =
+ (struct st_tesseval_program *) prog;
+
+ st_release_tep_variants(st, sttep);
+
+ if (sttep->glsl_to_tgsi)
+ free_glsl_to_tgsi_visitor(sttep->glsl_to_tgsi);
+ }
+ break;
default:
assert(0); /* problem */
}
@@ -214,6 +254,24 @@ st_program_string_notify( struct gl_context *ctx,
if (st->vp == stvp)
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
}
+ else if (target == GL_TESS_CONTROL_PROGRAM_NV) {
+ struct st_tessctrl_program *sttcp =
+ (struct st_tessctrl_program *) prog;
+
+ st_release_tcp_variants(st, sttcp);
+
+ if (st->tcp == sttcp)
+ st->dirty.st |= ST_NEW_TESSCTRL_PROGRAM;
+ }
+ else if (target == GL_TESS_EVALUATION_PROGRAM_NV) {
+ struct st_tesseval_program *sttep =
+ (struct st_tesseval_program *) prog;
+
+ st_release_tep_variants(st, sttep);
+
+ if (st->tep == sttep)
+ st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM;
+ }
if (ST_DEBUG & DEBUG_PRECOMPILE)
st_precompile_shader_variant(st, prog);
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index ed9ed0f..ef4ad1b 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -369,6 +369,8 @@ void st_destroy_context( struct st_context *st )
st_reference_fragprog(st, &st->fp, NULL);
st_reference_geomprog(st, &st->gp, NULL);
st_reference_vertprog(st, &st->vp, NULL);
+ st_reference_tesscprog(st, &st->tcp, NULL);
+ st_reference_tesseprog(st, &st->tep, NULL);
/* release framebuffer surfaces */
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index dac5a4b..3010727 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -58,6 +58,8 @@ struct u_upload_mgr;
#define ST_NEW_VERTEX_ARRAYS (1 << 6)
#define ST_NEW_RASTERIZER (1 << 7)
#define ST_NEW_UNIFORM_BUFFER (1 << 8)
+#define ST_NEW_TESSCTRL_PROGRAM (1 << 9)
+#define ST_NEW_TESSEVAL_PROGRAM (1 << 10)
struct st_state_flags {
@@ -147,10 +149,14 @@ struct st_context
struct st_vertex_program *vp; /**< Currently bound vertex program */
struct st_fragment_program *fp; /**< Currently bound fragment program */
struct st_geometry_program *gp; /**< Currently bound geometry program */
+ struct st_tessctrl_program *tcp; /**< Currently bound tess control program */
+ struct st_tesseval_program *tep; /**< Currently bound tess eval program */
struct st_vp_variant *vp_variant;
struct st_fp_variant *fp_variant;
struct st_gp_variant *gp_variant;
+ struct st_tcp_variant *tcp_variant;
+ struct st_tep_variant *tep_variant;
struct gl_texture_object *default_texture;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 9d10eef..c32ecb8 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -5587,6 +5587,10 @@ shader_stage_to_ptarget(gl_shader_stage stage)
return PIPE_SHADER_FRAGMENT;
case MESA_SHADER_GEOMETRY:
return PIPE_SHADER_GEOMETRY;
+ case MESA_SHADER_TESS_CTRL:
+ return PIPE_SHADER_TESS_CTRL;
+ case MESA_SHADER_TESS_EVAL:
+ return PIPE_SHADER_TESS_EVAL;
case MESA_SHADER_COMPUTE:
return PIPE_SHADER_COMPUTE;
}
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index fa792bc..9925794 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -163,6 +163,68 @@ st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp)
}
+/**
+ * Delete a tessellation control program variant. Note the caller must unlink
+ * the variant from the linked list.
+ */
+static void
+delete_tcp_variant(struct st_context *st, struct st_tcp_variant *tcpv)
+{
+ if (tcpv->driver_shader)
+ cso_delete_tessctrl_shader(st->cso_context, tcpv->driver_shader);
+
+ free(tcpv);
+}
+
+
+/**
+ * Free all variants of a tessellation control program.
+ */
+void
+st_release_tcp_variants(struct st_context *st, struct st_tessctrl_program *sttcp)
+{
+ struct st_tcp_variant *tcpv;
+
+ for (tcpv = sttcp->variants; tcpv; ) {
+ struct st_tcp_variant *next = tcpv->next;
+ delete_tcp_variant(st, tcpv);
+ tcpv = next;
+ }
+
+ sttcp->variants = NULL;
+}
+
+
+/**
+ * Delete a tessellation evaluation program variant. Note the caller must
+ * unlink the variant from the linked list.
+ */
+static void
+delete_tep_variant(struct st_context *st, struct st_tep_variant *tepv)
+{
+ if (tepv->driver_shader)
+ cso_delete_tesseval_shader(st->cso_context, tepv->driver_shader);
+
+ free(tepv);
+}
+
+
+/**
+ * Free all variants of a tessellation evaluation program.
+ */
+void
+st_release_tep_variants(struct st_context *st, struct st_tesseval_program *sttep)
+{
+ struct st_tep_variant *tepv;
+
+ for (tepv = sttep->variants; tepv; ) {
+ struct st_tep_variant *next = tepv->next;
+ delete_tep_variant(st, tepv);
+ tepv = next;
+ }
+
+ sttep->variants = NULL;
+}
/**
@@ -1168,6 +1230,92 @@ st_get_gp_variant(struct st_context *st,
/**
+ * Translate a tessellation control program to create a new variant.
+ */
+static struct st_tcp_variant *
+st_translate_tessctrl_program(struct st_context *st,
+ struct st_tessctrl_program *sttcp,
+ const struct st_tcp_variant_key *key)
+{
+ return NULL; /* will be updated in the next commit */
+}
+
+
+/**
+ * Get/create tessellation control program variant.
+ */
+struct st_tcp_variant *
+st_get_tcp_variant(struct st_context *st,
+ struct st_tessctrl_program *sttcp,
+ const struct st_tcp_variant_key *key)
+{
+ struct st_tcp_variant *tcpv;
+
+ /* Search for existing variant */
+ for (tcpv = sttcp->variants; tcpv; tcpv = tcpv->next) {
+ if (memcmp(&tcpv->key, key, sizeof(*key)) == 0) {
+ break;
+ }
+ }
+
+ if (!tcpv) {
+ /* create new */
+ tcpv = st_translate_tessctrl_program(st, sttcp, key);
+ if (tcpv) {
+ /* insert into list */
+ tcpv->next = sttcp->variants;
+ sttcp->variants = tcpv;
+ }
+ }
+
+ return tcpv;
+}
+
+
+/**
+ * Translate a tessellation evaluation program to create a new variant.
+ */
+static struct st_tep_variant *
+st_translate_tesseval_program(struct st_context *st,
+ struct st_tesseval_program *sttep,
+ const struct st_tep_variant_key *key)
+{
+ return NULL; /* will be updated in the next commit */
+}
+
+
+/**
+ * Get/create tessellation evaluation program variant.
+ */
+struct st_tep_variant *
+st_get_tep_variant(struct st_context *st,
+ struct st_tesseval_program *sttep,
+ const struct st_tep_variant_key *key)
+{
+ struct st_tep_variant *tepv;
+
+ /* Search for existing variant */
+ for (tepv = sttep->variants; tepv; tepv = tepv->next) {
+ if (memcmp(&tepv->key, key, sizeof(*key)) == 0) {
+ break;
+ }
+ }
+
+ if (!tepv) {
+ /* create new */
+ tepv = st_translate_tesseval_program(st, sttep, key);
+ if (tepv) {
+ /* insert into list */
+ tepv->next = sttep->variants;
+ sttep->variants = tepv;
+ }
+ }
+
+ return tepv;
+}
+
+
+/**
* Vert/Geom/Frag programs have per-context variants. Free all the
* variants attached to the given program which match the given context.
*/
@@ -1240,6 +1388,48 @@ destroy_program_variants(struct st_context *st, struct gl_program *program)
}
}
break;
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ {
+ struct st_tessctrl_program *sttcp =
+ (struct st_tessctrl_program *) program;
+ struct st_tcp_variant *tcpv, **prevPtr = &sttcp->variants;
+
+ for (tcpv = sttcp->variants; tcpv; ) {
+ struct st_tcp_variant *next = tcpv->next;
+ if (tcpv->key.st == st) {
+ /* unlink from list */
+ *prevPtr = next;
+ /* destroy this variant */
+ delete_tcp_variant(st, tcpv);
+ }
+ else {
+ prevPtr = &tcpv->next;
+ }
+ tcpv = next;
+ }
+ }
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ {
+ struct st_tesseval_program *sttep =
+ (struct st_tesseval_program *) program;
+ struct st_tep_variant *tepv, **prevPtr = &sttep->variants;
+
+ for (tepv = sttep->variants; tepv; ) {
+ struct st_tep_variant *next = tepv->next;
+ if (tepv->key.st == st) {
+ /* unlink from list */
+ *prevPtr = next;
+ /* destroy this variant */
+ delete_tep_variant(st, tepv);
+ }
+ else {
+ prevPtr = &tepv->next;
+ }
+ tepv = next;
+ }
+ }
+ break;
default:
_mesa_problem(NULL, "Unexpected program target 0x%x in "
"destroy_program_variants_cb()", program->Target);
@@ -1276,6 +1466,8 @@ destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
case GL_VERTEX_SHADER:
case GL_FRAGMENT_SHADER:
case GL_GEOMETRY_SHADER:
+ case GL_TESS_CONTROL_SHADER:
+ case GL_TESS_EVALUATION_SHADER:
{
destroy_program_variants(st, shader->Program);
}
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index bb77eb6..7013993 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -188,7 +188,7 @@ struct st_gp_variant_key
*/
struct st_gp_variant
{
- /* Parameters which generated this translated version of a vertex */
+ /* Parameters which generated this variant. */
struct st_gp_variant_key key;
void *driver_shader;
@@ -210,6 +210,76 @@ struct st_geometry_program
+/** Tessellation control program variant key */
+struct st_tcp_variant_key
+{
+ struct st_context *st; /**< variants are per-context */
+ /* no other fields yet */
+};
+
+
+/**
+ * Tessellation control program variant.
+ */
+struct st_tcp_variant
+{
+ /* Parameters which generated this variant. */
+ struct st_tcp_variant_key key;
+
+ void *driver_shader;
+
+ struct st_tcp_variant *next;
+};
+
+
+/**
+ * Derived from Mesa gl_tess_ctrl_program:
+ */
+struct st_tessctrl_program
+{
+ struct gl_tess_ctrl_program Base; /**< The Mesa tess ctrl program */
+ struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+
+ struct st_tcp_variant *variants;
+};
+
+
+
+/** Tessellation evaluation program variant key */
+struct st_tep_variant_key
+{
+ struct st_context *st; /**< variants are per-context */
+ /* no other fields yet */
+};
+
+
+/**
+ * Tessellation evaluation program variant.
+ */
+struct st_tep_variant
+{
+ /* Parameters which generated this variant. */
+ struct st_tep_variant_key key;
+
+ void *driver_shader;
+
+ struct st_tep_variant *next;
+};
+
+
+/**
+ * Derived from Mesa gl_tess_eval_program:
+ */
+struct st_tesseval_program
+{
+ struct gl_tess_eval_program Base; /**< The Mesa tess eval program */
+ struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+
+ struct st_tep_variant *variants;
+};
+
+
+
static inline struct st_fragment_program *
st_fragment_program( struct gl_fragment_program *fp )
{
@@ -229,6 +299,18 @@ st_geometry_program( struct gl_geometry_program *gp )
return (struct st_geometry_program *)gp;
}
+static inline struct st_tessctrl_program *
+st_tessctrl_program( struct gl_tess_ctrl_program *tcp )
+{
+ return (struct st_tessctrl_program *)tcp;
+}
+
+static inline struct st_tesseval_program *
+st_tesseval_program( struct gl_tess_eval_program *tep )
+{
+ return (struct st_tesseval_program *)tep;
+}
+
static inline void
st_reference_vertprog(struct st_context *st,
struct st_vertex_program **ptr,
@@ -259,6 +341,26 @@ st_reference_fragprog(struct st_context *st,
(struct gl_program *) prog);
}
+static inline void
+st_reference_tesscprog(struct st_context *st,
+ struct st_tessctrl_program **ptr,
+ struct st_tessctrl_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static inline void
+st_reference_tesseprog(struct st_context *st,
+ struct st_tesseval_program **ptr,
+ struct st_tesseval_program *prog)
+{
+ _mesa_reference_program(st->ctx,
+ (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
/**
* This defines mapping from Mesa VARYING_SLOTs to TGSI GENERIC slots.
*/
@@ -302,6 +404,16 @@ st_get_gp_variant(struct st_context *st,
struct st_geometry_program *stgp,
const struct st_gp_variant_key *key);
+extern struct st_tcp_variant *
+st_get_tcp_variant(struct st_context *st,
+ struct st_tessctrl_program *stgp,
+ const struct st_tcp_variant_key *key);
+
+extern struct st_tep_variant *
+st_get_tep_variant(struct st_context *st,
+ struct st_tesseval_program *stgp,
+ const struct st_tep_variant_key *key);
+
extern void
st_prepare_vertex_program(struct gl_context *ctx,
@@ -325,6 +437,14 @@ st_release_gp_variants(struct st_context *st,
struct st_geometry_program *stgp);
extern void
+st_release_tcp_variants(struct st_context *st,
+ struct st_tessctrl_program *stgp);
+
+extern void
+st_release_tep_variants(struct st_context *st,
+ struct st_tesseval_program *stgp);
+
+extern void
st_destroy_program_variants(struct st_context *st);
--
2.1.0
More information about the mesa-dev
mailing list