X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_shader_cache.c;h=a971b0d7ee73328e54c7f68db0606126780bc046;hb=5092610f29b9e10d3835af8b4ed1ca13809657b5;hp=e8c7289ec6dc6c9c91f227a296ee2d2ca46c8fce;hpb=b97faea162fe9999d241de679f99ad935a8bce26;p=mesa.git diff --git a/src/mesa/state_tracker/st_shader_cache.c b/src/mesa/state_tracker/st_shader_cache.c index e8c7289ec6d..a971b0d7ee7 100644 --- a/src/mesa/state_tracker/st_shader_cache.c +++ b/src/mesa/state_tracker/st_shader_cache.c @@ -22,7 +22,7 @@ */ #include - +#include "st_debug.h" #include "st_program.h" #include "st_shader_cache.h" #include "compiler/glsl/program.h" @@ -30,6 +30,12 @@ #include "program/ir_to_mesa.h" #include "util/u_memory.h" +void +st_get_program_binary_driver_sha1(struct gl_context *ctx, uint8_t *sha1) +{ + disk_cache_compute_key(ctx->Cache, NULL, 0, sha1); +} + static void write_stream_out_to_cache(struct blob *blob, struct pipe_shader_state *tgsi) @@ -39,103 +45,91 @@ write_stream_out_to_cache(struct blob *blob, } static void -write_tgsi_to_cache(struct blob *blob, struct pipe_shader_state *tgsi, - struct st_context *st, unsigned char *sha1, - unsigned num_tokens) +write_tgsi_to_cache(struct blob *blob, const struct tgsi_token *tokens, + struct gl_program *prog, unsigned num_tokens) { blob_write_uint32(blob, num_tokens); - blob_write_bytes(blob, tgsi->tokens, - num_tokens * sizeof(struct tgsi_token)); + blob_write_bytes(blob, tokens, num_tokens * sizeof(struct tgsi_token)); - disk_cache_put(st->ctx->Cache, sha1, blob->data, blob->size); + prog->driver_cache_blob = ralloc_size(NULL, blob->size); + memcpy(prog->driver_cache_blob, blob->data, blob->size); + 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, - struct pipe_shader_state *out_state, - unsigned num_tokens) +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; - - unsigned char *sha1; - struct blob *blob = blob_create(); + struct blob blob; + blob_init(&blob); switch (prog->info.stage) { case MESA_SHADER_VERTEX: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - sha1 = stvp->sha1; - blob_write_uint32(blob, stvp->num_inputs); - blob_write_bytes(blob, stvp->index_to_input, + blob_write_uint32(&blob, stvp->num_inputs); + blob_write_bytes(&blob, stvp->index_to_input, sizeof(stvp->index_to_input)); - blob_write_bytes(blob, stvp->result_to_output, + blob_write_bytes(&blob, stvp->result_to_output, sizeof(stvp->result_to_output)); - write_stream_out_to_cache(blob, &stvp->tgsi); - write_tgsi_to_cache(blob, &stvp->tgsi, st, sha1, num_tokens); - break; - } - case MESA_SHADER_TESS_CTRL: { - struct st_tessctrl_program *stcp = (struct st_tessctrl_program *) prog; - sha1 = stcp->sha1; - - write_stream_out_to_cache(blob, out_state); - write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens); - break; - } - case MESA_SHADER_TESS_EVAL: { - struct st_tesseval_program *step = (struct st_tesseval_program *) prog; - sha1 = step->sha1; - - write_stream_out_to_cache(blob, out_state); - write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens); + write_stream_out_to_cache(&blob, &stvp->tgsi); + write_tgsi_to_cache(&blob, stvp->tgsi.tokens, prog, + stvp->num_tgsi_tokens); break; } + case MESA_SHADER_TESS_CTRL: + case MESA_SHADER_TESS_EVAL: case MESA_SHADER_GEOMETRY: { - struct st_geometry_program *stgp = (struct st_geometry_program *) prog; - sha1 = stgp->sha1; + struct st_common_program *stcp = (struct st_common_program *) prog; - write_stream_out_to_cache(blob, out_state); - write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens); + write_stream_out_to_cache(&blob, &stcp->tgsi); + write_tgsi_to_cache(&blob, stcp->tgsi.tokens, prog, + stcp->num_tgsi_tokens); break; } case MESA_SHADER_FRAGMENT: { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; - sha1 = stfp->sha1; - write_tgsi_to_cache(blob, &stfp->tgsi, st, sha1, num_tokens); + write_tgsi_to_cache(&blob, stfp->tgsi.tokens, prog, + stfp->num_tgsi_tokens); break; } case MESA_SHADER_COMPUTE: { struct st_compute_program *stcp = (struct st_compute_program *) prog; - sha1 = stcp->sha1; - write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens); + write_tgsi_to_cache(&blob, stcp->tgsi.prog, prog, + stcp->num_tgsi_tokens); break; } default: 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) { - char sha1_buf[41]; - _mesa_sha1_format(sha1_buf, sha1); - fprintf(stderr, "putting %s tgsi_tokens in cache: %s\n", - _mesa_shader_stage_to_string(prog->info.stage), sha1_buf); + fprintf(stderr, "putting %s tgsi_tokens in cache\n", + _mesa_shader_stage_to_string(prog->info.stage)); } - - free(blob); } static void @@ -156,257 +150,165 @@ read_tgsi_from_cache(struct blob_reader *blob_reader, blob_copy_bytes(blob_reader, (uint8_t *) *tokens, tokens_size); } -bool -st_load_tgsi_from_disk_cache(struct gl_context *ctx, - struct gl_shader_program *prog) +void +st_deserialise_tgsi_program(struct gl_context *ctx, + struct gl_shader_program *shProg, + struct gl_program *prog) { - if (!ctx->Cache) - return false; - - unsigned char *stage_sha1[MESA_SHADER_STAGES]; - char sha1_buf[41]; - - /* Compute and store sha1 for each stage. These will be reused by the - * cache store pass if we fail to find the cached tgsi. - */ - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i] == NULL) - continue; - - char *buf = ralloc_strdup(NULL, "tgsi_tokens "); - _mesa_sha1_format(sha1_buf, - prog->_LinkedShaders[i]->Program->sh.data->sha1); - ralloc_strcat(&buf, sha1_buf); - - struct gl_program *glprog = prog->_LinkedShaders[i]->Program; - switch (glprog->info.stage) { - case MESA_SHADER_VERTEX: { - struct st_vertex_program *stvp = (struct st_vertex_program *) glprog; - stage_sha1[i] = stvp->sha1; - ralloc_strcat(&buf, " vs"); - disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]); - break; - } - case MESA_SHADER_TESS_CTRL: { - struct st_tessctrl_program *stcp = - (struct st_tessctrl_program *) glprog; - stage_sha1[i] = stcp->sha1; - ralloc_strcat(&buf, " tcs"); - disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]); - break; - } - case MESA_SHADER_TESS_EVAL: { - struct st_tesseval_program *step = - (struct st_tesseval_program *) glprog; - stage_sha1[i] = step->sha1; - ralloc_strcat(&buf, " tes"); - disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]); - break; - } - case MESA_SHADER_GEOMETRY: { - struct st_geometry_program *stgp = - (struct st_geometry_program *) glprog; - stage_sha1[i] = stgp->sha1; - ralloc_strcat(&buf, " gs"); - disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]); - break; - } - case MESA_SHADER_FRAGMENT: { - struct st_fragment_program *stfp = - (struct st_fragment_program *) glprog; - stage_sha1[i] = stfp->sha1; - ralloc_strcat(&buf, " fs"); - disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]); - break; - } - case MESA_SHADER_COMPUTE: { - struct st_compute_program *stcp = - (struct st_compute_program *) glprog; - stage_sha1[i] = stcp->sha1; - ralloc_strcat(&buf, " cs"); - disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]); - break; - } - default: - unreachable("Unsupported stage"); - } - - ralloc_free(buf); - } - - /* Now that we have created the sha1 keys that will be used for writting to - * the tgsi cache fallback to the regular glsl to tgsi path if we didn't - * load the GLSL IR from cache. We do this as glsl to tgsi can alter things - * such as gl_program_parameter_list which holds things like uniforms. - */ - if (prog->data->LinkStatus != linking_skipped) - return false; - struct st_context *st = st_context(ctx); - uint8_t *buffer = NULL; - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i] == NULL) - continue; + size_t size = prog->driver_cache_blob_size; + uint8_t *buffer = (uint8_t *) prog->driver_cache_blob; - unsigned char *sha1 = stage_sha1[i]; - size_t size; - buffer = (uint8_t *) disk_cache_get(ctx->Cache, sha1, &size); - if (buffer) { - struct blob_reader blob_reader; - blob_reader_init(&blob_reader, buffer, size); + struct blob_reader blob_reader; + blob_reader_init(&blob_reader, buffer, size); - struct gl_program *glprog = prog->_LinkedShaders[i]->Program; - switch (glprog->info.stage) { - case MESA_SHADER_VERTEX: { - struct st_vertex_program *stvp = - (struct st_vertex_program *) glprog; - - st_release_vp_variants(st, stvp); + switch (prog->info.stage) { + case MESA_SHADER_VERTEX: { + struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - 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)); + st_release_vp_variants(st, stvp); - read_stream_out_from_cache(&blob_reader, &stvp->tgsi); - read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens); + 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)); - if (st->vp == stvp) - st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp); + read_stream_out_from_cache(&blob_reader, &stvp->tgsi); + read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens); - break; - } - case MESA_SHADER_TESS_CTRL: { - struct st_tessctrl_program *sttcp = - (struct st_tessctrl_program *) glprog; + if (st->vp == stvp) + st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp); - st_release_basic_variants(st, sttcp->Base.Target, - &sttcp->variants, &sttcp->tgsi); + break; + } + case MESA_SHADER_TESS_CTRL: { + struct st_common_program *sttcp = st_common_program(prog); - read_stream_out_from_cache(&blob_reader, &sttcp->tgsi); - read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens); + st_release_basic_variants(st, sttcp->Base.Target, + &sttcp->variants, &sttcp->tgsi); - if (st->tcp == sttcp) - st->dirty |= sttcp->affected_states; + read_stream_out_from_cache(&blob_reader, &sttcp->tgsi); + read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens); - break; - } - case MESA_SHADER_TESS_EVAL: { - struct st_tesseval_program *sttep = - (struct st_tesseval_program *) glprog; + if (st->tcp == sttcp) + st->dirty |= sttcp->affected_states; - st_release_basic_variants(st, sttep->Base.Target, - &sttep->variants, &sttep->tgsi); + break; + } + case MESA_SHADER_TESS_EVAL: { + struct st_common_program *sttep = st_common_program(prog); - read_stream_out_from_cache(&blob_reader, &sttep->tgsi); - read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens); + st_release_basic_variants(st, sttep->Base.Target, + &sttep->variants, &sttep->tgsi); - if (st->tep == sttep) - st->dirty |= sttep->affected_states; + read_stream_out_from_cache(&blob_reader, &sttep->tgsi); + read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens); - break; - } - case MESA_SHADER_GEOMETRY: { - struct st_geometry_program *stgp = - (struct st_geometry_program *) glprog; + if (st->tep == sttep) + st->dirty |= sttep->affected_states; - st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, - &stgp->tgsi); + break; + } + case MESA_SHADER_GEOMETRY: { + struct st_common_program *stgp = st_common_program(prog); - read_stream_out_from_cache(&blob_reader, &stgp->tgsi); - read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens); + st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, + &stgp->tgsi); - if (st->gp == stgp) - st->dirty |= stgp->affected_states; + read_stream_out_from_cache(&blob_reader, &stgp->tgsi); + read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens); - break; - } - case MESA_SHADER_FRAGMENT: { - struct st_fragment_program *stfp = - (struct st_fragment_program *) glprog; + if (st->gp == stgp) + st->dirty |= stgp->affected_states; - st_release_fp_variants(st, stfp); + break; + } + case MESA_SHADER_FRAGMENT: { + struct st_fragment_program *stfp = (struct st_fragment_program *) prog; - read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens); + st_release_fp_variants(st, stfp); - if (st->fp == stfp) - st->dirty |= stfp->affected_states; + read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens); - break; - } - case MESA_SHADER_COMPUTE: { - struct st_compute_program *stcp = - (struct st_compute_program *) glprog; + if (st->fp == stfp) + st->dirty |= stfp->affected_states; - st_release_cp_variants(st, stcp); + break; + } + case MESA_SHADER_COMPUTE: { + struct st_compute_program *stcp = (struct st_compute_program *) prog; - read_tgsi_from_cache(&blob_reader, - (const struct tgsi_token**) &stcp->tgsi.prog); + st_release_cp_variants(st, stcp); - stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size; - stcp->tgsi.req_private_mem = 0; - stcp->tgsi.req_input_mem = 0; + read_tgsi_from_cache(&blob_reader, + (const struct tgsi_token**) &stcp->tgsi.prog); - if (st->cp == stcp) - st->dirty |= stcp->affected_states; + stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size; + stcp->tgsi.req_private_mem = 0; + stcp->tgsi.req_input_mem = 0; - break; - } - default: - unreachable("Unsupported stage"); - } + if (st->cp == stcp) + st->dirty |= stcp->affected_states; - if (blob_reader.current != blob_reader.end || blob_reader.overrun) { - /* Something very bad has gone wrong discard the item from the - * cache and rebuild/link from source. - */ - assert(!"Invalid TGSI shader disk cache item!"); + break; + } + default: + unreachable("Unsupported stage"); + } - if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { - fprintf(stderr, "Error reading program from cache (invalid " - "TGSI cache item)\n"); - } + /* 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!"); - disk_cache_remove(ctx->Cache, sha1); + if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { + fprintf(stderr, "Error reading program from cache (invalid " + "TGSI cache item)\n"); + } + } - goto fallback_recompile; - } + st_set_prog_affected_state_flags(prog); + _mesa_associate_uniform_storage(ctx, shProg, prog, false); - if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { - _mesa_sha1_format(sha1_buf, sha1); - fprintf(stderr, "%s tgsi_tokens retrieved from cache: %s\n", - _mesa_shader_stage_to_string(i), sha1_buf); - } + /* 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); +} - st_set_prog_affected_state_flags(glprog); - _mesa_associate_uniform_storage(ctx, prog, glprog->Parameters, - false); +bool +st_load_tgsi_from_disk_cache(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + if (!ctx->Cache) + return false; - free(buffer); - } else { - /* Failed to find a matching cached shader so fallback to recompile. - */ - if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { - fprintf(stderr, "TGSI cache item not found falling back to " - "compile.\n"); - } + /* If we didn't load the GLSL metadata from cache then we could not have + * loaded the tgsi either. + */ + if (prog->data->LinkStatus != linking_skipped) + return false; - goto fallback_recompile; - } - } + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; - return true; + struct gl_program *glprog = prog->_LinkedShaders[i]->Program; + st_deserialise_tgsi_program(ctx, prog, glprog); -fallback_recompile: - free(buffer); + /* 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; - for (unsigned i = 0; i < prog->NumShaders; i++) { - _mesa_glsl_compile_shader(ctx, prog->Shaders[i], false, false, true); + if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { + fprintf(stderr, "%s tgsi_tokens retrieved from cache\n", + _mesa_shader_stage_to_string(i)); + } } - prog->data->cache_fallback = true; - _mesa_glsl_link_shader(ctx, prog); - return true; }