1 /*
2 * Copyright © Microsoft 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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "nir.h"
25 #include "nir_clc_helpers.h"
26 #include "nir_serialize.h"
27 #include "glsl_types.h"
28 #include "clc_compiler.h"
29 #include "clc_helpers.h"
30 #include "clc_nir.h"
31 #include "../compiler/dxil_nir.h"
32 #include "../compiler/dxil_nir_lower_int_samplers.h"
33 #include "../compiler/nir_to_dxil.h"
34
35 #include "util/u_debug.h"
36 #include <util/u_math.h>
37 #include "spirv/nir_spirv.h"
38 #include "nir_builder.h"
39 #include "nir_builtin_builder.h"
40
41 #include "git_sha1.h"
42
43 struct clc_image_lower_context
44 {
45 struct clc_dxil_metadata *metadata;
46 unsigned *num_srvs;
47 unsigned *num_uavs;
48 nir_deref_instr *deref;
49 unsigned num_buf_ids;
50 int metadata_index;
51 };
52
53 static int
lower_image_deref_impl(nir_builder * b,struct clc_image_lower_context * context,const struct glsl_type * new_var_type,nir_variable_mode var_mode,unsigned * num_bindings)54 lower_image_deref_impl(nir_builder *b, struct clc_image_lower_context *context,
55 const struct glsl_type *new_var_type,
56 nir_variable_mode var_mode,
57 unsigned *num_bindings)
58 {
59 nir_variable *in_var = nir_deref_instr_get_variable(context->deref);
60 nir_foreach_variable_with_modes(var, b->shader, var_mode) {
61 // Check if we've already created a variable for this image
62 if (var->data.driver_location == in_var->data.driver_location &&
63 var->type == new_var_type)
64 return var->data.binding;
65 }
66 nir_variable *image = nir_variable_create(b->shader, var_mode, new_var_type, NULL);
67 image->data.access = in_var->data.access;
68 image->data.binding = in_var->data.binding;
69 image->data.driver_location = in_var->data.driver_location;
70 if (context->num_buf_ids > 0) {
71 // Need to assign a new binding
72 context->metadata->args[context->metadata_index].
73 image.buf_ids[context->num_buf_ids] = image->data.binding = (*num_bindings)++;
74 }
75 context->num_buf_ids++;
76 return image->data.binding;
77 }
78
79 static int
lower_read_only_image_deref(nir_builder * b,struct clc_image_lower_context * context,nir_alu_type image_type)80 lower_read_only_image_deref(nir_builder *b, struct clc_image_lower_context *context,
81 nir_alu_type image_type)
82 {
83 nir_variable *in_var = nir_deref_instr_get_variable(context->deref);
84
85 // Non-writeable images should be converted to samplers,
86 // since they may have texture operations done on them
87 const struct glsl_type *new_var_type =
88 glsl_texture_type(glsl_get_sampler_dim(in_var->type),
89 glsl_sampler_type_is_array(in_var->type),
90 nir_get_glsl_base_type_for_nir_type(image_type | 32));
91 return lower_image_deref_impl(b, context, new_var_type, nir_var_uniform, context->num_srvs);
92 }
93
94 static int
lower_read_write_image_deref(nir_builder * b,struct clc_image_lower_context * context,nir_alu_type image_type)95 lower_read_write_image_deref(nir_builder *b, struct clc_image_lower_context *context,
96 nir_alu_type image_type)
97 {
98 nir_variable *in_var = nir_deref_instr_get_variable(context->deref);
99 const struct glsl_type *new_var_type =
100 glsl_image_type(glsl_get_sampler_dim(in_var->type),
101 glsl_sampler_type_is_array(in_var->type),
102 nir_get_glsl_base_type_for_nir_type(image_type | 32));
103 return lower_image_deref_impl(b, context, new_var_type, nir_var_image, context->num_uavs);
104 }
105
106 static void
clc_lower_input_image_deref(nir_builder * b,struct clc_image_lower_context * context)107 clc_lower_input_image_deref(nir_builder *b, struct clc_image_lower_context *context)
108 {
109 // The input variable here isn't actually an image, it's just the
110 // image format data.
111 //
112 // For every use of an image in a different way, we'll add an
113 // appropriate image to match it. That can result in up to
114 // 3 images (float4, int4, uint4) for each image. Only one of these
115 // formats will actually produce correct data, but a single kernel
116 // could use runtime conditionals to potentially access any of them.
117 //
118 // If the image is used in a query that doesn't have a corresponding
119 // DXIL intrinsic (CL image channel order or channel format), then
120 // we'll add a kernel input for that data that'll be lowered by the
121 // explicit IO pass later on.
122 //
123 // After all that, we can remove the image input variable and deref.
124
125 enum image_type {
126 FLOAT4,
127 INT4,
128 UINT4,
129 IMAGE_TYPE_COUNT
130 };
131
132 int image_bindings[IMAGE_TYPE_COUNT] = {-1, -1, -1};
133 nir_def *format_deref_dest = NULL, *order_deref_dest = NULL;
134
135 nir_variable *in_var = nir_deref_instr_get_variable(context->deref);
136
137 context->metadata_index = 0;
138 while (context->metadata->args[context->metadata_index].offset != in_var->data.driver_location)
139 context->metadata_index++;
140
141 context->num_buf_ids = context->metadata->args[context->metadata_index].image.num_buf_ids;
142
143 /* Do this in 2 passes:
144 * 1. When encountering a strongly-typed access (load/store), replace the deref
145 * with one that references an appropriately typed variable. When encountering
146 * an untyped access (size query), if we have a strongly-typed variable already,
147 * replace the deref to point to it.
148 * 2. If there's any references left, they should all be untyped. If we found
149 * a strongly-typed access later in the 1st pass, then just replace the reference.
150 * If we didn't, e.g. the resource is only used for a size query, then pick an
151 * arbitrary type for it.
152 */
153 for (int pass = 0; pass < 2; ++pass) {
154 nir_foreach_use_safe(src, &context->deref->def) {
155 enum image_type type;
156
157 if (nir_src_parent_instr(src)->type == nir_instr_type_intrinsic) {
158 nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(nir_src_parent_instr(src));
159 nir_alu_type dest_type;
160
161 b->cursor = nir_before_instr(&intrinsic->instr);
162
163 switch (intrinsic->intrinsic) {
164 case nir_intrinsic_image_deref_load:
165 case nir_intrinsic_image_deref_store: {
166 dest_type = intrinsic->intrinsic == nir_intrinsic_image_deref_load ?
167 nir_intrinsic_dest_type(intrinsic) : nir_intrinsic_src_type(intrinsic);
168
169 switch (nir_alu_type_get_base_type(dest_type)) {
170 case nir_type_float: type = FLOAT4; break;
171 case nir_type_int: type = INT4; break;
172 case nir_type_uint: type = UINT4; break;
173 default: unreachable("Unsupported image type for load.");
174 }
175
176 int image_binding = image_bindings[type];
177 if (image_binding < 0) {
178 image_binding = image_bindings[type] =
179 lower_read_write_image_deref(b, context, dest_type);
180 }
181
182 assert((in_var->data.access & ACCESS_NON_WRITEABLE) == 0);
183 nir_rewrite_image_intrinsic(intrinsic, nir_imm_int(b, image_binding), false);
184 break;
185 }
186
187 case nir_intrinsic_image_deref_size: {
188 int image_binding = -1;
189 for (unsigned i = 0; i < IMAGE_TYPE_COUNT; ++i) {
190 if (image_bindings[i] >= 0) {
191 image_binding = image_bindings[i];
192 break;
193 }
194 }
195 if (image_binding < 0) {
196 // Skip for now and come back to it
197 if (pass == 0)
198 break;
199
200 type = FLOAT4;
201 image_binding = image_bindings[type] =
202 lower_read_write_image_deref(b, context, nir_type_float32);
203 }
204
205 assert((in_var->data.access & ACCESS_NON_WRITEABLE) == 0);
206 nir_rewrite_image_intrinsic(intrinsic, nir_imm_int(b, image_binding), false);
207 break;
208 }
209
210 case nir_intrinsic_image_deref_format:
211 case nir_intrinsic_image_deref_order: {
212 nir_def **cached_deref = intrinsic->intrinsic == nir_intrinsic_image_deref_format ?
213 &format_deref_dest : &order_deref_dest;
214 if (!*cached_deref) {
215 unsigned driver_location = in_var->data.driver_location;
216 if (intrinsic->intrinsic == nir_intrinsic_image_deref_format) {
217 /* Match cl_image_format { image_channel_order, image_channel_data_type }; */
218 driver_location += 4;
219 }
220
221 nir_variable *new_input = NULL;
222 nir_foreach_variable_with_modes(var, b->shader, nir_var_uniform) {
223 if (var->data.driver_location == driver_location &&
224 var->type == glsl_uint_type()) {
225 new_input = var;
226 break;
227 }
228 }
229 if (!new_input) {
230 new_input = nir_variable_create(b->shader, nir_var_uniform, glsl_uint_type(), NULL);
231 new_input->data.driver_location = driver_location;
232 }
233
234 b->cursor = nir_after_instr(&context->deref->instr);
235 *cached_deref = nir_load_var(b, new_input);
236 }
237
238 /* No actual intrinsic needed here, just reference the loaded variable */
239 nir_def_rewrite_uses(&intrinsic->def, *cached_deref);
240 nir_instr_remove(&intrinsic->instr);
241 break;
242 }
243
244 default:
245 unreachable("Unsupported image intrinsic");
246 }
247 } else if (nir_src_parent_instr(src)->type == nir_instr_type_tex) {
248 assert(in_var->data.access & ACCESS_NON_WRITEABLE);
249 nir_tex_instr *tex = nir_instr_as_tex(nir_src_parent_instr(src));
250
251 switch (nir_alu_type_get_base_type(tex->dest_type)) {
252 case nir_type_float: type = FLOAT4; break;
253 case nir_type_int: type = INT4; break;
254 case nir_type_uint: type = UINT4; break;
255 default: unreachable("Unsupported image format for sample.");
256 }
257
258 int image_binding = image_bindings[type];
259 if (image_binding < 0) {
260 image_binding = image_bindings[type] =
261 lower_read_only_image_deref(b, context, tex->dest_type);
262 }
263
264 nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_texture_deref));
265 tex->texture_index = image_binding;
266 }
267 }
268 }
269
270 context->metadata->args[context->metadata_index].image.num_buf_ids = context->num_buf_ids;
271
272 nir_instr_remove(&context->deref->instr);
273 }
274
275 static void
clc_lower_images(nir_shader * nir,struct clc_image_lower_context * context)276 clc_lower_images(nir_shader *nir, struct clc_image_lower_context *context)
277 {
278 nir_foreach_function(func, nir) {
279 if (!func->is_entrypoint)
280 continue;
281 assert(func->impl);
282
283 nir_builder b = nir_builder_create(func->impl);
284
285 nir_foreach_block(block, func->impl) {
286 nir_foreach_instr_safe(instr, block) {
287 if (instr->type == nir_instr_type_deref) {
288 context->deref = nir_instr_as_deref(instr);
289
290 if (glsl_type_is_image(context->deref->type)) {
291 assert(context->deref->deref_type == nir_deref_type_var);
292 clc_lower_input_image_deref(&b, context);
293 }
294 }
295 }
296 }
297 }
298
299 nir_foreach_variable_with_modes_safe(var, nir, nir_var_image) {
300 if (glsl_type_is_image(var->type) && glsl_get_sampler_result_type(var->type) == GLSL_TYPE_VOID)
301 exec_node_remove(&var->node);
302 }
303 }
304
305 static void
clc_lower_64bit_semantics(nir_shader * nir)306 clc_lower_64bit_semantics(nir_shader *nir)
307 {
308 nir_foreach_function_impl(impl, nir) {
309 nir_builder b = nir_builder_create(impl);
310
311 nir_foreach_block(block, impl) {
312 nir_foreach_instr_safe(instr, block) {
313 if (instr->type == nir_instr_type_intrinsic) {
314 nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(instr);
315 switch (intrinsic->intrinsic) {
316 case nir_intrinsic_load_global_invocation_id:
317 case nir_intrinsic_load_global_invocation_id_zero_base:
318 case nir_intrinsic_load_base_global_invocation_id:
319 case nir_intrinsic_load_local_invocation_id:
320 case nir_intrinsic_load_workgroup_id:
321 case nir_intrinsic_load_workgroup_id_zero_base:
322 case nir_intrinsic_load_base_workgroup_id:
323 case nir_intrinsic_load_num_workgroups:
324 break;
325 default:
326 continue;
327 }
328
329 if (nir_instr_def(instr)->bit_size != 64)
330 continue;
331
332 intrinsic->def.bit_size = 32;
333 b.cursor = nir_after_instr(instr);
334
335 nir_def *i64 = nir_u2u64(&b, &intrinsic->def);
336 nir_def_rewrite_uses_after(
337 &intrinsic->def,
338 i64,
339 i64->parent_instr);
340 }
341 }
342 }
343 }
344 }
345
346 static void
clc_lower_nonnormalized_samplers(nir_shader * nir,const dxil_wrap_sampler_state * states)347 clc_lower_nonnormalized_samplers(nir_shader *nir,
348 const dxil_wrap_sampler_state *states)
349 {
350 nir_foreach_function(func, nir) {
351 if (!func->is_entrypoint)
352 continue;
353 assert(func->impl);
354
355 nir_builder b = nir_builder_create(func->impl);
356
357 nir_foreach_block(block, func->impl) {
358 nir_foreach_instr_safe(instr, block) {
359 if (instr->type != nir_instr_type_tex)
360 continue;
361 nir_tex_instr *tex = nir_instr_as_tex(instr);
362
363 int sampler_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
364 if (sampler_src_idx == -1)
365 continue;
366
367 nir_src *sampler_src = &tex->src[sampler_src_idx].src;
368 assert(sampler_src->ssa->parent_instr->type == nir_instr_type_deref);
369 nir_variable *sampler = nir_deref_instr_get_variable(
370 nir_instr_as_deref(sampler_src->ssa->parent_instr));
371
372 // If the sampler returns ints, we'll handle this in the int lowering pass
373 if (nir_alu_type_get_base_type(tex->dest_type) != nir_type_float)
374 continue;
375
376 // If sampler uses normalized coords, nothing to do
377 if (!states[sampler->data.binding].is_nonnormalized_coords)
378 continue;
379
380 b.cursor = nir_before_instr(&tex->instr);
381
382 int coords_idx = nir_tex_instr_src_index(tex, nir_tex_src_coord);
383 assert(coords_idx != -1);
384 nir_def *coords =
385 tex->src[coords_idx].src.ssa;
386
387 nir_def *txs = nir_i2f32(&b, nir_get_texture_size(&b, tex));
388
389 // Normalize coords for tex
390 nir_def *scale = nir_frcp(&b, txs);
391 nir_def *comps[4];
392 for (unsigned i = 0; i < coords->num_components; ++i) {
393 comps[i] = nir_channel(&b, coords, i);
394 if (tex->is_array && i == coords->num_components - 1) {
395 // Don't scale the array index, but do clamp it
396 comps[i] = nir_fround_even(&b, comps[i]);
397 comps[i] = nir_fmax(&b, comps[i], nir_imm_float(&b, 0.0f));
398 comps[i] = nir_fmin(&b, comps[i], nir_fadd_imm(&b, nir_channel(&b, txs, i), -1.0f));
399 break;
400 }
401
402 // The CTS is pretty clear that this value has to be floored for nearest sampling
403 // but must not be for linear sampling.
404 if (!states[sampler->data.binding].is_linear_filtering)
405 comps[i] = nir_fadd_imm(&b, nir_ffloor(&b, comps[i]), 0.5f);
406 comps[i] = nir_fmul(&b, comps[i], nir_channel(&b, scale, i));
407 }
408 nir_def *normalized_coords = nir_vec(&b, comps, coords->num_components);
409 nir_src_rewrite(&tex->src[coords_idx].src, normalized_coords);
410 }
411 }
412 }
413 }
414
415 static nir_variable *
add_kernel_inputs_var(struct clc_dxil_object * dxil,nir_shader * nir,unsigned * cbv_id)416 add_kernel_inputs_var(struct clc_dxil_object *dxil, nir_shader *nir,
417 unsigned *cbv_id)
418 {
419 if (!dxil->kernel->num_args)
420 return NULL;
421
422 unsigned size = 0;
423
424 nir_foreach_variable_with_modes(var, nir, nir_var_uniform)
425 size = MAX2(size,
426 var->data.driver_location +
427 glsl_get_cl_size(var->type));
428
429 size = align(size, 4);
430
431 const struct glsl_type *array_type = glsl_array_type(glsl_uint_type(), size / 4, 4);
432 const struct glsl_struct_field field = { array_type, "arr" };
433 nir_variable *var =
434 nir_variable_create(nir, nir_var_mem_ubo,
435 glsl_struct_type(&field, 1, "kernel_inputs", false),
436 "kernel_inputs");
437 var->data.binding = (*cbv_id)++;
438 var->data.how_declared = nir_var_hidden;
439 return var;
440 }
441
442 static nir_variable *
add_work_properties_var(struct clc_dxil_object * dxil,struct nir_shader * nir,unsigned * cbv_id)443 add_work_properties_var(struct clc_dxil_object *dxil,
444 struct nir_shader *nir, unsigned *cbv_id)
445 {
446 const struct glsl_type *array_type =
447 glsl_array_type(glsl_uint_type(),
448 sizeof(struct clc_work_properties_data) / sizeof(unsigned),
449 sizeof(unsigned));
450 const struct glsl_struct_field field = { array_type, "arr" };
451 nir_variable *var =
452 nir_variable_create(nir, nir_var_mem_ubo,
453 glsl_struct_type(&field, 1, "kernel_work_properties", false),
454 "kernel_work_properies");
455 var->data.binding = (*cbv_id)++;
456 var->data.how_declared = nir_var_hidden;
457 return var;
458 }
459
460 static void
clc_lower_constant_to_ssbo(nir_shader * nir,const struct clc_kernel_info * kerninfo,unsigned * uav_id)461 clc_lower_constant_to_ssbo(nir_shader *nir,
462 const struct clc_kernel_info *kerninfo, unsigned *uav_id)
463 {
464 /* Update UBO vars and assign them a binding. */
465 nir_foreach_variable_with_modes(var, nir, nir_var_mem_constant) {
466 var->data.mode = nir_var_mem_ssbo;
467 var->data.binding = (*uav_id)++;
468 }
469
470 /* And finally patch all the derefs referincing the constant
471 * variables/pointers.
472 */
473 nir_foreach_function(func, nir) {
474 if (!func->is_entrypoint)
475 continue;
476
477 assert(func->impl);
478
479 nir_foreach_block(block, func->impl) {
480 nir_foreach_instr(instr, block) {
481 if (instr->type != nir_instr_type_deref)
482 continue;
483
484 nir_deref_instr *deref = nir_instr_as_deref(instr);
485
486 if (deref->modes != nir_var_mem_constant)
487 continue;
488
489 deref->modes = nir_var_mem_ssbo;
490 }
491 }
492 }
493 }
494
495 static void
clc_change_variable_mode(nir_shader * nir,nir_variable_mode from,nir_variable_mode to)496 clc_change_variable_mode(nir_shader *nir, nir_variable_mode from, nir_variable_mode to)
497 {
498 nir_foreach_variable_with_modes(var, nir, from)
499 var->data.mode = to;
500
501 nir_foreach_function(func, nir) {
502 if (!func->is_entrypoint)
503 continue;
504
505 assert(func->impl);
506
507 nir_foreach_block(block, func->impl) {
508 nir_foreach_instr(instr, block) {
509 if (instr->type != nir_instr_type_deref)
510 continue;
511
512 nir_deref_instr *deref = nir_instr_as_deref(instr);
513
514 if (deref->modes != from)
515 continue;
516
517 deref->modes = to;
518 }
519 }
520 }
521 }
522
523 static void
copy_const_initializer(const nir_constant * constant,const struct glsl_type * type,uint8_t * data)524 copy_const_initializer(const nir_constant *constant, const struct glsl_type *type,
525 uint8_t *data)
526 {
527 if (glsl_type_is_array(type)) {
528 const struct glsl_type *elm_type = glsl_get_array_element(type);
529 unsigned step_size = glsl_get_explicit_stride(type);
530
531 for (unsigned i = 0; i < constant->num_elements; i++) {
532 copy_const_initializer(constant->elements[i], elm_type,
533 data + (i * step_size));
534 }
535 } else if (glsl_type_is_struct(type)) {
536 for (unsigned i = 0; i < constant->num_elements; i++) {
537 const struct glsl_type *elm_type = glsl_get_struct_field(type, i);
538 int offset = glsl_get_struct_field_offset(type, i);
539 copy_const_initializer(constant->elements[i], elm_type, data + offset);
540 }
541 } else {
542 assert(glsl_type_is_vector_or_scalar(type));
543
544 for (unsigned i = 0; i < glsl_get_components(type); i++) {
545 switch (glsl_get_bit_size(type)) {
546 case 64:
547 *((uint64_t *)data) = constant->values[i].u64;
548 break;
549 case 32:
550 *((uint32_t *)data) = constant->values[i].u32;
551 break;
552 case 16:
553 *((uint16_t *)data) = constant->values[i].u16;
554 break;
555 case 8:
556 *((uint8_t *)data) = constant->values[i].u8;
557 break;
558 default:
559 unreachable("Invalid base type");
560 }
561
562 data += glsl_get_bit_size(type) / 8;
563 }
564 }
565 }
566
567 static enum dxil_tex_wrap
wrap_from_cl_addressing(unsigned addressing_mode)568 wrap_from_cl_addressing(unsigned addressing_mode)
569 {
570 switch (addressing_mode)
571 {
572 default:
573 case SAMPLER_ADDRESSING_MODE_NONE:
574 case SAMPLER_ADDRESSING_MODE_CLAMP:
575 // Since OpenCL's only border color is 0's and D3D specs out-of-bounds loads to return 0, don't apply any wrap mode
576 return (enum dxil_tex_wrap)-1;
577 case SAMPLER_ADDRESSING_MODE_CLAMP_TO_EDGE: return DXIL_TEX_WRAP_CLAMP_TO_EDGE;
578 case SAMPLER_ADDRESSING_MODE_REPEAT: return DXIL_TEX_WRAP_REPEAT;
579 case SAMPLER_ADDRESSING_MODE_REPEAT_MIRRORED: return DXIL_TEX_WRAP_MIRROR_REPEAT;
580 }
581 }
582
shader_has_double(nir_shader * nir)583 static bool shader_has_double(nir_shader *nir)
584 {
585 foreach_list_typed(nir_function, func, node, &nir->functions) {
586 if (!func->is_entrypoint)
587 continue;
588
589 assert(func->impl);
590
591 nir_foreach_block(block, func->impl) {
592 nir_foreach_instr_safe(instr, block) {
593 if (instr->type != nir_instr_type_alu)
594 continue;
595
596 nir_alu_instr *alu = nir_instr_as_alu(instr);
597 const nir_op_info *info = &nir_op_infos[alu->op];
598
599 if (info->output_type & nir_type_float &&
600 alu->def.bit_size == 64)
601 return true;
602 }
603 }
604 }
605
606 return false;
607 }
608
609 struct clc_libclc *
clc_libclc_new_dxil(const struct clc_logger * logger,const struct clc_libclc_dxil_options * options)610 clc_libclc_new_dxil(const struct clc_logger *logger,
611 const struct clc_libclc_dxil_options *options)
612 {
613 struct clc_libclc_options clc_options = {
614 .optimize = options->optimize,
615 .nir_options = dxil_get_base_nir_compiler_options(),
616 };
617
618 return clc_libclc_new(logger, &clc_options);
619 }
620
621 bool
clc_spirv_to_dxil(struct clc_libclc * lib,const struct clc_binary * linked_spirv,const struct clc_parsed_spirv * parsed_data,const char * entrypoint,const struct clc_runtime_kernel_conf * conf,const struct clc_spirv_specialization_consts * consts,const struct clc_logger * logger,struct clc_dxil_object * out_dxil)622 clc_spirv_to_dxil(struct clc_libclc *lib,
623 const struct clc_binary *linked_spirv,
624 const struct clc_parsed_spirv *parsed_data,
625 const char *entrypoint,
626 const struct clc_runtime_kernel_conf *conf,
627 const struct clc_spirv_specialization_consts *consts,
628 const struct clc_logger *logger,
629 struct clc_dxil_object *out_dxil)
630 {
631 struct nir_shader *nir;
632
633 for (unsigned i = 0; i < parsed_data->num_kernels; i++) {
634 if (!strcmp(parsed_data->kernels[i].name, entrypoint)) {
635 out_dxil->kernel = &parsed_data->kernels[i];
636 break;
637 }
638 }
639
640 if (!out_dxil->kernel) {
641 clc_error(logger, "no '%s' kernel found", entrypoint);
642 return false;
643 }
644
645 const struct spirv_to_nir_options spirv_options = {
646 .environment = NIR_SPIRV_OPENCL,
647 .clc_shader = clc_libclc_get_clc_shader(lib),
648 .constant_addr_format = nir_address_format_32bit_index_offset_pack64,
649 .global_addr_format = nir_address_format_32bit_index_offset_pack64,
650 .shared_addr_format = nir_address_format_32bit_offset_as_64bit,
651 .temp_addr_format = nir_address_format_32bit_offset_as_64bit,
652 .float_controls_execution_mode = FLOAT_CONTROLS_DENORM_FLUSH_TO_ZERO_FP32,
653 .caps = {
654 .address = true,
655 .float64 = true,
656 .int8 = true,
657 .int16 = true,
658 .int64 = true,
659 .kernel = true,
660 .kernel_image = true,
661 .kernel_image_read_write = true,
662 .literal_sampler = true,
663 .printf = true,
664
665 // These aren't fully supported, but silence warnings about them from
666 // code that doesn't really use them.
667 .linkage = true,
668 .generic_pointers = true,
669 },
670 };
671 unsigned supported_int_sizes = (16 | 32 | 64);
672 unsigned supported_float_sizes = (16 | 32);
673 if (conf) {
674 supported_int_sizes &= ~conf->lower_bit_size;
675 supported_float_sizes &= ~conf->lower_bit_size;
676 }
677 nir_shader_compiler_options nir_options;
678 dxil_get_nir_compiler_options(&nir_options,
679 conf ? conf->max_shader_model : SHADER_MODEL_6_2,
680 supported_int_sizes,
681 supported_float_sizes);
682
683 glsl_type_singleton_init_or_ref();
684
685 nir = spirv_to_nir(linked_spirv->data, linked_spirv->size / 4,
686 consts ? (struct nir_spirv_specialization *)consts->specializations : NULL,
687 consts ? consts->num_specializations : 0,
688 MESA_SHADER_KERNEL, entrypoint,
689 &spirv_options,
690 &nir_options);
691 if (!nir) {
692 clc_error(logger, "spirv_to_nir() failed");
693 goto err_free_dxil;
694 }
695 nir->info.workgroup_size_variable = true;
696
697 NIR_PASS_V(nir, nir_lower_goto_ifs);
698 NIR_PASS_V(nir, nir_opt_dead_cf);
699
700 struct clc_dxil_metadata *metadata = &out_dxil->metadata;
701
702 metadata->args = calloc(out_dxil->kernel->num_args,
703 sizeof(*metadata->args));
704 if (!metadata->args) {
705 clc_error(logger, "failed to allocate arg positions");
706 goto err_free_dxil;
707 }
708
709 {
710 bool progress;
711 do
712 {
713 progress = false;
714 NIR_PASS(progress, nir, nir_copy_prop);
715 NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
716 NIR_PASS(progress, nir, nir_opt_deref);
717 NIR_PASS(progress, nir, nir_opt_dce);
718 NIR_PASS(progress, nir, nir_opt_undef);
719 NIR_PASS(progress, nir, nir_opt_constant_folding);
720 NIR_PASS(progress, nir, nir_opt_cse);
721 NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
722 NIR_PASS(progress, nir, nir_opt_algebraic);
723 } while (progress);
724 }
725
726 // Inline all functions first.
727 // according to the comment on nir_inline_functions
728 NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp);
729 NIR_PASS_V(nir, nir_lower_returns);
730 NIR_PASS_V(nir, nir_link_shader_functions, clc_libclc_get_clc_shader(lib));
731 NIR_PASS_V(nir, nir_inline_functions);
732
733 // Pick off the single entrypoint that we want.
734 nir_remove_non_entrypoints(nir);
735
736 {
737 bool progress;
738 do
739 {
740 progress = false;
741 NIR_PASS(progress, nir, nir_copy_prop);
742 NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
743 NIR_PASS(progress, nir, nir_opt_deref);
744 NIR_PASS(progress, nir, nir_opt_dce);
745 NIR_PASS(progress, nir, nir_opt_undef);
746 NIR_PASS(progress, nir, nir_opt_constant_folding);
747 NIR_PASS(progress, nir, nir_opt_cse);
748 NIR_PASS(progress, nir, nir_split_var_copies);
749 NIR_PASS(progress, nir, nir_lower_var_copies);
750 NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
751 NIR_PASS(progress, nir, nir_opt_algebraic);
752 NIR_PASS(progress, nir, nir_opt_if, nir_opt_if_optimize_phi_true_false);
753 NIR_PASS(progress, nir, nir_opt_dead_cf);
754 NIR_PASS(progress, nir, nir_opt_remove_phis);
755 NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true);
756 NIR_PASS(progress, nir, nir_lower_vec3_to_vec4, nir_var_mem_generic | nir_var_uniform);
757 NIR_PASS(progress, nir, nir_opt_memcpy);
758 } while (progress);
759 }
760
761 NIR_PASS_V(nir, nir_scale_fdiv);
762
763 /* 128 is the minimum value for CL_DEVICE_MAX_READ_IMAGE_ARGS and used by CLOn12 */
764 dxil_wrap_sampler_state int_sampler_states[128] = { {{0}} };
765 unsigned sampler_id = 0;
766
767 NIR_PASS_V(nir, nir_lower_variable_initializers, ~(nir_var_function_temp | nir_var_shader_temp));
768
769 // Ensure the printf struct has explicit types, but we'll throw away the scratch size, because we haven't
770 // necessarily removed all temp variables (e.g. the printf struct itself) at this point, so we'll rerun this later
771 assert(nir->scratch_size == 0);
772 NIR_PASS_V(nir, nir_lower_vars_to_explicit_types, nir_var_function_temp, glsl_get_cl_type_size_align);
773
774 nir_lower_printf_options printf_options = {
775 .max_buffer_size = 1024 * 1024
776 };
777 NIR_PASS_V(nir, nir_lower_printf, &printf_options);
778
779 metadata->printf.info_count = nir->printf_info_count;
780 metadata->printf.infos = calloc(nir->printf_info_count, sizeof(struct clc_printf_info));
781 for (unsigned i = 0; i < nir->printf_info_count; i++) {
782 metadata->printf.infos[i].str = malloc(nir->printf_info[i].string_size);
783 memcpy(metadata->printf.infos[i].str, nir->printf_info[i].strings, nir->printf_info[i].string_size);
784 metadata->printf.infos[i].num_args = nir->printf_info[i].num_args;
785 metadata->printf.infos[i].arg_sizes = malloc(nir->printf_info[i].num_args * sizeof(unsigned));
786 memcpy(metadata->printf.infos[i].arg_sizes, nir->printf_info[i].arg_sizes, nir->printf_info[i].num_args * sizeof(unsigned));
787 }
788
789 // For uniforms (kernel inputs, minus images), run this before adjusting variable list via image/sampler lowering
790 NIR_PASS_V(nir, nir_lower_vars_to_explicit_types, nir_var_uniform, glsl_get_cl_type_size_align);
791
792 // Calculate input offsets/metadata.
793 unsigned uav_id = 0;
794 nir_foreach_variable_with_modes(var, nir, nir_var_uniform) {
795 int i = var->data.location;
796 if (i < 0)
797 continue;
798
799 unsigned size = glsl_get_cl_size(var->type);
800
801 metadata->args[i].offset = var->data.driver_location;
802 metadata->args[i].size = size;
803 metadata->kernel_inputs_buf_size = MAX2(metadata->kernel_inputs_buf_size,
804 var->data.driver_location + size);
805 if (out_dxil->kernel->args[i].address_qualifier == CLC_KERNEL_ARG_ADDRESS_GLOBAL ||
806 out_dxil->kernel->args[i].address_qualifier == CLC_KERNEL_ARG_ADDRESS_CONSTANT) {
807 metadata->args[i].globconstptr.buf_id = uav_id++;
808 } else if (glsl_type_is_sampler(var->type)) {
809 unsigned address_mode = conf ? conf->args[i].sampler.addressing_mode : 0u;
810 int_sampler_states[sampler_id].wrap[0] =
811 int_sampler_states[sampler_id].wrap[1] =
812 int_sampler_states[sampler_id].wrap[2] = wrap_from_cl_addressing(address_mode);
813 int_sampler_states[sampler_id].is_nonnormalized_coords =
814 conf ? !conf->args[i].sampler.normalized_coords : 0;
815 int_sampler_states[sampler_id].is_linear_filtering =
816 conf ? conf->args[i].sampler.linear_filtering : 0;
817 metadata->args[i].sampler.sampler_id = var->data.binding = sampler_id++;
818 }
819 }
820
821 unsigned num_global_inputs = uav_id;
822
823 // Second pass over inputs to calculate image bindings
824 unsigned srv_id = 0;
825 nir_foreach_image_variable(var, nir) {
826 int i = var->data.location;
827 if (i < 0)
828 continue;
829
830 assert(glsl_type_is_image(var->type));
831
832 if (var->data.access == ACCESS_NON_WRITEABLE) {
833 metadata->args[i].image.buf_ids[0] = srv_id++;
834 } else {
835 // Write or read-write are UAVs
836 metadata->args[i].image.buf_ids[0] = uav_id++;
837 }
838
839 metadata->args[i].image.num_buf_ids = 0;
840 var->data.binding = metadata->args[i].image.buf_ids[0];
841
842 // Assign location that'll be used for uniforms for format/order
843 var->data.driver_location = metadata->kernel_inputs_buf_size;
844 metadata->args[i].offset = metadata->kernel_inputs_buf_size;
845 metadata->args[i].size = 8;
846 metadata->kernel_inputs_buf_size += metadata->args[i].size;
847 }
848
849 // Before removing dead uniforms, dedupe inline samplers to make more dead uniforms
850 NIR_PASS_V(nir, nir_dedup_inline_samplers);
851 NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_uniform | nir_var_mem_ubo |
852 nir_var_mem_constant | nir_var_function_temp | nir_var_image, NULL);
853
854 // Fill out inline sampler metadata, now that they've been deduped and dead ones removed
855 nir_foreach_variable_with_modes(var, nir, nir_var_uniform) {
856 if (glsl_type_is_sampler(var->type) && var->data.sampler.is_inline_sampler) {
857 int_sampler_states[sampler_id].wrap[0] =
858 int_sampler_states[sampler_id].wrap[1] =
859 int_sampler_states[sampler_id].wrap[2] =
860 wrap_from_cl_addressing(var->data.sampler.addressing_mode);
861 int_sampler_states[sampler_id].is_nonnormalized_coords =
862 !var->data.sampler.normalized_coordinates;
863 int_sampler_states[sampler_id].is_linear_filtering =
864 var->data.sampler.filter_mode == SAMPLER_FILTER_MODE_LINEAR;
865 var->data.binding = sampler_id++;
866
867 assert(metadata->num_const_samplers < CLC_MAX_SAMPLERS);
868 metadata->const_samplers[metadata->num_const_samplers].sampler_id = var->data.binding;
869 metadata->const_samplers[metadata->num_const_samplers].addressing_mode = var->data.sampler.addressing_mode;
870 metadata->const_samplers[metadata->num_const_samplers].normalized_coords = var->data.sampler.normalized_coordinates;
871 metadata->const_samplers[metadata->num_const_samplers].filter_mode = var->data.sampler.filter_mode;
872 metadata->num_const_samplers++;
873 }
874 }
875
876 // Needs to come before lower_explicit_io
877 NIR_PASS_V(nir, nir_lower_readonly_images_to_tex, false);
878 struct clc_image_lower_context image_lower_context = { metadata, &srv_id, &uav_id };
879 NIR_PASS_V(nir, clc_lower_images, &image_lower_context);
880 NIR_PASS_V(nir, clc_lower_nonnormalized_samplers, int_sampler_states);
881 NIR_PASS_V(nir, nir_lower_samplers);
882 NIR_PASS_V(nir, dxil_lower_sample_to_txf_for_integer_tex,
883 sampler_id, int_sampler_states, NULL, 14.0f);
884
885 nir->scratch_size = 0;
886 NIR_PASS_V(nir, nir_lower_vars_to_explicit_types,
887 nir_var_mem_shared | nir_var_function_temp | nir_var_mem_global | nir_var_mem_constant,
888 glsl_get_cl_type_size_align);
889
890 // Lower memcpy - needs to wait until types are sized
891 {
892 bool progress;
893 do {
894 progress = false;
895 NIR_PASS(progress, nir, nir_opt_memcpy);
896 NIR_PASS(progress, nir, nir_copy_prop);
897 NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
898 NIR_PASS(progress, nir, nir_opt_deref);
899 NIR_PASS(progress, nir, nir_opt_dce);
900 NIR_PASS(progress, nir, nir_split_var_copies);
901 NIR_PASS(progress, nir, nir_lower_var_copies);
902 NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
903 NIR_PASS(progress, nir, nir_opt_constant_folding);
904 NIR_PASS(progress, nir, nir_opt_cse);
905 } while (progress);
906 }
907 NIR_PASS_V(nir, nir_lower_memcpy);
908
909 // Attempt to preserve derefs to constants by moving them to shader_temp
910 NIR_PASS_V(nir, dxil_nir_lower_constant_to_temp);
911 // While inserting new var derefs for our "logical" addressing mode, temporarily
912 // switch the pointer size to 32-bit.
913 nir->info.cs.ptr_size = 32;
914 NIR_PASS_V(nir, nir_split_struct_vars, nir_var_shader_temp);
915 NIR_PASS_V(nir, dxil_nir_flatten_var_arrays, nir_var_shader_temp);
916 NIR_PASS_V(nir, dxil_nir_lower_var_bit_size, nir_var_shader_temp,
917 (supported_int_sizes & 16) ? 16 : 32, (supported_int_sizes & 64) ? 64 : 32);
918 nir->info.cs.ptr_size = 64;
919
920 NIR_PASS_V(nir, clc_lower_constant_to_ssbo, out_dxil->kernel, &uav_id);
921 NIR_PASS_V(nir, clc_change_variable_mode, nir_var_shader_temp, nir_var_mem_constant);
922 NIR_PASS_V(nir, clc_change_variable_mode, nir_var_mem_global, nir_var_mem_ssbo);
923
924 bool has_printf = false;
925 NIR_PASS(has_printf, nir, clc_lower_printf_base, uav_id);
926 metadata->printf.uav_id = has_printf ? uav_id++ : -1;
927
928 NIR_PASS_V(nir, dxil_nir_lower_deref_ssbo);
929
930 NIR_PASS_V(nir, dxil_nir_split_unaligned_loads_stores, nir_var_mem_shared | nir_var_function_temp);
931
932 assert(nir->info.cs.ptr_size == 64);
933 NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_ssbo,
934 nir_address_format_32bit_index_offset_pack64);
935 NIR_PASS_V(nir, nir_lower_explicit_io,
936 nir_var_mem_shared | nir_var_function_temp | nir_var_uniform,
937 nir_address_format_32bit_offset_as_64bit);
938
939 NIR_PASS_V(nir, nir_lower_system_values);
940
941 nir_lower_compute_system_values_options compute_options = {
942 .has_base_global_invocation_id = (conf && conf->support_global_work_id_offsets),
943 .has_base_workgroup_id = (conf && conf->support_workgroup_id_offsets),
944 };
945 NIR_PASS_V(nir, nir_lower_compute_system_values, &compute_options);
946
947 NIR_PASS_V(nir, clc_lower_64bit_semantics);
948
949 NIR_PASS_V(nir, nir_opt_deref);
950 NIR_PASS_V(nir, nir_lower_vars_to_ssa);
951
952 unsigned cbv_id = 0;
953
954 nir_variable *inputs_var =
955 add_kernel_inputs_var(out_dxil, nir, &cbv_id);
956 nir_variable *work_properties_var =
957 add_work_properties_var(out_dxil, nir, &cbv_id);
958
959 memcpy(metadata->local_size, nir->info.workgroup_size,
960 sizeof(metadata->local_size));
961 memcpy(metadata->local_size_hint, nir->info.cs.workgroup_size_hint,
962 sizeof(metadata->local_size));
963
964 // Patch the localsize before calling clc_nir_lower_system_values().
965 if (conf) {
966 for (unsigned i = 0; i < ARRAY_SIZE(nir->info.workgroup_size); i++) {
967 if (!conf->local_size[i] ||
968 conf->local_size[i] == nir->info.workgroup_size[i])
969 continue;
970
971 if (nir->info.workgroup_size[i] &&
972 nir->info.workgroup_size[i] != conf->local_size[i]) {
973 debug_printf("D3D12: runtime local size does not match reqd_work_group_size() values\n");
974 goto err_free_dxil;
975 }
976
977 nir->info.workgroup_size[i] = conf->local_size[i];
978 }
979 memcpy(metadata->local_size, nir->info.workgroup_size,
980 sizeof(metadata->local_size));
981 } else {
982 /* Make sure there's at least one thread that's set to run */
983 for (unsigned i = 0; i < ARRAY_SIZE(nir->info.workgroup_size); i++) {
984 if (nir->info.workgroup_size[i] == 0)
985 nir->info.workgroup_size[i] = 1;
986 }
987 }
988
989 NIR_PASS_V(nir, clc_nir_lower_kernel_input_loads, inputs_var);
990 NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_ubo,
991 nir_address_format_32bit_index_offset);
992 NIR_PASS_V(nir, clc_nir_lower_system_values, work_properties_var);
993 const struct dxil_nir_lower_loads_stores_options loads_stores_options = {
994 .use_16bit_ssbo = false,
995 };
996
997 /* Now that function-declared local vars have been sized, append args */
998 for (unsigned i = 0; i < out_dxil->kernel->num_args; i++) {
999 if (out_dxil->kernel->args[i].address_qualifier != CLC_KERNEL_ARG_ADDRESS_LOCAL)
1000 continue;
1001
1002 /* If we don't have the runtime conf yet, we just create a dummy variable.
1003 * This will be adjusted when clc_spirv_to_dxil() is called with a conf
1004 * argument.
1005 */
1006 unsigned size = 4;
1007 if (conf && conf->args)
1008 size = conf->args[i].localptr.size;
1009
1010 /* The alignment required for the pointee type is not easy to get from
1011 * here, so let's base our logic on the size itself. Anything bigger than
1012 * the maximum alignment constraint (which is 128 bytes, since ulong16 or
1013 * doubl16 size are the biggest base types) should be aligned on this
1014 * maximum alignment constraint. For smaller types, we use the size
1015 * itself to calculate the alignment.
1016 */
1017 unsigned alignment = size < 128 ? (1 << (ffs(size) - 1)) : 128;
1018
1019 nir->info.shared_size = align(nir->info.shared_size, alignment);
1020 metadata->args[i].localptr.sharedmem_offset = nir->info.shared_size;
1021 nir->info.shared_size += size;
1022 }
1023
1024 NIR_PASS_V(nir, dxil_nir_lower_loads_stores_to_dxil, &loads_stores_options);
1025 NIR_PASS_V(nir, dxil_nir_opt_alu_deref_srcs);
1026 NIR_PASS_V(nir, nir_lower_fp16_casts, nir_lower_fp16_all);
1027 NIR_PASS_V(nir, nir_lower_convert_alu_types, NULL);
1028
1029 // Convert pack to pack_split
1030 NIR_PASS_V(nir, nir_lower_pack);
1031 // Lower pack_split to bit math
1032 NIR_PASS_V(nir, nir_opt_algebraic);
1033
1034 NIR_PASS_V(nir, nir_opt_dce);
1035
1036 nir_validate_shader(nir, "Validate before feeding NIR to the DXIL compiler");
1037 struct nir_to_dxil_options opts = {
1038 .interpolate_at_vertex = false,
1039 .lower_int16 = (conf && (conf->lower_bit_size & 16) != 0),
1040 .disable_math_refactoring = true,
1041 .num_kernel_globals = num_global_inputs,
1042 .environment = DXIL_ENVIRONMENT_CL,
1043 .shader_model_max = conf && conf->max_shader_model ? conf->max_shader_model : SHADER_MODEL_6_2,
1044 .validator_version_max = conf ? conf->validator_version : DXIL_VALIDATOR_1_4,
1045 };
1046
1047 metadata->local_mem_size = nir->info.shared_size;
1048 metadata->priv_mem_size = nir->scratch_size;
1049
1050 /* DXIL double math is too limited compared to what NIR expects. Let's refuse
1051 * to compile a shader when it contains double operations until we have
1052 * double lowering hooked up.
1053 */
1054 if (shader_has_double(nir)) {
1055 clc_error(logger, "NIR shader contains doubles, which we don't support yet");
1056 goto err_free_dxil;
1057 }
1058
1059 struct dxil_logger dxil_logger = { .priv = logger ? logger->priv : NULL,
1060 .log = logger ? logger->error : NULL};
1061
1062 struct blob tmp;
1063 if (!nir_to_dxil(nir, &opts, logger ? &dxil_logger : NULL, &tmp)) {
1064 debug_printf("D3D12: nir_to_dxil failed\n");
1065 goto err_free_dxil;
1066 }
1067
1068 nir_foreach_variable_with_modes(var, nir, nir_var_mem_ssbo) {
1069 if (var->constant_initializer) {
1070 if (glsl_type_is_array(var->type)) {
1071 int size = align(glsl_get_cl_size(var->type), 4);
1072 uint8_t *data = malloc(size);
1073 if (!data)
1074 goto err_free_dxil;
1075
1076 copy_const_initializer(var->constant_initializer, var->type, data);
1077 metadata->consts[metadata->num_consts].data = data;
1078 metadata->consts[metadata->num_consts].size = size;
1079 metadata->consts[metadata->num_consts].uav_id = var->data.binding;
1080 metadata->num_consts++;
1081 } else
1082 unreachable("unexpected constant initializer");
1083 }
1084 }
1085
1086 metadata->kernel_inputs_cbv_id = inputs_var ? inputs_var->data.binding : 0;
1087 metadata->work_properties_cbv_id = work_properties_var->data.binding;
1088 metadata->num_uavs = uav_id;
1089 metadata->num_srvs = srv_id;
1090 metadata->num_samplers = sampler_id;
1091
1092 ralloc_free(nir);
1093 glsl_type_singleton_decref();
1094
1095 blob_finish_get_buffer(&tmp, &out_dxil->binary.data,
1096 &out_dxil->binary.size);
1097 return true;
1098
1099 err_free_dxil:
1100 clc_free_dxil_object(out_dxil);
1101 return false;
1102 }
1103
clc_free_dxil_object(struct clc_dxil_object * dxil)1104 void clc_free_dxil_object(struct clc_dxil_object *dxil)
1105 {
1106 for (unsigned i = 0; i < dxil->metadata.num_consts; i++)
1107 free(dxil->metadata.consts[i].data);
1108
1109 for (unsigned i = 0; i < dxil->metadata.printf.info_count; i++) {
1110 free(dxil->metadata.printf.infos[i].arg_sizes);
1111 free(dxil->metadata.printf.infos[i].str);
1112 }
1113 free(dxil->metadata.printf.infos);
1114
1115 free(dxil->binary.data);
1116 }
1117
clc_compiler_get_version(void)1118 uint64_t clc_compiler_get_version(void)
1119 {
1120 const char sha1[] = MESA_GIT_SHA1;
1121 const char* dash = strchr(sha1, '-');
1122 if (dash) {
1123 return strtoull(dash + 1, NULL, 16);
1124 }
1125 return 0;
1126 }
1127