1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © Microsoft 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 "util/u_math.h"
25*61046927SAndroid Build Coastguard Worker #include "nir.h"
26*61046927SAndroid Build Coastguard Worker #include "glsl_types.h"
27*61046927SAndroid Build Coastguard Worker #include "nir_builder.h"
28*61046927SAndroid Build Coastguard Worker #include "nir_deref.h"
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker #include "clc_nir.h"
31*61046927SAndroid Build Coastguard Worker #include "clc_compiler.h"
32*61046927SAndroid Build Coastguard Worker #include "../compiler/dxil_nir.h"
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard Worker static nir_def *
load_ubo(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * var,unsigned offset)35*61046927SAndroid Build Coastguard Worker load_ubo(nir_builder *b, nir_intrinsic_instr *intr, nir_variable *var, unsigned offset)
36*61046927SAndroid Build Coastguard Worker {
37*61046927SAndroid Build Coastguard Worker return nir_load_ubo(b,
38*61046927SAndroid Build Coastguard Worker intr->def.num_components,
39*61046927SAndroid Build Coastguard Worker intr->def.bit_size,
40*61046927SAndroid Build Coastguard Worker nir_imm_int(b, var->data.binding),
41*61046927SAndroid Build Coastguard Worker nir_imm_int(b, offset),
42*61046927SAndroid Build Coastguard Worker .align_mul = 256,
43*61046927SAndroid Build Coastguard Worker .align_offset = offset,
44*61046927SAndroid Build Coastguard Worker .range_base = offset,
45*61046927SAndroid Build Coastguard Worker .range = intr->def.bit_size * intr->def.num_components / 8);
46*61046927SAndroid Build Coastguard Worker }
47*61046927SAndroid Build Coastguard Worker
48*61046927SAndroid Build Coastguard Worker static bool
lower_load_base_global_invocation_id(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * var)49*61046927SAndroid Build Coastguard Worker lower_load_base_global_invocation_id(nir_builder *b, nir_intrinsic_instr *intr,
50*61046927SAndroid Build Coastguard Worker nir_variable *var)
51*61046927SAndroid Build Coastguard Worker {
52*61046927SAndroid Build Coastguard Worker b->cursor = nir_after_instr(&intr->instr);
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker nir_def *offset = load_ubo(b, intr, var, offsetof(struct clc_work_properties_data,
55*61046927SAndroid Build Coastguard Worker global_offset_x));
56*61046927SAndroid Build Coastguard Worker nir_def_replace(&intr->def, offset);
57*61046927SAndroid Build Coastguard Worker return true;
58*61046927SAndroid Build Coastguard Worker }
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Worker static bool
lower_load_work_dim(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * var)61*61046927SAndroid Build Coastguard Worker lower_load_work_dim(nir_builder *b, nir_intrinsic_instr *intr,
62*61046927SAndroid Build Coastguard Worker nir_variable *var)
63*61046927SAndroid Build Coastguard Worker {
64*61046927SAndroid Build Coastguard Worker b->cursor = nir_after_instr(&intr->instr);
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker nir_def *dim = load_ubo(b, intr, var, offsetof(struct clc_work_properties_data,
67*61046927SAndroid Build Coastguard Worker work_dim));
68*61046927SAndroid Build Coastguard Worker nir_def_replace(&intr->def, dim);
69*61046927SAndroid Build Coastguard Worker return true;
70*61046927SAndroid Build Coastguard Worker }
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker static bool
lower_load_num_workgroups(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * var)73*61046927SAndroid Build Coastguard Worker lower_load_num_workgroups(nir_builder *b, nir_intrinsic_instr *intr,
74*61046927SAndroid Build Coastguard Worker nir_variable *var)
75*61046927SAndroid Build Coastguard Worker {
76*61046927SAndroid Build Coastguard Worker b->cursor = nir_after_instr(&intr->instr);
77*61046927SAndroid Build Coastguard Worker
78*61046927SAndroid Build Coastguard Worker nir_def *count =
79*61046927SAndroid Build Coastguard Worker load_ubo(b, intr, var, offsetof(struct clc_work_properties_data,
80*61046927SAndroid Build Coastguard Worker group_count_total_x));
81*61046927SAndroid Build Coastguard Worker nir_def_replace(&intr->def, count);
82*61046927SAndroid Build Coastguard Worker return true;
83*61046927SAndroid Build Coastguard Worker }
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker static bool
lower_load_base_workgroup_id(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * var)86*61046927SAndroid Build Coastguard Worker lower_load_base_workgroup_id(nir_builder *b, nir_intrinsic_instr *intr,
87*61046927SAndroid Build Coastguard Worker nir_variable *var)
88*61046927SAndroid Build Coastguard Worker {
89*61046927SAndroid Build Coastguard Worker b->cursor = nir_after_instr(&intr->instr);
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker nir_def *offset =
92*61046927SAndroid Build Coastguard Worker load_ubo(b, intr, var, offsetof(struct clc_work_properties_data,
93*61046927SAndroid Build Coastguard Worker group_id_offset_x));
94*61046927SAndroid Build Coastguard Worker nir_def_replace(&intr->def, offset);
95*61046927SAndroid Build Coastguard Worker return true;
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker bool
clc_nir_lower_system_values(nir_shader * nir,nir_variable * var)99*61046927SAndroid Build Coastguard Worker clc_nir_lower_system_values(nir_shader *nir, nir_variable *var)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker bool progress = false;
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_function, func, node, &nir->functions) {
104*61046927SAndroid Build Coastguard Worker if (!func->is_entrypoint)
105*61046927SAndroid Build Coastguard Worker continue;
106*61046927SAndroid Build Coastguard Worker assert(func->impl);
107*61046927SAndroid Build Coastguard Worker
108*61046927SAndroid Build Coastguard Worker nir_builder b = nir_builder_create(func->impl);
109*61046927SAndroid Build Coastguard Worker
110*61046927SAndroid Build Coastguard Worker nir_foreach_block(block, func->impl) {
111*61046927SAndroid Build Coastguard Worker nir_foreach_instr_safe(instr, block) {
112*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_intrinsic)
113*61046927SAndroid Build Coastguard Worker continue;
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker switch (intr->intrinsic) {
118*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_base_global_invocation_id:
119*61046927SAndroid Build Coastguard Worker progress |= lower_load_base_global_invocation_id(&b, intr, var);
120*61046927SAndroid Build Coastguard Worker break;
121*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_work_dim:
122*61046927SAndroid Build Coastguard Worker progress |= lower_load_work_dim(&b, intr, var);
123*61046927SAndroid Build Coastguard Worker break;
124*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_num_workgroups:
125*61046927SAndroid Build Coastguard Worker progress |= lower_load_num_workgroups(&b, intr, var);
126*61046927SAndroid Build Coastguard Worker break;
127*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_base_workgroup_id:
128*61046927SAndroid Build Coastguard Worker progress |= lower_load_base_workgroup_id(&b, intr, var);
129*61046927SAndroid Build Coastguard Worker break;
130*61046927SAndroid Build Coastguard Worker default: break;
131*61046927SAndroid Build Coastguard Worker }
132*61046927SAndroid Build Coastguard Worker }
133*61046927SAndroid Build Coastguard Worker }
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker return progress;
137*61046927SAndroid Build Coastguard Worker }
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker static bool
lower_load_kernel_input(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * var)140*61046927SAndroid Build Coastguard Worker lower_load_kernel_input(nir_builder *b, nir_intrinsic_instr *intr,
141*61046927SAndroid Build Coastguard Worker nir_variable *var)
142*61046927SAndroid Build Coastguard Worker {
143*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&intr->instr);
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker unsigned bit_size = intr->def.bit_size;
146*61046927SAndroid Build Coastguard Worker enum glsl_base_type base_type;
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Worker switch (bit_size) {
149*61046927SAndroid Build Coastguard Worker case 64:
150*61046927SAndroid Build Coastguard Worker base_type = GLSL_TYPE_UINT64;
151*61046927SAndroid Build Coastguard Worker break;
152*61046927SAndroid Build Coastguard Worker case 32:
153*61046927SAndroid Build Coastguard Worker base_type = GLSL_TYPE_UINT;
154*61046927SAndroid Build Coastguard Worker break;
155*61046927SAndroid Build Coastguard Worker case 16:
156*61046927SAndroid Build Coastguard Worker base_type = GLSL_TYPE_UINT16;
157*61046927SAndroid Build Coastguard Worker break;
158*61046927SAndroid Build Coastguard Worker case 8:
159*61046927SAndroid Build Coastguard Worker base_type = GLSL_TYPE_UINT8;
160*61046927SAndroid Build Coastguard Worker break;
161*61046927SAndroid Build Coastguard Worker default:
162*61046927SAndroid Build Coastguard Worker unreachable("invalid bit size");
163*61046927SAndroid Build Coastguard Worker }
164*61046927SAndroid Build Coastguard Worker
165*61046927SAndroid Build Coastguard Worker const struct glsl_type *type =
166*61046927SAndroid Build Coastguard Worker glsl_vector_type(base_type, intr->def.num_components);
167*61046927SAndroid Build Coastguard Worker nir_def *ptr = nir_vec2(b, nir_imm_int(b, var->data.binding),
168*61046927SAndroid Build Coastguard Worker nir_u2uN(b, intr->src[0].ssa, 32));
169*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref = nir_build_deref_cast(b, ptr, nir_var_mem_ubo, type,
170*61046927SAndroid Build Coastguard Worker bit_size / 8);
171*61046927SAndroid Build Coastguard Worker deref->cast.align_mul = nir_intrinsic_align_mul(intr);
172*61046927SAndroid Build Coastguard Worker deref->cast.align_offset = nir_intrinsic_align_offset(intr);
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker nir_def *result =
175*61046927SAndroid Build Coastguard Worker nir_load_deref(b, deref);
176*61046927SAndroid Build Coastguard Worker nir_def_replace(&intr->def, result);
177*61046927SAndroid Build Coastguard Worker return true;
178*61046927SAndroid Build Coastguard Worker }
179*61046927SAndroid Build Coastguard Worker
180*61046927SAndroid Build Coastguard Worker bool
clc_nir_lower_kernel_input_loads(nir_shader * nir,nir_variable * var)181*61046927SAndroid Build Coastguard Worker clc_nir_lower_kernel_input_loads(nir_shader *nir, nir_variable *var)
182*61046927SAndroid Build Coastguard Worker {
183*61046927SAndroid Build Coastguard Worker bool progress = false;
184*61046927SAndroid Build Coastguard Worker
185*61046927SAndroid Build Coastguard Worker foreach_list_typed(nir_function, func, node, &nir->functions) {
186*61046927SAndroid Build Coastguard Worker if (!func->is_entrypoint)
187*61046927SAndroid Build Coastguard Worker continue;
188*61046927SAndroid Build Coastguard Worker assert(func->impl);
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker nir_builder b = nir_builder_create(func->impl);
191*61046927SAndroid Build Coastguard Worker
192*61046927SAndroid Build Coastguard Worker nir_foreach_block(block, func->impl) {
193*61046927SAndroid Build Coastguard Worker nir_foreach_instr_safe(instr, block) {
194*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_intrinsic)
195*61046927SAndroid Build Coastguard Worker continue;
196*61046927SAndroid Build Coastguard Worker
197*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker if (intr->intrinsic == nir_intrinsic_load_kernel_input)
200*61046927SAndroid Build Coastguard Worker progress |= lower_load_kernel_input(&b, intr, var);
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker }
203*61046927SAndroid Build Coastguard Worker }
204*61046927SAndroid Build Coastguard Worker
205*61046927SAndroid Build Coastguard Worker return progress;
206*61046927SAndroid Build Coastguard Worker }
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Worker static nir_variable *
add_printf_var(struct nir_shader * nir,unsigned uav_id)210*61046927SAndroid Build Coastguard Worker add_printf_var(struct nir_shader *nir, unsigned uav_id)
211*61046927SAndroid Build Coastguard Worker {
212*61046927SAndroid Build Coastguard Worker /* This size is arbitrary. Minimum required per spec is 1MB */
213*61046927SAndroid Build Coastguard Worker const unsigned max_printf_size = 1 * 1024 * 1024;
214*61046927SAndroid Build Coastguard Worker const unsigned printf_array_size = max_printf_size / sizeof(unsigned);
215*61046927SAndroid Build Coastguard Worker nir_variable *var =
216*61046927SAndroid Build Coastguard Worker nir_variable_create(nir, nir_var_mem_ssbo,
217*61046927SAndroid Build Coastguard Worker glsl_array_type(glsl_uint_type(), printf_array_size, sizeof(unsigned)),
218*61046927SAndroid Build Coastguard Worker "printf");
219*61046927SAndroid Build Coastguard Worker var->data.binding = uav_id;
220*61046927SAndroid Build Coastguard Worker return var;
221*61046927SAndroid Build Coastguard Worker }
222*61046927SAndroid Build Coastguard Worker
223*61046927SAndroid Build Coastguard Worker bool
clc_lower_printf_base(nir_shader * nir,unsigned uav_id)224*61046927SAndroid Build Coastguard Worker clc_lower_printf_base(nir_shader *nir, unsigned uav_id)
225*61046927SAndroid Build Coastguard Worker {
226*61046927SAndroid Build Coastguard Worker nir_variable *printf_var = NULL;
227*61046927SAndroid Build Coastguard Worker nir_def *printf_deref = NULL;
228*61046927SAndroid Build Coastguard Worker nir_foreach_function_impl(impl, nir) {
229*61046927SAndroid Build Coastguard Worker nir_builder b = nir_builder_at(nir_before_impl(impl));
230*61046927SAndroid Build Coastguard Worker bool progress = false;
231*61046927SAndroid Build Coastguard Worker
232*61046927SAndroid Build Coastguard Worker nir_foreach_block(block, impl) {
233*61046927SAndroid Build Coastguard Worker nir_foreach_instr_safe(instr, block) {
234*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_intrinsic)
235*61046927SAndroid Build Coastguard Worker continue;
236*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
237*61046927SAndroid Build Coastguard Worker if (intrin->intrinsic != nir_intrinsic_load_printf_buffer_address)
238*61046927SAndroid Build Coastguard Worker continue;
239*61046927SAndroid Build Coastguard Worker
240*61046927SAndroid Build Coastguard Worker if (!printf_var) {
241*61046927SAndroid Build Coastguard Worker printf_var = add_printf_var(nir, uav_id);
242*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref = nir_build_deref_var(&b, printf_var);
243*61046927SAndroid Build Coastguard Worker printf_deref = &deref->def;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker nir_def_rewrite_uses(&intrin->def, printf_deref);
246*61046927SAndroid Build Coastguard Worker progress = true;
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker }
249*61046927SAndroid Build Coastguard Worker
250*61046927SAndroid Build Coastguard Worker if (progress)
251*61046927SAndroid Build Coastguard Worker nir_metadata_preserve(impl, nir_metadata_loop_analysis |
252*61046927SAndroid Build Coastguard Worker nir_metadata_block_index |
253*61046927SAndroid Build Coastguard Worker nir_metadata_dominance);
254*61046927SAndroid Build Coastguard Worker else
255*61046927SAndroid Build Coastguard Worker nir_metadata_preserve(impl, nir_metadata_all);
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker return printf_var != NULL;
259*61046927SAndroid Build Coastguard Worker }
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker /* Find patterns of:
262*61046927SAndroid Build Coastguard Worker * - deref_var for one of the kernel inputs
263*61046927SAndroid Build Coastguard Worker * - load_deref to get a pointer to global/constant memory
264*61046927SAndroid Build Coastguard Worker * - cast the pointer into a deref
265*61046927SAndroid Build Coastguard Worker * - use a basic deref chain that terminates in a load/store/atomic
266*61046927SAndroid Build Coastguard Worker *
267*61046927SAndroid Build Coastguard Worker * When this pattern is found, replace the load_deref with a constant value,
268*61046927SAndroid Build Coastguard Worker * based on which kernel argument is being loaded from. This can only be done
269*61046927SAndroid Build Coastguard Worker * for chains that terminate in a pointer access, since the presence of null
270*61046927SAndroid Build Coastguard Worker * pointers should be detected by actually performing the load and inspecting
271*61046927SAndroid Build Coastguard Worker * the resulting pointer value.
272*61046927SAndroid Build Coastguard Worker */
273*61046927SAndroid Build Coastguard Worker static bool
lower_deref_base_to_constant(nir_builder * b,nir_intrinsic_instr * intr,void * context)274*61046927SAndroid Build Coastguard Worker lower_deref_base_to_constant(nir_builder *b, nir_intrinsic_instr *intr, void *context)
275*61046927SAndroid Build Coastguard Worker {
276*61046927SAndroid Build Coastguard Worker switch (intr->intrinsic) {
277*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_deref:
278*61046927SAndroid Build Coastguard Worker case nir_intrinsic_store_deref:
279*61046927SAndroid Build Coastguard Worker case nir_intrinsic_deref_atomic:
280*61046927SAndroid Build Coastguard Worker case nir_intrinsic_deref_atomic_swap:
281*61046927SAndroid Build Coastguard Worker break;
282*61046927SAndroid Build Coastguard Worker default:
283*61046927SAndroid Build Coastguard Worker return false;
284*61046927SAndroid Build Coastguard Worker }
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
287*61046927SAndroid Build Coastguard Worker if (!nir_deref_mode_must_be(deref, nir_var_mem_global | nir_var_mem_constant))
288*61046927SAndroid Build Coastguard Worker return false;
289*61046927SAndroid Build Coastguard Worker
290*61046927SAndroid Build Coastguard Worker nir_deref_path path;
291*61046927SAndroid Build Coastguard Worker nir_deref_path_init(&path, deref, NULL);
292*61046927SAndroid Build Coastguard Worker bool ret = false;
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker if (path.path[0]->deref_type != nir_deref_type_cast)
295*61046927SAndroid Build Coastguard Worker goto done;
296*61046927SAndroid Build Coastguard Worker if (!nir_deref_mode_must_be(path.path[0], nir_var_mem_global | nir_var_mem_constant))
297*61046927SAndroid Build Coastguard Worker goto done;
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker nir_instr *cast_src = path.path[0]->parent.ssa->parent_instr;
300*61046927SAndroid Build Coastguard Worker if (cast_src->type != nir_instr_type_intrinsic)
301*61046927SAndroid Build Coastguard Worker goto done;
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker nir_intrinsic_instr *cast_src_intr = nir_instr_as_intrinsic(cast_src);
304*61046927SAndroid Build Coastguard Worker if (cast_src_intr->intrinsic != nir_intrinsic_load_deref)
305*61046927SAndroid Build Coastguard Worker goto done;
306*61046927SAndroid Build Coastguard Worker
307*61046927SAndroid Build Coastguard Worker nir_deref_instr *load_deref_src = nir_src_as_deref(cast_src_intr->src[0]);
308*61046927SAndroid Build Coastguard Worker if (load_deref_src->deref_type != nir_deref_type_var ||
309*61046927SAndroid Build Coastguard Worker load_deref_src->modes != nir_var_uniform)
310*61046927SAndroid Build Coastguard Worker goto done;
311*61046927SAndroid Build Coastguard Worker
312*61046927SAndroid Build Coastguard Worker nir_variable *var = load_deref_src->var;
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker ret = true;
315*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&path.path[0]->instr);
316*61046927SAndroid Build Coastguard Worker nir_def *original_offset = nir_unpack_64_2x32_split_x(b, &cast_src_intr->def);
317*61046927SAndroid Build Coastguard Worker nir_def *constant_ptr = nir_pack_64_2x32_split(b, original_offset, nir_imm_int(b, var->data.binding));
318*61046927SAndroid Build Coastguard Worker nir_deref_instr *new_path = nir_build_deref_cast_with_alignment(b, constant_ptr, path.path[0]->modes, path.path[0]->type, path.path[0]->cast.ptr_stride,
319*61046927SAndroid Build Coastguard Worker path.path[0]->cast.align_mul, path.path[0]->cast.align_offset);
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Worker for (unsigned i = 1; path.path[i]; ++i) {
322*61046927SAndroid Build Coastguard Worker b->cursor = nir_after_instr(&path.path[i]->instr);
323*61046927SAndroid Build Coastguard Worker new_path = nir_build_deref_follower(b, new_path, path.path[i]);
324*61046927SAndroid Build Coastguard Worker }
325*61046927SAndroid Build Coastguard Worker nir_src_rewrite(&intr->src[0], &new_path->def);
326*61046927SAndroid Build Coastguard Worker
327*61046927SAndroid Build Coastguard Worker done:
328*61046927SAndroid Build Coastguard Worker nir_deref_path_finish(&path);
329*61046927SAndroid Build Coastguard Worker return ret;
330*61046927SAndroid Build Coastguard Worker }
331*61046927SAndroid Build Coastguard Worker
332*61046927SAndroid Build Coastguard Worker bool
clc_nir_lower_global_pointers_to_constants(nir_shader * nir)333*61046927SAndroid Build Coastguard Worker clc_nir_lower_global_pointers_to_constants(nir_shader *nir)
334*61046927SAndroid Build Coastguard Worker {
335*61046927SAndroid Build Coastguard Worker return nir_shader_intrinsics_pass(nir, lower_deref_base_to_constant,
336*61046927SAndroid Build Coastguard Worker nir_metadata_control_flow |
337*61046927SAndroid Build Coastguard Worker nir_metadata_loop_analysis, NULL);
338*61046927SAndroid Build Coastguard Worker }
339