xref: /aosp_15_r20/external/mesa3d/src/asahi/clc/asahi_clc.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2023 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker  * Copyright 2020 Intel Corporation
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #include "asahi/compiler/agx_compile.h"
8*61046927SAndroid Build Coastguard Worker #include "compiler/clc/clc.h"
9*61046927SAndroid Build Coastguard Worker #include "compiler/glsl_types.h"
10*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/nir_spirv.h"
11*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/spirv_info.h"
12*61046927SAndroid Build Coastguard Worker #include "util/build_id.h"
13*61046927SAndroid Build Coastguard Worker #include "util/disk_cache.h"
14*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
15*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
16*61046927SAndroid Build Coastguard Worker #include "util/u_dynarray.h"
17*61046927SAndroid Build Coastguard Worker #include "nir.h"
18*61046927SAndroid Build Coastguard Worker #include "nir_builder.h"
19*61046927SAndroid Build Coastguard Worker #include "nir_serialize.h"
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
22*61046927SAndroid Build Coastguard Worker #include <getopt.h>
23*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
24*61046927SAndroid Build Coastguard Worker #include <stdio.h>
25*61046927SAndroid Build Coastguard Worker #include <string.h>
26*61046927SAndroid Build Coastguard Worker #include <unistd.h>
27*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
28*61046927SAndroid Build Coastguard Worker #include <sys/mman.h>
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker static const struct spirv_to_nir_options spirv_options = {
31*61046927SAndroid Build Coastguard Worker    .environment = NIR_SPIRV_OPENCL,
32*61046927SAndroid Build Coastguard Worker    .shared_addr_format = nir_address_format_62bit_generic,
33*61046927SAndroid Build Coastguard Worker    .global_addr_format = nir_address_format_62bit_generic,
34*61046927SAndroid Build Coastguard Worker    .temp_addr_format = nir_address_format_62bit_generic,
35*61046927SAndroid Build Coastguard Worker    .constant_addr_format = nir_address_format_64bit_global,
36*61046927SAndroid Build Coastguard Worker    .create_library = true,
37*61046927SAndroid Build Coastguard Worker };
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker static bool
lower_builtins(nir_builder * b,nir_instr * instr,void * data)40*61046927SAndroid Build Coastguard Worker lower_builtins(nir_builder *b, nir_instr *instr, void *data)
41*61046927SAndroid Build Coastguard Worker {
42*61046927SAndroid Build Coastguard Worker    if (instr->type != nir_instr_type_call)
43*61046927SAndroid Build Coastguard Worker       return false;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    nir_call_instr *call = nir_instr_as_call(instr);
46*61046927SAndroid Build Coastguard Worker    nir_function *func = call->callee;
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker    if (strcmp(func->name, "nir_interleave_agx") == 0) {
49*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
50*61046927SAndroid Build Coastguard Worker       nir_store_deref(
51*61046927SAndroid Build Coastguard Worker          b, nir_src_as_deref(call->params[0]),
52*61046927SAndroid Build Coastguard Worker          nir_interleave_agx(b, call->params[1].ssa, call->params[2].ssa), 1);
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker       return true;
55*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_doorbell_agx") == 0) {
56*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
57*61046927SAndroid Build Coastguard Worker       nir_doorbell_agx(b, call->params[0].ssa);
58*61046927SAndroid Build Coastguard Worker       return true;
59*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_stack_map_agx") == 0) {
60*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
61*61046927SAndroid Build Coastguard Worker       nir_stack_map_agx(b, call->params[0].ssa, call->params[1].ssa);
62*61046927SAndroid Build Coastguard Worker       return true;
63*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_stack_unmap_agx") == 0) {
64*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
65*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]),
66*61046927SAndroid Build Coastguard Worker                       nir_stack_unmap_agx(b, call->params[1].ssa), 1);
67*61046927SAndroid Build Coastguard Worker       return true;
68*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_load_core_id_agx") == 0) {
69*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
70*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]),
71*61046927SAndroid Build Coastguard Worker                       nir_load_core_id_agx(b), 1);
72*61046927SAndroid Build Coastguard Worker       return true;
73*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_load_helper_op_id_agx") == 0) {
74*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
75*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]),
76*61046927SAndroid Build Coastguard Worker                       nir_load_helper_op_id_agx(b, 1, 32), 1);
77*61046927SAndroid Build Coastguard Worker       return true;
78*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_load_helper_arg_lo_agx") == 0) {
79*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
80*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]),
81*61046927SAndroid Build Coastguard Worker                       nir_load_helper_arg_lo_agx(b, 1, 32), 1);
82*61046927SAndroid Build Coastguard Worker       return true;
83*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_load_helper_arg_hi_agx") == 0) {
84*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
85*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]),
86*61046927SAndroid Build Coastguard Worker                       nir_load_helper_arg_hi_agx(b, 1, 32), 1);
87*61046927SAndroid Build Coastguard Worker       return true;
88*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "ballot") == 0) {
89*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
90*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]),
91*61046927SAndroid Build Coastguard Worker                       nir_ballot(b, 1, 32, call->params[1].ssa), 1);
92*61046927SAndroid Build Coastguard Worker       return true;
93*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_fence_helper_exit_agx") == 0) {
94*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
95*61046927SAndroid Build Coastguard Worker       nir_fence_helper_exit_agx(b);
96*61046927SAndroid Build Coastguard Worker       return true;
97*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_bindless_image_load_array") == 0) {
98*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker       nir_def *texel = nir_bindless_image_load(
101*61046927SAndroid Build Coastguard Worker          b, 4, 32, call->params[1].ssa, call->params[2].ssa, nir_imm_int(b, 0),
102*61046927SAndroid Build Coastguard Worker          nir_imm_int(b, 0), .image_array = true,
103*61046927SAndroid Build Coastguard Worker          .image_dim = GLSL_SAMPLER_DIM_2D, .dest_type = nir_type_uint32,
104*61046927SAndroid Build Coastguard Worker          .access = ACCESS_IN_BOUNDS_AGX);
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]), texel, 0xf);
107*61046927SAndroid Build Coastguard Worker       return true;
108*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_bindless_image_store_array") == 0) {
109*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker       nir_bindless_image_store(
112*61046927SAndroid Build Coastguard Worker          b, call->params[0].ssa, call->params[1].ssa, nir_imm_int(b, 0),
113*61046927SAndroid Build Coastguard Worker          call->params[2].ssa, nir_imm_int(b, 0), .image_array = true,
114*61046927SAndroid Build Coastguard Worker          .image_dim = GLSL_SAMPLER_DIM_2D, .src_type = nir_type_uint32,
115*61046927SAndroid Build Coastguard Worker          .access = ACCESS_NON_READABLE);
116*61046927SAndroid Build Coastguard Worker       return true;
117*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_bindless_image_load_ms_array") == 0) {
118*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
119*61046927SAndroid Build Coastguard Worker 
120*61046927SAndroid Build Coastguard Worker       nir_def *texel = nir_bindless_image_load(
121*61046927SAndroid Build Coastguard Worker          b, 4, 32, call->params[1].ssa, call->params[2].ssa,
122*61046927SAndroid Build Coastguard Worker          call->params[3].ssa, nir_imm_int(b, 0), .image_array = true,
123*61046927SAndroid Build Coastguard Worker          .image_dim = GLSL_SAMPLER_DIM_MS, .dest_type = nir_type_uint32,
124*61046927SAndroid Build Coastguard Worker          .access = ACCESS_IN_BOUNDS_AGX);
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker       nir_store_deref(b, nir_src_as_deref(call->params[0]), texel, 0xf);
127*61046927SAndroid Build Coastguard Worker       return true;
128*61046927SAndroid Build Coastguard Worker    } else if (strcmp(func->name, "nir_bindless_image_store_ms_array") == 0) {
129*61046927SAndroid Build Coastguard Worker       b->cursor = nir_instr_remove(&call->instr);
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker       nir_bindless_image_store(
132*61046927SAndroid Build Coastguard Worker          b, call->params[0].ssa, call->params[1].ssa, call->params[2].ssa,
133*61046927SAndroid Build Coastguard Worker          call->params[3].ssa, nir_imm_int(b, 0), .image_array = true,
134*61046927SAndroid Build Coastguard Worker          .image_dim = GLSL_SAMPLER_DIM_MS, .src_type = nir_type_uint32,
135*61046927SAndroid Build Coastguard Worker          .access = ACCESS_NON_READABLE);
136*61046927SAndroid Build Coastguard Worker       return true;
137*61046927SAndroid Build Coastguard Worker    }
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    return false;
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker /* Standard optimization loop */
143*61046927SAndroid Build Coastguard Worker static void
optimize(nir_shader * nir)144*61046927SAndroid Build Coastguard Worker optimize(nir_shader *nir)
145*61046927SAndroid Build Coastguard Worker {
146*61046927SAndroid Build Coastguard Worker    bool progress;
147*61046927SAndroid Build Coastguard Worker    do {
148*61046927SAndroid Build Coastguard Worker       progress = false;
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_lower_var_copies);
151*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_copy_prop);
154*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_remove_phis);
155*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_lower_phis_to_scalar, true);
156*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_dce);
157*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_dead_cf);
158*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_cse);
159*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_peephole_select, 64, false, true);
160*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_phi_precision);
161*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_algebraic);
162*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_constant_folding);
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_deref);
165*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
166*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_undef);
167*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_lower_undef_to_zero);
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_shrink_vectors, true);
170*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_loop_unroll);
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_split_var_copies);
173*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_split_struct_vars, nir_var_function_temp);
174*61046927SAndroid Build Coastguard Worker    } while (progress);
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker static nir_shader *
compile(void * memctx,const uint32_t * spirv,size_t spirv_size)178*61046927SAndroid Build Coastguard Worker compile(void *memctx, const uint32_t *spirv, size_t spirv_size)
179*61046927SAndroid Build Coastguard Worker {
180*61046927SAndroid Build Coastguard Worker    const nir_shader_compiler_options *nir_options = &agx_nir_options;
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    assert(spirv_size % 4 == 0);
183*61046927SAndroid Build Coastguard Worker    nir_shader *nir =
184*61046927SAndroid Build Coastguard Worker       spirv_to_nir(spirv, spirv_size / 4, NULL, 0, MESA_SHADER_KERNEL,
185*61046927SAndroid Build Coastguard Worker                    "library", &spirv_options, nir_options);
186*61046927SAndroid Build Coastguard Worker    nir_validate_shader(nir, "after spirv_to_nir");
187*61046927SAndroid Build Coastguard Worker    nir_validate_ssa_dominance(nir, "after spirv_to_nir");
188*61046927SAndroid Build Coastguard Worker    ralloc_steal(memctx, nir);
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_system_values);
191*61046927SAndroid Build Coastguard Worker    nir_shader_instructions_pass(nir, lower_builtins, nir_metadata_none, NULL);
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    /* We have to lower away local constant initializers right before we
194*61046927SAndroid Build Coastguard Worker     * inline functions.  That way they get properly initialized at the top
195*61046927SAndroid Build Coastguard Worker     * of the function and not at the top of its caller.
196*61046927SAndroid Build Coastguard Worker     */
197*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_function_temp);
198*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_returns);
199*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_inline_functions);
200*61046927SAndroid Build Coastguard Worker    nir_remove_non_exported(nir);
201*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_copy_prop);
202*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_deref);
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    /* We can go ahead and lower the rest of the constant initializers.  We do
205*61046927SAndroid Build Coastguard Worker     * this here so that nir_remove_dead_variables and split_per_member_structs
206*61046927SAndroid Build Coastguard Worker     * below see the corresponding stores.
207*61046927SAndroid Build Coastguard Worker     */
208*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_variable_initializers, ~0);
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    /* LLVM loves take advantage of the fact that vec3s in OpenCL are 16B
211*61046927SAndroid Build Coastguard Worker     * aligned and so it can just read/write them as vec4s.  This results in a
212*61046927SAndroid Build Coastguard Worker     * LOT of vec4->vec3 casts on loads and stores.  One solution to this
213*61046927SAndroid Build Coastguard Worker     * problem is to get rid of all vec3 variables.
214*61046927SAndroid Build Coastguard Worker     */
215*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_vec3_to_vec4,
216*61046927SAndroid Build Coastguard Worker             nir_var_shader_temp | nir_var_function_temp | nir_var_mem_shared |
217*61046927SAndroid Build Coastguard Worker                nir_var_mem_global | nir_var_mem_constant);
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    /* We assign explicit types early so that the optimizer can take advantage
220*61046927SAndroid Build Coastguard Worker     * of that information and hopefully get rid of some of our memcpys.
221*61046927SAndroid Build Coastguard Worker     */
222*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_vars_to_explicit_types,
223*61046927SAndroid Build Coastguard Worker             nir_var_uniform | nir_var_shader_temp | nir_var_function_temp |
224*61046927SAndroid Build Coastguard Worker                nir_var_mem_shared | nir_var_mem_global,
225*61046927SAndroid Build Coastguard Worker             glsl_get_cl_type_size_align);
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker    optimize(nir);
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_remove_dead_variables, nir_var_all, NULL);
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    /* Lower again, this time after dead-variables to get more compact variable
232*61046927SAndroid Build Coastguard Worker     * layouts.
233*61046927SAndroid Build Coastguard Worker     */
234*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_vars_to_explicit_types,
235*61046927SAndroid Build Coastguard Worker             nir_var_shader_temp | nir_var_function_temp | nir_var_mem_shared |
236*61046927SAndroid Build Coastguard Worker                nir_var_mem_global | nir_var_mem_constant,
237*61046927SAndroid Build Coastguard Worker             glsl_get_cl_type_size_align);
238*61046927SAndroid Build Coastguard Worker    if (nir->constant_data_size > 0) {
239*61046927SAndroid Build Coastguard Worker       assert(nir->constant_data == NULL);
240*61046927SAndroid Build Coastguard Worker       nir->constant_data = rzalloc_size(nir, nir->constant_data_size);
241*61046927SAndroid Build Coastguard Worker       nir_gather_explicit_io_initializers(nir, nir->constant_data,
242*61046927SAndroid Build Coastguard Worker                                           nir->constant_data_size,
243*61046927SAndroid Build Coastguard Worker                                           nir_var_mem_constant);
244*61046927SAndroid Build Coastguard Worker    }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_memcpy);
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_constant,
249*61046927SAndroid Build Coastguard Worker             nir_address_format_64bit_global);
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_uniform,
252*61046927SAndroid Build Coastguard Worker             nir_address_format_32bit_offset_as_64bit);
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker    /* Note: we cannot lower explicit I/O here, because we need derefs in tact
255*61046927SAndroid Build Coastguard Worker     * for function calls into the library to work.
256*61046927SAndroid Build Coastguard Worker     */
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_convert_alu_types, NULL);
259*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_if, 0);
260*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_idiv_const, 16);
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    optimize(nir);
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker    return nir;
265*61046927SAndroid Build Coastguard Worker }
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker /* Shader functions */
268*61046927SAndroid Build Coastguard Worker #define SPIR_V_MAGIC_NUMBER 0x07230203
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker static void
msg_callback(void * priv,const char * msg)271*61046927SAndroid Build Coastguard Worker msg_callback(void *priv, const char *msg)
272*61046927SAndroid Build Coastguard Worker {
273*61046927SAndroid Build Coastguard Worker    (void)priv;
274*61046927SAndroid Build Coastguard Worker    fprintf(stderr, "%s", msg);
275*61046927SAndroid Build Coastguard Worker }
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker static void
print_u32_data(FILE * fp,const char * prefix,const char * arr_name,const uint32_t * data,size_t len)278*61046927SAndroid Build Coastguard Worker print_u32_data(FILE *fp, const char *prefix, const char *arr_name,
279*61046927SAndroid Build Coastguard Worker                const uint32_t *data, size_t len)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    fprintf(fp, "static const uint32_t %s_%s[] = {", prefix, arr_name);
282*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < (len / 4); i++) {
283*61046927SAndroid Build Coastguard Worker       if (i % 4 == 0)
284*61046927SAndroid Build Coastguard Worker          fprintf(fp, "\n   ");
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker       fprintf(fp, " 0x%08" PRIx32 ",", data[i]);
287*61046927SAndroid Build Coastguard Worker    }
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    if (len % 4) {
290*61046927SAndroid Build Coastguard Worker       const uint8_t *data_u8 = (const uint8_t *)data;
291*61046927SAndroid Build Coastguard Worker       uint32_t last = 0;
292*61046927SAndroid Build Coastguard Worker       unsigned last_offs = ROUND_DOWN_TO(len, 4);
293*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < len % 4; ++i) {
294*61046927SAndroid Build Coastguard Worker          last |= (uint32_t)data_u8[last_offs + i] << (i * 8);
295*61046927SAndroid Build Coastguard Worker       }
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker       fprintf(fp, " 0x%08" PRIx32 ",", last);
298*61046927SAndroid Build Coastguard Worker    }
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker    fprintf(fp, "\n};\n");
301*61046927SAndroid Build Coastguard Worker }
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker static void
print_usage(char * exec_name,FILE * f)304*61046927SAndroid Build Coastguard Worker print_usage(char *exec_name, FILE *f)
305*61046927SAndroid Build Coastguard Worker {
306*61046927SAndroid Build Coastguard Worker    fprintf(
307*61046927SAndroid Build Coastguard Worker       f,
308*61046927SAndroid Build Coastguard Worker       "Usage: %s [options] -- [clang args]\n"
309*61046927SAndroid Build Coastguard Worker       "Options:\n"
310*61046927SAndroid Build Coastguard Worker       "  -h  --help              Print this help.\n"
311*61046927SAndroid Build Coastguard Worker       "      --prefix <prefix>   Prefix for variable names in generated C code.\n"
312*61046927SAndroid Build Coastguard Worker       "  -o, --out <filename>    Specify the output filename.\n"
313*61046927SAndroid Build Coastguard Worker       "  -i, --in <filename>     Specify one input filename. Accepted multiple times.\n"
314*61046927SAndroid Build Coastguard Worker       "  -s, --spv <filename>    Specify the output filename for spirv.\n"
315*61046927SAndroid Build Coastguard Worker       "  -v, --verbose           Print more information during compilation.\n",
316*61046927SAndroid Build Coastguard Worker       exec_name);
317*61046927SAndroid Build Coastguard Worker }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker #define OPT_PREFIX 1000
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker static uint32_t
get_module_spirv_version(const uint32_t * spirv,size_t size)322*61046927SAndroid Build Coastguard Worker get_module_spirv_version(const uint32_t *spirv, size_t size)
323*61046927SAndroid Build Coastguard Worker {
324*61046927SAndroid Build Coastguard Worker    assert(size >= 8);
325*61046927SAndroid Build Coastguard Worker    assert(spirv[0] == SPIR_V_MAGIC_NUMBER);
326*61046927SAndroid Build Coastguard Worker    return spirv[1];
327*61046927SAndroid Build Coastguard Worker }
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker static void
set_module_spirv_version(uint32_t * spirv,size_t size,uint32_t version)330*61046927SAndroid Build Coastguard Worker set_module_spirv_version(uint32_t *spirv, size_t size, uint32_t version)
331*61046927SAndroid Build Coastguard Worker {
332*61046927SAndroid Build Coastguard Worker    assert(size >= 8);
333*61046927SAndroid Build Coastguard Worker    assert(spirv[0] == SPIR_V_MAGIC_NUMBER);
334*61046927SAndroid Build Coastguard Worker    spirv[1] = version;
335*61046927SAndroid Build Coastguard Worker }
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker int
main(int argc,char ** argv)338*61046927SAndroid Build Coastguard Worker main(int argc, char **argv)
339*61046927SAndroid Build Coastguard Worker {
340*61046927SAndroid Build Coastguard Worker    static struct option long_options[] = {
341*61046927SAndroid Build Coastguard Worker       {"help", no_argument, 0, 'h'},
342*61046927SAndroid Build Coastguard Worker       {"prefix", required_argument, 0, OPT_PREFIX},
343*61046927SAndroid Build Coastguard Worker       {"in", required_argument, 0, 'i'},
344*61046927SAndroid Build Coastguard Worker       {"out", required_argument, 0, 'o'},
345*61046927SAndroid Build Coastguard Worker       {"spv", required_argument, 0, 's'},
346*61046927SAndroid Build Coastguard Worker       {"verbose", no_argument, 0, 'v'},
347*61046927SAndroid Build Coastguard Worker       {0, 0, 0, 0},
348*61046927SAndroid Build Coastguard Worker    };
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker    char *outfile = NULL, *spv_outfile = NULL, *prefix = NULL;
351*61046927SAndroid Build Coastguard Worker    struct util_dynarray clang_args;
352*61046927SAndroid Build Coastguard Worker    struct util_dynarray input_files;
353*61046927SAndroid Build Coastguard Worker    struct util_dynarray spirv_objs;
354*61046927SAndroid Build Coastguard Worker    struct util_dynarray spirv_ptr_objs;
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    void *mem_ctx = ralloc_context(NULL);
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker    util_dynarray_init(&clang_args, mem_ctx);
359*61046927SAndroid Build Coastguard Worker    util_dynarray_init(&input_files, mem_ctx);
360*61046927SAndroid Build Coastguard Worker    util_dynarray_init(&spirv_objs, mem_ctx);
361*61046927SAndroid Build Coastguard Worker    util_dynarray_init(&spirv_ptr_objs, mem_ctx);
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    int ch;
364*61046927SAndroid Build Coastguard Worker    while ((ch = getopt_long(argc, argv, "he:p:s:i:o:v", long_options, NULL)) !=
365*61046927SAndroid Build Coastguard Worker           -1) {
366*61046927SAndroid Build Coastguard Worker       switch (ch) {
367*61046927SAndroid Build Coastguard Worker       case 'h':
368*61046927SAndroid Build Coastguard Worker          print_usage(argv[0], stdout);
369*61046927SAndroid Build Coastguard Worker          return 0;
370*61046927SAndroid Build Coastguard Worker       case 'o':
371*61046927SAndroid Build Coastguard Worker          outfile = optarg;
372*61046927SAndroid Build Coastguard Worker          break;
373*61046927SAndroid Build Coastguard Worker       case 'i':
374*61046927SAndroid Build Coastguard Worker          util_dynarray_append(&input_files, char *, optarg);
375*61046927SAndroid Build Coastguard Worker          break;
376*61046927SAndroid Build Coastguard Worker       case 's':
377*61046927SAndroid Build Coastguard Worker          spv_outfile = optarg;
378*61046927SAndroid Build Coastguard Worker          break;
379*61046927SAndroid Build Coastguard Worker       case OPT_PREFIX:
380*61046927SAndroid Build Coastguard Worker          prefix = optarg;
381*61046927SAndroid Build Coastguard Worker          break;
382*61046927SAndroid Build Coastguard Worker       default:
383*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Unrecognized option \"%s\".\n", optarg);
384*61046927SAndroid Build Coastguard Worker          print_usage(argv[0], stderr);
385*61046927SAndroid Build Coastguard Worker          return 1;
386*61046927SAndroid Build Coastguard Worker       }
387*61046927SAndroid Build Coastguard Worker    }
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    for (int i = optind; i < argc; i++) {
390*61046927SAndroid Build Coastguard Worker       util_dynarray_append(&clang_args, char *, argv[i]);
391*61046927SAndroid Build Coastguard Worker    }
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker    if (util_dynarray_num_elements(&input_files, char *) == 0) {
394*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "No input file(s).\n");
395*61046927SAndroid Build Coastguard Worker       print_usage(argv[0], stderr);
396*61046927SAndroid Build Coastguard Worker       return -1;
397*61046927SAndroid Build Coastguard Worker    }
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker    if (prefix == NULL) {
400*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "No prefix specified.\n");
401*61046927SAndroid Build Coastguard Worker       print_usage(argv[0], stderr);
402*61046927SAndroid Build Coastguard Worker       return -1;
403*61046927SAndroid Build Coastguard Worker    }
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker    struct clc_logger logger = {
406*61046927SAndroid Build Coastguard Worker       .error = msg_callback,
407*61046927SAndroid Build Coastguard Worker       .warning = msg_callback,
408*61046927SAndroid Build Coastguard Worker    };
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&input_files, char *, infile) {
411*61046927SAndroid Build Coastguard Worker       int fd = open(*infile, O_RDONLY);
412*61046927SAndroid Build Coastguard Worker       if (fd < 0) {
413*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Failed to open %s\n", *infile);
414*61046927SAndroid Build Coastguard Worker          ralloc_free(mem_ctx);
415*61046927SAndroid Build Coastguard Worker          return 1;
416*61046927SAndroid Build Coastguard Worker       }
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker       off_t len = lseek(fd, 0, SEEK_END);
419*61046927SAndroid Build Coastguard Worker       const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
420*61046927SAndroid Build Coastguard Worker       close(fd);
421*61046927SAndroid Build Coastguard Worker       if (map == MAP_FAILED) {
422*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "Failed to mmap the file: errno=%d, %s\n", errno,
423*61046927SAndroid Build Coastguard Worker                  strerror(errno));
424*61046927SAndroid Build Coastguard Worker          ralloc_free(mem_ctx);
425*61046927SAndroid Build Coastguard Worker          return 1;
426*61046927SAndroid Build Coastguard Worker       }
427*61046927SAndroid Build Coastguard Worker 
428*61046927SAndroid Build Coastguard Worker       const char *allowed_spirv_extensions[] = {
429*61046927SAndroid Build Coastguard Worker          "SPV_EXT_shader_atomic_float_add",
430*61046927SAndroid Build Coastguard Worker          "SPV_EXT_shader_atomic_float_min_max",
431*61046927SAndroid Build Coastguard Worker          "SPV_KHR_float_controls",
432*61046927SAndroid Build Coastguard Worker          "SPV_INTEL_subgroups",
433*61046927SAndroid Build Coastguard Worker          NULL,
434*61046927SAndroid Build Coastguard Worker       };
435*61046927SAndroid Build Coastguard Worker 
436*61046927SAndroid Build Coastguard Worker       struct clc_compile_args clc_args = {
437*61046927SAndroid Build Coastguard Worker          .source =
438*61046927SAndroid Build Coastguard Worker             {
439*61046927SAndroid Build Coastguard Worker                .name = *infile,
440*61046927SAndroid Build Coastguard Worker                .value = map,
441*61046927SAndroid Build Coastguard Worker             },
442*61046927SAndroid Build Coastguard Worker          .features =
443*61046927SAndroid Build Coastguard Worker             {
444*61046927SAndroid Build Coastguard Worker                .fp16 = true,
445*61046927SAndroid Build Coastguard Worker                .intel_subgroups = true,
446*61046927SAndroid Build Coastguard Worker                .subgroups = true,
447*61046927SAndroid Build Coastguard Worker                .subgroups_ifp = true,
448*61046927SAndroid Build Coastguard Worker             },
449*61046927SAndroid Build Coastguard Worker          .args = util_dynarray_begin(&clang_args),
450*61046927SAndroid Build Coastguard Worker          .num_args = util_dynarray_num_elements(&clang_args, char *),
451*61046927SAndroid Build Coastguard Worker          .allowed_spirv_extensions = allowed_spirv_extensions,
452*61046927SAndroid Build Coastguard Worker       };
453*61046927SAndroid Build Coastguard Worker 
454*61046927SAndroid Build Coastguard Worker       struct clc_binary *spirv_out =
455*61046927SAndroid Build Coastguard Worker          util_dynarray_grow(&spirv_objs, struct clc_binary, 1);
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker       if (!clc_compile_c_to_spirv(&clc_args, &logger, spirv_out)) {
458*61046927SAndroid Build Coastguard Worker          ralloc_free(mem_ctx);
459*61046927SAndroid Build Coastguard Worker          return 1;
460*61046927SAndroid Build Coastguard Worker       }
461*61046927SAndroid Build Coastguard Worker    }
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&spirv_objs, struct clc_binary, p) {
464*61046927SAndroid Build Coastguard Worker       util_dynarray_append(&spirv_ptr_objs, struct clc_binary *, p);
465*61046927SAndroid Build Coastguard Worker    }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    /* The SPIRV-Tools linker started checking that all modules have the same
468*61046927SAndroid Build Coastguard Worker     * version. But SPIRV-LLVM-Translator picks the lower required version for
469*61046927SAndroid Build Coastguard Worker     * each module it compiles. So we have to iterate over all of them and set
470*61046927SAndroid Build Coastguard Worker     * the max found to make SPIRV-Tools link our modules.
471*61046927SAndroid Build Coastguard Worker     *
472*61046927SAndroid Build Coastguard Worker     * TODO: This is not the correct thing to do. We need SPIRV-LLVM-Translator
473*61046927SAndroid Build Coastguard Worker     *       to pick a given SPIRV version given to it and have all the modules
474*61046927SAndroid Build Coastguard Worker     *       at that version. We should remove this hack when this issue is
475*61046927SAndroid Build Coastguard Worker     *       fixed :
476*61046927SAndroid Build Coastguard Worker     *       https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1445
477*61046927SAndroid Build Coastguard Worker     */
478*61046927SAndroid Build Coastguard Worker    uint32_t max_spirv_version = 0;
479*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&spirv_ptr_objs, struct clc_binary *, module) {
480*61046927SAndroid Build Coastguard Worker       max_spirv_version =
481*61046927SAndroid Build Coastguard Worker          MAX2(max_spirv_version,
482*61046927SAndroid Build Coastguard Worker               get_module_spirv_version((*module)->data, (*module)->size));
483*61046927SAndroid Build Coastguard Worker    }
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    assert(max_spirv_version > 0);
486*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&spirv_ptr_objs, struct clc_binary *, module) {
487*61046927SAndroid Build Coastguard Worker       set_module_spirv_version((*module)->data, (*module)->size,
488*61046927SAndroid Build Coastguard Worker                                max_spirv_version);
489*61046927SAndroid Build Coastguard Worker    }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker    struct clc_linker_args link_args = {
492*61046927SAndroid Build Coastguard Worker       .in_objs = util_dynarray_begin(&spirv_ptr_objs),
493*61046927SAndroid Build Coastguard Worker       .num_in_objs =
494*61046927SAndroid Build Coastguard Worker          util_dynarray_num_elements(&spirv_ptr_objs, struct clc_binary *),
495*61046927SAndroid Build Coastguard Worker       .create_library = true,
496*61046927SAndroid Build Coastguard Worker    };
497*61046927SAndroid Build Coastguard Worker    struct clc_binary final_spirv;
498*61046927SAndroid Build Coastguard Worker    if (!clc_link_spirv(&link_args, &logger, &final_spirv)) {
499*61046927SAndroid Build Coastguard Worker       ralloc_free(mem_ctx);
500*61046927SAndroid Build Coastguard Worker       return 1;
501*61046927SAndroid Build Coastguard Worker    }
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    if (spv_outfile) {
504*61046927SAndroid Build Coastguard Worker       FILE *fp = fopen(spv_outfile, "w");
505*61046927SAndroid Build Coastguard Worker       fwrite(final_spirv.data, final_spirv.size, 1, fp);
506*61046927SAndroid Build Coastguard Worker       fclose(fp);
507*61046927SAndroid Build Coastguard Worker    }
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker    FILE *fp = stdout;
510*61046927SAndroid Build Coastguard Worker    if (outfile != NULL)
511*61046927SAndroid Build Coastguard Worker       fp = fopen(outfile, "w");
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker    glsl_type_singleton_init_or_ref();
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    fprintf(fp, "/*\n");
516*61046927SAndroid Build Coastguard Worker    fprintf(fp, " * Copyright The Asahi Linux Contributors\n");
517*61046927SAndroid Build Coastguard Worker    fprintf(fp, " * SPDX-License-Identifier: MIT\n");
518*61046927SAndroid Build Coastguard Worker    fprintf(fp, " *\n");
519*61046927SAndroid Build Coastguard Worker    fprintf(fp, " * Autogenerated file, do not edit\n");
520*61046927SAndroid Build Coastguard Worker    fprintf(fp, " */\n");
521*61046927SAndroid Build Coastguard Worker    fprintf(fp, " #include <stdint.h>\n");
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker    /* Compile SPIR-V to NIR */
524*61046927SAndroid Build Coastguard Worker    nir_shader *nir = compile(mem_ctx, final_spirv.data, final_spirv.size);
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker    {
527*61046927SAndroid Build Coastguard Worker       nir_builder b = nir_builder_init_simple_shader(
528*61046927SAndroid Build Coastguard Worker          MESA_SHADER_COMPUTE, &agx_nir_options, "Helper shader");
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker       nir_function *func =
531*61046927SAndroid Build Coastguard Worker          nir_shader_get_function_for_name(nir, "libagx_helper");
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker       nir_call(&b, nir_function_clone(b.shader, func));
534*61046927SAndroid Build Coastguard Worker 
535*61046927SAndroid Build Coastguard Worker       struct agx_shader_part compiled;
536*61046927SAndroid Build Coastguard Worker       struct agx_shader_key key = {
537*61046927SAndroid Build Coastguard Worker          .libagx = nir,
538*61046927SAndroid Build Coastguard Worker          .is_helper = true,
539*61046927SAndroid Build Coastguard Worker       };
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker       agx_preprocess_nir(b.shader, nir);
542*61046927SAndroid Build Coastguard Worker       agx_compile_shader_nir(b.shader, &key, NULL, &compiled);
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker       print_u32_data(fp, "libagx_g13", "helper", compiled.binary,
545*61046927SAndroid Build Coastguard Worker                      compiled.binary_size);
546*61046927SAndroid Build Coastguard Worker       free(compiled.binary);
547*61046927SAndroid Build Coastguard Worker       ralloc_free(b.shader);
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker       /* Remove the NIR function, it's compiled, we don't need it at runtime */
550*61046927SAndroid Build Coastguard Worker       exec_node_remove(&func->node);
551*61046927SAndroid Build Coastguard Worker    }
552*61046927SAndroid Build Coastguard Worker 
553*61046927SAndroid Build Coastguard Worker    spirv_library_to_nir_builder(fp, final_spirv.data, final_spirv.size / 4,
554*61046927SAndroid Build Coastguard Worker                                 &spirv_options);
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    /* Serialize NIR for embedding */
557*61046927SAndroid Build Coastguard Worker    struct blob blob;
558*61046927SAndroid Build Coastguard Worker    blob_init(&blob);
559*61046927SAndroid Build Coastguard Worker    nir_serialize(&blob, nir, false /* strip */);
560*61046927SAndroid Build Coastguard Worker    print_u32_data(fp, prefix, "nir", (const uint32_t *)blob.data, blob.size);
561*61046927SAndroid Build Coastguard Worker    blob_finish(&blob);
562*61046927SAndroid Build Coastguard Worker 
563*61046927SAndroid Build Coastguard Worker    glsl_type_singleton_decref();
564*61046927SAndroid Build Coastguard Worker 
565*61046927SAndroid Build Coastguard Worker    if (fp != stdout)
566*61046927SAndroid Build Coastguard Worker       fclose(fp);
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&spirv_objs, struct clc_binary, p) {
569*61046927SAndroid Build Coastguard Worker       clc_free_spirv(p);
570*61046927SAndroid Build Coastguard Worker    }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker    clc_free_spirv(&final_spirv);
573*61046927SAndroid Build Coastguard Worker    ralloc_free(mem_ctx);
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker    return 0;
576*61046927SAndroid Build Coastguard Worker }
577