st/glsl_to_tgsi: add (de)serialise program helpers

These will be shared between the on-disk shader cache and
ARB_get_program_binary.

Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
Timothy Arceri 2017-11-28 16:00:50 +11:00
parent dbf7e483b4
commit 9eebc55cc2
2 changed files with 165 additions and 146 deletions

View file

@ -50,22 +50,9 @@ write_tgsi_to_cache(struct blob *blob, const struct tgsi_token *tokens,
prog->driver_cache_blob_size = blob->size;
}
/**
* Store tgsi and any other required state in on-disk shader cache.
*/
void
st_store_tgsi_in_disk_cache(struct st_context *st, struct gl_program *prog)
st_serialise_tgsi_program(struct gl_context *ctx, struct gl_program *prog)
{
if (!st->ctx->Cache)
return;
/* Exit early when we are dealing with a ff shader with no source file to
* generate a source from.
*/
static const char zero[sizeof(prog->sh.data->sha1)] = {0};
if (memcmp(prog->sh.data->sha1, zero, sizeof(prog->sh.data->sha1)) == 0)
return;
struct blob blob;
blob_init(&blob);
@ -112,12 +99,31 @@ st_store_tgsi_in_disk_cache(struct st_context *st, struct gl_program *prog)
unreachable("Unsupported stage");
}
blob_finish(&blob);
}
/**
* Store tgsi and any other required state in on-disk shader cache.
*/
void
st_store_tgsi_in_disk_cache(struct st_context *st, struct gl_program *prog)
{
if (!st->ctx->Cache)
return;
/* Exit early when we are dealing with a ff shader with no source file to
* generate a source from.
*/
static const char zero[sizeof(prog->sh.data->sha1)] = {0};
if (memcmp(prog->sh.data->sha1, zero, sizeof(prog->sh.data->sha1)) == 0)
return;
st_serialise_tgsi_program(st->ctx, prog);
if (st->ctx->_Shader->Flags & GLSL_CACHE_INFO) {
fprintf(stderr, "putting %s tgsi_tokens in cache\n",
_mesa_shader_stage_to_string(prog->info.stage));
}
blob_finish(&blob);
}
static void
@ -138,6 +144,135 @@ read_tgsi_from_cache(struct blob_reader *blob_reader,
blob_copy_bytes(blob_reader, (uint8_t *) *tokens, tokens_size);
}
void
st_deserialise_tgsi_program(struct gl_context *ctx,
struct gl_shader_program *shProg,
struct gl_program *prog)
{
struct st_context *st = st_context(ctx);
size_t size = prog->driver_cache_blob_size;
uint8_t *buffer = (uint8_t *) prog->driver_cache_blob;
struct blob_reader blob_reader;
blob_reader_init(&blob_reader, buffer, size);
switch (prog->info.stage) {
case MESA_SHADER_VERTEX: {
struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
st_release_vp_variants(st, stvp);
stvp->num_inputs = blob_read_uint32(&blob_reader);
blob_copy_bytes(&blob_reader, (uint8_t *) stvp->index_to_input,
sizeof(stvp->index_to_input));
blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output,
sizeof(stvp->result_to_output));
read_stream_out_from_cache(&blob_reader, &stvp->tgsi);
read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens);
if (st->vp == stvp)
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp);
break;
}
case MESA_SHADER_TESS_CTRL: {
struct st_common_program *sttcp = st_common_program(prog);
st_release_basic_variants(st, sttcp->Base.Target,
&sttcp->variants, &sttcp->tgsi);
read_stream_out_from_cache(&blob_reader, &sttcp->tgsi);
read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens);
if (st->tcp == sttcp)
st->dirty |= sttcp->affected_states;
break;
}
case MESA_SHADER_TESS_EVAL: {
struct st_common_program *sttep = st_common_program(prog);
st_release_basic_variants(st, sttep->Base.Target,
&sttep->variants, &sttep->tgsi);
read_stream_out_from_cache(&blob_reader, &sttep->tgsi);
read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens);
if (st->tep == sttep)
st->dirty |= sttep->affected_states;
break;
}
case MESA_SHADER_GEOMETRY: {
struct st_common_program *stgp = st_common_program(prog);
st_release_basic_variants(st, stgp->Base.Target, &stgp->variants,
&stgp->tgsi);
read_stream_out_from_cache(&blob_reader, &stgp->tgsi);
read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens);
if (st->gp == stgp)
st->dirty |= stgp->affected_states;
break;
}
case MESA_SHADER_FRAGMENT: {
struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
st_release_fp_variants(st, stfp);
read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens);
if (st->fp == stfp)
st->dirty |= stfp->affected_states;
break;
}
case MESA_SHADER_COMPUTE: {
struct st_compute_program *stcp = (struct st_compute_program *) prog;
st_release_cp_variants(st, stcp);
read_tgsi_from_cache(&blob_reader,
(const struct tgsi_token**) &stcp->tgsi.prog);
stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size;
stcp->tgsi.req_private_mem = 0;
stcp->tgsi.req_input_mem = 0;
if (st->cp == stcp)
st->dirty |= stcp->affected_states;
break;
}
default:
unreachable("Unsupported stage");
}
/* Make sure we don't try to read more data than we wrote. This should
* never happen in release builds but its useful to have this check to
* catch development bugs.
*/
if (blob_reader.current != blob_reader.end || blob_reader.overrun) {
assert(!"Invalid TGSI shader disk cache item!");
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
fprintf(stderr, "Error reading program from cache (invalid "
"TGSI cache item)\n");
}
}
st_set_prog_affected_state_flags(prog);
_mesa_associate_uniform_storage(ctx, shProg, prog, false);
/* Create Gallium shaders now instead of on demand. */
if (ST_DEBUG & DEBUG_PRECOMPILE ||
st->shader_has_one_variant[prog->info.stage])
st_precompile_shader_variant(st, prog);
}
bool
st_load_tgsi_from_disk_cache(struct gl_context *ctx,
struct gl_shader_program *prog)
@ -151,146 +286,22 @@ st_load_tgsi_from_disk_cache(struct gl_context *ctx,
if (prog->data->LinkStatus != linking_skipped)
return false;
struct st_context *st = st_context(ctx);
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
continue;
struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
size_t size = glprog->driver_cache_blob_size;
uint8_t *buffer = (uint8_t *) glprog->driver_cache_blob;
struct blob_reader blob_reader;
blob_reader_init(&blob_reader, buffer, size);
switch (glprog->info.stage) {
case MESA_SHADER_VERTEX: {
struct st_vertex_program *stvp = (struct st_vertex_program *) glprog;
st_release_vp_variants(st, stvp);
stvp->num_inputs = blob_read_uint32(&blob_reader);
blob_copy_bytes(&blob_reader, (uint8_t *) stvp->index_to_input,
sizeof(stvp->index_to_input));
blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output,
sizeof(stvp->result_to_output));
read_stream_out_from_cache(&blob_reader, &stvp->tgsi);
read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens);
if (st->vp == stvp)
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp);
break;
}
case MESA_SHADER_TESS_CTRL: {
struct st_common_program *sttcp = st_common_program(glprog);
st_release_basic_variants(st, sttcp->Base.Target,
&sttcp->variants, &sttcp->tgsi);
read_stream_out_from_cache(&blob_reader, &sttcp->tgsi);
read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens);
if (st->tcp == sttcp)
st->dirty |= sttcp->affected_states;
break;
}
case MESA_SHADER_TESS_EVAL: {
struct st_common_program *sttep = st_common_program(glprog);
st_release_basic_variants(st, sttep->Base.Target,
&sttep->variants, &sttep->tgsi);
read_stream_out_from_cache(&blob_reader, &sttep->tgsi);
read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens);
if (st->tep == sttep)
st->dirty |= sttep->affected_states;
break;
}
case MESA_SHADER_GEOMETRY: {
struct st_common_program *stgp = st_common_program(glprog);
st_release_basic_variants(st, stgp->Base.Target, &stgp->variants,
&stgp->tgsi);
read_stream_out_from_cache(&blob_reader, &stgp->tgsi);
read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens);
if (st->gp == stgp)
st->dirty |= stgp->affected_states;
break;
}
case MESA_SHADER_FRAGMENT: {
struct st_fragment_program *stfp =
(struct st_fragment_program *) glprog;
st_release_fp_variants(st, stfp);
read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens);
if (st->fp == stfp)
st->dirty |= stfp->affected_states;
break;
}
case MESA_SHADER_COMPUTE: {
struct st_compute_program *stcp =
(struct st_compute_program *) glprog;
st_release_cp_variants(st, stcp);
read_tgsi_from_cache(&blob_reader,
(const struct tgsi_token**) &stcp->tgsi.prog);
stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size;
stcp->tgsi.req_private_mem = 0;
stcp->tgsi.req_input_mem = 0;
if (st->cp == stcp)
st->dirty |= stcp->affected_states;
break;
}
default:
unreachable("Unsupported stage");
}
/* Make sure we don't try to read more data than we wrote. This should
* never happen in release builds but its useful to have this check to
* catch development bugs.
*/
if (blob_reader.current != blob_reader.end || blob_reader.overrun) {
assert(!"Invalid TGSI shader disk cache item!");
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
fprintf(stderr, "Error reading program from cache (invalid "
"TGSI cache item)\n");
}
}
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
fprintf(stderr, "%s tgsi_tokens retrieved from cache\n",
_mesa_shader_stage_to_string(i));
}
st_set_prog_affected_state_flags(glprog);
_mesa_associate_uniform_storage(ctx, prog, glprog, false);
/* Create Gallium shaders now instead of on demand. */
if (ST_DEBUG & DEBUG_PRECOMPILE ||
st->shader_has_one_variant[glprog->info.stage])
st_precompile_shader_variant(st, glprog);
st_deserialise_tgsi_program(ctx, prog, glprog);
/* We don't need the cached blob anymore so free it */
ralloc_free(glprog->driver_cache_blob);
glprog->driver_cache_blob = NULL;
glprog->driver_cache_blob_size = 0;
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
fprintf(stderr, "%s tgsi_tokens retrieved from cache\n",
_mesa_shader_stage_to_string(i));
}
}
return true;

View file

@ -32,6 +32,14 @@
extern "C" {
#endif
void
st_serialise_tgsi_program(struct gl_context *ctx, struct gl_program *prog);
void
st_deserialise_tgsi_program(struct gl_context *ctx,
struct gl_shader_program *shProg,
struct gl_program *prog);
bool
st_load_tgsi_from_disk_cache(struct gl_context *ctx,
struct gl_shader_program *prog);