xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/panfrost/pan_disk_cache.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2022 Amazon.com, Inc. or its affiliates.
3  * Copyright © 2018 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <assert.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "compiler/nir/nir.h"
30 #include "util/blob.h"
31 #include "util/build_id.h"
32 #include "util/disk_cache.h"
33 #include "util/mesa-sha1.h"
34 
35 #include "pan_context.h"
36 
37 #ifdef ENABLE_SHADER_CACHE
38 static bool debug = false;
39 #endif
40 
41 extern int midgard_debug;
42 extern int bifrost_debug;
43 
44 /**
45  * Compute a disk cache key for the given uncompiled shader and shader key.
46  */
47 static void
panfrost_disk_cache_compute_key(struct disk_cache * cache,const struct panfrost_uncompiled_shader * uncompiled,const struct panfrost_shader_key * shader_key,cache_key cache_key)48 panfrost_disk_cache_compute_key(
49    struct disk_cache *cache,
50    const struct panfrost_uncompiled_shader *uncompiled,
51    const struct panfrost_shader_key *shader_key, cache_key cache_key)
52 {
53    uint8_t data[sizeof(uncompiled->nir_sha1) + sizeof(*shader_key)];
54 
55    memcpy(data, uncompiled->nir_sha1, sizeof(uncompiled->nir_sha1));
56    memcpy(data + sizeof(uncompiled->nir_sha1), shader_key, sizeof(*shader_key));
57 
58    disk_cache_compute_key(cache, data, sizeof(data), cache_key);
59 }
60 
61 /**
62  * Store the given compiled shader in the disk cache.
63  *
64  * This should only be called on newly compiled shaders.  No checking is
65  * done to prevent repeated stores of the same shader.
66  */
67 void
panfrost_disk_cache_store(struct disk_cache * cache,const struct panfrost_uncompiled_shader * uncompiled,const struct panfrost_shader_key * key,const struct panfrost_shader_binary * binary)68 panfrost_disk_cache_store(struct disk_cache *cache,
69                           const struct panfrost_uncompiled_shader *uncompiled,
70                           const struct panfrost_shader_key *key,
71                           const struct panfrost_shader_binary *binary)
72 {
73 #ifdef ENABLE_SHADER_CACHE
74    if (!cache)
75       return;
76 
77    cache_key cache_key;
78    panfrost_disk_cache_compute_key(cache, uncompiled, key, cache_key);
79 
80    if (debug) {
81       char sha1[41];
82       _mesa_sha1_format(sha1, cache_key);
83       fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);
84    }
85 
86    struct blob blob;
87    blob_init(&blob);
88 
89    /* We write the following data to the cache blob:
90     *
91     * 1. Size of program binary
92     * 2. Program binary
93     * 3. Shader info
94     * 4. System values
95     */
96    blob_write_uint32(&blob, binary->binary.size);
97    blob_write_bytes(&blob, binary->binary.data, binary->binary.size);
98    blob_write_bytes(&blob, &binary->info, sizeof(binary->info));
99    blob_write_bytes(&blob, &binary->sysvals, sizeof(binary->sysvals));
100 
101    disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);
102    blob_finish(&blob);
103 #endif
104 }
105 
106 /**
107  * Search for a compiled shader in the disk cache.
108  */
109 bool
panfrost_disk_cache_retrieve(struct disk_cache * cache,const struct panfrost_uncompiled_shader * uncompiled,const struct panfrost_shader_key * key,struct panfrost_shader_binary * binary)110 panfrost_disk_cache_retrieve(struct disk_cache *cache,
111                              const struct panfrost_uncompiled_shader *uncompiled,
112                              const struct panfrost_shader_key *key,
113                              struct panfrost_shader_binary *binary)
114 {
115 #ifdef ENABLE_SHADER_CACHE
116    if (!cache)
117       return false;
118 
119    cache_key cache_key;
120    panfrost_disk_cache_compute_key(cache, uncompiled, key, cache_key);
121 
122    if (debug) {
123       char sha1[41];
124       _mesa_sha1_format(sha1, cache_key);
125       fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
126    }
127 
128    size_t size;
129    void *buffer = disk_cache_get(cache, cache_key, &size);
130 
131    if (debug)
132       fprintf(stderr, "%s\n", buffer ? "found" : "missing");
133 
134    if (!buffer)
135       return false;
136 
137    struct blob_reader blob;
138    blob_reader_init(&blob, buffer, size);
139 
140    util_dynarray_init(&binary->binary, NULL);
141 
142    uint32_t binary_size = blob_read_uint32(&blob);
143    void *ptr = util_dynarray_resize_bytes(&binary->binary, binary_size, 1);
144 
145    blob_copy_bytes(&blob, ptr, binary_size);
146    blob_copy_bytes(&blob, &binary->info, sizeof(binary->info));
147    blob_copy_bytes(&blob, &binary->sysvals, sizeof(binary->sysvals));
148 
149    free(buffer);
150 
151    return true;
152 #else
153    return false;
154 #endif
155 }
156 
157 /**
158  * Initialize the on-disk shader cache.
159  */
160 void
panfrost_disk_cache_init(struct panfrost_screen * screen)161 panfrost_disk_cache_init(struct panfrost_screen *screen)
162 {
163 #ifdef ENABLE_SHADER_CACHE
164    const char *renderer = screen->base.get_name(&screen->base);
165 
166    const struct build_id_note *note =
167       build_id_find_nhdr_for_addr(panfrost_disk_cache_init);
168    assert(note && build_id_length(note) == 20); /* sha1 */
169 
170    const uint8_t *id_sha1 = build_id_data(note);
171    assert(id_sha1);
172 
173    char timestamp[41];
174    _mesa_sha1_format(timestamp, id_sha1);
175 
176    /* Consider any flags affecting the compile when caching */
177    uint64_t driver_flags = screen->dev.debug;
178    driver_flags |= ((uint64_t)(midgard_debug | bifrost_debug) << 32);
179 
180    screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
181 #endif
182 }
183