[Mesa-dev] [RFC PATCH v2 4/6] nv50/ir: Add nv50_ir_prog_info serialize

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


Adds a function for serializing a nv50_ir_prog_info structure, which is
needed for shader caching.

Signed-off-by: Mark Menzynski <mmenzyns at redhat.com>
---
 .../drivers/nouveau/codegen/nv50_ir_driver.h  |  4 +
 .../nouveau/codegen/nv50_ir_serialize.cpp     | 81 +++++++++++++++++++
 .../drivers/nouveau/nvc0/nvc0_context.h       |  1 +
 .../drivers/nouveau/nvc0/nvc0_program.c       | 43 ++++++++--
 .../drivers/nouveau/nvc0/nvc0_shader_state.c  |  3 +-
 src/gallium/drivers/nouveau/nvc0/nvc0_state.c |  2 +
 6 files changed, 128 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
index 10ae5cbe420..3728470ab45 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
@@ -278,6 +278,10 @@ namespace nv50_ir
 extern void
 nv50_ir_prog_info_out_print(struct nv50_ir_prog_info_out *);
 
+/* Serialize a nv50_ir_prog_info structure and save it into blob */
+extern bool
+nv50_ir_prog_info_serialize(struct blob *, struct nv50_ir_prog_info *);
+
 /* Serialize a nv50_ir_prog_info_out structure and save it into blob */
 extern bool
 nv50_ir_prog_info_out_serialize(struct blob *, struct nv50_ir_prog_info_out *);
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp
index 5671483bd4e..b640cb67503 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_serialize.cpp
@@ -17,6 +17,87 @@ enum FixupApplyFunc {
    FLIP_GM107 = 7
 };
 
+extern bool
+nv50_ir_prog_info_serialize(struct blob *blob, struct nv50_ir_prog_info *info)
+{
+   blob_write_uint16(blob, info->target);
+   blob_write_uint8(blob, info->type);
+   blob_write_uint8(blob, info->optLevel);
+   blob_write_uint8(blob, info->dbgFlags);
+   blob_write_uint8(blob, info->omitLineNum);
+   blob_write_uint32(blob, info->bin.smemSize);
+   blob_write_uint16(blob, info->bin.maxOutput);
+   blob_write_uint8(blob, info->bin.sourceRep);
+
+   switch(info->bin.sourceRep) {
+      case PIPE_SHADER_IR_TGSI: {
+         struct tgsi_token *tokens = (struct tgsi_token *)info->bin.source;
+         unsigned int num_tokens = tgsi_num_tokens(tokens);
+
+         blob_write_uint32(blob, num_tokens);
+         blob_write_bytes(blob, tokens, num_tokens * sizeof(struct tgsi_token));
+         break;
+      }
+      case PIPE_SHADER_IR_NIR: {
+         struct nir_shader *nir = (struct nir_shader *)info->bin.source;
+         nir_serialize(blob, nir, false);
+         break;
+      }
+      default:
+         assert(!"unhandled info->bin.sourceRep");
+         return false;
+   }
+
+   blob_write_uint16(blob, info->immd.bufSize);
+   blob_write_bytes(blob, info->immd.buf, info->immd.bufSize * sizeof(*info->immd.buf));
+   blob_write_uint16(blob, info->immd.count);
+   blob_write_bytes(blob, info->immd.data, info->immd.count * sizeof(*info->immd.data));
+   blob_write_bytes(blob, info->immd.type, info->immd.count * 16); // for each vec4 (128 bit)
+
+   switch (info->type) {
+      case PIPE_SHADER_VERTEX:
+         blob_write_bytes(blob, info->prop.vp.inputMask,
+                          4 * sizeof(*info->prop.vp.inputMask)); /* array of size 4 */
+         break;
+      case PIPE_SHADER_TESS_CTRL:
+         blob_write_uint32(blob, info->prop.cp.inputOffset);
+         blob_write_uint32(blob, info->prop.cp.sharedOffset);
+         blob_write_uint32(blob, info->prop.cp.gridInfoBase);
+         blob_write_bytes(blob, info->prop.cp.numThreads,
+                          3 * sizeof(*info->prop.cp.numThreads)); /* array of size 3 */
+      case PIPE_SHADER_GEOMETRY:
+         blob_write_uint8(blob, info->prop.gp.inputPrim);
+         break;
+      case PIPE_SHADER_FRAGMENT:
+         blob_write_uint8(blob, info->prop.fp.persampleInvocation);
+         break;
+      default:
+         break;
+   }
+
+   blob_write_uint8(blob, info->io.auxCBSlot);
+   blob_write_uint16(blob, info->io.ucpBase);
+   blob_write_uint16(blob, info->io.drawInfoBase);
+   blob_write_uint16(blob, info->io.alphaRefBase);
+   blob_write_uint8(blob, info->io.pointSize);
+   blob_write_uint8(blob, info->io.viewportId);
+   blob_write_bytes(blob, info->io.backFaceColor, 2 * sizeof(*info->io.backFaceColor));
+   blob_write_uint8(blob, info->io.mul_zero_wins);
+   blob_write_uint8(blob, info->io.nv50styleSurfaces);
+   blob_write_uint16(blob, info->io.texBindBase);
+   blob_write_uint16(blob, info->io.fbtexBindBase);
+   blob_write_uint16(blob, info->io.suInfoBase);
+   blob_write_uint16(blob, info->io.bindlessBase);
+   blob_write_uint16(blob, info->io.bufInfoBase);
+   blob_write_uint16(blob, info->io.sampleInfoBase);
+   blob_write_uint8(blob, info->io.msInfoCBSlot);
+   blob_write_uint16(blob, info->io.msInfoBase);
+   blob_write_uint16(blob, info->io.uboInfoBase);
+   blob_write_uint8(blob, info->io.genUserClip);
+
+   return true;
+}
+
 extern bool
 nv50_ir_prog_info_out_serialize(struct blob *blob,
                                 struct nv50_ir_prog_info_out *info_out)
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 7f32dc941d6..bbf2fd8c6a2 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)
@@ -632,11 +641,35 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset,
    info->bin.smemSize = prog->cp.smem_size;
    info->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;
+   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);
+   }
+   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.24.1



More information about the mesa-dev mailing list