2 * Copyright (c) 2017 Intel Corporation
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 "compiler/nir/nir_serialize.h"
27 #include "util/build_id.h"
28 #include "util/mesa-sha1.h"
30 #include "brw_context.h"
31 #include "brw_program.h"
32 #include "brw_state.h"
34 static uint8_t driver_sha1
[20];
37 brw_program_binary_init(unsigned device_id
)
39 const struct build_id_note
*note
=
40 build_id_find_nhdr_for_addr(brw_program_binary_init
);
44 * With Mesa's megadrivers, taking the sha1 of i965_dri.so may not be
45 * unique. Therefore, we make a sha1 of the "i965" string and the sha1
46 * build id from i965_dri.so.
49 _mesa_sha1_init(&ctx
);
51 assert(device_id
< 0x10000);
52 int len
= snprintf(renderer
, sizeof(renderer
), "i965_%04x", device_id
);
53 assert(len
== sizeof(renderer
) - 1);
54 _mesa_sha1_update(&ctx
, renderer
, len
);
55 _mesa_sha1_update(&ctx
, build_id_data(note
), build_id_length(note
));
56 _mesa_sha1_final(&ctx
, driver_sha1
);
60 brw_get_program_binary_driver_sha1(struct gl_context
*ctx
, uint8_t *sha1
)
62 memcpy(sha1
, driver_sha1
, sizeof(uint8_t) * 20);
65 enum driver_cache_blob_part
{
72 blob_parts_valid(void *blob
, uint32_t size
)
74 struct blob_reader reader
;
75 blob_reader_init(&reader
, blob
, size
);
78 uint32_t part_type
= blob_read_uint32(&reader
);
81 if (part_type
== END_PART
)
82 return reader
.current
== reader
.end
;
83 switch ((enum driver_cache_blob_part
)part_type
) {
86 /* Read the uint32_t part-size and skip over it */
87 blob_skip_bytes(&reader
, blob_read_uint32(&reader
));
98 blob_has_part(void *blob
, uint32_t size
, enum driver_cache_blob_part part
)
100 struct blob_reader reader
;
101 blob_reader_init(&reader
, blob
, size
);
103 assert(blob_parts_valid(blob
, size
));
105 uint32_t part_type
= blob_read_uint32(&reader
);
106 if (part_type
== END_PART
)
108 if (part_type
== part
)
110 blob_skip_bytes(&reader
, blob_read_uint32(&reader
));
115 driver_blob_is_ready(void *blob
, uint32_t size
, bool with_gen_program
)
119 } else if (!blob_parts_valid(blob
, size
)) {
120 unreachable("Driver blob format is bad!");
122 } else if (blob_has_part(blob
, size
, GEN_PART
) == with_gen_program
) {
130 serialize_nir_part(struct blob
*writer
, struct gl_program
*prog
)
132 blob_write_uint32(writer
, NIR_PART
);
133 intptr_t size_offset
= blob_reserve_uint32(writer
);
134 size_t nir_start
= writer
->size
;
135 nir_serialize(writer
, prog
->nir
);
136 blob_overwrite_uint32(writer
, size_offset
, writer
->size
- nir_start
);
140 brw_program_serialize_nir(struct gl_context
*ctx
, struct gl_program
*prog
)
142 if (driver_blob_is_ready(prog
->driver_cache_blob
,
143 prog
->driver_cache_blob_size
, false))
146 if (prog
->driver_cache_blob
)
147 ralloc_free(prog
->driver_cache_blob
);
151 serialize_nir_part(&writer
, prog
);
152 blob_write_uint32(&writer
, END_PART
);
153 prog
->driver_cache_blob
= ralloc_size(NULL
, writer
.size
);
154 memcpy(prog
->driver_cache_blob
, writer
.data
, writer
.size
);
155 prog
->driver_cache_blob_size
= writer
.size
;
156 blob_finish(&writer
);
160 deserialize_gen_program(struct blob_reader
*reader
, struct gl_context
*ctx
,
161 struct gl_program
*prog
, gl_shader_stage stage
)
163 struct brw_context
*brw
= brw_context(ctx
);
165 union brw_any_prog_key prog_key
;
166 blob_copy_bytes(reader
, &prog_key
, brw_prog_key_size(stage
));
167 prog_key
.base
.program_string_id
= brw_program(prog
)->id
;
169 enum brw_cache_id cache_id
= brw_stage_cache_id(stage
);
171 const uint8_t *program
;
172 struct brw_stage_prog_data
*prog_data
=
173 ralloc_size(NULL
, sizeof(union brw_any_prog_data
));
175 if (!brw_read_blob_program_data(reader
, prog
, stage
, &program
, prog_data
)) {
176 ralloc_free(prog_data
);
182 brw_upload_cache(&brw
->cache
, cache_id
, &prog_key
, brw_prog_key_size(stage
),
183 program
, prog_data
->program_size
, prog_data
,
184 brw_prog_data_size(stage
), &offset
, &out_prog_data
);
186 ralloc_free(prog_data
);
192 brw_program_deserialize_driver_blob(struct gl_context
*ctx
,
193 struct gl_program
*prog
,
194 gl_shader_stage stage
)
196 if (!prog
->driver_cache_blob
)
199 struct blob_reader reader
;
200 blob_reader_init(&reader
, prog
->driver_cache_blob
,
201 prog
->driver_cache_blob_size
);
204 uint32_t part_type
= blob_read_uint32(&reader
);
205 if ((enum driver_cache_blob_part
)part_type
== END_PART
)
207 switch ((enum driver_cache_blob_part
)part_type
) {
209 MAYBE_UNUSED
uint32_t gen_size
= blob_read_uint32(&reader
);
210 assert(!reader
.overrun
&&
211 (uintptr_t)(reader
.end
- reader
.current
) > gen_size
);
212 deserialize_gen_program(&reader
, ctx
, prog
, stage
);
216 MAYBE_UNUSED
uint32_t nir_size
= blob_read_uint32(&reader
);
217 assert(!reader
.overrun
&&
218 (uintptr_t)(reader
.end
- reader
.current
) > nir_size
);
219 const struct nir_shader_compiler_options
*options
=
220 ctx
->Const
.ShaderCompilerOptions
[stage
].NirOptions
;
221 prog
->nir
= nir_deserialize(NULL
, options
, &reader
);
225 unreachable("Unsupported blob part type!");
230 ralloc_free(prog
->driver_cache_blob
);
231 prog
->driver_cache_blob
= NULL
;
232 prog
->driver_cache_blob_size
= 0;
235 /* This is just a wrapper around brw_program_deserialize_nir() as i965
236 * doesn't need gl_shader_program like other drivers do.
239 brw_deserialize_program_binary(struct gl_context
*ctx
,
240 struct gl_shader_program
*shProg
,
241 struct gl_program
*prog
)
243 brw_program_deserialize_driver_blob(ctx
, prog
, prog
->info
.stage
);
247 serialize_gen_part(struct blob
*writer
, struct gl_context
*ctx
,
248 struct gl_shader_program
*sh_prog
,
249 struct gl_program
*prog
)
251 struct brw_context
*brw
= brw_context(ctx
);
253 union brw_any_prog_key key
;
254 brw_populate_default_key(brw
->screen
->compiler
, &key
, sh_prog
, prog
);
256 const gl_shader_stage stage
= prog
->info
.stage
;
258 void *prog_data
= NULL
;
259 if (brw_search_cache(&brw
->cache
, brw_stage_cache_id(stage
), &key
,
260 brw_prog_key_size(stage
), &offset
, &prog_data
,
262 const void *program_map
= brw
->cache
.map
+ offset
;
263 /* TODO: Improve perf for non-LLC. It would be best to save it at
264 * program generation time when the program is in normal memory
265 * accessible with cache to the CPU. Another easier change would be to
266 * use _mesa_streaming_load_memcpy to read from the program mapped
269 blob_write_uint32(writer
, GEN_PART
);
270 intptr_t size_offset
= blob_reserve_uint32(writer
);
271 size_t gen_start
= writer
->size
;
272 blob_write_bytes(writer
, &key
, brw_prog_key_size(stage
));
273 brw_write_blob_program_data(writer
, stage
, program_map
, prog_data
);
274 blob_overwrite_uint32(writer
, size_offset
, writer
->size
- gen_start
);
279 brw_serialize_program_binary(struct gl_context
*ctx
,
280 struct gl_shader_program
*sh_prog
,
281 struct gl_program
*prog
)
283 if (driver_blob_is_ready(prog
->driver_cache_blob
,
284 prog
->driver_cache_blob_size
, true))
287 if (prog
->driver_cache_blob
) {
289 /* If we loaded from the disk shader cache, then the nir might not
290 * have been deserialized yet.
292 brw_program_deserialize_driver_blob(ctx
, prog
, prog
->info
.stage
);
294 ralloc_free(prog
->driver_cache_blob
);
299 serialize_nir_part(&writer
, prog
);
300 serialize_gen_part(&writer
, ctx
, sh_prog
, prog
);
301 blob_write_uint32(&writer
, END_PART
);
302 prog
->driver_cache_blob
= ralloc_size(NULL
, writer
.size
);
303 memcpy(prog
->driver_cache_blob
, writer
.data
, writer
.size
);
304 prog
->driver_cache_blob_size
= writer
.size
;
305 blob_finish(&writer
);
309 brw_write_blob_program_data(struct blob
*binary
, gl_shader_stage stage
,
311 struct brw_stage_prog_data
*prog_data
)
313 /* Write prog_data to blob. */
314 blob_write_bytes(binary
, prog_data
, brw_prog_data_size(stage
));
316 /* Write program to blob. */
317 blob_write_bytes(binary
, program
, prog_data
->program_size
);
319 /* Write push params */
320 blob_write_bytes(binary
, prog_data
->param
,
321 sizeof(uint32_t) * prog_data
->nr_params
);
323 /* Write pull params */
324 blob_write_bytes(binary
, prog_data
->pull_param
,
325 sizeof(uint32_t) * prog_data
->nr_pull_params
);
329 brw_read_blob_program_data(struct blob_reader
*binary
, struct gl_program
*prog
,
330 gl_shader_stage stage
, const uint8_t **program
,
331 struct brw_stage_prog_data
*prog_data
)
333 /* Read shader prog_data from blob. */
334 blob_copy_bytes(binary
, prog_data
, brw_prog_data_size(stage
));
338 /* Read shader program from blob. */
339 *program
= blob_read_bytes(binary
, prog_data
->program_size
);
341 /* Read push params */
342 prog_data
->param
= rzalloc_array(NULL
, uint32_t, prog_data
->nr_params
);
343 blob_copy_bytes(binary
, prog_data
->param
,
344 sizeof(uint32_t) * prog_data
->nr_params
);
346 /* Read pull params */
347 prog_data
->pull_param
= rzalloc_array(NULL
, uint32_t,
348 prog_data
->nr_pull_params
);
349 blob_copy_bytes(binary
, prog_data
->pull_param
,
350 sizeof(uint32_t) * prog_data
->nr_pull_params
);
352 return !binary
->overrun
;