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
42static bool debug = false;
43
44/**
45 * Compute a disk cache key for the given uncompiled shader and NOS key.
46 */
47static void
48iris_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 */
77void
78iris_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
131static 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 */
144bool
145iris_disk_cache_retrieve(struct iris_screen *screen,
146                         struct u_upload_mgr *uploader,
147                         struct iris_uncompiled_shader *ish,
148                         struct iris_compiled_shader *shader,
149                         const void *prog_key,
150                         uint32_t key_size)
151{
152#ifdef ENABLE_SHADER_CACHE
153   struct disk_cache *cache = screen->disk_cache;
154   gl_shader_stage stage = ish->nir->info.stage;
155
156   if (!cache)
157      return false;
158
159   cache_key cache_key;
160   iris_disk_cache_compute_key(cache, ish, prog_key, key_size, cache_key);
161
162   if (debug) {
163      char sha1[41];
164      _mesa_sha1_format(sha1, cache_key);
165      fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
166   }
167
168   size_t size;
169   void *buffer = disk_cache_get(screen->disk_cache, cache_key, &size);
170
171   if (debug)
172      fprintf(stderr, "%s\n", buffer ? "found" : "missing");
173
174   if (!buffer)
175      return false;
176
177   const uint32_t prog_data_size = brw_prog_data_size(stage);
178
179   struct brw_stage_prog_data *prog_data = ralloc_size(NULL, prog_data_size);
180   const void *assembly;
181   uint32_t num_system_values;
182   uint32_t kernel_input_size;
183   uint32_t *system_values = NULL;
184   uint32_t *so_decls = NULL;
185
186   struct blob_reader blob;
187   blob_reader_init(&blob, buffer, size);
188   blob_copy_bytes(&blob, prog_data, prog_data_size);
189   assembly = blob_read_bytes(&blob, prog_data->program_size);
190   num_system_values = blob_read_uint32(&blob);
191   if (num_system_values) {
192      system_values =
193         ralloc_array(NULL, enum brw_param_builtin, num_system_values);
194      blob_copy_bytes(&blob, system_values,
195                      num_system_values * sizeof(enum brw_param_builtin));
196   }
197
198   kernel_input_size = blob_read_uint32(&blob);
199
200   prog_data->relocs = NULL;
201   if (prog_data->num_relocs) {
202      struct brw_shader_reloc *relocs =
203         ralloc_array(NULL, struct brw_shader_reloc, prog_data->num_relocs);
204      blob_copy_bytes(&blob, relocs,
205                      prog_data->num_relocs * sizeof(struct brw_shader_reloc));
206      prog_data->relocs = relocs;
207   }
208
209   prog_data->param = NULL;
210   if (prog_data->nr_params) {
211      prog_data->param = ralloc_array(NULL, uint32_t, prog_data->nr_params);
212      blob_copy_bytes(&blob, prog_data->param,
213                      prog_data->nr_params * sizeof(uint32_t));
214   }
215
216   struct iris_binding_table bt;
217   blob_copy_bytes(&blob, &bt, sizeof(bt));
218
219   if (stage == MESA_SHADER_VERTEX ||
220       stage == MESA_SHADER_TESS_EVAL ||
221       stage == MESA_SHADER_GEOMETRY) {
222      struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
223      so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output,
224                                               &vue_prog_data->vue_map);
225   }
226
227   /* System values and uniforms are stored in constant buffer 0, the
228    * user-facing UBOs are indexed by one.  So if any constant buffer is
229    * needed, the constant buffer 0 will be needed, so account for it.
230    */
231   unsigned num_cbufs = ish->nir->info.num_ubos;
232
233   if (num_cbufs || ish->nir->num_uniforms)
234      num_cbufs++;
235
236   if (num_system_values || kernel_input_size)
237      num_cbufs++;
238
239   iris_finalize_program(shader, prog_data, so_decls, system_values,
240                         num_system_values, kernel_input_size, num_cbufs,
241                         &bt);
242
243   assert(stage < ARRAY_SIZE(cache_id_for_stage));
244   enum iris_program_cache_id cache_id = cache_id_for_stage[stage];
245
246   /* Upload our newly read shader to the in-memory program cache. */
247   iris_upload_shader(screen, ish, shader, NULL, uploader,
248                      cache_id, key_size, prog_key, assembly);
249
250   free(buffer);
251
252   return true;
253#else
254   return false;
255#endif
256}
257
258/**
259 * Initialize the on-disk shader cache.
260 */
261void
262iris_disk_cache_init(struct iris_screen *screen)
263{
264#ifdef ENABLE_SHADER_CACHE
265   if (INTEL_DEBUG(DEBUG_DISK_CACHE_DISABLE_MASK))
266      return;
267
268   /* array length = print length + nul char + 1 extra to verify it's unused */
269   char renderer[11];
270   UNUSED int len =
271      snprintf(renderer, sizeof(renderer), "iris_%04x", screen->pci_id);
272   assert(len == sizeof(renderer) - 2);
273
274   const struct build_id_note *note =
275      build_id_find_nhdr_for_addr(iris_disk_cache_init);
276   assert(note && build_id_length(note) == 20); /* sha1 */
277
278   const uint8_t *id_sha1 = build_id_data(note);
279   assert(id_sha1);
280
281   char timestamp[41];
282   _mesa_sha1_format(timestamp, id_sha1);
283
284   const uint64_t driver_flags =
285      brw_get_compiler_config_value(screen->compiler);
286   screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
287#endif
288}
289