[Mesa-dev] [RFC PATCH 2/2] nv50: Add shader disk caching

Mark Menzynski mmenzyns at redhat.com
Thu Mar 19 20:20:23 UTC 2020


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 <mmenzyns at 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



More information about the mesa-dev mailing list