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