xref: /aosp_15_r20/external/mesa3d/src/microsoft/clc/clc_nir.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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