• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2018 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 /**
24  * @file iris_disk_cache.c
25  *
26  * Functions for interacting with the on-disk shader cache.
27  */
28 
29 #include <stdio.h>
30 #include <stdint.h>
31 #include <assert.h>
32 #include <string.h>
33 
34 #include "compiler/nir/nir.h"
35 #include "util/blob.h"
36 #include "util/build_id.h"
37 #include "util/disk_cache.h"
38 #include "util/mesa-sha1.h"
39 
40 #include "iris_context.h"
41 
42 static bool debug = false;
43 
44 /**
45  * Compute a disk cache key for the given uncompiled shader and NOS key.
46  */
47 static void
iris_disk_cache_compute_key(struct disk_cache * cache,const struct iris_uncompiled_shader * ish,const void * orig_prog_key,uint32_t prog_key_size,cache_key cache_key)48 iris_disk_cache_compute_key(struct disk_cache *cache,
49                             const struct iris_uncompiled_shader *ish,
50                             const void *orig_prog_key,
51                             uint32_t prog_key_size,
52                             cache_key cache_key)
53 {
54    /* Create a copy of the program key with program_string_id zeroed out.
55     * It's essentially random data which we don't want to include in our
56     * hashing and comparisons.  We'll set a proper value on a cache hit.
57     */
58    union brw_any_prog_key prog_key;
59    memcpy(&prog_key, orig_prog_key, prog_key_size);
60    prog_key.base.program_string_id = 0;
61 
62    uint8_t data[sizeof(prog_key) + sizeof(ish->nir_sha1)];
63    uint32_t data_size = prog_key_size + sizeof(ish->nir_sha1);
64 
65    memcpy(data, ish->nir_sha1, sizeof(ish->nir_sha1));
66    memcpy(data + sizeof(ish->nir_sha1), &prog_key, prog_key_size);
67 
68    disk_cache_compute_key(cache, data, data_size, cache_key);
69 }
70 
71 /**
72  * Store the given compiled shader in the disk cache.
73  *
74  * This should only be called on newly compiled shaders.  No checking is
75  * done to prevent repeated stores of the same shader.
76  */
77 void
iris_disk_cache_store(struct disk_cache * cache,const struct iris_uncompiled_shader * ish,const struct iris_compiled_shader * shader,const void * prog_key,uint32_t prog_key_size)78 iris_disk_cache_store(struct disk_cache *cache,
79                       const struct iris_uncompiled_shader *ish,
80                       const struct iris_compiled_shader *shader,
81                       const void *prog_key,
82                       uint32_t prog_key_size)
83 {
84 #ifdef ENABLE_SHADER_CACHE
85    if (!cache)
86       return;
87 
88    gl_shader_stage stage = ish->nir->info.stage;
89    const struct brw_stage_prog_data *prog_data = shader->prog_data;
90 
91    cache_key cache_key;
92    iris_disk_cache_compute_key(cache, ish, prog_key, prog_key_size, cache_key);
93 
94    if (debug) {
95       char sha1[41];
96       _mesa_sha1_format(sha1, cache_key);
97       fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);
98    }
99 
100    struct blob blob;
101    blob_init(&blob);
102 
103    /* We write the following data to the cache blob:
104     *
105     * 1. Prog data (must come first because it has the assembly size)
106     * 2. Assembly code
107     * 3. Number of entries in the system value array
108     * 4. System value array
109     * 5. Size (in bytes) of kernel inputs
110     * 6. Shader relocations
111     * 7. Legacy param array (only used for compute workgroup ID)
112     * 8. Binding table
113     */
114    blob_write_bytes(&blob, shader->prog_data, brw_prog_data_size(stage));
115    blob_write_bytes(&blob, shader->map, shader->prog_data->program_size);
116    blob_write_uint32(&blob, shader->num_system_values);
117    blob_write_bytes(&blob, shader->system_values,
118                     shader->num_system_values * sizeof(enum brw_param_builtin));
119    blob_write_uint32(&blob, shader->kernel_input_size);
120    blob_write_bytes(&blob, prog_data->relocs,
121                     prog_data->num_relocs * sizeof(struct brw_shader_reloc));
122    blob_write_bytes(&blob, prog_data->param,
123                     prog_data->nr_params * sizeof(uint32_t));
124    blob_write_bytes(&blob, &shader->bt, sizeof(shader->bt));
125 
126    disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);
127    blob_finish(&blob);
128 #endif
129 }
130 
131 static const enum iris_program_cache_id cache_id_for_stage[] = {
132    [MESA_SHADER_VERTEX]    = IRIS_CACHE_VS,
133    [MESA_SHADER_TESS_CTRL] = IRIS_CACHE_TCS,
134    [MESA_SHADER_TESS_EVAL] = IRIS_CACHE_TES,
135    [MESA_SHADER_GEOMETRY]  = IRIS_CACHE_GS,
136    [MESA_SHADER_FRAGMENT]  = IRIS_CACHE_FS,
137    [MESA_SHADER_COMPUTE]   = IRIS_CACHE_CS,
138 };
139 
140 /**
141  * Search for a compiled shader in the disk cache.  If found, upload it
142  * to the in-memory program cache so we can use it.
143  */
144 struct iris_compiled_shader *
iris_disk_cache_retrieve(struct iris_context * ice,const struct iris_uncompiled_shader * ish,const void * prog_key,uint32_t key_size)145 iris_disk_cache_retrieve(struct iris_context *ice,
146                          const struct iris_uncompiled_shader *ish,
147                          const void *prog_key,
148                          uint32_t key_size)
149 {
150 #ifdef ENABLE_SHADER_CACHE
151    struct iris_screen *screen = (void *) ice->ctx.screen;
152    struct disk_cache *cache = screen->disk_cache;
153    gl_shader_stage stage = ish->nir->info.stage;
154 
155    if (!cache)
156       return NULL;
157 
158    cache_key cache_key;
159    iris_disk_cache_compute_key(cache, ish, prog_key, key_size, cache_key);
160 
161    if (debug) {
162       char sha1[41];
163       _mesa_sha1_format(sha1, cache_key);
164       fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
165    }
166 
167    size_t size;
168    void *buffer = disk_cache_get(screen->disk_cache, cache_key, &size);
169 
170    if (debug)
171       fprintf(stderr, "%s\n", buffer ? "found" : "missing");
172 
173    if (!buffer)
174       return NULL;
175 
176    const uint32_t prog_data_size = brw_prog_data_size(stage);
177 
178    struct brw_stage_prog_data *prog_data = ralloc_size(NULL, prog_data_size);
179    const void *assembly;
180    uint32_t num_system_values;
181    uint32_t kernel_input_size;
182    uint32_t *system_values = NULL;
183    uint32_t *so_decls = NULL;
184 
185    struct blob_reader blob;
186    blob_reader_init(&blob, buffer, size);
187    blob_copy_bytes(&blob, prog_data, prog_data_size);
188    assembly = blob_read_bytes(&blob, prog_data->program_size);
189    num_system_values = blob_read_uint32(&blob);
190    if (num_system_values) {
191       system_values =
192          ralloc_array(NULL, enum brw_param_builtin, num_system_values);
193       blob_copy_bytes(&blob, system_values,
194                       num_system_values * sizeof(enum brw_param_builtin));
195    }
196 
197    kernel_input_size = blob_read_uint32(&blob);
198 
199    prog_data->relocs = NULL;
200    if (prog_data->num_relocs) {
201       struct brw_shader_reloc *relocs =
202          ralloc_array(NULL, struct brw_shader_reloc, prog_data->num_relocs);
203       blob_copy_bytes(&blob, relocs,
204                       prog_data->num_relocs * sizeof(struct brw_shader_reloc));
205       prog_data->relocs = relocs;
206    }
207 
208    prog_data->param = NULL;
209    prog_data->pull_param = NULL;
210    assert(prog_data->nr_pull_params == 0);
211 
212    if (prog_data->nr_params) {
213       prog_data->param = ralloc_array(NULL, uint32_t, prog_data->nr_params);
214       blob_copy_bytes(&blob, prog_data->param,
215                       prog_data->nr_params * sizeof(uint32_t));
216    }
217 
218    struct iris_binding_table bt;
219    blob_copy_bytes(&blob, &bt, sizeof(bt));
220 
221    if (stage == MESA_SHADER_VERTEX ||
222        stage == MESA_SHADER_TESS_EVAL ||
223        stage == MESA_SHADER_GEOMETRY) {
224       struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
225       so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output,
226                                                &vue_prog_data->vue_map);
227    }
228 
229    /* System values and uniforms are stored in constant buffer 0, the
230     * user-facing UBOs are indexed by one.  So if any constant buffer is
231     * needed, the constant buffer 0 will be needed, so account for it.
232     */
233    unsigned num_cbufs = ish->nir->info.num_ubos;
234 
235    if (num_cbufs || ish->nir->num_uniforms)
236       num_cbufs++;
237 
238    if (num_system_values || kernel_input_size)
239       num_cbufs++;
240 
241    assert(stage < ARRAY_SIZE(cache_id_for_stage));
242    enum iris_program_cache_id cache_id = cache_id_for_stage[stage];
243 
244    /* Upload our newly read shader to the in-memory program cache and
245     * return it to the caller.
246     */
247    struct iris_compiled_shader *shader =
248       iris_upload_shader(ice, cache_id, key_size, prog_key, assembly,
249                          prog_data, so_decls, system_values,
250                          num_system_values, kernel_input_size, num_cbufs, &bt);
251 
252    free(buffer);
253 
254    return shader;
255 #else
256    return NULL;
257 #endif
258 }
259 
260 /**
261  * Initialize the on-disk shader cache.
262  */
263 void
iris_disk_cache_init(struct iris_screen * screen)264 iris_disk_cache_init(struct iris_screen *screen)
265 {
266 #ifdef ENABLE_SHADER_CACHE
267    if (INTEL_DEBUG & DEBUG_DISK_CACHE_DISABLE_MASK)
268       return;
269 
270    /* array length = print length + nul char + 1 extra to verify it's unused */
271    char renderer[11];
272    UNUSED int len =
273       snprintf(renderer, sizeof(renderer), "iris_%04x", screen->pci_id);
274    assert(len == sizeof(renderer) - 2);
275 
276    const struct build_id_note *note =
277       build_id_find_nhdr_for_addr(iris_disk_cache_init);
278    assert(note && build_id_length(note) == 20); /* sha1 */
279 
280    const uint8_t *id_sha1 = build_id_data(note);
281    assert(id_sha1);
282 
283    char timestamp[41];
284    _mesa_sha1_format(timestamp, id_sha1);
285 
286    const uint64_t driver_flags =
287       brw_get_compiler_config_value(screen->compiler);
288    screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
289 #endif
290 }
291