Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/iris/iris_disk_cache.c
4565 views
1
/*
2
* Copyright © 2018 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 shall be included
12
* in all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
* DEALINGS IN THE SOFTWARE.
21
*/
22
23
/**
24
* @file iris_disk_cache.c
25
*
26
* Functions for interacting with the on-disk shader cache.
27
*/
28
29
#include <stdio.h>
30
#include <stdint.h>
31
#include <assert.h>
32
#include <string.h>
33
34
#include "compiler/nir/nir.h"
35
#include "util/blob.h"
36
#include "util/build_id.h"
37
#include "util/disk_cache.h"
38
#include "util/mesa-sha1.h"
39
40
#include "iris_context.h"
41
42
static bool debug = false;
43
44
/**
45
* Compute a disk cache key for the given uncompiled shader and NOS key.
46
*/
47
static void
48
iris_disk_cache_compute_key(struct disk_cache *cache,
49
const struct iris_uncompiled_shader *ish,
50
const void *orig_prog_key,
51
uint32_t prog_key_size,
52
cache_key cache_key)
53
{
54
/* Create a copy of the program key with program_string_id zeroed out.
55
* It's essentially random data which we don't want to include in our
56
* hashing and comparisons. We'll set a proper value on a cache hit.
57
*/
58
union brw_any_prog_key prog_key;
59
memcpy(&prog_key, orig_prog_key, prog_key_size);
60
prog_key.base.program_string_id = 0;
61
62
uint8_t data[sizeof(prog_key) + sizeof(ish->nir_sha1)];
63
uint32_t data_size = prog_key_size + sizeof(ish->nir_sha1);
64
65
memcpy(data, ish->nir_sha1, sizeof(ish->nir_sha1));
66
memcpy(data + sizeof(ish->nir_sha1), &prog_key, prog_key_size);
67
68
disk_cache_compute_key(cache, data, data_size, cache_key);
69
}
70
71
/**
72
* Store the given compiled shader in the disk cache.
73
*
74
* This should only be called on newly compiled shaders. No checking is
75
* done to prevent repeated stores of the same shader.
76
*/
77
void
78
iris_disk_cache_store(struct disk_cache *cache,
79
const struct iris_uncompiled_shader *ish,
80
const struct iris_compiled_shader *shader,
81
const void *prog_key,
82
uint32_t prog_key_size)
83
{
84
#ifdef ENABLE_SHADER_CACHE
85
if (!cache)
86
return;
87
88
gl_shader_stage stage = ish->nir->info.stage;
89
const struct brw_stage_prog_data *prog_data = shader->prog_data;
90
91
cache_key cache_key;
92
iris_disk_cache_compute_key(cache, ish, prog_key, prog_key_size, cache_key);
93
94
if (debug) {
95
char sha1[41];
96
_mesa_sha1_format(sha1, cache_key);
97
fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);
98
}
99
100
struct blob blob;
101
blob_init(&blob);
102
103
/* We write the following data to the cache blob:
104
*
105
* 1. Prog data (must come first because it has the assembly size)
106
* 2. Assembly code
107
* 3. Number of entries in the system value array
108
* 4. System value array
109
* 5. Size (in bytes) of kernel inputs
110
* 6. Shader relocations
111
* 7. Legacy param array (only used for compute workgroup ID)
112
* 8. Binding table
113
*/
114
blob_write_bytes(&blob, shader->prog_data, brw_prog_data_size(stage));
115
blob_write_bytes(&blob, shader->map, shader->prog_data->program_size);
116
blob_write_uint32(&blob, shader->num_system_values);
117
blob_write_bytes(&blob, shader->system_values,
118
shader->num_system_values * sizeof(enum brw_param_builtin));
119
blob_write_uint32(&blob, shader->kernel_input_size);
120
blob_write_bytes(&blob, prog_data->relocs,
121
prog_data->num_relocs * sizeof(struct brw_shader_reloc));
122
blob_write_bytes(&blob, prog_data->param,
123
prog_data->nr_params * sizeof(uint32_t));
124
blob_write_bytes(&blob, &shader->bt, sizeof(shader->bt));
125
126
disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);
127
blob_finish(&blob);
128
#endif
129
}
130
131
static const enum iris_program_cache_id cache_id_for_stage[] = {
132
[MESA_SHADER_VERTEX] = IRIS_CACHE_VS,
133
[MESA_SHADER_TESS_CTRL] = IRIS_CACHE_TCS,
134
[MESA_SHADER_TESS_EVAL] = IRIS_CACHE_TES,
135
[MESA_SHADER_GEOMETRY] = IRIS_CACHE_GS,
136
[MESA_SHADER_FRAGMENT] = IRIS_CACHE_FS,
137
[MESA_SHADER_COMPUTE] = IRIS_CACHE_CS,
138
};
139
140
/**
141
* Search for a compiled shader in the disk cache. If found, upload it
142
* to the in-memory program cache so we can use it.
143
*/
144
struct iris_compiled_shader *
145
iris_disk_cache_retrieve(struct iris_screen *screen,
146
struct u_upload_mgr *uploader,
147
struct iris_uncompiled_shader *ish,
148
const void *prog_key,
149
uint32_t key_size)
150
{
151
#ifdef ENABLE_SHADER_CACHE
152
struct disk_cache *cache = screen->disk_cache;
153
gl_shader_stage stage = ish->nir->info.stage;
154
155
if (!cache)
156
return NULL;
157
158
cache_key cache_key;
159
iris_disk_cache_compute_key(cache, ish, prog_key, key_size, cache_key);
160
161
if (debug) {
162
char sha1[41];
163
_mesa_sha1_format(sha1, cache_key);
164
fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);
165
}
166
167
size_t size;
168
void *buffer = disk_cache_get(screen->disk_cache, cache_key, &size);
169
170
if (debug)
171
fprintf(stderr, "%s\n", buffer ? "found" : "missing");
172
173
if (!buffer)
174
return NULL;
175
176
const uint32_t prog_data_size = brw_prog_data_size(stage);
177
178
struct brw_stage_prog_data *prog_data = ralloc_size(NULL, prog_data_size);
179
const void *assembly;
180
uint32_t num_system_values;
181
uint32_t kernel_input_size;
182
uint32_t *system_values = NULL;
183
uint32_t *so_decls = NULL;
184
185
struct blob_reader blob;
186
blob_reader_init(&blob, buffer, size);
187
blob_copy_bytes(&blob, prog_data, prog_data_size);
188
assembly = blob_read_bytes(&blob, prog_data->program_size);
189
num_system_values = blob_read_uint32(&blob);
190
if (num_system_values) {
191
system_values =
192
ralloc_array(NULL, enum brw_param_builtin, num_system_values);
193
blob_copy_bytes(&blob, system_values,
194
num_system_values * sizeof(enum brw_param_builtin));
195
}
196
197
kernel_input_size = blob_read_uint32(&blob);
198
199
prog_data->relocs = NULL;
200
if (prog_data->num_relocs) {
201
struct brw_shader_reloc *relocs =
202
ralloc_array(NULL, struct brw_shader_reloc, prog_data->num_relocs);
203
blob_copy_bytes(&blob, relocs,
204
prog_data->num_relocs * sizeof(struct brw_shader_reloc));
205
prog_data->relocs = relocs;
206
}
207
208
prog_data->param = NULL;
209
prog_data->pull_param = NULL;
210
assert(prog_data->nr_pull_params == 0);
211
212
if (prog_data->nr_params) {
213
prog_data->param = ralloc_array(NULL, uint32_t, prog_data->nr_params);
214
blob_copy_bytes(&blob, prog_data->param,
215
prog_data->nr_params * sizeof(uint32_t));
216
}
217
218
struct iris_binding_table bt;
219
blob_copy_bytes(&blob, &bt, sizeof(bt));
220
221
if (stage == MESA_SHADER_VERTEX ||
222
stage == MESA_SHADER_TESS_EVAL ||
223
stage == MESA_SHADER_GEOMETRY) {
224
struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
225
so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output,
226
&vue_prog_data->vue_map);
227
}
228
229
/* System values and uniforms are stored in constant buffer 0, the
230
* user-facing UBOs are indexed by one. So if any constant buffer is
231
* needed, the constant buffer 0 will be needed, so account for it.
232
*/
233
unsigned num_cbufs = ish->nir->info.num_ubos;
234
235
if (num_cbufs || ish->nir->num_uniforms)
236
num_cbufs++;
237
238
if (num_system_values || kernel_input_size)
239
num_cbufs++;
240
241
assert(stage < ARRAY_SIZE(cache_id_for_stage));
242
enum iris_program_cache_id cache_id = cache_id_for_stage[stage];
243
244
/* Upload our newly read shader to the in-memory program cache and
245
* return it to the caller.
246
*/
247
struct iris_compiled_shader *shader =
248
iris_upload_shader(screen, ish, NULL, uploader,
249
cache_id, key_size, prog_key, assembly,
250
prog_data, so_decls, system_values,
251
num_system_values, kernel_input_size, num_cbufs, &bt);
252
253
free(buffer);
254
255
return shader;
256
#else
257
return NULL;
258
#endif
259
}
260
261
/**
262
* Initialize the on-disk shader cache.
263
*/
264
void
265
iris_disk_cache_init(struct iris_screen *screen)
266
{
267
#ifdef ENABLE_SHADER_CACHE
268
if (INTEL_DEBUG & DEBUG_DISK_CACHE_DISABLE_MASK)
269
return;
270
271
/* array length = print length + nul char + 1 extra to verify it's unused */
272
char renderer[11];
273
UNUSED int len =
274
snprintf(renderer, sizeof(renderer), "iris_%04x", screen->pci_id);
275
assert(len == sizeof(renderer) - 2);
276
277
const struct build_id_note *note =
278
build_id_find_nhdr_for_addr(iris_disk_cache_init);
279
assert(note && build_id_length(note) == 20); /* sha1 */
280
281
const uint8_t *id_sha1 = build_id_data(note);
282
assert(id_sha1);
283
284
char timestamp[41];
285
_mesa_sha1_format(timestamp, id_sha1);
286
287
const uint64_t driver_flags =
288
brw_get_compiler_config_value(screen->compiler);
289
screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
290
#endif
291
}
292
293