[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