[Mesa-dev] [PATCH v3 11/19] st/mesa: add compute shader states
Samuel Pitoiset
samuel.pitoiset at gmail.com
Wed Feb 10 18:10:40 UTC 2016
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Reviewed-by: Ilia Mirkin <imirkin at 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
More information about the mesa-dev
mailing list