mesa: Add gl_shader_program param to ProgramBinarySerializeDriverBlob
[mesa.git] / src / mesa / drivers / dri / i965 / brw_program_binary.c
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
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
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
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
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
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 void
130 brw_program_serialize_nir(struct gl_context *ctx, struct gl_program *prog)
131 {
132 if (driver_blob_is_ready(prog->driver_cache_blob,
133 prog->driver_cache_blob_size, false))
134 return;
135
136 if (prog->driver_cache_blob)
137 ralloc_free(prog->driver_cache_blob);
138
139 struct blob writer;
140 blob_init(&writer);
141 blob_write_uint32(&writer, NIR_PART);
142 intptr_t size_offset = blob_reserve_uint32(&writer);
143 size_t nir_start = writer.size;
144 nir_serialize(&writer, prog->nir);
145 blob_overwrite_uint32(&writer, size_offset, writer.size - nir_start);
146 blob_write_uint32(&writer, END_PART);
147 prog->driver_cache_blob = ralloc_size(NULL, writer.size);
148 memcpy(prog->driver_cache_blob, writer.data, writer.size);
149 prog->driver_cache_blob_size = writer.size;
150 blob_finish(&writer);
151 }
152
153 static bool
154 deserialize_gen_program(struct blob_reader *reader, struct gl_context *ctx,
155 struct gl_program *prog, gl_shader_stage stage)
156 {
157 struct brw_context *brw = brw_context(ctx);
158
159 union brw_any_prog_key prog_key;
160 blob_copy_bytes(reader, &prog_key, brw_prog_key_size(stage));
161 brw_prog_key_set_id(&prog_key, stage, brw_program(prog)->id);
162
163 enum brw_cache_id cache_id = brw_stage_cache_id(stage);
164
165 const uint8_t *program;
166 struct brw_stage_prog_data *prog_data =
167 ralloc_size(NULL, sizeof(union brw_any_prog_data));
168
169 if (!brw_read_blob_program_data(reader, prog, stage, &program, prog_data)) {
170 ralloc_free(prog_data);
171 return false;
172 }
173
174 uint32_t offset;
175 void *out_prog_data;
176 brw_upload_cache(&brw->cache, cache_id, &prog_key, brw_prog_key_size(stage),
177 program, prog_data->program_size, prog_data,
178 brw_prog_data_size(stage), &offset, &out_prog_data);
179
180 ralloc_free(prog_data);
181
182 return true;
183 }
184
185 void
186 brw_program_deserialize_driver_blob(struct gl_context *ctx,
187 struct gl_program *prog,
188 gl_shader_stage stage)
189 {
190 if (!prog->driver_cache_blob)
191 return;
192
193 struct blob_reader reader;
194 blob_reader_init(&reader, prog->driver_cache_blob,
195 prog->driver_cache_blob_size);
196
197 do {
198 uint32_t part_type = blob_read_uint32(&reader);
199 if ((enum driver_cache_blob_part)part_type == END_PART)
200 break;
201 switch ((enum driver_cache_blob_part)part_type) {
202 case GEN_PART: {
203 uint32_t gen_size = blob_read_uint32(&reader);
204 assert(!reader.overrun &&
205 (uintptr_t)(reader.end - reader.current) > gen_size);
206 deserialize_gen_program(&reader, ctx, prog, stage);
207 break;
208 }
209 case NIR_PART: {
210 uint32_t nir_size = blob_read_uint32(&reader);
211 assert(!reader.overrun &&
212 (uintptr_t)(reader.end - reader.current) > nir_size);
213 const struct nir_shader_compiler_options *options =
214 ctx->Const.ShaderCompilerOptions[stage].NirOptions;
215 prog->nir = nir_deserialize(NULL, options, &reader);
216 break;
217 }
218 default:
219 unreachable("Unsupported blob part type!");
220 break;
221 }
222 } while (true);
223
224 ralloc_free(prog->driver_cache_blob);
225 prog->driver_cache_blob = NULL;
226 prog->driver_cache_blob_size = 0;
227 }
228
229 /* This is just a wrapper around brw_program_deserialize_nir() as i965
230 * doesn't need gl_shader_program like other drivers do.
231 */
232 void
233 brw_deserialize_program_binary(struct gl_context *ctx,
234 struct gl_shader_program *shProg,
235 struct gl_program *prog)
236 {
237 brw_program_deserialize_driver_blob(ctx, prog, prog->info.stage);
238 }
239
240 void
241 brw_serialize_program_binary(struct gl_context *ctx,
242 struct gl_shader_program *sh_prog,
243 struct gl_program *prog)
244 {
245 brw_program_serialize_nir(ctx, prog);
246 }
247
248 void
249 brw_write_blob_program_data(struct blob *binary, gl_shader_stage stage,
250 const void *program,
251 struct brw_stage_prog_data *prog_data)
252 {
253 /* Write prog_data to blob. */
254 blob_write_bytes(binary, prog_data, brw_prog_data_size(stage));
255
256 /* Write program to blob. */
257 blob_write_bytes(binary, program, prog_data->program_size);
258
259 /* Write push params */
260 blob_write_bytes(binary, prog_data->param,
261 sizeof(uint32_t) * prog_data->nr_params);
262
263 /* Write pull params */
264 blob_write_bytes(binary, prog_data->pull_param,
265 sizeof(uint32_t) * prog_data->nr_pull_params);
266 }
267
268 bool
269 brw_read_blob_program_data(struct blob_reader *binary, struct gl_program *prog,
270 gl_shader_stage stage, const uint8_t **program,
271 struct brw_stage_prog_data *prog_data)
272 {
273 /* Read shader prog_data from blob. */
274 blob_copy_bytes(binary, prog_data, brw_prog_data_size(stage));
275 if (binary->overrun)
276 return false;
277
278 /* Read shader program from blob. */
279 *program = blob_read_bytes(binary, prog_data->program_size);
280
281 /* Read push params */
282 prog_data->param = rzalloc_array(NULL, uint32_t, prog_data->nr_params);
283 blob_copy_bytes(binary, prog_data->param,
284 sizeof(uint32_t) * prog_data->nr_params);
285
286 /* Read pull params */
287 prog_data->pull_param = rzalloc_array(NULL, uint32_t,
288 prog_data->nr_pull_params);
289 blob_copy_bytes(binary, prog_data->pull_param,
290 sizeof(uint32_t) * prog_data->nr_pull_params);
291
292 return !binary->overrun;
293 }