From e12d6791c5e4bff60bb2e6c04414b1b4d1325f3e Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 13 Dec 2010 13:38:12 -0700 Subject: st/mesa: implement geometry shader varients Only needed in order to support per-context gallium shaders. --- src/mesa/state_tracker/st_atom_shader.c | 39 ++++------ src/mesa/state_tracker/st_cb_program.c | 28 ++----- src/mesa/state_tracker/st_context.h | 1 + src/mesa/state_tracker/st_program.c | 132 +++++++++++++++++++++++++------- src/mesa/state_tracker/st_program.h | 50 +++++++++--- 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 ) { @@ -232,20 +258,18 @@ 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 ); @@ -267,6 +292,11 @@ extern void 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); -- cgit v1.2.3