[Mesa-dev] [PATCH 8/8] nvc0: Add shader disk caching

Karol Herbst kherbst at redhat.com
Mon Feb 17 20:12:57 UTC 2020


On Mon, Feb 17, 2020 at 6:41 PM Mark Menzynski <mmenzyns at 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 <mmenzyns at 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>



More information about the mesa-dev mailing list