st/mesa: add tessellation shader states

additional fixes by Marek
This commit is contained in:
Ilia Mirkin 2014-07-11 22:11:21 -04:00 committed by Marek Olšák
parent df4ee8ef36
commit ba9fb96f86
9 changed files with 459 additions and 1 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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 */
};

View file

@ -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);

View file

@ -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++) {

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);