i965: Add support for driver cache blob containing the gen program
[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 void
72 brw_program_serialize_nir(struct gl_context *ctx, struct gl_program *prog)
73 {
74 if (prog->driver_cache_blob)
75 return;
76
77 struct blob writer;
78 blob_init(&writer);
79 blob_write_uint32(&writer, NIR_PART);
80 intptr_t size_offset = blob_reserve_uint32(&writer);
81 size_t nir_start = writer.size;
82 nir_serialize(&writer, prog->nir);
83 blob_overwrite_uint32(&writer, size_offset, writer.size - nir_start);
84 blob_write_uint32(&writer, END_PART);
85 prog->driver_cache_blob = ralloc_size(NULL, writer.size);
86 memcpy(prog->driver_cache_blob, writer.data, writer.size);
87 prog->driver_cache_blob_size = writer.size;
88 blob_finish(&writer);
89 }
90
91 static bool
92 deserialize_gen_program(struct blob_reader *reader, struct gl_context *ctx,
93 struct gl_program *prog, gl_shader_stage stage)
94 {
95 struct brw_context *brw = brw_context(ctx);
96
97 union brw_any_prog_key prog_key;
98 blob_copy_bytes(reader, &prog_key, brw_prog_key_size(stage));
99 brw_prog_key_set_id(&prog_key, stage, brw_program(prog)->id);
100
101 enum brw_cache_id cache_id = brw_stage_cache_id(stage);
102
103 const uint8_t *program;
104 struct brw_stage_prog_data *prog_data =
105 ralloc_size(NULL, sizeof(union brw_any_prog_data));
106
107 if (!brw_read_blob_program_data(reader, prog, stage, &program, prog_data)) {
108 ralloc_free(prog_data);
109 return false;
110 }
111
112 uint32_t offset;
113 void *out_prog_data;
114 brw_upload_cache(&brw->cache, cache_id, &prog_key, brw_prog_key_size(stage),
115 program, prog_data->program_size, prog_data,
116 brw_prog_data_size(stage), &offset, &out_prog_data);
117
118 ralloc_free(prog_data);
119
120 return true;
121 }
122
123 void
124 brw_program_deserialize_driver_blob(struct gl_context *ctx,
125 struct gl_program *prog,
126 gl_shader_stage stage)
127 {
128 if (!prog->driver_cache_blob)
129 return;
130
131 struct blob_reader reader;
132 blob_reader_init(&reader, prog->driver_cache_blob,
133 prog->driver_cache_blob_size);
134
135 do {
136 uint32_t part_type = blob_read_uint32(&reader);
137 if ((enum driver_cache_blob_part)part_type == END_PART)
138 break;
139 switch ((enum driver_cache_blob_part)part_type) {
140 case GEN_PART: {
141 uint32_t gen_size = blob_read_uint32(&reader);
142 assert(!reader.overrun &&
143 (uintptr_t)(reader.end - reader.current) > gen_size);
144 deserialize_gen_program(&reader, ctx, prog, stage);
145 break;
146 }
147 case NIR_PART: {
148 uint32_t nir_size = blob_read_uint32(&reader);
149 assert(!reader.overrun &&
150 (uintptr_t)(reader.end - reader.current) > nir_size);
151 const struct nir_shader_compiler_options *options =
152 ctx->Const.ShaderCompilerOptions[stage].NirOptions;
153 prog->nir = nir_deserialize(NULL, options, &reader);
154 break;
155 }
156 default:
157 unreachable("Unsupported blob part type!");
158 break;
159 }
160 } while (true);
161
162 ralloc_free(prog->driver_cache_blob);
163 prog->driver_cache_blob = NULL;
164 prog->driver_cache_blob_size = 0;
165 }
166
167 /* This is just a wrapper around brw_program_deserialize_nir() as i965
168 * doesn't need gl_shader_program like other drivers do.
169 */
170 void
171 brw_deserialize_program_binary(struct gl_context *ctx,
172 struct gl_shader_program *shProg,
173 struct gl_program *prog)
174 {
175 brw_program_deserialize_driver_blob(ctx, prog, prog->info.stage);
176 }
177
178 void
179 brw_write_blob_program_data(struct blob *binary, gl_shader_stage stage,
180 const void *program,
181 struct brw_stage_prog_data *prog_data)
182 {
183 /* Write prog_data to blob. */
184 blob_write_bytes(binary, prog_data, brw_prog_data_size(stage));
185
186 /* Write program to blob. */
187 blob_write_bytes(binary, program, prog_data->program_size);
188
189 /* Write push params */
190 blob_write_bytes(binary, prog_data->param,
191 sizeof(uint32_t) * prog_data->nr_params);
192
193 /* Write pull params */
194 blob_write_bytes(binary, prog_data->pull_param,
195 sizeof(uint32_t) * prog_data->nr_pull_params);
196 }
197
198 bool
199 brw_read_blob_program_data(struct blob_reader *binary, struct gl_program *prog,
200 gl_shader_stage stage, const uint8_t **program,
201 struct brw_stage_prog_data *prog_data)
202 {
203 /* Read shader prog_data from blob. */
204 blob_copy_bytes(binary, prog_data, brw_prog_data_size(stage));
205 if (binary->overrun)
206 return false;
207
208 /* Read shader program from blob. */
209 *program = blob_read_bytes(binary, prog_data->program_size);
210
211 /* Read push params */
212 prog_data->param = rzalloc_array(NULL, uint32_t, prog_data->nr_params);
213 blob_copy_bytes(binary, prog_data->param,
214 sizeof(uint32_t) * prog_data->nr_params);
215
216 /* Read pull params */
217 prog_data->pull_param = rzalloc_array(NULL, uint32_t,
218 prog_data->nr_pull_params);
219 blob_copy_bytes(binary, prog_data->pull_param,
220 sizeof(uint32_t) * prog_data->nr_pull_params);
221
222 return !binary->overrun;
223 }