util/disk_cache: use a helper to compute cache keys
[mesa.git] / src / mesa / state_tracker / st_shader_cache.c
1 /*
2 * Copyright © 2017 Timothy Arceri
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <stdio.h>
25
26 #include "st_program.h"
27 #include "st_shader_cache.h"
28 #include "compiler/glsl/program.h"
29 #include "pipe/p_shader_tokens.h"
30 #include "program/ir_to_mesa.h"
31 #include "util/u_memory.h"
32
33 static void
34 write_stream_out_to_cache(struct blob *blob,
35 struct pipe_shader_state *tgsi)
36 {
37 blob_write_bytes(blob, &tgsi->stream_output,
38 sizeof(tgsi->stream_output));
39 }
40
41 static void
42 write_tgsi_to_cache(struct blob *blob, struct pipe_shader_state *tgsi,
43 struct st_context *st, unsigned char *sha1,
44 unsigned num_tokens)
45 {
46 blob_write_uint32(blob, num_tokens);
47 blob_write_bytes(blob, tgsi->tokens,
48 num_tokens * sizeof(struct tgsi_token));
49
50 disk_cache_put(st->ctx->Cache, sha1, blob->data, blob->size);
51 }
52
53 /**
54 * Store tgsi and any other required state in on-disk shader cache.
55 */
56 void
57 st_store_tgsi_in_disk_cache(struct st_context *st, struct gl_program *prog,
58 struct pipe_shader_state *out_state,
59 unsigned num_tokens)
60 {
61 if (!st->ctx->Cache)
62 return;
63
64 /* Exit early when we are dealing with a ff shader with no source file to
65 * generate a source from.
66 */
67 if (*prog->sh.data->sha1 == 0)
68 return;
69
70 unsigned char *sha1;
71 struct blob *blob = blob_create();
72
73 switch (prog->info.stage) {
74 case MESA_SHADER_VERTEX: {
75 struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
76 sha1 = stvp->sha1;
77
78 blob_write_uint32(blob, stvp->num_inputs);
79 blob_write_bytes(blob, stvp->index_to_input,
80 sizeof(stvp->index_to_input));
81 blob_write_bytes(blob, stvp->result_to_output,
82 sizeof(stvp->result_to_output));
83
84 write_stream_out_to_cache(blob, &stvp->tgsi);
85 write_tgsi_to_cache(blob, &stvp->tgsi, st, sha1, num_tokens);
86 break;
87 }
88 case MESA_SHADER_TESS_CTRL: {
89 struct st_tessctrl_program *stcp = (struct st_tessctrl_program *) prog;
90 sha1 = stcp->sha1;
91
92 write_stream_out_to_cache(blob, out_state);
93 write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens);
94 break;
95 }
96 case MESA_SHADER_TESS_EVAL: {
97 struct st_tesseval_program *step = (struct st_tesseval_program *) prog;
98 sha1 = step->sha1;
99
100 write_stream_out_to_cache(blob, out_state);
101 write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens);
102 break;
103 }
104 case MESA_SHADER_GEOMETRY: {
105 struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
106 sha1 = stgp->sha1;
107
108 write_stream_out_to_cache(blob, out_state);
109 write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens);
110 break;
111 }
112 case MESA_SHADER_FRAGMENT: {
113 struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
114 sha1 = stfp->sha1;
115
116 write_tgsi_to_cache(blob, &stfp->tgsi, st, sha1, num_tokens);
117 break;
118 }
119 case MESA_SHADER_COMPUTE: {
120 struct st_compute_program *stcp = (struct st_compute_program *) prog;
121 sha1 = stcp->sha1;
122
123 write_tgsi_to_cache(blob, out_state, st, sha1, num_tokens);
124 break;
125 }
126 default:
127 unreachable("Unsupported stage");
128 }
129
130 if (st->ctx->_Shader->Flags & GLSL_CACHE_INFO) {
131 char sha1_buf[41];
132 _mesa_sha1_format(sha1_buf, sha1);
133 fprintf(stderr, "putting %s tgsi_tokens in cache: %s\n",
134 _mesa_shader_stage_to_string(prog->info.stage), sha1_buf);
135 }
136
137 free(blob);
138 }
139
140 static void
141 read_stream_out_from_cache(struct blob_reader *blob_reader,
142 struct pipe_shader_state *tgsi)
143 {
144 blob_copy_bytes(blob_reader, (uint8_t *) &tgsi->stream_output,
145 sizeof(tgsi->stream_output));
146 }
147
148 static void
149 read_tgsi_from_cache(struct blob_reader *blob_reader,
150 const struct tgsi_token **tokens)
151 {
152 uint32_t num_tokens = blob_read_uint32(blob_reader);
153 unsigned tokens_size = num_tokens * sizeof(struct tgsi_token);
154 *tokens = (const struct tgsi_token*) MALLOC(tokens_size);
155 blob_copy_bytes(blob_reader, (uint8_t *) *tokens, tokens_size);
156 }
157
158 bool
159 st_load_tgsi_from_disk_cache(struct gl_context *ctx,
160 struct gl_shader_program *prog)
161 {
162 if (!ctx->Cache)
163 return false;
164
165 unsigned char *stage_sha1[MESA_SHADER_STAGES];
166 char sha1_buf[41];
167
168 /* Compute and store sha1 for each stage. These will be reused by the
169 * cache store pass if we fail to find the cached tgsi.
170 */
171 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
172 if (prog->_LinkedShaders[i] == NULL)
173 continue;
174
175 char *buf = ralloc_strdup(NULL, "tgsi_tokens ");
176 _mesa_sha1_format(sha1_buf,
177 prog->_LinkedShaders[i]->Program->sh.data->sha1);
178 ralloc_strcat(&buf, sha1_buf);
179
180 struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
181 switch (glprog->info.stage) {
182 case MESA_SHADER_VERTEX: {
183 struct st_vertex_program *stvp = (struct st_vertex_program *) glprog;
184 stage_sha1[i] = stvp->sha1;
185 ralloc_strcat(&buf, " vs");
186 disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]);
187 break;
188 }
189 case MESA_SHADER_TESS_CTRL: {
190 struct st_tessctrl_program *stcp =
191 (struct st_tessctrl_program *) glprog;
192 stage_sha1[i] = stcp->sha1;
193 ralloc_strcat(&buf, " tcs");
194 disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]);
195 break;
196 }
197 case MESA_SHADER_TESS_EVAL: {
198 struct st_tesseval_program *step =
199 (struct st_tesseval_program *) glprog;
200 stage_sha1[i] = step->sha1;
201 ralloc_strcat(&buf, " tes");
202 disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]);
203 break;
204 }
205 case MESA_SHADER_GEOMETRY: {
206 struct st_geometry_program *stgp =
207 (struct st_geometry_program *) glprog;
208 stage_sha1[i] = stgp->sha1;
209 ralloc_strcat(&buf, " gs");
210 disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]);
211 break;
212 }
213 case MESA_SHADER_FRAGMENT: {
214 struct st_fragment_program *stfp =
215 (struct st_fragment_program *) glprog;
216 stage_sha1[i] = stfp->sha1;
217 ralloc_strcat(&buf, " fs");
218 disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]);
219 break;
220 }
221 case MESA_SHADER_COMPUTE: {
222 struct st_compute_program *stcp =
223 (struct st_compute_program *) glprog;
224 stage_sha1[i] = stcp->sha1;
225 ralloc_strcat(&buf, " cs");
226 disk_cache_compute_key(ctx->Cache, buf, strlen(buf), stage_sha1[i]);
227 break;
228 }
229 default:
230 unreachable("Unsupported stage");
231 }
232
233 ralloc_free(buf);
234 }
235
236 /* Now that we have created the sha1 keys that will be used for writting to
237 * the tgsi cache fallback to the regular glsl to tgsi path if we didn't
238 * load the GLSL IR from cache. We do this as glsl to tgsi can alter things
239 * such as gl_program_parameter_list which holds things like uniforms.
240 */
241 if (prog->data->LinkStatus != linking_skipped)
242 return false;
243
244 struct st_context *st = st_context(ctx);
245 uint8_t *buffer = NULL;
246 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
247 if (prog->_LinkedShaders[i] == NULL)
248 continue;
249
250 unsigned char *sha1 = stage_sha1[i];
251 size_t size;
252 buffer = (uint8_t *) disk_cache_get(ctx->Cache, sha1, &size);
253 if (buffer) {
254 struct blob_reader blob_reader;
255 blob_reader_init(&blob_reader, buffer, size);
256
257 struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
258 switch (glprog->info.stage) {
259 case MESA_SHADER_VERTEX: {
260 struct st_vertex_program *stvp =
261 (struct st_vertex_program *) glprog;
262
263 st_release_vp_variants(st, stvp);
264
265 stvp->num_inputs = blob_read_uint32(&blob_reader);
266 blob_copy_bytes(&blob_reader, (uint8_t *) stvp->index_to_input,
267 sizeof(stvp->index_to_input));
268 blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output,
269 sizeof(stvp->result_to_output));
270
271 read_stream_out_from_cache(&blob_reader, &stvp->tgsi);
272 read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens);
273
274 if (st->vp == stvp)
275 st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp);
276
277 break;
278 }
279 case MESA_SHADER_TESS_CTRL: {
280 struct st_tessctrl_program *sttcp =
281 (struct st_tessctrl_program *) glprog;
282
283 st_release_basic_variants(st, sttcp->Base.Target,
284 &sttcp->variants, &sttcp->tgsi);
285
286 read_stream_out_from_cache(&blob_reader, &sttcp->tgsi);
287 read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens);
288
289 if (st->tcp == sttcp)
290 st->dirty |= sttcp->affected_states;
291
292 break;
293 }
294 case MESA_SHADER_TESS_EVAL: {
295 struct st_tesseval_program *sttep =
296 (struct st_tesseval_program *) glprog;
297
298 st_release_basic_variants(st, sttep->Base.Target,
299 &sttep->variants, &sttep->tgsi);
300
301 read_stream_out_from_cache(&blob_reader, &sttep->tgsi);
302 read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens);
303
304 if (st->tep == sttep)
305 st->dirty |= sttep->affected_states;
306
307 break;
308 }
309 case MESA_SHADER_GEOMETRY: {
310 struct st_geometry_program *stgp =
311 (struct st_geometry_program *) glprog;
312
313 st_release_basic_variants(st, stgp->Base.Target, &stgp->variants,
314 &stgp->tgsi);
315
316 read_stream_out_from_cache(&blob_reader, &stgp->tgsi);
317 read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens);
318
319 if (st->gp == stgp)
320 st->dirty |= stgp->affected_states;
321
322 break;
323 }
324 case MESA_SHADER_FRAGMENT: {
325 struct st_fragment_program *stfp =
326 (struct st_fragment_program *) glprog;
327
328 st_release_fp_variants(st, stfp);
329
330 read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens);
331
332 if (st->fp == stfp)
333 st->dirty |= stfp->affected_states;
334
335 break;
336 }
337 case MESA_SHADER_COMPUTE: {
338 struct st_compute_program *stcp =
339 (struct st_compute_program *) glprog;
340
341 st_release_cp_variants(st, stcp);
342
343 read_tgsi_from_cache(&blob_reader,
344 (const struct tgsi_token**) &stcp->tgsi.prog);
345
346 stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size;
347 stcp->tgsi.req_private_mem = 0;
348 stcp->tgsi.req_input_mem = 0;
349
350 if (st->cp == stcp)
351 st->dirty |= stcp->affected_states;
352
353 break;
354 }
355 default:
356 unreachable("Unsupported stage");
357 }
358
359 if (blob_reader.current != blob_reader.end || blob_reader.overrun) {
360 /* Something very bad has gone wrong discard the item from the
361 * cache and rebuild/link from source.
362 */
363 assert(!"Invalid TGSI shader disk cache item!");
364
365 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
366 fprintf(stderr, "Error reading program from cache (invalid "
367 "TGSI cache item)\n");
368 }
369
370 disk_cache_remove(ctx->Cache, sha1);
371
372 goto fallback_recompile;
373 }
374
375 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
376 _mesa_sha1_format(sha1_buf, sha1);
377 fprintf(stderr, "%s tgsi_tokens retrieved from cache: %s\n",
378 _mesa_shader_stage_to_string(i), sha1_buf);
379 }
380
381 st_set_prog_affected_state_flags(glprog);
382 _mesa_associate_uniform_storage(ctx, prog, glprog->Parameters,
383 false);
384
385 free(buffer);
386 } else {
387 /* Failed to find a matching cached shader so fallback to recompile.
388 */
389 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
390 fprintf(stderr, "TGSI cache item not found falling back to "
391 "compile.\n");
392 }
393
394 goto fallback_recompile;
395 }
396 }
397
398 return true;
399
400 fallback_recompile:
401 free(buffer);
402
403 for (unsigned i = 0; i < prog->NumShaders; i++) {
404 _mesa_glsl_compile_shader(ctx, prog->Shaders[i], false, false, true);
405 }
406
407 prog->data->cache_fallback = true;
408 _mesa_glsl_link_shader(ctx, prog);
409
410 return true;
411 }