1 /*
2  * Copyright © 2018 Intel Corporation
3  * Copyright (c) 2021 Lima Project
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, sub license,
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 (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  */
25 
26 #include "compiler/nir/nir.h"
27 #include "util/blob.h"
28 #include "util/build_id.h"
29 #include "util/disk_cache.h"
30 #include "util/mesa-sha1.h"
31 
32 #include "lima_context.h"
33 #include "lima_screen.h"
34 #include "lima_disk_cache.h"
35 
36 void
lima_vs_disk_cache_store(struct disk_cache * cache,const struct lima_vs_key * key,const struct lima_vs_compiled_shader * shader)37 lima_vs_disk_cache_store(struct disk_cache *cache,
38                          const struct lima_vs_key *key,
39                          const struct lima_vs_compiled_shader *shader)
40 {
41    if (!cache)
42       return;
43 
44    cache_key cache_key;
45    disk_cache_compute_key(cache, key, sizeof(*key), cache_key);
46 
47    if (lima_debug & LIMA_DEBUG_DISK_CACHE) {
48       char sha1[41];
49       _mesa_sha1_format(sha1, cache_key);
50       fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);
51    }
52 
53    struct blob blob;
54    blob_init(&blob);
55 
56    blob_write_bytes(&blob, &shader->state, sizeof(shader->state));
57    blob_write_bytes(&blob, shader->shader, shader->state.shader_size);
58    blob_write_bytes(&blob, shader->constant, shader->state.constant_size);
59 
60    disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);
61    blob_finish(&blob);
62 }
63 
64 void
lima_fs_disk_cache_store(struct disk_cache * cache,const struct lima_fs_key * key,const struct lima_fs_compiled_shader * shader)65 lima_fs_disk_cache_store(struct disk_cache *cache,
66                          const struct lima_fs_key *key,
67                          const struct lima_fs_compiled_shader *shader)
68 {
69    if (!cache)
70       return;
71 
72    cache_key cache_key;
73    disk_cache_compute_key(cache, key, sizeof(*key), cache_key);
74 
75    if (lima_debug & LIMA_DEBUG_DISK_CACHE) {
76       char sha1[41];
77       _mesa_sha1_format(sha1, cache_key);
78       fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);
79    }
80 
81    struct blob blob;
82    blob_init(&blob);
83 
84    blob_write_bytes(&blob, &shader->state, sizeof(shader->state));
85    blob_write_bytes(&blob, shader->shader, shader->state.shader_size);
86 
87    disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);
88    blob_finish(&blob);
89 }
90 
91 struct lima_vs_compiled_shader *
lima_vs_disk_cache_retrieve(struct disk_cache * cache,struct lima_vs_key * key)92 lima_vs_disk_cache_retrieve(struct disk_cache *cache,
93                             struct lima_vs_key *key)
94 {
95    struct lima_vs_compiled_shader *shader = NULL;
96 
97    if (!cache)
98       return NULL;
99 
100    cache_key cache_key;
101    disk_cache_compute_key(cache, key, sizeof(*key), cache_key);
102 
103    if (lima_debug & LIMA_DEBUG_DISK_CACHE) {
104       char sha1[41];
105       _mesa_sha1_format(sha1, cache_key);
106       fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
107    }
108 
109    size_t size;
110    void *buffer = disk_cache_get(cache, cache_key, &size);
111 
112    if (lima_debug & LIMA_DEBUG_DISK_CACHE)
113       fprintf(stderr, "%s\n", buffer ? "found" : "missing");
114 
115    if (!buffer)
116       return NULL;
117 
118    shader = rzalloc(NULL, struct lima_vs_compiled_shader);
119    if (!shader)
120       goto out;
121 
122    struct blob_reader blob;
123    blob_reader_init(&blob, buffer, size);
124    blob_copy_bytes(&blob, &shader->state, sizeof(shader->state));
125    shader->shader = rzalloc_size(shader, shader->state.shader_size);
126    if (!shader->shader)
127       goto err;
128    blob_copy_bytes(&blob, shader->shader, shader->state.shader_size);
129    shader->constant = rzalloc_size(shader, shader->state.constant_size);
130    if (!shader->constant)
131       goto err;
132    blob_copy_bytes(&blob, shader->constant, shader->state.constant_size);
133 
134 out:
135    free(buffer);
136    return shader;
137 
138 err:
139    ralloc_free(shader);
140    return NULL;
141 }
142 
143 struct lima_fs_compiled_shader *
lima_fs_disk_cache_retrieve(struct disk_cache * cache,struct lima_fs_key * key)144 lima_fs_disk_cache_retrieve(struct disk_cache *cache,
145                             struct lima_fs_key *key)
146 {
147    struct lima_fs_compiled_shader *shader = NULL;
148 
149    if (!cache)
150       return NULL;
151 
152    cache_key cache_key;
153    disk_cache_compute_key(cache, key, sizeof(*key), cache_key);
154 
155    if (lima_debug & LIMA_DEBUG_DISK_CACHE) {
156       char sha1[41];
157       _mesa_sha1_format(sha1, cache_key);
158       fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
159    }
160 
161    size_t size;
162    void *buffer = disk_cache_get(cache, cache_key, &size);
163 
164    if (lima_debug & LIMA_DEBUG_DISK_CACHE)
165       fprintf(stderr, "%s\n", buffer ? "found" : "missing");
166 
167    if (!buffer)
168       return NULL;
169 
170    shader = rzalloc(NULL, struct lima_fs_compiled_shader);
171    if (!shader)
172       goto out;
173 
174    struct blob_reader blob;
175    blob_reader_init(&blob, buffer, size);
176    blob_copy_bytes(&blob, &shader->state, sizeof(shader->state));
177    shader->shader = rzalloc_size(shader, shader->state.shader_size);
178    if (!shader->shader)
179       goto err;
180    blob_copy_bytes(&blob, shader->shader, shader->state.shader_size);
181 
182 out:
183    free(buffer);
184    return shader;
185 
186 err:
187    ralloc_free(shader);
188    return NULL;
189 }
190 
191 void
lima_disk_cache_init(struct lima_screen * screen)192 lima_disk_cache_init(struct lima_screen *screen)
193 {
194    const struct build_id_note *note =
195       build_id_find_nhdr_for_addr(lima_disk_cache_init);
196    assert(note && build_id_length(note) == 20); /* sha1 */
197 
198    const uint8_t *id_sha1 = build_id_data(note);
199    assert(id_sha1);
200 
201    char timestamp[41];
202    _mesa_sha1_format(timestamp, id_sha1);
203 
204    screen->disk_cache = disk_cache_create(screen->base.get_name(&screen->base), timestamp, 0);
205 }
206