2 * Copyright © 2017 Timothy Arceri
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:
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
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.
26 #include "st_program.h"
27 #include "st_shader_cache.h"
29 #include "compiler/glsl/program.h"
30 #include "compiler/nir/nir.h"
31 #include "compiler/nir/nir_serialize.h"
32 #include "pipe/p_shader_tokens.h"
33 #include "program/ir_to_mesa.h"
34 #include "tgsi/tgsi_parse.h"
35 #include "util/u_memory.h"
38 st_get_program_binary_driver_sha1(struct gl_context
*ctx
, uint8_t *sha1
)
40 disk_cache_compute_key(ctx
->Cache
, NULL
, 0, sha1
);
44 write_stream_out_to_cache(struct blob
*blob
,
45 struct pipe_shader_state
*state
)
47 blob_write_uint32(blob
, state
->stream_output
.num_outputs
);
48 if (state
->stream_output
.num_outputs
) {
49 blob_write_bytes(blob
, &state
->stream_output
.stride
,
50 sizeof(state
->stream_output
.stride
));
51 blob_write_bytes(blob
, &state
->stream_output
.output
,
52 sizeof(state
->stream_output
.output
));
57 copy_blob_to_driver_cache_blob(struct blob
*blob
, struct gl_program
*prog
)
59 prog
->driver_cache_blob
= ralloc_size(NULL
, blob
->size
);
60 memcpy(prog
->driver_cache_blob
, blob
->data
, blob
->size
);
61 prog
->driver_cache_blob_size
= blob
->size
;
65 write_tgsi_to_cache(struct blob
*blob
, const struct tgsi_token
*tokens
,
66 struct gl_program
*prog
)
68 unsigned num_tokens
= tgsi_num_tokens(tokens
);
70 blob_write_uint32(blob
, num_tokens
);
71 blob_write_bytes(blob
, tokens
, num_tokens
* sizeof(struct tgsi_token
));
72 copy_blob_to_driver_cache_blob(blob
, prog
);
76 write_nir_to_cache(struct blob
*blob
, struct gl_program
*prog
)
78 struct st_program
*stp
= (struct st_program
*)prog
;
80 st_serialize_nir(stp
);
82 blob_write_intptr(blob
, stp
->serialized_nir_size
);
83 blob_write_bytes(blob
, stp
->serialized_nir
, stp
->serialized_nir_size
);
85 copy_blob_to_driver_cache_blob(blob
, prog
);
89 st_serialise_ir_program(struct gl_context
*ctx
, struct gl_program
*prog
,
92 if (prog
->driver_cache_blob
)
95 struct st_program
*stp
= (struct st_program
*)prog
;
99 if (prog
->info
.stage
== MESA_SHADER_VERTEX
) {
100 struct st_vertex_program
*stvp
= (struct st_vertex_program
*)stp
;
102 blob_write_uint32(&blob
, stvp
->num_inputs
);
103 blob_write_bytes(&blob
, stvp
->index_to_input
,
104 sizeof(stvp
->index_to_input
));
105 blob_write_bytes(&blob
, stvp
->input_to_index
,
106 sizeof(stvp
->input_to_index
));
107 blob_write_bytes(&blob
, stvp
->result_to_output
,
108 sizeof(stvp
->result_to_output
));
111 if (prog
->info
.stage
== MESA_SHADER_VERTEX
||
112 prog
->info
.stage
== MESA_SHADER_TESS_EVAL
||
113 prog
->info
.stage
== MESA_SHADER_GEOMETRY
)
114 write_stream_out_to_cache(&blob
, &stp
->state
);
117 write_nir_to_cache(&blob
, prog
);
119 write_tgsi_to_cache(&blob
, stp
->state
.tokens
, prog
);
125 * Store TGSI or NIR and any other required state in on-disk shader cache.
128 st_store_ir_in_disk_cache(struct st_context
*st
, struct gl_program
*prog
,
134 /* Exit early when we are dealing with a ff shader with no source file to
135 * generate a source from.
137 static const char zero
[sizeof(prog
->sh
.data
->sha1
)] = {0};
138 if (memcmp(prog
->sh
.data
->sha1
, zero
, sizeof(prog
->sh
.data
->sha1
)) == 0)
141 st_serialise_ir_program(st
->ctx
, prog
, nir
);
143 if (st
->ctx
->_Shader
->Flags
& GLSL_CACHE_INFO
) {
144 fprintf(stderr
, "putting %s state tracker IR in cache\n",
145 _mesa_shader_stage_to_string(prog
->info
.stage
));
150 read_stream_out_from_cache(struct blob_reader
*blob_reader
,
151 struct pipe_shader_state
*state
)
153 memset(&state
->stream_output
, 0, sizeof(state
->stream_output
));
154 state
->stream_output
.num_outputs
= blob_read_uint32(blob_reader
);
155 if (state
->stream_output
.num_outputs
) {
156 blob_copy_bytes(blob_reader
, &state
->stream_output
.stride
,
157 sizeof(state
->stream_output
.stride
));
158 blob_copy_bytes(blob_reader
, &state
->stream_output
.output
,
159 sizeof(state
->stream_output
.output
));
164 read_tgsi_from_cache(struct blob_reader
*blob_reader
,
165 const struct tgsi_token
**tokens
)
167 unsigned num_tokens
= blob_read_uint32(blob_reader
);
168 unsigned tokens_size
= num_tokens
* sizeof(struct tgsi_token
);
169 *tokens
= (const struct tgsi_token
*) MALLOC(tokens_size
);
170 blob_copy_bytes(blob_reader
, (uint8_t *) *tokens
, tokens_size
);
174 st_deserialise_ir_program(struct gl_context
*ctx
,
175 struct gl_shader_program
*shProg
,
176 struct gl_program
*prog
, bool nir
)
178 struct st_context
*st
= st_context(ctx
);
179 size_t size
= prog
->driver_cache_blob_size
;
180 uint8_t *buffer
= (uint8_t *) prog
->driver_cache_blob
;
182 st_set_prog_affected_state_flags(prog
);
183 _mesa_associate_uniform_storage(ctx
, shProg
, prog
);
185 assert(prog
->driver_cache_blob
&& prog
->driver_cache_blob_size
> 0);
187 struct st_program
*stp
= st_program(prog
);
188 struct blob_reader blob_reader
;
189 blob_reader_init(&blob_reader
, buffer
, size
);
191 st_release_variants(st
, stp
);
193 if (prog
->info
.stage
== MESA_SHADER_VERTEX
) {
194 struct st_vertex_program
*stvp
= (struct st_vertex_program
*)stp
;
195 stvp
->num_inputs
= blob_read_uint32(&blob_reader
);
196 blob_copy_bytes(&blob_reader
, (uint8_t *) stvp
->index_to_input
,
197 sizeof(stvp
->index_to_input
));
198 blob_copy_bytes(&blob_reader
, (uint8_t *) stvp
->input_to_index
,
199 sizeof(stvp
->input_to_index
));
200 blob_copy_bytes(&blob_reader
, (uint8_t *) stvp
->result_to_output
,
201 sizeof(stvp
->result_to_output
));
204 if (prog
->info
.stage
== MESA_SHADER_VERTEX
||
205 prog
->info
.stage
== MESA_SHADER_TESS_EVAL
||
206 prog
->info
.stage
== MESA_SHADER_GEOMETRY
)
207 read_stream_out_from_cache(&blob_reader
, &stp
->state
);
210 assert(prog
->nir
== NULL
);
211 assert(stp
->serialized_nir
== NULL
);
213 stp
->state
.type
= PIPE_SHADER_IR_NIR
;
214 stp
->serialized_nir_size
= blob_read_intptr(&blob_reader
);
215 stp
->serialized_nir
= malloc(stp
->serialized_nir_size
);
216 blob_copy_bytes(&blob_reader
, stp
->serialized_nir
, stp
->serialized_nir_size
);
217 stp
->shader_program
= shProg
;
219 read_tgsi_from_cache(&blob_reader
, &stp
->state
.tokens
);
222 /* Make sure we don't try to read more data than we wrote. This should
223 * never happen in release builds but its useful to have this check to
224 * catch development bugs.
226 if (blob_reader
.current
!= blob_reader
.end
|| blob_reader
.overrun
) {
227 assert(!"Invalid TGSI shader disk cache item!");
229 if (ctx
->_Shader
->Flags
& GLSL_CACHE_INFO
) {
230 fprintf(stderr
, "Error reading program from cache (invalid "
231 "TGSI cache item)\n");
235 st_finalize_program(st
, prog
);
239 st_load_ir_from_disk_cache(struct gl_context
*ctx
,
240 struct gl_shader_program
*prog
,
246 /* If we didn't load the GLSL metadata from cache then we could not have
247 * loaded TGSI or NIR either.
249 if (prog
->data
->LinkStatus
!= LINKING_SKIPPED
)
252 for (unsigned i
= 0; i
< MESA_SHADER_STAGES
; i
++) {
253 if (prog
->_LinkedShaders
[i
] == NULL
)
256 struct gl_program
*glprog
= prog
->_LinkedShaders
[i
]->Program
;
257 st_deserialise_ir_program(ctx
, prog
, glprog
, nir
);
259 /* We don't need the cached blob anymore so free it */
260 ralloc_free(glprog
->driver_cache_blob
);
261 glprog
->driver_cache_blob
= NULL
;
262 glprog
->driver_cache_blob_size
= 0;
264 if (ctx
->_Shader
->Flags
& GLSL_CACHE_INFO
) {
265 fprintf(stderr
, "%s state tracker IR retrieved from cache\n",
266 _mesa_shader_stage_to_string(i
));
274 st_serialise_tgsi_program(struct gl_context
*ctx
, struct gl_program
*prog
)
276 st_serialise_ir_program(ctx
, prog
, false);
280 st_serialise_tgsi_program_binary(struct gl_context
*ctx
,
281 struct gl_shader_program
*shProg
,
282 struct gl_program
*prog
)
284 st_serialise_ir_program(ctx
, prog
, false);
288 st_deserialise_tgsi_program(struct gl_context
*ctx
,
289 struct gl_shader_program
*shProg
,
290 struct gl_program
*prog
)
292 st_deserialise_ir_program(ctx
, shProg
, prog
, false);
296 st_serialise_nir_program(struct gl_context
*ctx
, struct gl_program
*prog
)
298 st_serialise_ir_program(ctx
, prog
, true);
302 st_serialise_nir_program_binary(struct gl_context
*ctx
,
303 struct gl_shader_program
*shProg
,
304 struct gl_program
*prog
)
306 st_serialise_ir_program(ctx
, prog
, true);
310 st_deserialise_nir_program(struct gl_context
*ctx
,
311 struct gl_shader_program
*shProg
,
312 struct gl_program
*prog
)
314 st_deserialise_ir_program(ctx
, shProg
, prog
, true);