• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Amazon.com, Inc. or its affiliates.
3  * Copyright © 2018 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR 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
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <assert.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "compiler/nir/nir.h"
30 #include "util/blob.h"
31 #include "util/build_id.h"
32 #include "util/disk_cache.h"
33 #include "util/mesa-sha1.h"
34 
35 #include "pan_context.h"
36 
37 static bool debug = false;
38 
39 extern int midgard_debug;
40 extern int bifrost_debug;
41 
42 /**
43  * Compute a disk cache key for the given uncompiled shader and shader key.
44  */
45 static void
panfrost_disk_cache_compute_key(struct disk_cache * cache,const struct panfrost_uncompiled_shader * uncompiled,const struct panfrost_shader_key * shader_key,cache_key cache_key)46 panfrost_disk_cache_compute_key(
47    struct disk_cache *cache,
48    const struct panfrost_uncompiled_shader *uncompiled,
49    const struct panfrost_shader_key *shader_key, cache_key cache_key)
50 {
51    uint8_t data[sizeof(uncompiled->nir_sha1) + sizeof(*shader_key)];
52 
53    memcpy(data, uncompiled->nir_sha1, sizeof(uncompiled->nir_sha1));
54    memcpy(data + sizeof(uncompiled->nir_sha1), shader_key, sizeof(*shader_key));
55 
56    disk_cache_compute_key(cache, data, sizeof(data), cache_key);
57 }
58 
59 /**
60  * Store the given compiled shader in the disk cache.
61  *
62  * This should only be called on newly compiled shaders.  No checking is
63  * done to prevent repeated stores of the same shader.
64  */
65 void
panfrost_disk_cache_store(struct disk_cache * cache,const struct panfrost_uncompiled_shader * uncompiled,const struct panfrost_shader_key * key,const struct panfrost_shader_binary * binary)66 panfrost_disk_cache_store(struct disk_cache *cache,
67                           const struct panfrost_uncompiled_shader *uncompiled,
68                           const struct panfrost_shader_key *key,
69                           const struct panfrost_shader_binary *binary)
70 {
71 #ifdef ENABLE_SHADER_CACHE
72    if (!cache)
73       return;
74 
75    cache_key cache_key;
76    panfrost_disk_cache_compute_key(cache, uncompiled, key, cache_key);
77 
78    if (debug) {
79       char sha1[41];
80       _mesa_sha1_format(sha1, cache_key);
81       fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);
82    }
83 
84    struct blob blob;
85    blob_init(&blob);
86 
87    /* We write the following data to the cache blob:
88     *
89     * 1. Size of program binary
90     * 2. Program binary
91     * 3. Shader info
92     * 4. System values
93     */
94    blob_write_uint32(&blob, binary->binary.size);
95    blob_write_bytes(&blob, binary->binary.data, binary->binary.size);
96    blob_write_bytes(&blob, &binary->info, sizeof(binary->info));
97    blob_write_bytes(&blob, &binary->sysvals, sizeof(binary->sysvals));
98 
99    disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);
100    blob_finish(&blob);
101 #endif
102 }
103 
104 /**
105  * Search for a compiled shader in the disk cache.
106  */
107 bool
panfrost_disk_cache_retrieve(struct disk_cache * cache,const struct panfrost_uncompiled_shader * uncompiled,const struct panfrost_shader_key * key,struct panfrost_shader_binary * binary)108 panfrost_disk_cache_retrieve(struct disk_cache *cache,
109                              const struct panfrost_uncompiled_shader *uncompiled,
110                              const struct panfrost_shader_key *key,
111                              struct panfrost_shader_binary *binary)
112 {
113 #ifdef ENABLE_SHADER_CACHE
114    if (!cache)
115       return false;
116 
117    cache_key cache_key;
118    panfrost_disk_cache_compute_key(cache, uncompiled, key, cache_key);
119 
120    if (debug) {
121       char sha1[41];
122       _mesa_sha1_format(sha1, cache_key);
123       fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
124    }
125 
126    size_t size;
127    void *buffer = disk_cache_get(cache, cache_key, &size);
128 
129    if (debug)
130       fprintf(stderr, "%s\n", buffer ? "found" : "missing");
131 
132    if (!buffer)
133       return false;
134 
135    struct blob_reader blob;
136    blob_reader_init(&blob, buffer, size);
137 
138    util_dynarray_init(&binary->binary, NULL);
139 
140    uint32_t binary_size = blob_read_uint32(&blob);
141    void *ptr = util_dynarray_resize_bytes(&binary->binary, binary_size, 1);
142 
143    blob_copy_bytes(&blob, ptr, binary_size);
144    blob_copy_bytes(&blob, &binary->info, sizeof(binary->info));
145    blob_copy_bytes(&blob, &binary->sysvals, sizeof(binary->sysvals));
146 
147    free(buffer);
148 
149    return true;
150 #else
151    return false;
152 #endif
153 }
154 
155 /**
156  * Initialize the on-disk shader cache.
157  */
158 void
panfrost_disk_cache_init(struct panfrost_screen * screen)159 panfrost_disk_cache_init(struct panfrost_screen *screen)
160 {
161 #ifdef ENABLE_SHADER_CACHE
162    const char *renderer = screen->base.get_name(&screen->base);
163 
164    const struct build_id_note *note =
165       build_id_find_nhdr_for_addr(panfrost_disk_cache_init);
166    assert(note && build_id_length(note) == 20); /* sha1 */
167 
168    const uint8_t *id_sha1 = build_id_data(note);
169    assert(id_sha1);
170 
171    char timestamp[41];
172    _mesa_sha1_format(timestamp, id_sha1);
173 
174    /* Consider any flags affecting the compile when caching */
175    uint64_t driver_flags = screen->dev.debug;
176    driver_flags |= ((uint64_t)(midgard_debug | bifrost_debug) << 32);
177 
178    screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
179 #endif
180 }
181