Adds shader disk caching for nv50 to reduce the need to every time compile shaders. Shaders are saved into disk_shader_cache from nv50_screen structure.
It can be disabled with MESA_GLSL_CACHE_DISABLE=1. It serializes the input nv50_ir_prog_info to compute the hash key and also to do a byte compare between the original nv50_ir_prog_info and the one saved in the cache. If keys match and also the byte compare returns they are equal, shaders are same, and the compiled nv50_ir_prog_info_out from the cache can be used instead of compiling input info. Signed-off-by: Mark Menzynski <mmenz...@redhat.com> --- .../drivers/nouveau/nv50/nv50_program.c | 55 ++++++++++++++++--- .../drivers/nouveau/nv50/nv50_program.h | 2 + .../drivers/nouveau/nv50/nv50_shader_state.c | 4 +- src/gallium/drivers/nouveau/nv50/nv50_state.c | 1 + 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c index bf63b20f613..0b85267f36f 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_program.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c @@ -667,10 +667,21 @@ nv50_program_create_strmout_state(const struct nv50_ir_prog_info_out *info, bool nv50_program_translate(struct nv50_program *prog, uint16_t chipset, + struct disk_cache *disk_shader_cache, struct pipe_debug_callback *debug) { + struct blob blob; struct nv50_ir_prog_info *info; - int i, ret; + struct nv50_ir_prog_info_out info_out = {}; + + void *cached_data = NULL; + size_t cached_size; + bool shader_found = false; + + int i; + int ret = 0; + cache_key key; + const uint8_t map_undef = (prog->type == PIPE_SHADER_VERTEX) ? 0x40 : 0x80; info = CALLOC_STRUCT(nv50_ir_prog_info); @@ -704,7 +715,7 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset, info->io.msInfoCBSlot = 15; info->io.msInfoBase = NV50_CB_AUX_MS_OFFSET; - info->assignSlots = nv50_program_assign_varying_slots; + info->assignSlots = nv50_program_assign_varying_slots_info; prog->vp.bfc[0] = 0xff; prog->vp.bfc[1] = 0xff; @@ -726,16 +737,42 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset, info->optLevel = 3; #endif - struct nv50_ir_prog_info_out info_out = {}; /* these fields might be overwritten by the compiler */ - info_out.bin.smemSize = prog->cp.smem_size; - info_out.io.genUserClip = prog->vp.clpd_nr; + info->bin.smemSize = prog->cp.smem_size; + info->io.genUserClip = prog->vp.clpd_nr; + + blob_init(&blob); + + if (disk_shader_cache) { + nv50_ir_prog_info_serialize(&blob, info); + disk_cache_compute_key(disk_shader_cache, blob.data, blob.size, key); + cached_data = disk_cache_get(disk_shader_cache, key, &cached_size); + + if (cached_data && cached_size >= blob.size) { // blob.size is the size of serialized "info" + if (memcmp(cached_data, blob.data, blob.size) == 0) { + shader_found = true; + /* Blob contains only "info". In disk cache, "info_out" comes right after it */ + size_t offset = blob.size; + nv50_ir_prog_info_out_deserialize(cached_data, cached_size, offset, &info_out); + } + } + free(cached_data); + } info_out.driverPriv = prog; - ret = nv50_ir_generate_code(info, &info_out); - if (ret) { - NOUVEAU_ERR("shader translation failed: %i\n", ret); - goto out; + + if (!shader_found) { + ret = nv50_ir_generate_code(info, &info_out); + if (ret) { + NOUVEAU_ERR("shader translation failed: %i\n", ret); + goto out; + } + if (disk_shader_cache) { + nv50_ir_prog_info_out_serialize(&blob, &info_out); + disk_cache_put(disk_shader_cache, key, blob.data, blob.size, NULL); + } } + blob_finish(&blob); + nv50_program_assign_varying_slots_prog(&info_out); prog->code = info_out.bin.code; prog->code_size = info_out.bin.codeSize; diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.h b/src/gallium/drivers/nouveau/nv50/nv50_program.h index 1a89e0d5067..528e1d01fa1 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_program.h +++ b/src/gallium/drivers/nouveau/nv50/nv50_program.h @@ -116,7 +116,9 @@ struct nv50_program { struct nv50_stream_output_state *so; }; +struct disk_cache; bool nv50_program_translate(struct nv50_program *, uint16_t chipset, + struct disk_cache *, struct pipe_debug_callback *); bool nv50_program_upload_code(struct nv50_context *, struct nv50_program *); void nv50_program_destroy(struct nv50_context *, struct nv50_program *); diff --git a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c index 2cbbdc0cc35..65891108464 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c @@ -116,7 +116,9 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog) { if (!prog->translated) { prog->translated = nv50_program_translate( - prog, nv50->screen->base.device->chipset, &nv50->base.debug); + prog, nv50->screen->base.device->chipset, + nv50->screen->base.disk_shader_cache, + &nv50->base.debug); if (!prog->translated) return false; } else diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state.c b/src/gallium/drivers/nouveau/nv50/nv50_state.c index 6488c71f4ad..7250ee35895 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_state.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_state.c @@ -779,6 +779,7 @@ nv50_sp_state_create(struct pipe_context *pipe, prog->translated = nv50_program_translate( prog, nv50_context(pipe)->screen->base.device->chipset, + nv50_context(pipe)->screen->base.disk_shader_cache, &nouveau_context(pipe)->debug); return (void *)prog; -- 2.24.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev