On Mon, Feb 17, 2020 at 6:41 PM Mark Menzynski <mmenz...@redhat.com> wrote: > > Adds shader disk caching for nvc0 to reduce the need to every time compile > shaders. Shaders are saved into disk_shader_cache from nvc0_screen structure. > > 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. > > Seems to be significantly improving loading times. Piglit tests seem > to be OK. > > Signed-off-by: Mark Menzynski <mmenz...@redhat.com> > --- > .../drivers/nouveau/nvc0/nvc0_context.h | 1 + > .../drivers/nouveau/nvc0/nvc0_program.c | 49 ++++++++++++++++--- > .../drivers/nouveau/nvc0/nvc0_shader_state.c | 3 +- > src/gallium/drivers/nouveau/nvc0/nvc0_state.c | 2 + > 4 files changed, 46 insertions(+), 9 deletions(-) > > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > index 8a2a8f2797e..4b83d1afeb4 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h > @@ -321,6 +321,7 @@ extern struct draw_stage *nvc0_draw_render_stage(struct > nvc0_context *); > > /* nvc0_program.c */ > bool nvc0_program_translate(struct nvc0_program *, uint16_t chipset, > + struct disk_cache *, > struct pipe_debug_callback *); > bool nvc0_program_upload(struct nvc0_context *, struct nvc0_program *); > void nvc0_program_destroy(struct nvc0_context *, struct nvc0_program *); > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > index 1a5073292e8..06b6f7b4db5 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c > @@ -24,6 +24,7 @@ > > #include "compiler/nir/nir.h" > #include "tgsi/tgsi_ureg.h" > +#include "util/blob.h" > > #include "nvc0/nvc0_context.h" > > @@ -568,11 +569,19 @@ nvc0_program_dump(struct nvc0_program *prog) > > bool > nvc0_program_translate(struct nvc0_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; > struct nv50_ir_prog_info_out info_out = {}; > - int ret; > + > + void *cached_data = NULL; > + size_t cached_size; > + bool shader_found = false; > + > + int ret = 0; > + cache_key key; > > info = CALLOC_STRUCT(nv50_ir_prog_info); > if (!info) > @@ -631,14 +640,38 @@ nvc0_program_translate(struct nvc0_program *prog, > uint16_t chipset, > info->assignSlots = nvc0_program_assign_varying_slots; > > /* these fields might be overwritten by the compiler */ > - info_out.bin.smemSize = prog->cp.smem_size; > - info_out.io.genUserClip = prog->vp.num_ucps; > - > - ret = nv50_ir_generate_code(info, &info_out); > - if (ret) { > - NOUVEAU_ERR("shader translation failed: %i\n", ret); > - goto out; > + info->bin.smemSize = prog->cp.smem_size; > + info->io.genUserClip = prog->vp.num_ucps; > + > + blob_init(&blob); > + nv50_ir_prog_info_serialize(&blob, info); > + > + if (disk_shader_cache) { > + 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); > + }
I am still a bit unsure if we really really need this check... other drivers don't seem to do it either, but it's definitely safer to keep it... let's see what others think about it. > + } > + free(cached_data); > + } > + 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); > > prog->code = info_out.bin.code; > prog->code_size = info_out.bin.codeSize; > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > index 774c5648113..4327a89454b 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c > @@ -54,7 +54,8 @@ nvc0_program_validate(struct nvc0_context *nvc0, struct > nvc0_program *prog) > > if (!prog->translated) { > prog->translated = nvc0_program_translate( > - prog, nvc0->screen->base.device->chipset, &nvc0->base.debug); > + prog, nvc0->screen->base.device->chipset, > + nvc0->screen->base.disk_shader_cache, &nvc0->base.debug); > if (!prog->translated) > return false; > } > diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c > b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c > index 49546e5de68..e57d1ed39e9 100644 > --- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c > +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c > @@ -619,6 +619,7 @@ nvc0_sp_state_create(struct pipe_context *pipe, > > prog->translated = nvc0_program_translate( > prog, nvc0_context(pipe)->screen->base.device->chipset, > + nvc0_context(pipe)->screen->base.disk_shader_cache, > &nouveau_context(pipe)->debug); > > return (void *)prog; > @@ -758,6 +759,7 @@ nvc0_cp_state_create(struct pipe_context *pipe, > > prog->translated = nvc0_program_translate( > prog, nvc0_context(pipe)->screen->base.device->chipset, > + nvc0_context(pipe)->screen->base.disk_shader_cache, > &nouveau_context(pipe)->debug); > > return (void *)prog; > -- > 2.21.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev