• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2015 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 (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
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "util/disk_cache.h"
25 #include "util/macros.h"
26 #include "util/mesa-blake3.h"
27 #include "util/mesa-sha1.h"
28 #include "util/u_atomic.h"
29 #include "util/u_debug.h"
30 #include "vulkan/util/vk_util.h"
31 #include "aco_interface.h"
32 #include "nir_serialize.h"
33 #include "radv_debug.h"
34 #include "radv_private.h"
35 #include "radv_shader.h"
36 #include "vk_pipeline.h"
37 
38 static bool
radv_is_cache_disabled(struct radv_device * device)39 radv_is_cache_disabled(struct radv_device *device)
40 {
41    /* The buffer address used for debug printf is hardcoded. */
42    if (device->printf.buffer_addr)
43       return true;
44 
45    /* Pipeline caches can be disabled with RADV_DEBUG=nocache, with MESA_GLSL_CACHE_DISABLE=1 and
46     * when ACO_DEBUG is used. MESA_GLSL_CACHE_DISABLE is done elsewhere.
47     */
48    return (device->instance->debug_flags & RADV_DEBUG_NO_CACHE) ||
49           (device->physical_device->use_llvm ? 0 : aco_get_codegen_flags());
50 }
51 
52 void
radv_hash_shaders(const struct radv_device * device,unsigned char * hash,const struct radv_shader_stage * stages,uint32_t stage_count,const struct radv_pipeline_layout * layout,const struct radv_graphics_state_key * gfx_state)53 radv_hash_shaders(const struct radv_device *device, unsigned char *hash, const struct radv_shader_stage *stages,
54                   uint32_t stage_count, const struct radv_pipeline_layout *layout,
55                   const struct radv_graphics_state_key *gfx_state)
56 {
57    struct mesa_sha1 ctx;
58 
59    _mesa_sha1_init(&ctx);
60    _mesa_sha1_update(&ctx, device->cache_hash, sizeof(device->cache_hash));
61    if (gfx_state)
62       _mesa_sha1_update(&ctx, gfx_state, sizeof(*gfx_state));
63    if (layout)
64       _mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
65 
66    for (unsigned s = 0; s < stage_count; s++) {
67       if (!stages[s].entrypoint)
68          continue;
69 
70       _mesa_sha1_update(&ctx, stages[s].shader_sha1, sizeof(stages[s].shader_sha1));
71       _mesa_sha1_update(&ctx, &stages[s].key, sizeof(stages[s].key));
72    }
73    _mesa_sha1_final(&ctx, hash);
74 }
75 
76 void
radv_hash_graphics_spirv_to_nir(blake3_hash hash,const struct radv_shader_stage * stage,const struct radv_spirv_to_nir_options * options)77 radv_hash_graphics_spirv_to_nir(blake3_hash hash, const struct radv_shader_stage *stage,
78                                 const struct radv_spirv_to_nir_options *options)
79 {
80    struct mesa_blake3 ctx;
81    _mesa_blake3_init(&ctx);
82    _mesa_blake3_update(&ctx, &stage->key, sizeof(stage->key));
83    _mesa_blake3_update(&ctx, options, sizeof(*options));
84    _mesa_blake3_update(&ctx, stage->shader_sha1, sizeof(stage->shader_sha1));
85    _mesa_blake3_final(&ctx, hash);
86 }
87 
88 void
radv_hash_rt_shaders(const struct radv_device * device,unsigned char * hash,const struct radv_ray_tracing_stage * stages,const VkRayTracingPipelineCreateInfoKHR * pCreateInfo,const struct radv_ray_tracing_group * groups)89 radv_hash_rt_shaders(const struct radv_device *device, unsigned char *hash, const struct radv_ray_tracing_stage *stages,
90                      const VkRayTracingPipelineCreateInfoKHR *pCreateInfo, const struct radv_ray_tracing_group *groups)
91 {
92    RADV_FROM_HANDLE(radv_pipeline_layout, layout, pCreateInfo->layout);
93    struct mesa_sha1 ctx;
94 
95    _mesa_sha1_init(&ctx);
96    _mesa_sha1_update(&ctx, device->cache_hash, sizeof(device->cache_hash));
97    if (layout)
98       _mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
99 
100    for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
101       _mesa_sha1_update(&ctx, stages[i].sha1, sizeof(stages[i].sha1));
102    }
103 
104    for (uint32_t i = 0; i < pCreateInfo->groupCount; i++) {
105       _mesa_sha1_update(&ctx, &pCreateInfo->pGroups[i].type, sizeof(pCreateInfo->pGroups[i].type));
106       _mesa_sha1_update(&ctx, &pCreateInfo->pGroups[i].generalShader, sizeof(pCreateInfo->pGroups[i].generalShader));
107       _mesa_sha1_update(&ctx, &pCreateInfo->pGroups[i].anyHitShader, sizeof(pCreateInfo->pGroups[i].anyHitShader));
108       _mesa_sha1_update(&ctx, &pCreateInfo->pGroups[i].closestHitShader,
109                         sizeof(pCreateInfo->pGroups[i].closestHitShader));
110       _mesa_sha1_update(&ctx, &pCreateInfo->pGroups[i].intersectionShader,
111                         sizeof(pCreateInfo->pGroups[i].intersectionShader));
112       _mesa_sha1_update(&ctx, &groups[i].handle, sizeof(struct radv_pipeline_group_handle));
113    }
114 
115    if (pCreateInfo->pLibraryInfo) {
116       for (uint32_t i = 0; i < pCreateInfo->pLibraryInfo->libraryCount; ++i) {
117          RADV_FROM_HANDLE(radv_pipeline, lib_pipeline, pCreateInfo->pLibraryInfo->pLibraries[i]);
118          struct radv_ray_tracing_pipeline *lib = radv_pipeline_to_ray_tracing(lib_pipeline);
119          _mesa_sha1_update(&ctx, lib->sha1, SHA1_DIGEST_LENGTH);
120       }
121    }
122 
123    const uint64_t pipeline_flags =
124       vk_rt_pipeline_create_flags(pCreateInfo) &
125       (VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR | VK_PIPELINE_CREATE_2_RAY_TRACING_SKIP_AABBS_BIT_KHR |
126        VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR |
127        VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR |
128        VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR |
129        VK_PIPELINE_CREATE_2_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR | VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR);
130    _mesa_sha1_update(&ctx, &pipeline_flags, sizeof(pipeline_flags));
131 
132    _mesa_sha1_final(&ctx, hash);
133 }
134 
135 static void
radv_shader_destroy(struct vk_device * _device,struct vk_pipeline_cache_object * object)136 radv_shader_destroy(struct vk_device *_device, struct vk_pipeline_cache_object *object)
137 {
138    struct radv_device *device = container_of(_device, struct radv_device, vk);
139    struct radv_shader *shader = container_of(object, struct radv_shader, base);
140 
141    if (device->shader_use_invisible_vram) {
142       /* Wait for any pending upload to complete, or we'll be writing into freed shader memory. */
143       radv_shader_wait_for_upload(device, shader->upload_seq);
144    }
145 
146    radv_free_shader_memory(device, shader->alloc);
147 
148    free(shader->code);
149    free(shader->spirv);
150    free(shader->nir_string);
151    free(shader->disasm_string);
152    free(shader->ir_string);
153    free(shader->statistics);
154 
155    vk_pipeline_cache_object_finish(&shader->base);
156    free(shader);
157 }
158 
159 static struct vk_pipeline_cache_object *
radv_shader_deserialize(struct vk_pipeline_cache * cache,const void * key_data,size_t key_size,struct blob_reader * blob)160 radv_shader_deserialize(struct vk_pipeline_cache *cache, const void *key_data, size_t key_size,
161                         struct blob_reader *blob)
162 {
163    struct radv_device *device = container_of(cache->base.device, struct radv_device, vk);
164    const struct radv_shader_binary *binary = blob_read_bytes(blob, sizeof(struct radv_shader_binary));
165 
166    struct radv_shader *shader;
167    radv_shader_create_uncached(device, binary, false, NULL, &shader);
168    if (!shader)
169       return NULL;
170 
171    assert(key_size == sizeof(shader->hash));
172    memcpy(shader->hash, key_data, key_size);
173    blob_skip_bytes(blob, binary->total_size - sizeof(struct radv_shader_binary));
174 
175    return &shader->base;
176 }
177 
178 static bool
radv_shader_serialize(struct vk_pipeline_cache_object * object,struct blob * blob)179 radv_shader_serialize(struct vk_pipeline_cache_object *object, struct blob *blob)
180 {
181    struct radv_shader *shader = container_of(object, struct radv_shader, base);
182    size_t stats_size = shader->statistics ? aco_num_statistics * sizeof(uint32_t) : 0;
183    size_t code_size = shader->code_size;
184    uint32_t total_size = sizeof(struct radv_shader_binary_legacy) + code_size + stats_size;
185 
186    struct radv_shader_binary_legacy binary = {
187       .base =
188          {
189             .type = RADV_BINARY_TYPE_LEGACY,
190             .config = shader->config,
191             .info = shader->info,
192             .total_size = total_size,
193          },
194       .code_size = code_size,
195       .exec_size = shader->exec_size,
196       .ir_size = 0,
197       .disasm_size = 0,
198       .stats_size = stats_size,
199    };
200 
201    blob_write_bytes(blob, &binary, sizeof(struct radv_shader_binary_legacy));
202    blob_write_bytes(blob, shader->statistics, stats_size);
203    blob_write_bytes(blob, shader->code, code_size);
204 
205    return true;
206 }
207 
208 struct radv_shader *
radv_shader_create(struct radv_device * device,struct vk_pipeline_cache * cache,const struct radv_shader_binary * binary,bool skip_cache)209 radv_shader_create(struct radv_device *device, struct vk_pipeline_cache *cache, const struct radv_shader_binary *binary,
210                    bool skip_cache)
211 {
212    if (radv_is_cache_disabled(device) || skip_cache) {
213       struct radv_shader *shader;
214       radv_shader_create_uncached(device, binary, false, NULL, &shader);
215       return shader;
216    }
217 
218    if (!cache)
219       cache = device->mem_cache;
220 
221    blake3_hash hash;
222    _mesa_blake3_compute(binary, binary->total_size, hash);
223 
224    struct vk_pipeline_cache_object *shader_obj;
225    shader_obj = vk_pipeline_cache_create_and_insert_object(cache, hash, sizeof(hash), binary, binary->total_size,
226                                                            &radv_shader_ops);
227 
228    return shader_obj ? container_of(shader_obj, struct radv_shader, base) : NULL;
229 }
230 
231 const struct vk_pipeline_cache_object_ops radv_shader_ops = {
232    .serialize = radv_shader_serialize,
233    .deserialize = radv_shader_deserialize,
234    .destroy = radv_shader_destroy,
235 };
236 
237 struct radv_pipeline_cache_object {
238    struct vk_pipeline_cache_object base;
239    unsigned num_shaders;
240    uint32_t data_size;
241    void *data; /* Generic data stored alongside the shaders */
242    uint8_t sha1[SHA1_DIGEST_LENGTH];
243    struct radv_shader *shaders[];
244 };
245 
246 const struct vk_pipeline_cache_object_ops radv_pipeline_ops;
247 
248 static struct radv_pipeline_cache_object *
radv_pipeline_cache_object_create(struct vk_device * device,unsigned num_shaders,const void * hash,unsigned data_size)249 radv_pipeline_cache_object_create(struct vk_device *device, unsigned num_shaders, const void *hash, unsigned data_size)
250 {
251    const size_t size =
252       sizeof(struct radv_pipeline_cache_object) + (num_shaders * sizeof(struct radv_shader *)) + data_size;
253 
254    struct radv_pipeline_cache_object *object = vk_alloc(&device->alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
255    if (!object)
256       return NULL;
257 
258    vk_pipeline_cache_object_init(device, &object->base, &radv_pipeline_ops, object->sha1, SHA1_DIGEST_LENGTH);
259    object->num_shaders = num_shaders;
260    object->data = &object->shaders[num_shaders];
261    object->data_size = data_size;
262    memcpy(object->sha1, hash, SHA1_DIGEST_LENGTH);
263    memset(object->shaders, 0, sizeof(object->shaders[0]) * num_shaders);
264 
265    return object;
266 }
267 
268 static void
radv_pipeline_cache_object_destroy(struct vk_device * _device,struct vk_pipeline_cache_object * object)269 radv_pipeline_cache_object_destroy(struct vk_device *_device, struct vk_pipeline_cache_object *object)
270 {
271    struct radv_device *device = container_of(_device, struct radv_device, vk);
272    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
273 
274    for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
275       if (pipeline_obj->shaders[i])
276          radv_shader_unref(device, pipeline_obj->shaders[i]);
277    }
278 
279    vk_pipeline_cache_object_finish(&pipeline_obj->base);
280    vk_free(&_device->alloc, pipeline_obj);
281 }
282 
283 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)284 radv_pipeline_cache_object_deserialize(struct vk_pipeline_cache *cache, const void *key_data, size_t key_size,
285                                        struct blob_reader *blob)
286 {
287    struct radv_device *device = container_of(cache->base.device, struct radv_device, vk);
288    assert(key_size == SHA1_DIGEST_LENGTH);
289    unsigned total_size = blob->end - blob->current;
290    unsigned num_shaders = blob_read_uint32(blob);
291    unsigned data_size = blob_read_uint32(blob);
292 
293    struct radv_pipeline_cache_object *object;
294    object = radv_pipeline_cache_object_create(&device->vk, num_shaders, key_data, data_size);
295    if (!object)
296       return NULL;
297 
298    object->base.data_size = total_size;
299 
300    for (unsigned i = 0; i < num_shaders; i++) {
301       const uint8_t *hash = blob_read_bytes(blob, sizeof(blake3_hash));
302       struct vk_pipeline_cache_object *shader =
303          vk_pipeline_cache_lookup_object(cache, hash, sizeof(blake3_hash), &radv_shader_ops, NULL);
304 
305       if (!shader) {
306          /* If some shader could not be created from cache, better return NULL here than having
307           * an incomplete cache object which needs to be fixed up later.
308           */
309          vk_pipeline_cache_object_unref(&device->vk, &object->base);
310          return NULL;
311       }
312 
313       object->shaders[i] = container_of(shader, struct radv_shader, base);
314    }
315 
316    blob_copy_bytes(blob, object->data, data_size);
317 
318    return &object->base;
319 }
320 
321 static bool
radv_pipeline_cache_object_serialize(struct vk_pipeline_cache_object * object,struct blob * blob)322 radv_pipeline_cache_object_serialize(struct vk_pipeline_cache_object *object, struct blob *blob)
323 {
324    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
325 
326    blob_write_uint32(blob, pipeline_obj->num_shaders);
327    blob_write_uint32(blob, pipeline_obj->data_size);
328 
329    for (unsigned i = 0; i < pipeline_obj->num_shaders; i++)
330       blob_write_bytes(blob, pipeline_obj->shaders[i]->hash, sizeof(pipeline_obj->shaders[i]->hash));
331 
332    blob_write_bytes(blob, pipeline_obj->data, pipeline_obj->data_size);
333 
334    return true;
335 }
336 
337 const struct vk_pipeline_cache_object_ops radv_pipeline_ops = {
338    .serialize = radv_pipeline_cache_object_serialize,
339    .deserialize = radv_pipeline_cache_object_deserialize,
340    .destroy = radv_pipeline_cache_object_destroy,
341 };
342 
343 bool
radv_pipeline_cache_search(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_pipeline * pipeline,const unsigned char * sha1,bool * found_in_application_cache)344 radv_pipeline_cache_search(struct radv_device *device, struct vk_pipeline_cache *cache, struct radv_pipeline *pipeline,
345                            const unsigned char *sha1, bool *found_in_application_cache)
346 {
347    *found_in_application_cache = false;
348 
349    if (radv_is_cache_disabled(device))
350       return false;
351 
352    bool *found = found_in_application_cache;
353    if (!cache) {
354       cache = device->mem_cache;
355       found = NULL;
356    }
357 
358    struct vk_pipeline_cache_object *object =
359       vk_pipeline_cache_lookup_object(cache, sha1, SHA1_DIGEST_LENGTH, &radv_pipeline_ops, found);
360 
361    if (!object)
362       return false;
363 
364    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
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->shaders[MESA_SHADER_GEOMETRY]);
371          pipeline->gs_copy_shader = radv_shader_ref(pipeline_obj->shaders[i]);
372       } else {
373          pipeline->shaders[s] = radv_shader_ref(pipeline_obj->shaders[i]);
374       }
375    }
376 
377    pipeline->cache_object = object;
378    return true;
379 }
380 
381 void
radv_pipeline_cache_insert(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_pipeline * pipeline,const unsigned char * sha1)382 radv_pipeline_cache_insert(struct radv_device *device, struct vk_pipeline_cache *cache, struct radv_pipeline *pipeline,
383                            const unsigned char *sha1)
384 {
385    if (radv_is_cache_disabled(device))
386       return;
387 
388    if (!cache)
389       cache = device->mem_cache;
390 
391    /* Count shaders */
392    unsigned num_shaders = 0;
393    for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; ++i)
394       num_shaders += pipeline->shaders[i] ? 1 : 0;
395    num_shaders += pipeline->gs_copy_shader ? 1 : 0;
396 
397    struct radv_pipeline_cache_object *pipeline_obj;
398    pipeline_obj = radv_pipeline_cache_object_create(&device->vk, num_shaders, sha1, 0);
399 
400    if (!pipeline_obj)
401       return;
402 
403    unsigned idx = 0;
404    for (unsigned i = 0; i < MESA_VULKAN_SHADER_STAGES; ++i) {
405       if (pipeline->shaders[i])
406          pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->shaders[i]);
407    }
408    /* Place the GS copy-shader after all other stages */
409    if (pipeline->gs_copy_shader)
410       pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->gs_copy_shader);
411 
412    assert(idx == num_shaders);
413 
414    /* Add the object to the cache */
415    pipeline->cache_object = vk_pipeline_cache_add_object(cache, &pipeline_obj->base);
416 }
417 
418 struct radv_ray_tracing_stage_cache_data {
419    uint32_t stack_size : 31;
420    uint32_t has_shader : 1;
421 };
422 
423 struct radv_ray_tracing_pipeline_cache_data {
424    uint32_t has_traversal_shader : 1;
425    struct radv_ray_tracing_stage_cache_data stages[];
426 };
427 
428 bool
radv_ray_tracing_pipeline_cache_search(struct radv_device * device,struct vk_pipeline_cache * cache,struct radv_ray_tracing_pipeline * pipeline,const VkRayTracingPipelineCreateInfoKHR * pCreateInfo)429 radv_ray_tracing_pipeline_cache_search(struct radv_device *device, struct vk_pipeline_cache *cache,
430                                        struct radv_ray_tracing_pipeline *pipeline,
431                                        const VkRayTracingPipelineCreateInfoKHR *pCreateInfo)
432 {
433    if (radv_is_cache_disabled(device))
434       return false;
435 
436    if (!cache)
437       cache = device->mem_cache;
438 
439    bool cache_hit = false;
440    struct vk_pipeline_cache_object *object =
441       vk_pipeline_cache_lookup_object(cache, pipeline->sha1, SHA1_DIGEST_LENGTH, &radv_pipeline_ops, &cache_hit);
442 
443    if (!object)
444       return false;
445 
446    struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
447    struct radv_ray_tracing_pipeline_cache_data *data = pipeline_obj->data;
448 
449    bool is_library = pipeline->base.base.create_flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR;
450    bool complete = true;
451    unsigned idx = 0;
452 
453    if (data->has_traversal_shader)
454       pipeline->base.base.shaders[MESA_SHADER_INTERSECTION] = radv_shader_ref(pipeline_obj->shaders[idx++]);
455 
456    for (unsigned i = 0; i < pCreateInfo->stageCount; i++) {
457       pipeline->stages[i].stack_size = data->stages[i].stack_size;
458 
459       if (data->stages[i].has_shader)
460          pipeline->stages[i].shader = radv_shader_ref(pipeline_obj->shaders[idx++]);
461 
462       if (is_library) {
463          pipeline->stages[i].nir = radv_pipeline_cache_lookup_nir_handle(device, cache, pipeline->stages[i].sha1);
464          complete &= pipeline->stages[i].nir != NULL;
465       }
466    }
467 
468    assert(idx == pipeline_obj->num_shaders);
469 
470    if (cache_hit && cache != device->mem_cache) {
471       const VkPipelineCreationFeedbackCreateInfo *creation_feedback =
472          vk_find_struct_const(pCreateInfo->pNext, PIPELINE_CREATION_FEEDBACK_CREATE_INFO);
473       if (creation_feedback)
474          creation_feedback->pPipelineCreationFeedback->flags |=
475             VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT;
476    }
477 
478    pipeline->base.base.cache_object = object;
479    return complete;
480 }
481 
482 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,const unsigned char * sha1)483 radv_ray_tracing_pipeline_cache_insert(struct radv_device *device, struct vk_pipeline_cache *cache,
484                                        struct radv_ray_tracing_pipeline *pipeline, unsigned num_stages,
485                                        const unsigned char *sha1)
486 {
487    if (radv_is_cache_disabled(device))
488       return;
489 
490    if (!cache)
491       cache = device->mem_cache;
492 
493    /* Skip insertion on cache hit.
494     * This branch can be triggered if a cache_object was found but not all NIR shaders could be
495     * looked up. The cache_object is already complete in that case.
496     */
497    if (pipeline->base.base.cache_object)
498       return;
499 
500    /* Count compiled shaders excl. library shaders */
501    unsigned num_shaders = pipeline->base.base.shaders[MESA_SHADER_INTERSECTION] ? 1 : 0;
502    for (unsigned i = 0; i < num_stages; ++i)
503       num_shaders += pipeline->stages[i].shader ? 1 : 0;
504 
505    uint32_t data_size = sizeof(struct radv_ray_tracing_pipeline_cache_data) +
506                         num_stages * sizeof(struct radv_ray_tracing_stage_cache_data);
507 
508    struct radv_pipeline_cache_object *pipeline_obj =
509       radv_pipeline_cache_object_create(&device->vk, num_shaders, sha1, data_size);
510    struct radv_ray_tracing_pipeline_cache_data *data = pipeline_obj->data;
511 
512    data->has_traversal_shader = !!pipeline->base.base.shaders[MESA_SHADER_INTERSECTION];
513 
514    unsigned idx = 0;
515    if (data->has_traversal_shader)
516       pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->base.base.shaders[MESA_SHADER_INTERSECTION]);
517 
518    for (unsigned i = 0; i < num_stages; ++i) {
519       data->stages[i].stack_size = pipeline->stages[i].stack_size;
520       data->stages[i].has_shader = !!pipeline->stages[i].shader;
521 
522       if (pipeline->stages[i].shader)
523          pipeline_obj->shaders[idx++] = radv_shader_ref(pipeline->stages[i].shader);
524    }
525    assert(idx == num_shaders);
526 
527    /* Add the object to the cache */
528    pipeline->base.base.cache_object = vk_pipeline_cache_add_object(cache, &pipeline_obj->base);
529 }
530 
531 nir_shader *
radv_pipeline_cache_lookup_nir(struct radv_device * device,struct vk_pipeline_cache * cache,gl_shader_stage stage,const blake3_hash key)532 radv_pipeline_cache_lookup_nir(struct radv_device *device, struct vk_pipeline_cache *cache, gl_shader_stage stage,
533                                const blake3_hash key)
534 {
535    if (radv_is_cache_disabled(device))
536       return NULL;
537 
538    if (!cache)
539       cache = device->mem_cache;
540 
541    return vk_pipeline_cache_lookup_nir(cache, key, sizeof(blake3_hash), &device->physical_device->nir_options[stage],
542                                        NULL, NULL);
543 }
544 
545 void
radv_pipeline_cache_insert_nir(struct radv_device * device,struct vk_pipeline_cache * cache,const blake3_hash key,const nir_shader * nir)546 radv_pipeline_cache_insert_nir(struct radv_device *device, struct vk_pipeline_cache *cache, const blake3_hash key,
547                                const nir_shader *nir)
548 {
549    if (radv_is_cache_disabled(device))
550       return;
551 
552    if (!cache)
553       cache = device->mem_cache;
554 
555    vk_pipeline_cache_add_nir(cache, key, sizeof(blake3_hash), nir);
556 }
557 
558 struct vk_pipeline_cache_object *
radv_pipeline_cache_lookup_nir_handle(struct radv_device * device,struct vk_pipeline_cache * cache,const uint8_t * sha1)559 radv_pipeline_cache_lookup_nir_handle(struct radv_device *device, struct vk_pipeline_cache *cache, const uint8_t *sha1)
560 {
561    if (radv_is_cache_disabled(device))
562       return NULL;
563 
564    if (!cache)
565       cache = device->mem_cache;
566 
567    return vk_pipeline_cache_lookup_object(cache, sha1, SHA1_DIGEST_LENGTH, &vk_raw_data_cache_object_ops, NULL);
568 }
569 
570 struct nir_shader *
radv_pipeline_cache_handle_to_nir(struct radv_device * device,struct vk_pipeline_cache_object * object)571 radv_pipeline_cache_handle_to_nir(struct radv_device *device, struct vk_pipeline_cache_object *object)
572 {
573    struct blob_reader blob;
574    struct vk_raw_data_cache_object *nir_object = container_of(object, struct vk_raw_data_cache_object, base);
575    blob_reader_init(&blob, nir_object->data, nir_object->data_size);
576    nir_shader *nir = nir_deserialize(NULL, NULL, &blob);
577 
578    if (blob.overrun) {
579       ralloc_free(nir);
580       return NULL;
581    }
582    nir->options = &device->physical_device->nir_options[nir->info.stage];
583 
584    return nir;
585 }
586 
587 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)588 radv_pipeline_cache_nir_to_handle(struct radv_device *device, struct vk_pipeline_cache *cache, struct nir_shader *nir,
589                                   const uint8_t *sha1, bool cached)
590 {
591    if (!cache)
592       cache = device->mem_cache;
593 
594    struct blob blob;
595    blob_init(&blob);
596    nir_serialize(&blob, nir, true);
597 
598    if (blob.out_of_memory) {
599       blob_finish(&blob);
600       return NULL;
601    }
602 
603    void *data;
604    size_t size;
605    blob_finish_get_buffer(&blob, &data, &size);
606    struct vk_pipeline_cache_object *object;
607 
608    if (cached && !radv_is_cache_disabled(device)) {
609       object = vk_pipeline_cache_create_and_insert_object(cache, sha1, SHA1_DIGEST_LENGTH, data, size,
610                                                           &vk_raw_data_cache_object_ops);
611    } else {
612       struct vk_raw_data_cache_object *nir_object =
613          vk_raw_data_cache_object_create(&device->vk, sha1, SHA1_DIGEST_LENGTH, data, size);
614       object = nir_object ? &nir_object->base : NULL;
615    }
616 
617    free(data);
618    return object;
619 }
620