1/* 2 * Copyright © 2020 Google, Inc. 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 (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * 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 FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include "nir_serialize.h" 25 26#include "ir3_compiler.h" 27#include "ir3_nir.h" 28 29#define debug 0 30 31/* 32 * Shader disk-cache implementation. 33 * 34 * Note that at least in the EGL_ANDROID_blob_cache, we should never 35 * rely on inter-dependencies between different cache entries: 36 * 37 * No guarantees are made as to whether a given key/value pair is present in 38 * the cache after the set call. If a different value has been associated 39 * with the given key in the past then it is undefined which value, if any, 40 * is associated with the key after the set call. Note that while there are 41 * no guarantees, the cache implementation should attempt to cache the most 42 * recently set value for a given key. 43 * 44 * for this reason, because binning pass variants share const_state with 45 * their draw-pass counterpart, both variants are serialized together. 46 */ 47 48void 49ir3_disk_cache_init(struct ir3_compiler *compiler) 50{ 51 if (ir3_shader_debug & IR3_DBG_NOCACHE) 52 return; 53 54 const char *renderer = fd_dev_name(compiler->dev_id); 55 const struct build_id_note *note = 56 build_id_find_nhdr_for_addr(ir3_disk_cache_init); 57 assert(note && build_id_length(note) == 20); /* sha1 */ 58 59 const uint8_t *id_sha1 = build_id_data(note); 60 assert(id_sha1); 61 62 char timestamp[41]; 63 _mesa_sha1_format(timestamp, id_sha1); 64 65 uint64_t driver_flags = ir3_shader_debug; 66 if (compiler->robust_buffer_access2) 67 driver_flags |= IR3_DBG_ROBUST_UBO_ACCESS; 68 compiler->disk_cache = disk_cache_create(renderer, timestamp, driver_flags); 69} 70 71void 72ir3_disk_cache_init_shader_key(struct ir3_compiler *compiler, 73 struct ir3_shader *shader) 74{ 75 if (!compiler->disk_cache) 76 return; 77 78 struct mesa_sha1 ctx; 79 80 _mesa_sha1_init(&ctx); 81 82 /* Serialize the NIR to a binary blob that we can hash for the disk 83 * cache. Drop unnecessary information (like variable names) 84 * so the serialized NIR is smaller, and also to let us detect more 85 * isomorphic shaders when hashing, increasing cache hits. 86 */ 87 struct blob blob; 88 blob_init(&blob); 89 nir_serialize(&blob, shader->nir, true); 90 _mesa_sha1_update(&ctx, blob.data, blob.size); 91 blob_finish(&blob); 92 93 _mesa_sha1_update(&ctx, &shader->api_wavesize, 94 sizeof(shader->api_wavesize)); 95 _mesa_sha1_update(&ctx, &shader->real_wavesize, 96 sizeof(shader->real_wavesize)); 97 98 /* Note that on some gens stream-out is lowered in ir3 to stg. For later 99 * gens we maybe don't need to include stream-out in the cache key. 100 */ 101 _mesa_sha1_update(&ctx, &shader->stream_output, 102 sizeof(shader->stream_output)); 103 104 _mesa_sha1_final(&ctx, shader->cache_key); 105} 106 107static void 108compute_variant_key(struct ir3_shader *shader, struct ir3_shader_variant *v, 109 cache_key cache_key) 110{ 111 struct blob blob; 112 blob_init(&blob); 113 114 blob_write_bytes(&blob, &shader->cache_key, sizeof(shader->cache_key)); 115 blob_write_bytes(&blob, &v->key, sizeof(v->key)); 116 blob_write_uint8(&blob, v->binning_pass); 117 118 disk_cache_compute_key(shader->compiler->disk_cache, blob.data, blob.size, 119 cache_key); 120 121 blob_finish(&blob); 122} 123 124static void 125retrieve_variant(struct blob_reader *blob, struct ir3_shader_variant *v) 126{ 127 blob_copy_bytes(blob, VARIANT_CACHE_PTR(v), VARIANT_CACHE_SIZE); 128 129 /* 130 * pointers need special handling: 131 */ 132 133 v->bin = rzalloc_size(v, v->info.size); 134 blob_copy_bytes(blob, v->bin, v->info.size); 135 136 if (!v->binning_pass) { 137 blob_copy_bytes(blob, v->const_state, sizeof(*v->const_state)); 138 unsigned immeds_sz = v->const_state->immediates_size * 139 sizeof(v->const_state->immediates[0]); 140 v->const_state->immediates = ralloc_size(v->const_state, immeds_sz); 141 blob_copy_bytes(blob, v->const_state->immediates, immeds_sz); 142 } 143} 144 145static void 146store_variant(struct blob *blob, struct ir3_shader_variant *v) 147{ 148 blob_write_bytes(blob, VARIANT_CACHE_PTR(v), VARIANT_CACHE_SIZE); 149 150 /* 151 * pointers need special handling: 152 */ 153 154 blob_write_bytes(blob, v->bin, v->info.size); 155 156 /* No saving constant_data, it's already baked into bin at this point. */ 157 158 if (!v->binning_pass) { 159 blob_write_bytes(blob, v->const_state, sizeof(*v->const_state)); 160 unsigned immeds_sz = v->const_state->immediates_size * 161 sizeof(v->const_state->immediates[0]); 162 blob_write_bytes(blob, v->const_state->immediates, immeds_sz); 163 } 164} 165 166struct ir3_shader_variant * 167ir3_retrieve_variant(struct blob_reader *blob, struct ir3_compiler *compiler, 168 void *mem_ctx) 169{ 170 struct ir3_shader_variant *v = rzalloc_size(mem_ctx, sizeof(*v)); 171 172 v->id = 0; 173 v->compiler = compiler; 174 v->binning_pass = false; 175 v->nonbinning = NULL; 176 v->binning = NULL; 177 blob_copy_bytes(blob, &v->key, sizeof(v->key)); 178 v->type = blob_read_uint32(blob); 179 v->mergedregs = blob_read_uint32(blob); 180 v->const_state = rzalloc_size(v, sizeof(*v->const_state)); 181 182 retrieve_variant(blob, v); 183 184 if (v->type == MESA_SHADER_VERTEX && ir3_has_binning_vs(&v->key)) { 185 v->binning = rzalloc_size(v, sizeof(*v->binning)); 186 v->binning->id = 0; 187 v->binning->compiler = compiler; 188 v->binning->binning_pass = true; 189 v->binning->nonbinning = v; 190 v->binning->key = v->key; 191 v->binning->type = MESA_SHADER_VERTEX; 192 v->binning->mergedregs = v->mergedregs; 193 v->binning->const_state = v->const_state; 194 195 retrieve_variant(blob, v->binning); 196 } 197 198 return v; 199} 200 201void 202ir3_store_variant(struct blob *blob, struct ir3_shader_variant *v) 203{ 204 blob_write_bytes(blob, &v->key, sizeof(v->key)); 205 blob_write_uint32(blob, v->type); 206 blob_write_uint32(blob, v->mergedregs); 207 208 store_variant(blob, v); 209 210 if (v->type == MESA_SHADER_VERTEX && ir3_has_binning_vs(&v->key)) { 211 store_variant(blob, v->binning); 212 } 213} 214 215bool 216ir3_disk_cache_retrieve(struct ir3_shader *shader, 217 struct ir3_shader_variant *v) 218{ 219 if (!shader->compiler->disk_cache) 220 return false; 221 222 cache_key cache_key; 223 224 compute_variant_key(shader, v, cache_key); 225 226 if (debug) { 227 char sha1[41]; 228 _mesa_sha1_format(sha1, cache_key); 229 fprintf(stderr, "[mesa disk cache] retrieving variant %s: ", sha1); 230 } 231 232 size_t size; 233 void *buffer = disk_cache_get(shader->compiler->disk_cache, cache_key, &size); 234 235 if (debug) 236 fprintf(stderr, "%s\n", buffer ? "found" : "missing"); 237 238 if (!buffer) 239 return false; 240 241 struct blob_reader blob; 242 blob_reader_init(&blob, buffer, size); 243 244 retrieve_variant(&blob, v); 245 246 if (v->binning) 247 retrieve_variant(&blob, v->binning); 248 249 free(buffer); 250 251 return true; 252} 253 254void 255ir3_disk_cache_store(struct ir3_shader *shader, 256 struct ir3_shader_variant *v) 257{ 258 if (!shader->compiler->disk_cache) 259 return; 260 261 cache_key cache_key; 262 263 compute_variant_key(shader, v, cache_key); 264 265 if (debug) { 266 char sha1[41]; 267 _mesa_sha1_format(sha1, cache_key); 268 fprintf(stderr, "[mesa disk cache] storing variant %s\n", sha1); 269 } 270 271 struct blob blob; 272 blob_init(&blob); 273 274 store_variant(&blob, v); 275 276 if (v->binning) 277 store_variant(&blob, v->binning); 278 279 disk_cache_put(shader->compiler->disk_cache, cache_key, blob.data, blob.size, NULL); 280 blob_finish(&blob); 281} 282