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