xref: /aosp_15_r20/external/mesa3d/src/amd/vulkan/radv_pipeline_cache.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2015 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "radv_pipeline_cache.h"
8 #include "util/disk_cache.h"
9 #include "util/macros.h"
10 #include "util/mesa-blake3.h"
11 #include "util/mesa-sha1.h"
12 #include "util/u_atomic.h"
13 #include "util/u_debug.h"
14 #include "nir_serialize.h"
15 #include "radv_debug.h"
16 #include "radv_descriptor_set.h"
17 #include "radv_pipeline.h"
18 #include "radv_pipeline_compute.h"
19 #include "radv_pipeline_graphics.h"
20 #include "radv_pipeline_binary.h"
21 #include "radv_pipeline_rt.h"
22 #include "radv_shader.h"
23 #include "vk_pipeline.h"
24 #include "vk_util.h"
25 
26 #include "aco_interface.h"
27 
28 void
radv_hash_graphics_spirv_to_nir(blake3_hash hash,const struct radv_shader_stage * stage,const struct radv_spirv_to_nir_options * options)29 radv_hash_graphics_spirv_to_nir(blake3_hash hash, const struct radv_shader_stage *stage,
30                                 const struct radv_spirv_to_nir_options *options)
31 {
32    struct mesa_blake3 ctx;
33    _mesa_blake3_init(&ctx);
34    _mesa_blake3_update(&ctx, &stage->key, sizeof(stage->key));
35    _mesa_blake3_update(&ctx, options, sizeof(*options));
36    _mesa_blake3_update(&ctx, stage->shader_sha1, sizeof(stage->shader_sha1));
37    _mesa_blake3_final(&ctx, hash);
38 }
39 
40 static void
radv_shader_destroy(struct vk_device * _device,struct vk_pipeline_cache_object * object)41 radv_shader_destroy(struct vk_device *_device, struct vk_pipeline_cache_object *object)
42 {
43    struct radv_device *device = container_of(_device, struct radv_device, vk);
44    struct radv_shader *shader = container_of(object, struct radv_shader, base);
45 
46    if (device->shader_use_invisible_vram) {
47       /* Wait for any pending upload to complete, or we'll be writing into freed shader memory. */
48       radv_shader_wait_for_upload(device, shader->upload_seq);
49    }
50 
51    radv_free_shader_memory(device, shader->alloc);
52 
53    free(shader->code);
54    free(shader->spirv);
55    free(shader->nir_string);
56    free(shader->disasm_string);
57    free(shader->ir_string);
58    free(shader->statistics);
59 
60    vk_pipeline_cache_object_finish(&shader->base);
61    free(shader);
62 }
63 
64 struct radv_shader *
radv_shader_deserialize(struct radv_device * device,const void * key_data,size_t key_size,struct blob_reader * blob)65 radv_shader_deserialize(struct radv_device *device, const void *key_data, size_t key_size, struct blob_reader *blob)
66 {
67    const struct radv_shader_binary *binary = blob_read_bytes(blob, sizeof(struct radv_shader_binary));
68 
69    struct radv_shader *shader;
70    radv_shader_create_uncached(device, binary, false, NULL, &shader);
71    if (!shader)
72       return NULL;
73 
74    assert(key_size == sizeof(shader->hash));
75    memcpy(shader->hash, key_data, key_size);
76    blob_skip_bytes(blob, binary->total_size - sizeof(struct radv_shader_binary));
77 
78    return shader;
79 }
80 
81 static struct vk_pipeline_cache_object *
radv_shader_cache_deserialize(struct vk_pipeline_cache * cache,const void * key_data,size_t key_size,struct blob_reader * blob)82 radv_shader_cache_deserialize(struct vk_pipeline_cache *cache, const void *key_data, size_t key_size,
83                               struct blob_reader *blob)
84 {
85    struct radv_device *device = container_of(cache->base.device, struct radv_device, vk);
86    struct radv_shader *shader;
87 
88    shader = radv_shader_deserialize(device, key_data, key_size, blob);
89 
90    return shader ? &shader->base : NULL;
91 }
92 
93 void
radv_shader_serialize(struct radv_shader * shader,struct blob * blob)94 radv_shader_serialize(struct radv_shader *shader, struct blob *blob)
95 {
96    size_t stats_size = shader->statistics ? aco_num_statistics * sizeof(uint32_t) : 0;
97    size_t code_size = shader->code_size;
98    uint32_t total_size = sizeof(struct radv_shader_binary_legacy) + code_size + stats_size;
99 
100    struct radv_shader_binary_legacy binary = {
101       .base =
102          {
103             .type = RADV_BINARY_TYPE_LEGACY,
104             .config = shader->config,
105             .info = shader->info,
106             .total_size = total_size,
107          },
108       .code_size = code_size,
109       .exec_size = shader->exec_size,
110       .ir_size = 0,
111       .disasm_size = 0,
112       .stats_size = stats_size,
113    };
114 
115    blob_write_bytes(blob, &binary, sizeof(struct radv_shader_binary_legacy));
116    blob_write_bytes(blob, shader->statistics, stats_size);
117    blob_write_bytes(blob, shader->code, code_size);
118 }
119 
120 static bool
radv_shader_cache_serialize(struct vk_pipeline_cache_object * object,struct blob * blob)121 radv_shader_cache_serialize(struct vk_pipeline_cache_object *object, struct blob *blob)
122 {
123    struct radv_shader *shader = container_of(object, struct radv_shader, base);
124 
125    radv_shader_serialize(shader, blob);
126    return true;
127 }
128 
129 static bool
radv_is_cache_disabled(const struct radv_device * device,const struct vk_pipeline_cache * cache)130 radv_is_cache_disabled(const struct radv_device *device, const struct vk_pipeline_cache *cache)
131 {
132    const struct radv_physical_device *pdev = radv_device_physical(device);
133    const struct radv_instance *instance = radv_physical_device_instance(pdev);
134 
135    /* The buffer address used for debug printf is hardcoded. */
136    if (device->printf.buffer_addr)
137       return true;
138 
139    /* Pipeline caches can be disabled with RADV_DEBUG=nocache, with MESA_GLSL_CACHE_DISABLE=1 and
140     * when ACO_DEBUG is used. MESA_GLSL_CACHE_DISABLE is done elsewhere.
141     */
142    if ((instance->debug_flags & RADV_DEBUG_NO_CACHE) || (pdev->use_llvm ? 0 : aco_get_codegen_flags()))
143       return true;
144 
145    if (!cache) {
146       /* When the application doesn't provide a pipeline cache and the in-memory cache is also
147        * disabled.
148        */
149       cache = device->mem_cache;
150       if (!cache)
151          return true;
152    }
153 
154    return false;
155 }
156 
157 struct radv_shader *
radv_shader_create(struct radv_device * device,struct vk_pipeline_cache * cache,const struct radv_shader_binary * binary,bool skip_cache)158 radv_shader_create(struct radv_device *device, struct vk_pipeline_cache *cache, const struct radv_shader_binary *binary,
159                    bool skip_cache)
160 {
161    if (radv_is_cache_disabled(device, cache) || skip_cache) {
162       struct radv_shader *shader;
163       radv_shader_create_uncached(device, binary, false, NULL, &shader);
164       return shader;
165    }
166 
167    if (!cache)
168       cache = device->mem_cache;
169 
170    blake3_hash hash;
171    _mesa_blake3_compute(binary, binary->total_size, hash);
172 
173    struct vk_pipeline_cache_object *shader_obj;
174    shader_obj = vk_pipeline_cache_create_and_insert_object(cache, hash, sizeof(hash), binary, binary->total_size,
175                                                            &radv_shader_ops);
176 
177    return shader_obj ? container_of(shader_obj, struct radv_shader, base) : NULL;
178 }
179 
180 const struct vk_pipeline_cache_object_ops radv_shader_ops = {
181    .serialize = radv_shader_cache_serialize,
182    .deserialize = radv_shader_cache_deserialize,
183    .destroy = radv_shader_destroy,
184 };
185 
186 struct radv_pipeline_cache_object {
187    struct vk_pipeline_cache_object base;
188    unsigned num_shaders;
189    uint32_t data_size;
190    void *data; /* Generic data stored alongside the shaders */
191    uint8_t sha1[SHA1_DIGEST_LENGTH];
192    struct radv_shader *shaders[];
193 };
194 
195 const struct vk_pipeline_cache_object_ops radv_pipeline_ops;
196 
197 static struct radv_pipeline_cache_object *
radv_pipeline_cache_object_create(struct vk_device * device,unsigned num_shaders,const void * hash,unsigned data_size)198 radv_pipeline_cache_object_create(struct vk_device *device, unsigned num_shaders, const void *hash, unsigned data_size)
199 {
200    const size_t size =
201       sizeof(struct radv_pipeline_cache_object) + (num_shaders * sizeof(struct radv_shader *)) + data_size;
202 
203    struct radv_pipeline_cache_object *object = vk_alloc(&device->alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
204    if (!object)
205       return NULL;
206 
207    vk_pipeline_cache_object_init(device, &object->base, &radv_pipeline_ops, object->sha1, SHA1_DIGEST_LENGTH);
208    object->num_shaders = num_shaders;
209    object->data = &object->shaders[num_shaders];
210    object->data_size = data_size;
211    memcpy(object->sha1, hash, SHA1_DIGEST_LENGTH);
212    memset(object->shaders, 0, sizeof(object->shaders[0]) * num_shaders);
213    memset(object->data, 0, data_size);
214 
215    return object;
216 }
217 
218 static void
radv_pipeline_cache_object_destroy(struct vk_device * _device,struct vk_pipeline_cache_object * object)219 radv_pipeline_cache_object_destroy(struct vk_device *_device, struct vk_pipeline_cache_object *object)
220 {
221    struct radv_device *device = container_of(_device, struct radv_device, vk);
222    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
223 
224    for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
225       if (pipeline_obj->shaders[i])
226          radv_shader_unref(device, pipeline_obj->shaders[i]);
227    }
228 
229    vk_pipeline_cache_object_finish(&pipeline_obj->base);
230    vk_free(&_device->alloc, pipeline_obj);
231 }
232 
233 static struct vk_pipeline_cache_object *
radv_pipeline_cache_object_deserialize(struct vk_pipeline_cache * cache,const void * key_data,size_t key_size,struct blob_reader * blob)234 radv_pipeline_cache_object_deserialize(struct vk_pipeline_cache *cache, const void *key_data, size_t key_size,
235                                        struct blob_reader *blob)
236 {
237    struct radv_device *device = container_of(cache->base.device, struct radv_device, vk);
238    assert(key_size == SHA1_DIGEST_LENGTH);
239    unsigned total_size = blob->end - blob->current;
240    unsigned num_shaders = blob_read_uint32(blob);
241    unsigned data_size = blob_read_uint32(blob);
242 
243    struct radv_pipeline_cache_object *object;
244    object = radv_pipeline_cache_object_create(&device->vk, num_shaders, key_data, data_size);
245    if (!object)
246       return NULL;
247 
248    object->base.data_size = total_size;
249 
250    for (unsigned i = 0; i < num_shaders; i++) {
251       const uint8_t *hash = blob_read_bytes(blob, sizeof(blake3_hash));
252       struct vk_pipeline_cache_object *shader =
253          vk_pipeline_cache_lookup_object(cache, hash, sizeof(blake3_hash), &radv_shader_ops, NULL);
254 
255       if (!shader) {
256          /* If some shader could not be created from cache, better return NULL here than having
257           * an incomplete cache object which needs to be fixed up later.
258           */
259          vk_pipeline_cache_object_unref(&device->vk, &object->base);
260          return NULL;
261       }
262 
263       object->shaders[i] = container_of(shader, struct radv_shader, base);
264    }
265 
266    blob_copy_bytes(blob, object->data, data_size);
267 
268    return &object->base;
269 }
270 
271 static bool
radv_pipeline_cache_object_serialize(struct vk_pipeline_cache_object * object,struct blob * blob)272 radv_pipeline_cache_object_serialize(struct vk_pipeline_cache_object *object, struct blob *blob)
273 {
274    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
275 
276    blob_write_uint32(blob, pipeline_obj->num_shaders);
277    blob_write_uint32(blob, pipeline_obj->data_size);
278 
279    for (unsigned i = 0; i < pipeline_obj->num_shaders; i++)
280       blob_write_bytes(blob, pipeline_obj->shaders[i]->hash, sizeof(pipeline_obj->shaders[i]->hash));
281 
282    blob_write_bytes(blob, pipeline_obj->data, pipeline_obj->data_size);
283 
284    return true;
285 }
286 
287 const struct vk_pipeline_cache_object_ops radv_pipeline_ops = {
288    .serialize = radv_pipeline_cache_object_serialize,
289    .deserialize = radv_pipeline_cache_object_deserialize,
290    .destroy = radv_pipeline_cache_object_destroy,
291 };
292 
293 static void
radv_report_pso_cache_stats(struct radv_device * device,const struct radv_pipeline * pipeline,bool cache_hit)294 radv_report_pso_cache_stats(struct radv_device *device, const struct radv_pipeline *pipeline, bool cache_hit)
295 {
296    const struct radv_physical_device *pdev = radv_device_physical(device);
297    const struct radv_instance *instance = radv_physical_device_instance(pdev);
298 
299    if (!(instance->debug_flags & RADV_DEBUG_PSO_CACHE_STATS))
300       return;
301 
302    /* Only gather PSO cache stats for application pipelines. */
303    if (pipeline->is_internal)
304       return;
305 
306    assert(pipeline->type < ARRAY_SIZE(device->pso_cache_stats));
307 
308    simple_mtx_lock(&device->pso_cache_stats_mtx);
309 
310    if (cache_hit) {
311       device->pso_cache_stats[pipeline->type].hits++;
312    } else {
313       device->pso_cache_stats[pipeline->type].misses++;
314    }
315 
316    fprintf(
317       stderr,
318       "radv: PSO cache stats: gfx (hits=%d, misses=%d), gfx_lib (hits=%d, misses=%d), compute (hits=%d, misses=%d), rt "
319       "(hits=%d, misses=%d)\nt",
320       device->pso_cache_stats[RADV_PIPELINE_GRAPHICS].hits, device->pso_cache_stats[RADV_PIPELINE_GRAPHICS].misses,
321       device->pso_cache_stats[RADV_PIPELINE_GRAPHICS_LIB].hits,
322       device->pso_cache_stats[RADV_PIPELINE_GRAPHICS_LIB].misses, device->pso_cache_stats[RADV_PIPELINE_COMPUTE].hits,
323       device->pso_cache_stats[RADV_PIPELINE_COMPUTE].misses, device->pso_cache_stats[RADV_PIPELINE_RAY_TRACING].hits,
324       device->pso_cache_stats[RADV_PIPELINE_RAY_TRACING].misses);
325 
326    simple_mtx_unlock(&device->pso_cache_stats_mtx);
327 }
328 
329 static struct radv_pipeline_cache_object *
radv_pipeline_cache_object_search(struct radv_device * device,struct vk_pipeline_cache * cache,const struct radv_pipeline * pipeline,bool * found_in_application_cache)330 radv_pipeline_cache_object_search(struct radv_device *device, struct vk_pipeline_cache *cache,
331                                   const struct radv_pipeline *pipeline, bool *found_in_application_cache)
332 {
333    *found_in_application_cache = false;
334 
335    if (radv_is_cache_disabled(device, cache))
336       return false;
337 
338    bool *found = found_in_application_cache;
339    if (!cache) {
340       cache = device->mem_cache;
341       found = NULL;
342    }
343 
344    struct vk_pipeline_cache_object *object =
345       vk_pipeline_cache_lookup_object(cache, pipeline->sha1, SHA1_DIGEST_LENGTH, &radv_pipeline_ops, found);
346 
347    radv_report_pso_cache_stats(device, pipeline, !!object);
348 
349    if (!object)
350       return false;
351 
352    return container_of(object, struct radv_pipeline_cache_object, base);
353 }
354 
355 bool
radv_graphics_pipeline_cache_search(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_graphics_pipeline * pipeline,bool * found_in_application_cache)356 radv_graphics_pipeline_cache_search(struct radv_device *device, struct vk_pipeline_cache *cache,
357                                     struct radv_graphics_pipeline *pipeline, bool *found_in_application_cache)
358 {
359    struct radv_pipeline_cache_object *pipeline_obj;
360 
361    pipeline_obj = radv_pipeline_cache_object_search(device, cache, &pipeline->base, found_in_application_cache);
362    if (!pipeline_obj)
363       return false;
364 
365    for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
366       gl_shader_stage s = pipeline_obj->shaders[i]->info.stage;
367       if (s == MESA_SHADER_VERTEX && i > 0) {
368          /* The GS copy-shader is a VS placed after all other stages */
369          assert(i == pipeline_obj->num_shaders - 1 && pipeline->base.shaders[MESA_SHADER_GEOMETRY]);
370          pipeline->base.gs_copy_shader = radv_shader_ref(pipeline_obj->shaders[i]);
371       } else {
372          pipeline->base.shaders[s] = radv_shader_ref(pipeline_obj->shaders[i]);
373       }
374    }
375 
376    pipeline->base.cache_object = &pipeline_obj->base;
377    return true;
378 }
379 
380 bool
radv_compute_pipeline_cache_search(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_compute_pipeline * pipeline,bool * found_in_application_cache)381 radv_compute_pipeline_cache_search(struct radv_device *device, struct vk_pipeline_cache *cache,
382                                    struct radv_compute_pipeline *pipeline, bool *found_in_application_cache)
383 {
384    struct radv_pipeline_cache_object *pipeline_obj;
385 
386    pipeline_obj = radv_pipeline_cache_object_search(device, cache, &pipeline->base, found_in_application_cache);
387    if (!pipeline_obj)
388       return false;
389 
390    assert(pipeline_obj->num_shaders == 1);
391    pipeline->base.shaders[MESA_SHADER_COMPUTE] = radv_shader_ref(pipeline_obj->shaders[0]);
392 
393    pipeline->base.cache_object = &pipeline_obj->base;
394    return true;
395 }
396 
397 void
radv_pipeline_cache_insert(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_pipeline * pipeline)398 radv_pipeline_cache_insert(struct radv_device *device, struct vk_pipeline_cache *cache, struct radv_pipeline *pipeline)
399 {
400    if (radv_is_cache_disabled(device, cache))
401       return;
402 
403    if (!cache)
404       cache = device->mem_cache;
405 
406    /* Count shaders */
407    unsigned num_shaders = 0;
408    for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; ++i)
409       num_shaders += pipeline->shaders[i] ? 1 : 0;
410    num_shaders += pipeline->gs_copy_shader ? 1 : 0;
411 
412    struct radv_pipeline_cache_object *pipeline_obj;
413    pipeline_obj = radv_pipeline_cache_object_create(&device->vk, num_shaders, pipeline->sha1, 0);
414 
415    if (!pipeline_obj)
416       return;
417 
418    unsigned idx = 0;
419    for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; ++i) {
420       if (pipeline->shaders[i])
421          pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->shaders[i]);
422    }
423    /* Place the GS copy-shader after all other stages */
424    if (pipeline->gs_copy_shader)
425       pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->gs_copy_shader);
426 
427    assert(idx == num_shaders);
428 
429    /* Add the object to the cache */
430    pipeline->cache_object = vk_pipeline_cache_add_object(cache, &pipeline_obj->base);
431 }
432 
433 struct radv_ray_tracing_stage_cache_data {
434    uint32_t stack_size : 31;
435    uint32_t has_shader : 1;
436    uint8_t sha1[SHA1_DIGEST_LENGTH];
437    struct radv_ray_tracing_stage_info info;
438 };
439 
440 struct radv_ray_tracing_pipeline_cache_data {
441    uint32_t has_traversal_shader : 1;
442    uint32_t is_library : 1;
443    uint32_t num_stages;
444    struct radv_ray_tracing_stage_cache_data stages[];
445 };
446 
447 bool
radv_ray_tracing_pipeline_cache_search(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_ray_tracing_pipeline * pipeline,bool * found_in_application_cache)448 radv_ray_tracing_pipeline_cache_search(struct radv_device *device, struct vk_pipeline_cache *cache,
449                                        struct radv_ray_tracing_pipeline *pipeline,
450                                        bool *found_in_application_cache)
451 {
452    struct radv_pipeline_cache_object *pipeline_obj;
453 
454    pipeline_obj = radv_pipeline_cache_object_search(device, cache, &pipeline->base.base, found_in_application_cache);
455    if (!pipeline_obj)
456       return false;
457 
458    struct radv_ray_tracing_pipeline_cache_data *data = pipeline_obj->data;
459 
460    bool complete = true;
461    unsigned idx = 0;
462 
463    if (data->has_traversal_shader)
464       pipeline->base.base.shaders[MESA_SHADER_INTERSECTION] = radv_shader_ref(pipeline_obj->shaders[idx++]);
465 
466    const uint32_t num_stages = data->num_stages;
467    for (unsigned i = 0; i < num_stages; i++) {
468       pipeline->stages[i].stack_size = data->stages[i].stack_size;
469       pipeline->stages[i].info = data->stages[i].info;
470       memcpy(pipeline->stages[i].sha1, data->stages[i].sha1, sizeof(pipeline->stages[i].sha1));
471 
472       if (data->stages[i].has_shader)
473          pipeline->stages[i].shader = radv_shader_ref(pipeline_obj->shaders[idx++]);
474 
475       if (data->is_library) {
476          pipeline->stages[i].nir = radv_pipeline_cache_lookup_nir_handle(device, cache, pipeline->stages[i].sha1);
477          complete &= pipeline->stages[i].nir != NULL;
478       }
479    }
480 
481    assert(idx == pipeline_obj->num_shaders);
482 
483    pipeline->base.base.cache_object = &pipeline_obj->base;
484    return complete;
485 }
486 
487 void
radv_ray_tracing_pipeline_cache_insert(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_ray_tracing_pipeline * pipeline,unsigned num_stages)488 radv_ray_tracing_pipeline_cache_insert(struct radv_device *device, struct vk_pipeline_cache *cache,
489                                        struct radv_ray_tracing_pipeline *pipeline, unsigned num_stages)
490 {
491    if (radv_is_cache_disabled(device, cache))
492       return;
493 
494    if (!cache)
495       cache = device->mem_cache;
496 
497    /* Skip insertion on cache hit.
498     * This branch can be triggered if a cache_object was found but not all NIR shaders could be
499     * looked up. The cache_object is already complete in that case.
500     */
501    if (pipeline->base.base.cache_object)
502       return;
503 
504    /* Count compiled shaders excl. library shaders */
505    unsigned num_shaders = pipeline->base.base.shaders[MESA_SHADER_INTERSECTION] ? 1 : 0;
506    for (unsigned i = 0; i < num_stages; ++i)
507       num_shaders += pipeline->stages[i].shader ? 1 : 0;
508 
509    uint32_t data_size = sizeof(struct radv_ray_tracing_pipeline_cache_data) +
510                         num_stages * sizeof(struct radv_ray_tracing_stage_cache_data);
511 
512    struct radv_pipeline_cache_object *pipeline_obj =
513       radv_pipeline_cache_object_create(&device->vk, num_shaders, pipeline->base.base.sha1, data_size);
514    struct radv_ray_tracing_pipeline_cache_data *data = pipeline_obj->data;
515 
516    data->is_library = !!(pipeline->base.base.create_flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR);
517    data->has_traversal_shader = !!pipeline->base.base.shaders[MESA_SHADER_INTERSECTION];
518 
519    unsigned idx = 0;
520    if (data->has_traversal_shader)
521       pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->base.base.shaders[MESA_SHADER_INTERSECTION]);
522 
523    data->num_stages = num_stages;
524 
525    for (unsigned i = 0; i < num_stages; ++i) {
526       data->stages[i].stack_size = pipeline->stages[i].stack_size;
527       data->stages[i].info = pipeline->stages[i].info;
528       data->stages[i].has_shader = !!pipeline->stages[i].shader;
529       memcpy(data->stages[i].sha1, pipeline->stages[i].sha1, sizeof(pipeline->stages[i].sha1));
530 
531       if (pipeline->stages[i].shader)
532          pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->stages[i].shader);
533    }
534    assert(idx == num_shaders);
535 
536    /* Add the object to the cache */
537    pipeline->base.base.cache_object = vk_pipeline_cache_add_object(cache, &pipeline_obj->base);
538 }
539 
540 nir_shader *
radv_pipeline_cache_lookup_nir(struct radv_device * device,struct vk_pipeline_cache * cache,gl_shader_stage stage,const blake3_hash key)541 radv_pipeline_cache_lookup_nir(struct radv_device *device, struct vk_pipeline_cache *cache, gl_shader_stage stage,
542                                const blake3_hash key)
543 {
544    const struct radv_physical_device *pdev = radv_device_physical(device);
545 
546    if (radv_is_cache_disabled(device, cache))
547       return NULL;
548 
549    if (!cache)
550       cache = device->mem_cache;
551 
552    return vk_pipeline_cache_lookup_nir(cache, key, sizeof(blake3_hash), &pdev->nir_options[stage], NULL, NULL);
553 }
554 
555 void
radv_pipeline_cache_insert_nir(struct radv_device * device,struct vk_pipeline_cache * cache,const blake3_hash key,const nir_shader * nir)556 radv_pipeline_cache_insert_nir(struct radv_device *device, struct vk_pipeline_cache *cache, const blake3_hash key,
557                                const nir_shader *nir)
558 {
559    if (radv_is_cache_disabled(device, cache))
560       return;
561 
562    if (!cache)
563       cache = device->mem_cache;
564 
565    vk_pipeline_cache_add_nir(cache, key, sizeof(blake3_hash), nir);
566 }
567 
568 struct vk_pipeline_cache_object *
radv_pipeline_cache_lookup_nir_handle(struct radv_device * device,struct vk_pipeline_cache * cache,const uint8_t * sha1)569 radv_pipeline_cache_lookup_nir_handle(struct radv_device *device, struct vk_pipeline_cache *cache, const uint8_t *sha1)
570 {
571    if (radv_is_cache_disabled(device, cache))
572       return NULL;
573 
574    if (!cache)
575       cache = device->mem_cache;
576 
577    return vk_pipeline_cache_lookup_object(cache, sha1, SHA1_DIGEST_LENGTH, &vk_raw_data_cache_object_ops, NULL);
578 }
579 
580 struct nir_shader *
radv_pipeline_cache_handle_to_nir(struct radv_device * device,struct vk_pipeline_cache_object * object)581 radv_pipeline_cache_handle_to_nir(struct radv_device *device, struct vk_pipeline_cache_object *object)
582 {
583    const struct radv_physical_device *pdev = radv_device_physical(device);
584    struct blob_reader blob;
585    struct vk_raw_data_cache_object *nir_object = container_of(object, struct vk_raw_data_cache_object, base);
586    blob_reader_init(&blob, nir_object->data, nir_object->data_size);
587    nir_shader *nir = nir_deserialize(NULL, NULL, &blob);
588 
589    if (blob.overrun) {
590       ralloc_free(nir);
591       return NULL;
592    }
593    nir->options = &pdev->nir_options[nir->info.stage];
594 
595    return nir;
596 }
597 
598 struct vk_pipeline_cache_object *
radv_pipeline_cache_nir_to_handle(struct radv_device * device,struct vk_pipeline_cache * cache,struct nir_shader * nir,const uint8_t * sha1,bool cached)599 radv_pipeline_cache_nir_to_handle(struct radv_device *device, struct vk_pipeline_cache *cache, struct nir_shader *nir,
600                                   const uint8_t *sha1, bool cached)
601 {
602    if (!cache)
603       cache = device->mem_cache;
604 
605    struct blob blob;
606    blob_init(&blob);
607    nir_serialize(&blob, nir, true);
608 
609    if (blob.out_of_memory) {
610       blob_finish(&blob);
611       return NULL;
612    }
613 
614    void *data;
615    size_t size;
616    blob_finish_get_buffer(&blob, &data, &size);
617    struct vk_pipeline_cache_object *object;
618 
619    if (cached && !radv_is_cache_disabled(device, cache)) {
620       object = vk_pipeline_cache_create_and_insert_object(cache, sha1, SHA1_DIGEST_LENGTH, data, size,
621                                                           &vk_raw_data_cache_object_ops);
622    } else {
623       struct vk_raw_data_cache_object *nir_object =
624          vk_raw_data_cache_object_create(&device->vk, sha1, SHA1_DIGEST_LENGTH, data, size);
625       object = nir_object ? &nir_object->base : NULL;
626    }
627 
628    free(data);
629    return object;
630 }
631 
632 VkResult
radv_pipeline_cache_get_binaries(struct radv_device * device,const VkAllocationCallbacks * pAllocator,const unsigned char * sha1,struct util_dynarray * pipeline_binaries,uint32_t * num_binaries,bool * found_in_internal_cache)633 radv_pipeline_cache_get_binaries(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
634                                  const unsigned char *sha1, struct util_dynarray *pipeline_binaries,
635                                  uint32_t *num_binaries, bool *found_in_internal_cache)
636 {
637    struct vk_pipeline_cache *cache = device->mem_cache;
638    VkResult result;
639 
640    *found_in_internal_cache = false;
641 
642    if (radv_is_cache_disabled(device, cache))
643       return VK_SUCCESS;
644 
645    struct vk_pipeline_cache_object *object =
646       vk_pipeline_cache_lookup_object(cache, sha1, SHA1_DIGEST_LENGTH, &radv_pipeline_ops, NULL);
647    if (!object)
648       return VK_SUCCESS;
649 
650    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
651 
652    bool complete = true;
653    bool is_rt = false;
654    for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
655       if (gl_shader_stage_is_rt(pipeline_obj->shaders[i]->info.stage)) {
656          is_rt = true;
657          break;
658       }
659    }
660 
661    if (is_rt) {
662       struct radv_ray_tracing_pipeline_cache_data *data = pipeline_obj->data;
663       struct radv_shader *traversal_shader = NULL;
664       unsigned idx = 0;
665 
666       if (data->has_traversal_shader)
667          traversal_shader = pipeline_obj->shaders[idx++];
668 
669       for (unsigned i = 0; i < data->num_stages; i++) {
670          const struct radv_ray_tracing_stage_cache_data *stage_data = &data->stages[i];
671          struct vk_pipeline_cache_object *nir = NULL;
672          struct radv_shader *shader = NULL;
673 
674          if (stage_data->has_shader)
675             shader = pipeline_obj->shaders[idx++];
676 
677          if (data->is_library)
678             nir = radv_pipeline_cache_lookup_nir_handle(device, cache, data->stages[i].sha1);
679 
680          result = radv_create_pipeline_binary_from_rt_shader(device, pAllocator, shader, false, data->stages[i].sha1,
681                                                              &stage_data->info, stage_data->stack_size, nir,
682                                                              pipeline_binaries, num_binaries);
683 
684          if (data->is_library)
685             complete &= nir != NULL;
686 
687          if (nir)
688             vk_pipeline_cache_object_unref(&device->vk, nir);
689 
690          if (result != VK_SUCCESS)
691             goto fail;
692       }
693 
694       if (traversal_shader) {
695          result = radv_create_pipeline_binary_from_rt_shader(device, pAllocator, traversal_shader, true,
696                                                              traversal_shader->hash, NULL, 0, NULL, pipeline_binaries,
697                                                              num_binaries);
698          if (result != VK_SUCCESS)
699             goto fail;
700       }
701    } else {
702       struct radv_shader *gs_copy_shader = NULL;
703 
704       for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
705          struct radv_shader *shader = pipeline_obj->shaders[i];
706          gl_shader_stage s = shader->info.stage;
707 
708          if (s == MESA_SHADER_VERTEX && i > 0) {
709             /* The GS copy-shader is a VS placed after all other stages */
710             gs_copy_shader = shader;
711          } else {
712             result =
713                radv_create_pipeline_binary_from_shader(device, pAllocator, shader, pipeline_binaries, num_binaries);
714             if (result != VK_SUCCESS)
715                goto fail;
716          }
717       }
718 
719       if (gs_copy_shader) {
720          result = radv_create_pipeline_binary_from_shader(device, pAllocator, gs_copy_shader, pipeline_binaries,
721                                                           num_binaries);
722          if (result != VK_SUCCESS)
723             goto fail;
724       }
725    }
726 
727    *found_in_internal_cache = complete;
728 
729 fail:
730    vk_pipeline_cache_object_unref(&device->vk, &pipeline_obj->base);
731    return result;
732 }
733