Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> Reviewed-by: Marek Olšák <marek.ol...@amd.com> Reviewed-by: Ilia Mirkin <imir...@alum.mit.edu> --- src/mesa/state_tracker/st_atom.c | 2 +- src/mesa/state_tracker/st_atom.h | 1 + src/mesa/state_tracker/st_atom_shader.c | 36 +++++++++ src/mesa/state_tracker/st_cb_program.c | 28 +++++++ src/mesa/state_tracker/st_context.c | 1 + src/mesa/state_tracker/st_context.h | 3 + src/mesa/state_tracker/st_extensions.c | 7 +- src/mesa/state_tracker/st_program.c | 130 ++++++++++++++++++++++++++++++++ src/mesa/state_tracker/st_program.h | 63 ++++++++++++++++ 9 files changed, 268 insertions(+), 3 deletions(-)
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 2d89512..3427a92 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -98,7 +98,7 @@ static const struct st_tracked_state *render_atoms[] = */ static const struct st_tracked_state *compute_atoms[] = { - /* will be updated in the next commit */ + &st_update_cp, }; diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index 77e2163..ef33645 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -58,6 +58,7 @@ 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_cp; extern const struct st_tracked_state st_update_rasterizer; extern const struct st_tracked_state st_update_polygon_stipple; extern const struct st_tracked_state st_update_viewport; diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 23b7abf..954166e 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -252,3 +252,39 @@ const struct st_tracked_state st_update_tep = { }, update_tep /* update */ }; + + + +static void +update_cp( struct st_context *st ) +{ + struct st_compute_program *stcp; + struct st_cp_variant_key key; + + if (!st->ctx->ComputeProgram._Current) { + cso_set_compute_shader_handle(st->cso_context, NULL); + return; + } + + stcp = st_compute_program(st->ctx->ComputeProgram._Current); + assert(stcp->Base.Base.Target == GL_COMPUTE_PROGRAM_NV); + + memset(&key, 0, sizeof(key)); + key.st = st->has_shareable_shaders ? NULL : st; + + st->cp_variant = st_get_cp_variant(st, stcp, &key); + + st_reference_compprog(st, &st->cp, stcp); + + cso_set_compute_shader_handle(st->cso_context, + st->cp_variant->driver_shader); +} + +const struct st_tracked_state st_update_cp = { + "st_update_cp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_COMPUTE_PROGRAM /* st */ + }, + update_cp /* update */ +}; diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index ca493d8..70cbbec 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -74,6 +74,9 @@ st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog) case GL_TESS_EVALUATION_PROGRAM_NV: st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM; break; + case GL_COMPUTE_PROGRAM_NV: + st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM; + break; } } @@ -92,6 +95,7 @@ st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; st->dirty.st |= ST_NEW_TESSCTRL_PROGRAM; st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM; + st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM; } @@ -123,6 +127,10 @@ st_new_program(struct gl_context *ctx, GLenum target, GLuint id) struct st_tesseval_program *prog = ST_CALLOC_STRUCT(st_tesseval_program); return _mesa_init_gl_program(&prog->Base.Base, target, id); } + case GL_COMPUTE_PROGRAM_NV: { + struct st_compute_program *prog = ST_CALLOC_STRUCT(st_compute_program); + return _mesa_init_gl_program(&prog->Base.Base, target, id); + } default: assert(0); return NULL; @@ -195,6 +203,16 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) free_glsl_to_tgsi_visitor(sttep->glsl_to_tgsi); } break; + case GL_COMPUTE_PROGRAM_NV: + { + struct st_compute_program *stcp = (struct st_compute_program *) prog; + + st_release_cp_variants(st, stcp); + + if (stcp->glsl_to_tgsi) + free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi); + } + break; default: assert(0); /* problem */ } @@ -272,6 +290,16 @@ st_program_string_notify( struct gl_context *ctx, if (st->tep == sttep) st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM; } + else if (target == GL_COMPUTE_PROGRAM_NV) { + struct st_compute_program *stcp = (struct st_compute_program *) prog; + + st_release_cp_variants(st, stcp); + if (!st_translate_compute_program(st, stcp)) + return false; + + if (st->cp == stcp) + st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM; + } if (ST_DEBUG & DEBUG_PRECOMPILE || st->shader_has_one_variant[stage]) diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index b73b0ab..287a4ea 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -446,6 +446,7 @@ void st_destroy_context( struct st_context *st ) st_reference_vertprog(st, &st->vp, NULL); st_reference_tesscprog(st, &st->tcp, NULL); st_reference_tesseprog(st, &st->tep, NULL); + st_reference_compprog(st, &st->cp, 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 b8f7aa9..843cd3a 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -64,6 +64,7 @@ struct u_upload_mgr; #define ST_NEW_SAMPLER_VIEWS (1 << 11) #define ST_NEW_ATOMIC_BUFFER (1 << 12) #define ST_NEW_STORAGE_BUFFER (1 << 13) +#define ST_NEW_COMPUTE_PROGRAM (1 << 14) struct st_state_flags { @@ -174,12 +175,14 @@ struct st_context 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_compute_program *cp; /**< Currently bound compute program */ struct st_vp_variant *vp_variant; struct st_fp_variant *fp_variant; struct st_basic_variant *gp_variant; struct st_basic_variant *tcp_variant; struct st_basic_variant *tep_variant; + struct st_cp_variant *cp_variant; struct gl_texture_object *default_texture; diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index feabe62..556cd65 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -174,9 +174,12 @@ void st_init_limits(struct pipe_screen *screen, pc = &c->Program[MESA_SHADER_TESS_EVAL]; options = &c->ShaderCompilerOptions[MESA_SHADER_TESS_EVAL]; break; + case PIPE_SHADER_COMPUTE: + pc = &c->Program[MESA_SHADER_COMPUTE]; + options = &c->ShaderCompilerOptions[MESA_SHADER_COMPUTE]; + break; default: - /* compute shader, etc. */ - continue; + assert(0); } pc->MaxTextureImageUnits = diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 624586e..e9b5ace 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -193,6 +193,43 @@ st_release_basic_variants(struct st_context *st, GLenum target, /** + * Delete a compute program variant. Note the caller must unlink the variant + * from the linked list. + */ +static void +delete_cp_variant(struct st_context *st, struct st_cp_variant *cpv) +{ + if (cpv->driver_shader) + cso_delete_compute_shader(st->cso_context, cpv->driver_shader); + + free(cpv); +} + + +/** + * Free all variants of a compute program. + */ +void +st_release_cp_variants(struct st_context *st, struct st_compute_program *stcp) +{ + struct st_cp_variant *cpv; + + for (cpv = stcp->variants; cpv; ) { + struct st_cp_variant *next = cpv->next; + delete_cp_variant(st, cpv); + cpv = next; + } + + stcp->variants = NULL; + + if (stcp->tgsi.prog) { + ureg_free_tokens(stcp->tgsi.prog); + stcp->tgsi.prog = NULL; + } +} + + +/** * Translate a vertex program. */ bool @@ -1379,6 +1416,67 @@ st_translate_tesseval_program(struct st_context *st, /** + * Translate a compute program to create a new variant. + */ +bool +st_translate_compute_program(struct st_context *st, + struct st_compute_program *stcp) +{ + return false; /* will be updated in the next commit */ +} + + +static struct st_cp_variant * +st_create_cp_variant(struct st_context *st, + struct st_compute_program *stcp, + const struct st_cp_variant_key *key) +{ + struct pipe_context *pipe = st->pipe; + struct st_cp_variant *cpv; + + cpv = CALLOC_STRUCT(st_cp_variant); + if (!cpv) + return NULL; + + /* fill in new variant */ + cpv->driver_shader = pipe->create_compute_state(pipe, &stcp->tgsi); + cpv->key = *key; + return cpv; +} + + +/** + * Get/create compute program variant. + */ +struct st_cp_variant * +st_get_cp_variant(struct st_context *st, + struct st_compute_program *stcp, + const struct st_cp_variant_key *key) +{ + struct st_cp_variant *cpv; + + /* Search for existing variant */ + for (cpv = stcp->variants; cpv; cpv = cpv->next) { + if (memcmp(&cpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!cpv) { + /* create new */ + cpv = st_create_cp_variant(st, stcp, key); + if (cpv) { + /* insert into list */ + cpv->next = stcp->variants; + stcp->variants = cpv; + } + } + + return cpv; +} + + +/** * Vert/Geom/Frag programs have per-context variants. Free all the * variants attached to the given program which match the given context. */ @@ -1459,6 +1557,27 @@ destroy_program_variants(struct st_context *st, struct gl_program *target) } } break; + case GL_COMPUTE_PROGRAM_NV: + { + struct st_compute_program *stcp = + (struct st_compute_program *) target; + struct st_cp_variant *cpv, **prevPtr = &stcp->variants; + + for (cpv = stcp->variants; cpv; ) { + struct st_cp_variant *next = cpv->next; + if (cpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_cp_variant(st, cpv); + } + else { + prevPtr = &cpv->next; + } + cpv = next; + } + } + break; default: _mesa_problem(NULL, "Unexpected program target 0x%x in " "destroy_program_variants_cb()", target->Target); @@ -1497,6 +1616,7 @@ destroy_shader_program_variants_cb(GLuint key, void *data, void *userData) case GL_GEOMETRY_SHADER: case GL_TESS_CONTROL_SHADER: case GL_TESS_EVALUATION_SHADER: + case GL_COMPUTE_SHADER: { destroy_program_variants(st, shader->Program); } @@ -1613,6 +1733,16 @@ st_precompile_shader_variant(struct st_context *st, break; } + case GL_COMPUTE_PROGRAM_NV: { + struct st_compute_program *p = (struct st_compute_program *)prog; + struct st_cp_variant_key key; + + memset(&key, 0, sizeof(key)); + key.st = st->has_shareable_shaders ? NULL : st; + st_get_cp_variant(st, p, &key); + break; + } + default: assert(0); } diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 7717d02..7e64ab6 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -231,6 +231,40 @@ struct st_tesseval_program }; +/** Compute program variant key */ +struct st_cp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + /* no other fields yet */ +}; + + +/** + * Compute program variant. + */ +struct st_cp_variant +{ + /* Parameters which generated this variant. */ + struct st_cp_variant_key key; + + void *driver_shader; + + struct st_cp_variant *next; +}; + + +/** + * Derived from Mesa gl_compute_program: + */ +struct st_compute_program +{ + struct gl_compute_program Base; /**< The Mesa compute program */ + struct pipe_compute_state tgsi; + struct glsl_to_tgsi_visitor* glsl_to_tgsi; + + struct st_cp_variant *variants; +}; + static inline struct st_fragment_program * st_fragment_program( struct gl_fragment_program *fp ) @@ -263,6 +297,12 @@ st_tesseval_program( struct gl_tess_eval_program *tep ) return (struct st_tesseval_program *)tep; } +static inline struct st_compute_program * +st_compute_program( struct gl_compute_program *cp ) +{ + return (struct st_compute_program *)cp; +} + static inline void st_reference_vertprog(struct st_context *st, struct st_vertex_program **ptr, @@ -313,6 +353,16 @@ st_reference_tesseprog(struct st_context *st, (struct gl_program *) prog); } +static inline void +st_reference_compprog(struct st_context *st, + struct st_compute_program **ptr, + struct st_compute_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. */ @@ -355,6 +405,11 @@ st_get_basic_variant(struct st_context *st, struct pipe_shader_state *tgsi, struct st_basic_variant **variants); +extern struct st_cp_variant * +st_get_cp_variant(struct st_context *st, + struct st_compute_program *stcp, + const struct st_cp_variant_key *key); + extern void st_release_vp_variants( struct st_context *st, struct st_vertex_program *stvp ); @@ -369,6 +424,10 @@ st_release_basic_variants(struct st_context *st, GLenum target, struct pipe_shader_state *tgsi); extern void +st_release_cp_variants(struct st_context *st, + struct st_compute_program *stcp); + +extern void st_destroy_program_variants(struct st_context *st); extern bool @@ -391,6 +450,10 @@ extern bool st_translate_tesseval_program(struct st_context *st, struct st_tesseval_program *sttep); +extern bool +st_translate_compute_program(struct st_context *st, + struct st_compute_program *stcp); + extern void st_print_current_vertex_program(void); -- 2.6.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev