Module: Mesa
Branch: main
Commit: 4e14da056d623ababf7cf82cf2fca51c18b462f1
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=4e14da056d623ababf7cf82cf2fca51c18b462f1

Author: Emma Anholt <[email protected]>
Date:   Mon Oct 17 11:46:52 2022 -0700

zink: Enable mesa/st frontend shader caching.

This required fixing up the disk cache to hash in stuff that was missing
(like the proper pipeline cache uuid rather than just PCI IDs, and also
zink's build ID).  Once we do that, we can just hand the frontend our disk
cache and avoid GLSL->NIR recompiles.

tu asphalt_9 trace perf +3.14859% +/- 1.36891% (n=4)

Fixes: #7513
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19124>

---

 src/gallium/drivers/zink/ci/zink-lvp-fails.txt |  1 -
 src/gallium/drivers/zink/zink_screen.c         | 67 ++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/zink/ci/zink-lvp-fails.txt 
b/src/gallium/drivers/zink/ci/zink-lvp-fails.txt
index 7f173e97724..e61edddab14 100644
--- a/src/gallium/drivers/zink/ci/zink-lvp-fails.txt
+++ b/src/gallium/drivers/zink/ci/zink-lvp-fails.txt
@@ -95,7 +95,6 @@ spec@!opengl 2.1@polygon-stipple-fs,Fail
 spec@!opengl es 2.0@glsl-fs-pointcoord,Fail
 spec@arb_depth_texture@depth-tex-modes,Fail
 spec@arb_framebuffer_object@fbo-gl_pointcoord,Fail
-spec@arb_get_program_binary@restore-sso-program,Fail
 spec@arb_gpu_shader_fp64@execution@arb_gpu_shader_fp64-tf-separate,Fail
 spec@arb_pipeline_statistics_query@arb_pipeline_statistics_query-frag,Fail
 spec@arb_point_sprite@arb_point_sprite-checkerboard,Fail
diff --git a/src/gallium/drivers/zink/zink_screen.c 
b/src/gallium/drivers/zink/zink_screen.c
index 71cadcc7bc0..8eae99e9e29 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -204,16 +204,68 @@ get_video_mem(struct zink_screen *screen)
    return size;
 }
 
+/**
+ * Creates the disk cache used by mesa/st frontend for caching the GLSL -> NIR
+ * path.
+ *
+ * The output that gets stored in the frontend's cache is the result of
+ * zink_shader_finalize().  So, our sha1 cache key here needs to include
+ * everything that would change the NIR we generate from a given set of GLSL
+ * source, including our driver build, the Vulkan device and driver (which 
could
+ * affect the pipe caps we show the frontend), and any debug flags that change
+ * codegen.
+ *
+ * This disk cache also gets used by zink itself for storing its output from 
NIR
+ * -> SPIRV translation.
+ */
 static bool
 disk_cache_init(struct zink_screen *screen)
 {
    if (zink_debug & ZINK_DEBUG_SHADERDB)
       return true;
+
 #ifdef ENABLE_SHADER_CACHE
-   static char buf[1000];
-   snprintf(buf, sizeof(buf), "zink_%x04x", screen->info.props.vendorID);
+   struct mesa_sha1 ctx;
+   _mesa_sha1_init(&ctx);
+
+   /* Hash in the zink driver build. */
+   const struct build_id_note *note =
+       build_id_find_nhdr_for_addr(disk_cache_init);
+   unsigned build_id_len = build_id_length(note);
+   assert(note && build_id_len == 20); /* sha1 */
+   _mesa_sha1_update(&ctx, build_id_data(note), build_id_len);
+
+   /* Hash in the Vulkan pipeline cache UUID to identify the combination of
+   *  vulkan device and driver (or any inserted layer that would invalidate our
+   *  cached pipelines).
+   *
+   * "Although they have identical descriptions, VkPhysicalDeviceIDProperties
+   *  ::deviceUUID may differ from
+   *  VkPhysicalDeviceProperties2::pipelineCacheUUID. The former is intended to
+   *  identify and correlate devices across API and driver boundaries, while 
the
+   *  latter is used to identify a compatible device and driver combination to
+   *  use when serializing and de-serializing pipeline state."
+   */
+   _mesa_sha1_update(&ctx, screen->info.props.pipelineCacheUUID, VK_UUID_SIZE);
+
+   /* Hash in our debug flags that affect NIR generation as of finalize_nir */
+   unsigned shader_debug_flags = zink_debug & ZINK_DEBUG_COMPACT;
+   _mesa_sha1_update(&ctx, &shader_debug_flags, sizeof(shader_debug_flags));
+
+   /* Some of the driconf options change shaders.  Let's just hash the whole
+    * thing to not forget any (especially as options get added).
+    */
+   _mesa_sha1_update(&ctx, &screen->driconf, sizeof(screen->driconf));
+
+   /* Finish the sha1 and format it as text. */
+   unsigned char sha1[20];
+   _mesa_sha1_final(&ctx, sha1);
+
+   char cache_id[20 * 2 + 1];
+   disk_cache_format_hex_id(cache_id, sha1, 20 * 2);
+
+   screen->disk_cache = disk_cache_create("zink", cache_id, 0);
 
-   screen->disk_cache = disk_cache_create(buf, screen->info.props.deviceName, 
0);
    if (!screen->disk_cache)
       return true;
 
@@ -2366,6 +2418,14 @@ init_driver_workarounds(struct zink_screen *screen)
 #endif
 }
 
+static struct disk_cache *
+zink_get_disk_shader_cache(struct pipe_screen *_screen)
+{
+   struct zink_screen *screen = zink_screen(_screen);
+
+   return screen->disk_cache;
+}
+
 static struct zink_screen *
 zink_internal_create_screen(const struct pipe_screen_config *config)
 {
@@ -2545,6 +2605,7 @@ zink_internal_create_screen(const struct 
pipe_screen_config *config)
    screen->base.flush_frontbuffer = zink_flush_frontbuffer;
    screen->base.destroy = zink_destroy_screen;
    screen->base.finalize_nir = zink_shader_finalize;
+   screen->base.get_disk_shader_cache = zink_get_disk_shader_cache;
    screen->base.get_sparse_texture_virtual_page_size = 
zink_get_sparse_texture_virtual_page_size;
 
    if (screen->info.have_EXT_sample_locations) {

Reply via email to