mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-19 12:20:40 +02:00
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:
parent
dbf7e483b4
commit
9eebc55cc2
2 changed files with 165 additions and 146 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue