1 /*
2 * Copyright (c) 2017 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 (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 <stdint.h>
25
26 #include "compiler/nir/nir_serialize.h"
27 #include "util/build_id.h"
28 #include "util/mesa-sha1.h"
29
30 #include "brw_context.h"
31 #include "brw_program.h"
32 #include "brw_state.h"
33
34 static uint8_t driver_sha1[20];
35
36 void
brw_program_binary_init(unsigned device_id)37 brw_program_binary_init(unsigned device_id)
38 {
39 const struct build_id_note *note =
40 build_id_find_nhdr_for_addr(brw_program_binary_init);
41 assert(note);
42
43 /**
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.
47 */
48 struct mesa_sha1 ctx;
49 _mesa_sha1_init(&ctx);
50 char renderer[10];
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);
57 }
58
59 void
brw_get_program_binary_driver_sha1(struct gl_context * ctx,uint8_t * sha1)60 brw_get_program_binary_driver_sha1(struct gl_context *ctx, uint8_t *sha1)
61 {
62 memcpy(sha1, driver_sha1, sizeof(uint8_t) * 20);
63 }
64
65 enum driver_cache_blob_part {
66 END_PART,
67 GEN_PART,
68 NIR_PART,
69 };
70
71 static bool
blob_parts_valid(void * blob,uint32_t size)72 blob_parts_valid(void *blob, uint32_t size)
73 {
74 struct blob_reader reader;
75 blob_reader_init(&reader, blob, size);
76
77 do {
78 uint32_t part_type = blob_read_uint32(&reader);
79 if (reader.overrun)
80 return false;
81 if (part_type == END_PART)
82 return reader.current == reader.end;
83 switch ((enum driver_cache_blob_part)part_type) {
84 case GEN_PART:
85 case NIR_PART:
86 /* Read the uint32_t part-size and skip over it */
87 blob_skip_bytes(&reader, blob_read_uint32(&reader));
88 if (reader.overrun)
89 return false;
90 break;
91 default:
92 return false;
93 }
94 } while (true);
95 }
96
97 static bool
blob_has_part(void * blob,uint32_t size,enum driver_cache_blob_part part)98 blob_has_part(void *blob, uint32_t size, enum driver_cache_blob_part part)
99 {
100 struct blob_reader reader;
101 blob_reader_init(&reader, blob, size);
102
103 assert(blob_parts_valid(blob, size));
104 do {
105 uint32_t part_type = blob_read_uint32(&reader);
106 if (part_type == END_PART)
107 return false;
108 if (part_type == part)
109 return true;
110 blob_skip_bytes(&reader, blob_read_uint32(&reader));
111 } while (true);
112 }
113
114 static bool
driver_blob_is_ready(void * blob,uint32_t size,bool with_gen_program)115 driver_blob_is_ready(void *blob, uint32_t size, bool with_gen_program)
116 {
117 if (!blob) {
118 return false;
119 } else if (!blob_parts_valid(blob, size)) {
120 unreachable("Driver blob format is bad!");
121 return false;
122 } else if (blob_has_part(blob, size, GEN_PART) == with_gen_program) {
123 return true;
124 } else {
125 return false;
126 }
127 }
128
129 static void
serialize_nir_part(struct blob * writer,struct gl_program * prog)130 serialize_nir_part(struct blob *writer, struct gl_program *prog)
131 {
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, false);
136 blob_overwrite_uint32(writer, size_offset, writer->size - nir_start);
137 }
138
139 void
brw_program_serialize_nir(struct gl_context * ctx,struct gl_program * prog)140 brw_program_serialize_nir(struct gl_context *ctx, struct gl_program *prog)
141 {
142 if (driver_blob_is_ready(prog->driver_cache_blob,
143 prog->driver_cache_blob_size, false))
144 return;
145
146 if (prog->driver_cache_blob)
147 ralloc_free(prog->driver_cache_blob);
148
149 struct blob writer;
150 blob_init(&writer);
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);
157 }
158
159 static bool
deserialize_gen_program(struct blob_reader * reader,struct gl_context * ctx,struct gl_program * prog,gl_shader_stage stage)160 deserialize_gen_program(struct blob_reader *reader, struct gl_context *ctx,
161 struct gl_program *prog, gl_shader_stage stage)
162 {
163 struct brw_context *brw = brw_context(ctx);
164
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;
168
169 enum brw_cache_id cache_id = brw_stage_cache_id(stage);
170
171 const uint8_t *program;
172 struct brw_stage_prog_data *prog_data =
173 ralloc_size(NULL, sizeof(union brw_any_prog_data));
174
175 if (!brw_read_blob_program_data(reader, prog, stage, &program, prog_data)) {
176 ralloc_free(prog_data);
177 return false;
178 }
179
180 uint32_t offset;
181 void *out_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);
185
186 ralloc_free(prog_data);
187
188 return true;
189 }
190
191 void
brw_program_deserialize_driver_blob(struct gl_context * ctx,struct gl_program * prog,gl_shader_stage stage)192 brw_program_deserialize_driver_blob(struct gl_context *ctx,
193 struct gl_program *prog,
194 gl_shader_stage stage)
195 {
196 if (!prog->driver_cache_blob)
197 return;
198
199 struct blob_reader reader;
200 blob_reader_init(&reader, prog->driver_cache_blob,
201 prog->driver_cache_blob_size);
202
203 do {
204 uint32_t part_type = blob_read_uint32(&reader);
205 if ((enum driver_cache_blob_part)part_type == END_PART)
206 break;
207 switch ((enum driver_cache_blob_part)part_type) {
208 case GEN_PART: {
209 ASSERTED 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);
213 break;
214 }
215 case NIR_PART: {
216 ASSERTED 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);
222 break;
223 }
224 default:
225 unreachable("Unsupported blob part type!");
226 break;
227 }
228 } while (true);
229
230 ralloc_free(prog->driver_cache_blob);
231 prog->driver_cache_blob = NULL;
232 prog->driver_cache_blob_size = 0;
233 }
234
235 /* This is just a wrapper around brw_program_deserialize_nir() as i965
236 * doesn't need gl_shader_program like other drivers do.
237 */
238 void
brw_deserialize_program_binary(struct gl_context * ctx,struct gl_shader_program * shProg,struct gl_program * prog)239 brw_deserialize_program_binary(struct gl_context *ctx,
240 struct gl_shader_program *shProg,
241 struct gl_program *prog)
242 {
243 brw_program_deserialize_driver_blob(ctx, prog, prog->info.stage);
244 }
245
246 static void
serialize_gen_part(struct blob * writer,struct gl_context * ctx,struct gl_shader_program * sh_prog,struct gl_program * prog)247 serialize_gen_part(struct blob *writer, struct gl_context *ctx,
248 struct gl_shader_program *sh_prog,
249 struct gl_program *prog)
250 {
251 struct brw_context *brw = brw_context(ctx);
252
253 union brw_any_prog_key key;
254 brw_populate_default_key(brw->screen->compiler, &key, sh_prog, prog);
255
256 const gl_shader_stage stage = prog->info.stage;
257 uint32_t offset = 0;
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,
261 false)) {
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
267 * memory.
268 */
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);
275 }
276 }
277
278 void
brw_serialize_program_binary(struct gl_context * ctx,struct gl_shader_program * sh_prog,struct gl_program * prog)279 brw_serialize_program_binary(struct gl_context *ctx,
280 struct gl_shader_program *sh_prog,
281 struct gl_program *prog)
282 {
283 if (driver_blob_is_ready(prog->driver_cache_blob,
284 prog->driver_cache_blob_size, true))
285 return;
286
287 if (prog->driver_cache_blob) {
288 if (!prog->nir) {
289 /* If we loaded from the disk shader cache, then the nir might not
290 * have been deserialized yet.
291 */
292 brw_program_deserialize_driver_blob(ctx, prog, prog->info.stage);
293 }
294 ralloc_free(prog->driver_cache_blob);
295 }
296
297 struct blob writer;
298 blob_init(&writer);
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);
306 }
307
308 void
brw_write_blob_program_data(struct blob * binary,gl_shader_stage stage,const void * program,struct brw_stage_prog_data * prog_data)309 brw_write_blob_program_data(struct blob *binary, gl_shader_stage stage,
310 const void *program,
311 struct brw_stage_prog_data *prog_data)
312 {
313 /* Write prog_data to blob. */
314 blob_write_bytes(binary, prog_data, brw_prog_data_size(stage));
315
316 /* Write program to blob. */
317 blob_write_bytes(binary, program, prog_data->program_size);
318
319 /* Write push params */
320 blob_write_bytes(binary, prog_data->param,
321 sizeof(uint32_t) * prog_data->nr_params);
322
323 /* Write pull params */
324 blob_write_bytes(binary, prog_data->pull_param,
325 sizeof(uint32_t) * prog_data->nr_pull_params);
326 }
327
328 bool
brw_read_blob_program_data(struct blob_reader * binary,struct gl_program * prog,gl_shader_stage stage,const uint8_t ** program,struct brw_stage_prog_data * prog_data)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)
332 {
333 /* Read shader prog_data from blob. */
334 blob_copy_bytes(binary, prog_data, brw_prog_data_size(stage));
335 if (binary->overrun)
336 return false;
337
338 /* Read shader program from blob. */
339 *program = blob_read_bytes(binary, prog_data->program_size);
340
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);
345
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);
351
352 return !binary->overrun;
353 }
354