From: Ilia Mirkin Date: Sat, 12 Jul 2014 02:11:21 +0000 (-0400) Subject: st/mesa: add tessellation shader states X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ba9fb96f86344f1631b82114bb0ce6f926d3853a;p=mesa.git st/mesa: add tessellation shader states additional fixes by Marek --- diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 428f2d9d7d7..1c3eb7ec45a 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 c50111d501f..bec4a810406 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 ad8d2624fc9..d27882def7b 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 6aa7d5796d9..3029909d12d 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 62a0fbee3bb..0c80fa1179d 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -374,6 +374,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 dac5a4b9006..301072742cf 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 0ed16aeab87..be3ae6fc47d 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5622,6 +5622,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 fa792bc349b..99257949ba3 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; +} /** @@ -1167,6 +1229,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 bb77eb6ed65..7013993fe38 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, @@ -324,6 +436,14 @@ extern void 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);