xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/brw_kernel.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2020 Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "brw_kernel.h"
25*61046927SAndroid Build Coastguard Worker #include "brw_nir.h"
26*61046927SAndroid Build Coastguard Worker #include "elk/elk_nir_options.h"
27*61046927SAndroid Build Coastguard Worker #include "intel_nir.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include "intel_nir.h"
30*61046927SAndroid Build Coastguard Worker #include "nir_clc_helpers.h"
31*61046927SAndroid Build Coastguard Worker #include "compiler/nir/nir_builder.h"
32*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/nir_spirv.h"
33*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/spirv_info.h"
34*61046927SAndroid Build Coastguard Worker #include "dev/intel_debug.h"
35*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
36*61046927SAndroid Build Coastguard Worker #include "util/u_dynarray.h"
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker static const nir_shader *
load_clc_shader(struct brw_compiler * compiler,struct disk_cache * disk_cache,const nir_shader_compiler_options * nir_options,const struct spirv_to_nir_options * spirv_options)39*61046927SAndroid Build Coastguard Worker load_clc_shader(struct brw_compiler *compiler, struct disk_cache *disk_cache,
40*61046927SAndroid Build Coastguard Worker                 const nir_shader_compiler_options *nir_options,
41*61046927SAndroid Build Coastguard Worker                 const struct spirv_to_nir_options *spirv_options)
42*61046927SAndroid Build Coastguard Worker {
43*61046927SAndroid Build Coastguard Worker    if (compiler->clc_shader)
44*61046927SAndroid Build Coastguard Worker       return compiler->clc_shader;
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker    nir_shader *nir =  nir_load_libclc_shader(64, disk_cache,
47*61046927SAndroid Build Coastguard Worker                                              spirv_options, nir_options,
48*61046927SAndroid Build Coastguard Worker                                              disk_cache != NULL);
49*61046927SAndroid Build Coastguard Worker    if (nir == NULL)
50*61046927SAndroid Build Coastguard Worker       return NULL;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker    const nir_shader *old_nir =
53*61046927SAndroid Build Coastguard Worker       p_atomic_cmpxchg(&compiler->clc_shader, NULL, nir);
54*61046927SAndroid Build Coastguard Worker    if (old_nir == NULL) {
55*61046927SAndroid Build Coastguard Worker       /* We won the race */
56*61046927SAndroid Build Coastguard Worker       ralloc_steal(compiler, nir);
57*61046927SAndroid Build Coastguard Worker       return nir;
58*61046927SAndroid Build Coastguard Worker    } else {
59*61046927SAndroid Build Coastguard Worker       /* Someone else built the shader first */
60*61046927SAndroid Build Coastguard Worker       ralloc_free(nir);
61*61046927SAndroid Build Coastguard Worker       return old_nir;
62*61046927SAndroid Build Coastguard Worker    }
63*61046927SAndroid Build Coastguard Worker }
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker static nir_builder
builder_init_new_impl(nir_function * func)66*61046927SAndroid Build Coastguard Worker builder_init_new_impl(nir_function *func)
67*61046927SAndroid Build Coastguard Worker {
68*61046927SAndroid Build Coastguard Worker    nir_function_impl *impl = nir_function_impl_create(func);
69*61046927SAndroid Build Coastguard Worker    return nir_builder_at(nir_before_impl(impl));
70*61046927SAndroid Build Coastguard Worker }
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker static void
implement_atomic_builtin(nir_function * func,nir_atomic_op atomic_op,enum glsl_base_type data_base_type,nir_variable_mode mode)73*61046927SAndroid Build Coastguard Worker implement_atomic_builtin(nir_function *func, nir_atomic_op atomic_op,
74*61046927SAndroid Build Coastguard Worker                          enum glsl_base_type data_base_type,
75*61046927SAndroid Build Coastguard Worker                          nir_variable_mode mode)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker    nir_builder b = builder_init_new_impl(func);
78*61046927SAndroid Build Coastguard Worker    const struct glsl_type *data_type = glsl_scalar_type(data_base_type);
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    unsigned p = 0;
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker    nir_deref_instr *ret = NULL;
83*61046927SAndroid Build Coastguard Worker    ret = nir_build_deref_cast(&b, nir_load_param(&b, p++),
84*61046927SAndroid Build Coastguard Worker                               nir_var_function_temp, data_type, 0);
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    nir_intrinsic_op op = nir_intrinsic_deref_atomic;
87*61046927SAndroid Build Coastguard Worker    nir_intrinsic_instr *atomic = nir_intrinsic_instr_create(b.shader, op);
88*61046927SAndroid Build Coastguard Worker    nir_intrinsic_set_atomic_op(atomic, atomic_op);
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < nir_intrinsic_infos[op].num_srcs; i++) {
91*61046927SAndroid Build Coastguard Worker       nir_def *src = nir_load_param(&b, p++);
92*61046927SAndroid Build Coastguard Worker       if (i == 0) {
93*61046927SAndroid Build Coastguard Worker          /* The first source is our deref */
94*61046927SAndroid Build Coastguard Worker          assert(nir_intrinsic_infos[op].src_components[i] == -1);
95*61046927SAndroid Build Coastguard Worker          src = &nir_build_deref_cast(&b, src, mode, data_type, 0)->def;
96*61046927SAndroid Build Coastguard Worker       }
97*61046927SAndroid Build Coastguard Worker       atomic->src[i] = nir_src_for_ssa(src);
98*61046927SAndroid Build Coastguard Worker    }
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    nir_def_init_for_type(&atomic->instr, &atomic->def, data_type);
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    nir_builder_instr_insert(&b, &atomic->instr);
103*61046927SAndroid Build Coastguard Worker    nir_store_deref(&b, ret, &atomic->def, ~0);
104*61046927SAndroid Build Coastguard Worker }
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker static void
implement_sub_group_ballot_builtin(nir_function * func)107*61046927SAndroid Build Coastguard Worker implement_sub_group_ballot_builtin(nir_function *func)
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker    nir_builder b = builder_init_new_impl(func);
110*61046927SAndroid Build Coastguard Worker    nir_deref_instr *ret =
111*61046927SAndroid Build Coastguard Worker       nir_build_deref_cast(&b, nir_load_param(&b, 0),
112*61046927SAndroid Build Coastguard Worker                            nir_var_function_temp, glsl_uint_type(), 0);
113*61046927SAndroid Build Coastguard Worker    nir_def *cond = nir_load_param(&b, 1);
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    nir_intrinsic_instr *ballot =
116*61046927SAndroid Build Coastguard Worker       nir_intrinsic_instr_create(b.shader, nir_intrinsic_ballot);
117*61046927SAndroid Build Coastguard Worker    ballot->src[0] = nir_src_for_ssa(cond);
118*61046927SAndroid Build Coastguard Worker    ballot->num_components = 1;
119*61046927SAndroid Build Coastguard Worker    nir_def_init(&ballot->instr, &ballot->def, 1, 32);
120*61046927SAndroid Build Coastguard Worker    nir_builder_instr_insert(&b, &ballot->instr);
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    nir_store_deref(&b, ret, &ballot->def, ~0);
123*61046927SAndroid Build Coastguard Worker }
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker static bool
implement_intel_builtins(nir_shader * nir)126*61046927SAndroid Build Coastguard Worker implement_intel_builtins(nir_shader *nir)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker    bool progress = false;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    nir_foreach_function(func, nir) {
131*61046927SAndroid Build Coastguard Worker       if (strcmp(func->name, "_Z10atomic_minPU3AS1Vff") == 0) {
132*61046927SAndroid Build Coastguard Worker          /* float atom_min(__global float volatile *p, float val) */
133*61046927SAndroid Build Coastguard Worker          implement_atomic_builtin(func, nir_atomic_op_fmin,
134*61046927SAndroid Build Coastguard Worker                                   GLSL_TYPE_FLOAT, nir_var_mem_global);
135*61046927SAndroid Build Coastguard Worker          progress = true;
136*61046927SAndroid Build Coastguard Worker       } else if (strcmp(func->name, "_Z10atomic_maxPU3AS1Vff") == 0) {
137*61046927SAndroid Build Coastguard Worker          /* float atom_max(__global float volatile *p, float val) */
138*61046927SAndroid Build Coastguard Worker          implement_atomic_builtin(func, nir_atomic_op_fmax,
139*61046927SAndroid Build Coastguard Worker                                   GLSL_TYPE_FLOAT, nir_var_mem_global);
140*61046927SAndroid Build Coastguard Worker          progress = true;
141*61046927SAndroid Build Coastguard Worker       } else if (strcmp(func->name, "_Z10atomic_minPU3AS3Vff") == 0) {
142*61046927SAndroid Build Coastguard Worker          /* float atomic_min(__shared float volatile *, float) */
143*61046927SAndroid Build Coastguard Worker          implement_atomic_builtin(func, nir_atomic_op_fmin,
144*61046927SAndroid Build Coastguard Worker                                   GLSL_TYPE_FLOAT, nir_var_mem_shared);
145*61046927SAndroid Build Coastguard Worker          progress = true;
146*61046927SAndroid Build Coastguard Worker       } else if (strcmp(func->name, "_Z10atomic_maxPU3AS3Vff") == 0) {
147*61046927SAndroid Build Coastguard Worker          /* float atomic_max(__shared float volatile *, float) */
148*61046927SAndroid Build Coastguard Worker          implement_atomic_builtin(func, nir_atomic_op_fmax,
149*61046927SAndroid Build Coastguard Worker                                   GLSL_TYPE_FLOAT, nir_var_mem_shared);
150*61046927SAndroid Build Coastguard Worker          progress = true;
151*61046927SAndroid Build Coastguard Worker       } else if (strcmp(func->name, "intel_sub_group_ballot") == 0) {
152*61046927SAndroid Build Coastguard Worker          implement_sub_group_ballot_builtin(func);
153*61046927SAndroid Build Coastguard Worker          progress = true;
154*61046927SAndroid Build Coastguard Worker       }
155*61046927SAndroid Build Coastguard Worker    }
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    nir_shader_preserve_all_metadata(nir);
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    return progress;
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker static bool
lower_kernel_intrinsics(nir_shader * nir)163*61046927SAndroid Build Coastguard Worker lower_kernel_intrinsics(nir_shader *nir)
164*61046927SAndroid Build Coastguard Worker {
165*61046927SAndroid Build Coastguard Worker    nir_function_impl *impl = nir_shader_get_entrypoint(nir);
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    bool progress = false;
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    unsigned kernel_sysvals_start = 0;
170*61046927SAndroid Build Coastguard Worker    unsigned kernel_arg_start = sizeof(struct brw_kernel_sysvals);
171*61046927SAndroid Build Coastguard Worker    nir->num_uniforms += kernel_arg_start;
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    nir_builder b = nir_builder_create(impl);
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker    nir_foreach_block(block, impl) {
176*61046927SAndroid Build Coastguard Worker       nir_foreach_instr_safe(instr, block) {
177*61046927SAndroid Build Coastguard Worker          if (instr->type != nir_instr_type_intrinsic)
178*61046927SAndroid Build Coastguard Worker             continue;
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker          nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
181*61046927SAndroid Build Coastguard Worker          switch (intrin->intrinsic) {
182*61046927SAndroid Build Coastguard Worker          case nir_intrinsic_load_kernel_input: {
183*61046927SAndroid Build Coastguard Worker             b.cursor = nir_instr_remove(&intrin->instr);
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker             nir_intrinsic_instr *load =
186*61046927SAndroid Build Coastguard Worker                nir_intrinsic_instr_create(nir, nir_intrinsic_load_uniform);
187*61046927SAndroid Build Coastguard Worker             load->num_components = intrin->num_components;
188*61046927SAndroid Build Coastguard Worker             load->src[0] = nir_src_for_ssa(nir_u2u32(&b, intrin->src[0].ssa));
189*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_base(load, kernel_arg_start);
190*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_range(load, nir->num_uniforms);
191*61046927SAndroid Build Coastguard Worker             nir_def_init(&load->instr, &load->def,
192*61046927SAndroid Build Coastguard Worker                          intrin->def.num_components,
193*61046927SAndroid Build Coastguard Worker                          intrin->def.bit_size);
194*61046927SAndroid Build Coastguard Worker             nir_builder_instr_insert(&b, &load->instr);
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker             nir_def_rewrite_uses(&intrin->def, &load->def);
197*61046927SAndroid Build Coastguard Worker             progress = true;
198*61046927SAndroid Build Coastguard Worker             break;
199*61046927SAndroid Build Coastguard Worker          }
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker          case nir_intrinsic_load_constant_base_ptr: {
202*61046927SAndroid Build Coastguard Worker             b.cursor = nir_instr_remove(&intrin->instr);
203*61046927SAndroid Build Coastguard Worker             nir_def *const_data_base_addr = nir_pack_64_2x32_split(&b,
204*61046927SAndroid Build Coastguard Worker                nir_load_reloc_const_intel(&b, BRW_SHADER_RELOC_CONST_DATA_ADDR_LOW),
205*61046927SAndroid Build Coastguard Worker                nir_load_reloc_const_intel(&b, BRW_SHADER_RELOC_CONST_DATA_ADDR_HIGH));
206*61046927SAndroid Build Coastguard Worker             nir_def_rewrite_uses(&intrin->def, const_data_base_addr);
207*61046927SAndroid Build Coastguard Worker             progress = true;
208*61046927SAndroid Build Coastguard Worker             break;
209*61046927SAndroid Build Coastguard Worker          }
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker          case nir_intrinsic_load_num_workgroups: {
212*61046927SAndroid Build Coastguard Worker             b.cursor = nir_instr_remove(&intrin->instr);
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker             nir_intrinsic_instr *load =
215*61046927SAndroid Build Coastguard Worker                nir_intrinsic_instr_create(nir, nir_intrinsic_load_uniform);
216*61046927SAndroid Build Coastguard Worker             load->num_components = 3;
217*61046927SAndroid Build Coastguard Worker             load->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0));
218*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_base(load, kernel_sysvals_start +
219*61046927SAndroid Build Coastguard Worker                offsetof(struct brw_kernel_sysvals, num_work_groups));
220*61046927SAndroid Build Coastguard Worker             nir_intrinsic_set_range(load, 3 * 4);
221*61046927SAndroid Build Coastguard Worker             nir_def_init(&load->instr, &load->def, 3, 32);
222*61046927SAndroid Build Coastguard Worker             nir_builder_instr_insert(&b, &load->instr);
223*61046927SAndroid Build Coastguard Worker             nir_def_rewrite_uses(&intrin->def, &load->def);
224*61046927SAndroid Build Coastguard Worker             progress = true;
225*61046927SAndroid Build Coastguard Worker             break;
226*61046927SAndroid Build Coastguard Worker          }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker          default:
229*61046927SAndroid Build Coastguard Worker             break;
230*61046927SAndroid Build Coastguard Worker          }
231*61046927SAndroid Build Coastguard Worker       }
232*61046927SAndroid Build Coastguard Worker    }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    if (progress) {
235*61046927SAndroid Build Coastguard Worker       nir_metadata_preserve(impl, nir_metadata_control_flow);
236*61046927SAndroid Build Coastguard Worker    } else {
237*61046927SAndroid Build Coastguard Worker       nir_metadata_preserve(impl, nir_metadata_all);
238*61046927SAndroid Build Coastguard Worker    }
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker    return progress;
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker static const struct spirv_capabilities spirv_caps = {
244*61046927SAndroid Build Coastguard Worker    .Addresses = true,
245*61046927SAndroid Build Coastguard Worker    .Float16 = true,
246*61046927SAndroid Build Coastguard Worker    .Float64 = true,
247*61046927SAndroid Build Coastguard Worker    .Groups = true,
248*61046927SAndroid Build Coastguard Worker    .StorageImageWriteWithoutFormat = true,
249*61046927SAndroid Build Coastguard Worker    .Int8 = true,
250*61046927SAndroid Build Coastguard Worker    .Int16 = true,
251*61046927SAndroid Build Coastguard Worker    .Int64 = true,
252*61046927SAndroid Build Coastguard Worker    .Int64Atomics = true,
253*61046927SAndroid Build Coastguard Worker    .Kernel = true,
254*61046927SAndroid Build Coastguard Worker    .Linkage = true, /* We receive linked kernel from clc */
255*61046927SAndroid Build Coastguard Worker    .DenormFlushToZero = true,
256*61046927SAndroid Build Coastguard Worker    .DenormPreserve = true,
257*61046927SAndroid Build Coastguard Worker    .SignedZeroInfNanPreserve = true,
258*61046927SAndroid Build Coastguard Worker    .RoundingModeRTE = true,
259*61046927SAndroid Build Coastguard Worker    .RoundingModeRTZ = true,
260*61046927SAndroid Build Coastguard Worker    .GenericPointer = true,
261*61046927SAndroid Build Coastguard Worker    .GroupNonUniform = true,
262*61046927SAndroid Build Coastguard Worker    .GroupNonUniformArithmetic = true,
263*61046927SAndroid Build Coastguard Worker    .GroupNonUniformClustered = true,
264*61046927SAndroid Build Coastguard Worker    .GroupNonUniformBallot = true,
265*61046927SAndroid Build Coastguard Worker    .GroupNonUniformQuad = true,
266*61046927SAndroid Build Coastguard Worker    .GroupNonUniformShuffle = true,
267*61046927SAndroid Build Coastguard Worker    .GroupNonUniformVote = true,
268*61046927SAndroid Build Coastguard Worker    .SubgroupDispatch = true,
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    .SubgroupShuffleINTEL = true,
271*61046927SAndroid Build Coastguard Worker    .SubgroupBufferBlockIOINTEL = true,
272*61046927SAndroid Build Coastguard Worker };
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker bool
brw_kernel_from_spirv(struct brw_compiler * compiler,struct disk_cache * disk_cache,struct brw_kernel * kernel,void * log_data,void * mem_ctx,const uint32_t * spirv,size_t spirv_size,const char * entrypoint_name,char ** error_str)275*61046927SAndroid Build Coastguard Worker brw_kernel_from_spirv(struct brw_compiler *compiler,
276*61046927SAndroid Build Coastguard Worker                       struct disk_cache *disk_cache,
277*61046927SAndroid Build Coastguard Worker                       struct brw_kernel *kernel,
278*61046927SAndroid Build Coastguard Worker                       void *log_data, void *mem_ctx,
279*61046927SAndroid Build Coastguard Worker                       const uint32_t *spirv, size_t spirv_size,
280*61046927SAndroid Build Coastguard Worker                       const char *entrypoint_name,
281*61046927SAndroid Build Coastguard Worker                       char **error_str)
282*61046927SAndroid Build Coastguard Worker {
283*61046927SAndroid Build Coastguard Worker    const struct intel_device_info *devinfo = compiler->devinfo;
284*61046927SAndroid Build Coastguard Worker    const nir_shader_compiler_options *nir_options =
285*61046927SAndroid Build Coastguard Worker       compiler->nir_options[MESA_SHADER_KERNEL];
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    struct spirv_to_nir_options spirv_options = {
288*61046927SAndroid Build Coastguard Worker       .environment = NIR_SPIRV_OPENCL,
289*61046927SAndroid Build Coastguard Worker       .capabilities = &spirv_caps,
290*61046927SAndroid Build Coastguard Worker       .printf = true,
291*61046927SAndroid Build Coastguard Worker       .shared_addr_format = nir_address_format_62bit_generic,
292*61046927SAndroid Build Coastguard Worker       .global_addr_format = nir_address_format_62bit_generic,
293*61046927SAndroid Build Coastguard Worker       .temp_addr_format = nir_address_format_62bit_generic,
294*61046927SAndroid Build Coastguard Worker       .constant_addr_format = nir_address_format_64bit_global,
295*61046927SAndroid Build Coastguard Worker    };
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker    spirv_options.clc_shader = load_clc_shader(compiler, disk_cache,
298*61046927SAndroid Build Coastguard Worker                                               nir_options, &spirv_options);
299*61046927SAndroid Build Coastguard Worker    if (spirv_options.clc_shader == NULL) {
300*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: libclc shader missing."
301*61046927SAndroid Build Coastguard Worker               " Consider installing the libclc package\n");
302*61046927SAndroid Build Coastguard Worker       abort();
303*61046927SAndroid Build Coastguard Worker    }
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker    assert(spirv_size % 4 == 0);
306*61046927SAndroid Build Coastguard Worker    nir_shader *nir =
307*61046927SAndroid Build Coastguard Worker       spirv_to_nir(spirv, spirv_size / 4, NULL, 0, MESA_SHADER_KERNEL,
308*61046927SAndroid Build Coastguard Worker                    entrypoint_name, &spirv_options, nir_options);
309*61046927SAndroid Build Coastguard Worker    nir_validate_shader(nir, "after spirv_to_nir");
310*61046927SAndroid Build Coastguard Worker    nir_validate_ssa_dominance(nir, "after spirv_to_nir");
311*61046927SAndroid Build Coastguard Worker    ralloc_steal(mem_ctx, nir);
312*61046927SAndroid Build Coastguard Worker    nir->info.name = ralloc_strdup(nir, entrypoint_name);
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    if (INTEL_DEBUG(DEBUG_CS)) {
315*61046927SAndroid Build Coastguard Worker       /* Re-index SSA defs so we print more sensible numbers. */
316*61046927SAndroid Build Coastguard Worker       nir_foreach_function_impl(impl, nir) {
317*61046927SAndroid Build Coastguard Worker          nir_index_ssa_defs(impl);
318*61046927SAndroid Build Coastguard Worker       }
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "NIR (from SPIR-V) for kernel\n");
321*61046927SAndroid Build Coastguard Worker       nir_print_shader(nir, stderr);
322*61046927SAndroid Build Coastguard Worker    }
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker    nir_lower_printf_options printf_opts = {
325*61046927SAndroid Build Coastguard Worker       .ptr_bit_size               = 64,
326*61046927SAndroid Build Coastguard Worker       .use_printf_base_identifier = true,
327*61046927SAndroid Build Coastguard Worker    };
328*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_printf, &printf_opts);
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, implement_intel_builtins);
331*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_link_shader_functions, spirv_options.clc_shader);
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    /* We have to lower away local constant initializers right before we
334*61046927SAndroid Build Coastguard Worker     * inline functions.  That way they get properly initialized at the top
335*61046927SAndroid Build Coastguard Worker     * of the function and not at the top of its caller.
336*61046927SAndroid Build Coastguard Worker     */
337*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp);
338*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_returns);
339*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_inline_functions);
340*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_copy_prop);
341*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_opt_deref);
342*61046927SAndroid Build Coastguard Worker 
343*61046927SAndroid Build Coastguard Worker    /* Pick off the single entrypoint that we want */
344*61046927SAndroid Build Coastguard Worker    nir_remove_non_entrypoints(nir);
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker    /* Now that we've deleted all but the main function, we can go ahead and
347*61046927SAndroid Build Coastguard Worker     * lower the rest of the constant initializers.  We do this here so that
348*61046927SAndroid Build Coastguard Worker     * nir_remove_dead_variables and split_per_member_structs below see the
349*61046927SAndroid Build Coastguard Worker     * corresponding stores.
350*61046927SAndroid Build Coastguard Worker     */
351*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_variable_initializers, ~0);
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker    /* LLVM loves take advantage of the fact that vec3s in OpenCL are 16B
354*61046927SAndroid Build Coastguard Worker     * aligned and so it can just read/write them as vec4s.  This results in a
355*61046927SAndroid Build Coastguard Worker     * LOT of vec4->vec3 casts on loads and stores.  One solution to this
356*61046927SAndroid Build Coastguard Worker     * problem is to get rid of all vec3 variables.
357*61046927SAndroid Build Coastguard Worker     */
358*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vec3_to_vec4,
359*61046927SAndroid Build Coastguard Worker               nir_var_shader_temp | nir_var_function_temp |
360*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_mem_global|
361*61046927SAndroid Build Coastguard Worker               nir_var_mem_constant);
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    /* We assign explicit types early so that the optimizer can take advantage
364*61046927SAndroid Build Coastguard Worker     * of that information and hopefully get rid of some of our memcpys.
365*61046927SAndroid Build Coastguard Worker     */
366*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vars_to_explicit_types,
367*61046927SAndroid Build Coastguard Worker               nir_var_uniform |
368*61046927SAndroid Build Coastguard Worker               nir_var_shader_temp | nir_var_function_temp |
369*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_mem_global,
370*61046927SAndroid Build Coastguard Worker               glsl_get_cl_type_size_align);
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker    struct brw_nir_compiler_opts opts = {};
373*61046927SAndroid Build Coastguard Worker    brw_preprocess_nir(compiler, nir, &opts);
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    int max_arg_idx = -1;
376*61046927SAndroid Build Coastguard Worker    nir_foreach_uniform_variable(var, nir) {
377*61046927SAndroid Build Coastguard Worker       assert(var->data.location < 256);
378*61046927SAndroid Build Coastguard Worker       max_arg_idx = MAX2(max_arg_idx, var->data.location);
379*61046927SAndroid Build Coastguard Worker    }
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker    kernel->args_size = nir->num_uniforms;
382*61046927SAndroid Build Coastguard Worker    kernel->arg_count = max_arg_idx + 1;
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    /* No bindings */
385*61046927SAndroid Build Coastguard Worker    struct brw_kernel_arg_desc *args =
386*61046927SAndroid Build Coastguard Worker       rzalloc_array(mem_ctx, struct brw_kernel_arg_desc, kernel->arg_count);
387*61046927SAndroid Build Coastguard Worker    kernel->args = args;
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    nir_foreach_uniform_variable(var, nir) {
390*61046927SAndroid Build Coastguard Worker       struct brw_kernel_arg_desc arg_desc = {
391*61046927SAndroid Build Coastguard Worker          .offset = var->data.driver_location,
392*61046927SAndroid Build Coastguard Worker          .size = glsl_get_explicit_size(var->type, false),
393*61046927SAndroid Build Coastguard Worker       };
394*61046927SAndroid Build Coastguard Worker       assert(arg_desc.offset + arg_desc.size <= nir->num_uniforms);
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker       assert(var->data.location >= 0);
397*61046927SAndroid Build Coastguard Worker       args[var->data.location] = arg_desc;
398*61046927SAndroid Build Coastguard Worker    }
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_all, NULL);
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker    /* Lower again, this time after dead-variables to get more compact variable
403*61046927SAndroid Build Coastguard Worker     * layouts.
404*61046927SAndroid Build Coastguard Worker     */
405*61046927SAndroid Build Coastguard Worker    nir->global_mem_size = 0;
406*61046927SAndroid Build Coastguard Worker    nir->scratch_size = 0;
407*61046927SAndroid Build Coastguard Worker    nir->info.shared_size = 0;
408*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vars_to_explicit_types,
409*61046927SAndroid Build Coastguard Worker               nir_var_shader_temp | nir_var_function_temp |
410*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_mem_global | nir_var_mem_constant,
411*61046927SAndroid Build Coastguard Worker               glsl_get_cl_type_size_align);
412*61046927SAndroid Build Coastguard Worker    if (nir->constant_data_size > 0) {
413*61046927SAndroid Build Coastguard Worker       assert(nir->constant_data == NULL);
414*61046927SAndroid Build Coastguard Worker       nir->constant_data = rzalloc_size(nir, nir->constant_data_size);
415*61046927SAndroid Build Coastguard Worker       nir_gather_explicit_io_initializers(nir, nir->constant_data,
416*61046927SAndroid Build Coastguard Worker                                           nir->constant_data_size,
417*61046927SAndroid Build Coastguard Worker                                           nir_var_mem_constant);
418*61046927SAndroid Build Coastguard Worker    }
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker    if (INTEL_DEBUG(DEBUG_CS)) {
421*61046927SAndroid Build Coastguard Worker       /* Re-index SSA defs so we print more sensible numbers. */
422*61046927SAndroid Build Coastguard Worker       nir_foreach_function_impl(impl, nir) {
423*61046927SAndroid Build Coastguard Worker          nir_index_ssa_defs(impl);
424*61046927SAndroid Build Coastguard Worker       }
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "NIR (before I/O lowering) for kernel\n");
427*61046927SAndroid Build Coastguard Worker       nir_print_shader(nir, stderr);
428*61046927SAndroid Build Coastguard Worker    }
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_memcpy);
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_constant,
433*61046927SAndroid Build Coastguard Worker               nir_address_format_64bit_global);
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_uniform,
436*61046927SAndroid Build Coastguard Worker               nir_address_format_32bit_offset_as_64bit);
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io,
439*61046927SAndroid Build Coastguard Worker               nir_var_shader_temp | nir_var_function_temp |
440*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_mem_global,
441*61046927SAndroid Build Coastguard Worker               nir_address_format_62bit_generic);
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_convert_alu_types, NULL);
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, brw_nir_lower_cs_intrinsics, devinfo, NULL);
446*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, lower_kernel_intrinsics);
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker    struct brw_cs_prog_key key = { };
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker    memset(&kernel->prog_data, 0, sizeof(kernel->prog_data));
451*61046927SAndroid Build Coastguard Worker    kernel->prog_data.base.nr_params = DIV_ROUND_UP(nir->num_uniforms, 4);
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker    struct brw_compile_cs_params params = {
454*61046927SAndroid Build Coastguard Worker       .base = {
455*61046927SAndroid Build Coastguard Worker          .nir = nir,
456*61046927SAndroid Build Coastguard Worker          .stats = kernel->stats,
457*61046927SAndroid Build Coastguard Worker          .log_data = log_data,
458*61046927SAndroid Build Coastguard Worker          .mem_ctx = mem_ctx,
459*61046927SAndroid Build Coastguard Worker       },
460*61046927SAndroid Build Coastguard Worker       .key = &key,
461*61046927SAndroid Build Coastguard Worker       .prog_data = &kernel->prog_data,
462*61046927SAndroid Build Coastguard Worker    };
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker    kernel->code = brw_compile_cs(compiler, &params);
465*61046927SAndroid Build Coastguard Worker 
466*61046927SAndroid Build Coastguard Worker    if (error_str)
467*61046927SAndroid Build Coastguard Worker       *error_str = params.base.error_str;
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker    return kernel->code != NULL;
470*61046927SAndroid Build Coastguard Worker }
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker static nir_def *
rebuild_value_from_store(struct util_dynarray * stores,nir_def * value,unsigned read_offset)473*61046927SAndroid Build Coastguard Worker rebuild_value_from_store(struct util_dynarray *stores,
474*61046927SAndroid Build Coastguard Worker                          nir_def *value, unsigned read_offset)
475*61046927SAndroid Build Coastguard Worker {
476*61046927SAndroid Build Coastguard Worker    unsigned read_size = value->num_components * value->bit_size / 8;
477*61046927SAndroid Build Coastguard Worker 
478*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(stores, nir_intrinsic_instr *, _store) {
479*61046927SAndroid Build Coastguard Worker       nir_intrinsic_instr *store = *_store;
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker       unsigned write_offset = nir_src_as_uint(store->src[1]);
482*61046927SAndroid Build Coastguard Worker       unsigned write_size = nir_src_num_components(store->src[0]) *
483*61046927SAndroid Build Coastguard Worker                             nir_src_bit_size(store->src[0]) / 8;
484*61046927SAndroid Build Coastguard Worker       if (write_offset <= read_offset &&
485*61046927SAndroid Build Coastguard Worker           (write_offset + write_size) >= (read_offset + read_size)) {
486*61046927SAndroid Build Coastguard Worker          assert(nir_block_dominates(store->instr.block, value->parent_instr->block));
487*61046927SAndroid Build Coastguard Worker          assert(write_size == read_size);
488*61046927SAndroid Build Coastguard Worker          return store->src[0].ssa;
489*61046927SAndroid Build Coastguard Worker       }
490*61046927SAndroid Build Coastguard Worker    }
491*61046927SAndroid Build Coastguard Worker    unreachable("Matching scratch store not found");
492*61046927SAndroid Build Coastguard Worker }
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker /**
495*61046927SAndroid Build Coastguard Worker  * Remove temporary variables stored to scratch to be then reloaded
496*61046927SAndroid Build Coastguard Worker  * immediately. Remap the load to the store SSA value.
497*61046927SAndroid Build Coastguard Worker  *
498*61046927SAndroid Build Coastguard Worker  * This workaround is only meant to be applied to shaders in src/intel/shaders
499*61046927SAndroid Build Coastguard Worker  * were we know there should be no issue. More complex cases might not work
500*61046927SAndroid Build Coastguard Worker  * with this approach.
501*61046927SAndroid Build Coastguard Worker  */
502*61046927SAndroid Build Coastguard Worker static bool
nir_remove_llvm17_scratch(nir_shader * nir)503*61046927SAndroid Build Coastguard Worker nir_remove_llvm17_scratch(nir_shader *nir)
504*61046927SAndroid Build Coastguard Worker {
505*61046927SAndroid Build Coastguard Worker    struct util_dynarray scratch_stores;
506*61046927SAndroid Build Coastguard Worker    void *mem_ctx = ralloc_context(NULL);
507*61046927SAndroid Build Coastguard Worker 
508*61046927SAndroid Build Coastguard Worker    util_dynarray_init(&scratch_stores, mem_ctx);
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker    nir_foreach_function_impl(func, nir) {
511*61046927SAndroid Build Coastguard Worker       nir_foreach_block(block, func) {
512*61046927SAndroid Build Coastguard Worker          nir_foreach_instr(instr, block) {
513*61046927SAndroid Build Coastguard Worker             if (instr->type != nir_instr_type_intrinsic)
514*61046927SAndroid Build Coastguard Worker                continue;
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker             nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
517*61046927SAndroid Build Coastguard Worker 
518*61046927SAndroid Build Coastguard Worker             if (intrin->intrinsic != nir_intrinsic_store_scratch)
519*61046927SAndroid Build Coastguard Worker                continue;
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker             nir_const_value *offset = nir_src_as_const_value(intrin->src[1]);
522*61046927SAndroid Build Coastguard Worker             if (offset != NULL) {
523*61046927SAndroid Build Coastguard Worker                util_dynarray_append(&scratch_stores, nir_intrinsic_instr *, intrin);
524*61046927SAndroid Build Coastguard Worker             }
525*61046927SAndroid Build Coastguard Worker          }
526*61046927SAndroid Build Coastguard Worker       }
527*61046927SAndroid Build Coastguard Worker    }
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker    bool progress = false;
530*61046927SAndroid Build Coastguard Worker    if (util_dynarray_num_elements(&scratch_stores, nir_intrinsic_instr *) > 0) {
531*61046927SAndroid Build Coastguard Worker       nir_foreach_function_impl(func, nir) {
532*61046927SAndroid Build Coastguard Worker          nir_foreach_block(block, func) {
533*61046927SAndroid Build Coastguard Worker             nir_foreach_instr_safe(instr, block) {
534*61046927SAndroid Build Coastguard Worker                if (instr->type != nir_instr_type_intrinsic)
535*61046927SAndroid Build Coastguard Worker                   continue;
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker                nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker                if (intrin->intrinsic != nir_intrinsic_load_scratch)
540*61046927SAndroid Build Coastguard Worker                   continue;
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker                nir_const_value *offset = nir_src_as_const_value(intrin->src[0]);
543*61046927SAndroid Build Coastguard Worker                if (offset == NULL)
544*61046927SAndroid Build Coastguard Worker                   continue;
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker                nir_def_replace(&intrin->def,
547*61046927SAndroid Build Coastguard Worker                                rebuild_value_from_store(&scratch_stores, &intrin->def, nir_src_as_uint(intrin->src[0])));
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker                progress = true;
550*61046927SAndroid Build Coastguard Worker             }
551*61046927SAndroid Build Coastguard Worker          }
552*61046927SAndroid Build Coastguard Worker       }
553*61046927SAndroid Build Coastguard Worker    }
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&scratch_stores, nir_intrinsic_instr *, _store) {
556*61046927SAndroid Build Coastguard Worker       nir_intrinsic_instr *store = *_store;
557*61046927SAndroid Build Coastguard Worker       nir_instr_remove(&store->instr);
558*61046927SAndroid Build Coastguard Worker    }
559*61046927SAndroid Build Coastguard Worker 
560*61046927SAndroid Build Coastguard Worker    /* Quick sanity check */
561*61046927SAndroid Build Coastguard Worker    assert(util_dynarray_num_elements(&scratch_stores, nir_intrinsic_instr *) == 0 ||
562*61046927SAndroid Build Coastguard Worker           progress);
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker    ralloc_free(mem_ctx);
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    return progress;
567*61046927SAndroid Build Coastguard Worker }
568*61046927SAndroid Build Coastguard Worker 
569*61046927SAndroid Build Coastguard Worker static void
cleanup_llvm17_scratch(nir_shader * nir)570*61046927SAndroid Build Coastguard Worker cleanup_llvm17_scratch(nir_shader *nir)
571*61046927SAndroid Build Coastguard Worker {
572*61046927SAndroid Build Coastguard Worker    {
573*61046927SAndroid Build Coastguard Worker       bool progress;
574*61046927SAndroid Build Coastguard Worker       do {
575*61046927SAndroid Build Coastguard Worker          progress = false;
576*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_copy_prop);
577*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_dce);
578*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_constant_folding);
579*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_cse);
580*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_algebraic);
581*61046927SAndroid Build Coastguard Worker       } while (progress);
582*61046927SAndroid Build Coastguard Worker    }
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker    nir_remove_llvm17_scratch(nir);
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker    {
587*61046927SAndroid Build Coastguard Worker       bool progress;
588*61046927SAndroid Build Coastguard Worker       do {
589*61046927SAndroid Build Coastguard Worker          progress = false;
590*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_copy_prop);
591*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_dce);
592*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_constant_folding);
593*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_cse);
594*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_algebraic);
595*61046927SAndroid Build Coastguard Worker       } while (progress);
596*61046927SAndroid Build Coastguard Worker    }
597*61046927SAndroid Build Coastguard Worker }
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker nir_shader *
brw_nir_from_spirv(void * mem_ctx,unsigned gfx_version,const uint32_t * spirv,size_t spirv_size,bool llvm17_wa)600*61046927SAndroid Build Coastguard Worker brw_nir_from_spirv(void *mem_ctx, unsigned gfx_version, const uint32_t *spirv,
601*61046927SAndroid Build Coastguard Worker                    size_t spirv_size, bool llvm17_wa)
602*61046927SAndroid Build Coastguard Worker {
603*61046927SAndroid Build Coastguard Worker    struct spirv_to_nir_options spirv_options = {
604*61046927SAndroid Build Coastguard Worker       .environment = NIR_SPIRV_OPENCL,
605*61046927SAndroid Build Coastguard Worker       .capabilities = &spirv_caps,
606*61046927SAndroid Build Coastguard Worker       .printf = true,
607*61046927SAndroid Build Coastguard Worker       .shared_addr_format = nir_address_format_62bit_generic,
608*61046927SAndroid Build Coastguard Worker       .global_addr_format = nir_address_format_62bit_generic,
609*61046927SAndroid Build Coastguard Worker       .temp_addr_format = nir_address_format_62bit_generic,
610*61046927SAndroid Build Coastguard Worker       .constant_addr_format = nir_address_format_64bit_global,
611*61046927SAndroid Build Coastguard Worker       .create_library = true,
612*61046927SAndroid Build Coastguard Worker    };
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker    assert(spirv_size % 4 == 0);
615*61046927SAndroid Build Coastguard Worker 
616*61046927SAndroid Build Coastguard Worker    assert(gfx_version);
617*61046927SAndroid Build Coastguard Worker    const nir_shader_compiler_options *nir_options =
618*61046927SAndroid Build Coastguard Worker       gfx_version >= 9 ? &brw_scalar_nir_options
619*61046927SAndroid Build Coastguard Worker                        : &elk_scalar_nir_options;
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker    nir_shader *nir =
622*61046927SAndroid Build Coastguard Worker       spirv_to_nir(spirv, spirv_size / 4, NULL, 0, MESA_SHADER_KERNEL,
623*61046927SAndroid Build Coastguard Worker                    "library", &spirv_options, nir_options);
624*61046927SAndroid Build Coastguard Worker    nir_validate_shader(nir, "after spirv_to_nir");
625*61046927SAndroid Build Coastguard Worker    nir_validate_ssa_dominance(nir, "after spirv_to_nir");
626*61046927SAndroid Build Coastguard Worker    ralloc_steal(mem_ctx, nir);
627*61046927SAndroid Build Coastguard Worker    nir->info.name = ralloc_strdup(nir, "library");
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker    if (INTEL_DEBUG(DEBUG_CS)) {
630*61046927SAndroid Build Coastguard Worker       /* Re-index SSA defs so we print more sensible numbers. */
631*61046927SAndroid Build Coastguard Worker       nir_foreach_function_impl(impl, nir) {
632*61046927SAndroid Build Coastguard Worker          nir_index_ssa_defs(impl);
633*61046927SAndroid Build Coastguard Worker       }
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "NIR (from SPIR-V) for kernel\n");
636*61046927SAndroid Build Coastguard Worker       nir_print_shader(nir, stderr);
637*61046927SAndroid Build Coastguard Worker    }
638*61046927SAndroid Build Coastguard Worker 
639*61046927SAndroid Build Coastguard Worker    nir_lower_printf_options printf_opts = {
640*61046927SAndroid Build Coastguard Worker       .ptr_bit_size               = 64,
641*61046927SAndroid Build Coastguard Worker       .use_printf_base_identifier = true,
642*61046927SAndroid Build Coastguard Worker    };
643*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_printf, &printf_opts);
644*61046927SAndroid Build Coastguard Worker 
645*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, implement_intel_builtins);
646*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_link_shader_functions, spirv_options.clc_shader);
647*61046927SAndroid Build Coastguard Worker 
648*61046927SAndroid Build Coastguard Worker    /* We have to lower away local constant initializers right before we
649*61046927SAndroid Build Coastguard Worker     * inline functions.  That way they get properly initialized at the top
650*61046927SAndroid Build Coastguard Worker     * of the function and not at the top of its caller.
651*61046927SAndroid Build Coastguard Worker     */
652*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_variable_initializers, ~(nir_var_shader_temp |
653*61046927SAndroid Build Coastguard Worker                                                       nir_var_function_temp));
654*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_uniform | nir_var_mem_ubo |
655*61046927SAndroid Build Coastguard Worker               nir_var_mem_constant | nir_var_function_temp | nir_var_image, NULL);
656*61046927SAndroid Build Coastguard Worker    {
657*61046927SAndroid Build Coastguard Worker       bool progress;
658*61046927SAndroid Build Coastguard Worker       do
659*61046927SAndroid Build Coastguard Worker       {
660*61046927SAndroid Build Coastguard Worker          progress = false;
661*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_copy_prop);
662*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
663*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_deref);
664*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_dce);
665*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_undef);
666*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_constant_folding);
667*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_cse);
668*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
669*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_algebraic);
670*61046927SAndroid Build Coastguard Worker       } while (progress);
671*61046927SAndroid Build Coastguard Worker    }
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp);
674*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_returns);
675*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_inline_functions);
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker    assert(nir->scratch_size == 0);
678*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vars_to_explicit_types, nir_var_function_temp, glsl_get_cl_type_size_align);
679*61046927SAndroid Build Coastguard Worker 
680*61046927SAndroid Build Coastguard Worker    {
681*61046927SAndroid Build Coastguard Worker       bool progress;
682*61046927SAndroid Build Coastguard Worker       do
683*61046927SAndroid Build Coastguard Worker       {
684*61046927SAndroid Build Coastguard Worker          progress = false;
685*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_copy_prop);
686*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
687*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_deref);
688*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_dce);
689*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_undef);
690*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_constant_folding);
691*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_cse);
692*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_split_var_copies);
693*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_lower_var_copies);
694*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
695*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_algebraic);
696*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_if, nir_opt_if_optimize_phi_true_false);
697*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_dead_cf);
698*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_remove_phis);
699*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true);
700*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_lower_vec3_to_vec4, nir_var_mem_generic | nir_var_uniform);
701*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_memcpy);
702*61046927SAndroid Build Coastguard Worker       } while (progress);
703*61046927SAndroid Build Coastguard Worker    }
704*61046927SAndroid Build Coastguard Worker 
705*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_scale_fdiv);
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_uniform | nir_var_mem_ubo |
708*61046927SAndroid Build Coastguard Worker               nir_var_mem_constant | nir_var_function_temp | nir_var_image, NULL);
709*61046927SAndroid Build Coastguard Worker 
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_mem_shared | nir_var_function_temp, NULL);
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker    nir->scratch_size = 0;
714*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vars_to_explicit_types,
715*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_function_temp | nir_var_shader_temp |
716*61046927SAndroid Build Coastguard Worker               nir_var_mem_global | nir_var_mem_constant,
717*61046927SAndroid Build Coastguard Worker               glsl_get_cl_type_size_align);
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker    // Lower memcpy - needs to wait until types are sized
720*61046927SAndroid Build Coastguard Worker    {
721*61046927SAndroid Build Coastguard Worker       bool progress;
722*61046927SAndroid Build Coastguard Worker       do {
723*61046927SAndroid Build Coastguard Worker          progress = false;
724*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_memcpy);
725*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_copy_prop);
726*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_copy_prop_vars);
727*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_deref);
728*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_dce);
729*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_split_var_copies);
730*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_lower_var_copies);
731*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_lower_vars_to_ssa);
732*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_constant_folding);
733*61046927SAndroid Build Coastguard Worker          NIR_PASS(progress, nir, nir_opt_cse);
734*61046927SAndroid Build Coastguard Worker       } while (progress);
735*61046927SAndroid Build Coastguard Worker    }
736*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_memcpy);
737*61046927SAndroid Build Coastguard Worker 
738*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io,
739*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_function_temp | nir_var_shader_temp | nir_var_uniform,
740*61046927SAndroid Build Coastguard Worker               nir_address_format_32bit_offset_as_64bit);
741*61046927SAndroid Build Coastguard Worker 
742*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_system_values);
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker    /* Hopefully we can drop this once lower_vars_to_ssa has improved to not
745*61046927SAndroid Build Coastguard Worker     * lower everything to scratch.
746*61046927SAndroid Build Coastguard Worker     */
747*61046927SAndroid Build Coastguard Worker    if (llvm17_wa)
748*61046927SAndroid Build Coastguard Worker       cleanup_llvm17_scratch(nir);
749*61046927SAndroid Build Coastguard Worker 
750*61046927SAndroid Build Coastguard Worker    /* Lower again, this time after dead-variables to get more compact variable
751*61046927SAndroid Build Coastguard Worker     * layouts.
752*61046927SAndroid Build Coastguard Worker     */
753*61046927SAndroid Build Coastguard Worker    nir->global_mem_size = 0;
754*61046927SAndroid Build Coastguard Worker    nir->scratch_size = 0;
755*61046927SAndroid Build Coastguard Worker    nir->info.shared_size = 0;
756*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vars_to_explicit_types,
757*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_mem_global | nir_var_mem_constant,
758*61046927SAndroid Build Coastguard Worker               glsl_get_cl_type_size_align);
759*61046927SAndroid Build Coastguard Worker    if (nir->constant_data_size > 0) {
760*61046927SAndroid Build Coastguard Worker       assert(nir->constant_data == NULL);
761*61046927SAndroid Build Coastguard Worker       nir->constant_data = rzalloc_size(nir, nir->constant_data_size);
762*61046927SAndroid Build Coastguard Worker       nir_gather_explicit_io_initializers(nir, nir->constant_data,
763*61046927SAndroid Build Coastguard Worker                                           nir->constant_data_size,
764*61046927SAndroid Build Coastguard Worker                                           nir_var_mem_constant);
765*61046927SAndroid Build Coastguard Worker    }
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_mem_constant,
768*61046927SAndroid Build Coastguard Worker               nir_address_format_64bit_global);
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io, nir_var_uniform,
771*61046927SAndroid Build Coastguard Worker               nir_address_format_32bit_offset_as_64bit);
772*61046927SAndroid Build Coastguard Worker 
773*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_explicit_io,
774*61046927SAndroid Build Coastguard Worker               nir_var_shader_temp | nir_var_function_temp |
775*61046927SAndroid Build Coastguard Worker               nir_var_mem_shared | nir_var_mem_global,
776*61046927SAndroid Build Coastguard Worker               nir_address_format_62bit_generic);
777*61046927SAndroid Build Coastguard Worker 
778*61046927SAndroid Build Coastguard Worker    if (INTEL_DEBUG(DEBUG_CS)) {
779*61046927SAndroid Build Coastguard Worker       /* Re-index SSA defs so we print more sensible numbers. */
780*61046927SAndroid Build Coastguard Worker       nir_foreach_function_impl(impl, nir) {
781*61046927SAndroid Build Coastguard Worker          nir_index_ssa_defs(impl);
782*61046927SAndroid Build Coastguard Worker       }
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "NIR (before I/O lowering) for kernel\n");
785*61046927SAndroid Build Coastguard Worker       nir_print_shader(nir, stderr);
786*61046927SAndroid Build Coastguard Worker    }
787*61046927SAndroid Build Coastguard Worker 
788*61046927SAndroid Build Coastguard Worker    return nir;
789*61046927SAndroid Build Coastguard Worker }
790