Adds a function for serializing a nv50_ir_prog_info structure, which is needed for shader caching.
Signed-off-by: Mark Menzynski <mmenz...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev