xref: /aosp_15_r20/external/mesa3d/src/microsoft/compiler/dxil_nir_lower_int_cubemaps.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "dxil_nir_lower_int_cubemaps.h"
25 
26 #include "nir_builder.h"
27 #include "nir_builtin_builder.h"
28 
29 static bool
type_needs_lowering(const struct glsl_type * type,bool lower_samplers)30 type_needs_lowering(const struct glsl_type *type, bool lower_samplers)
31 {
32    type = glsl_without_array(type);
33    if (!glsl_type_is_image(type) && !glsl_type_is_sampler(type))
34       return false;
35    if (glsl_get_sampler_dim(type) != GLSL_SAMPLER_DIM_CUBE)
36       return false;
37    if (glsl_type_is_image(type))
38       return true;
39    return lower_samplers && glsl_base_type_is_integer(glsl_get_sampler_result_type(type));
40 }
41 
42 static bool
lower_int_cubmap_to_array_filter(const nir_instr * instr,const void * options)43 lower_int_cubmap_to_array_filter(const nir_instr *instr,
44                                  const void *options)
45 {
46    bool lower_samplers = *(bool *)options;
47    if (instr->type == nir_instr_type_intrinsic) {
48       nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
49       switch (intr->intrinsic) {
50       case nir_intrinsic_image_atomic:
51       case nir_intrinsic_image_atomic_swap:
52       case nir_intrinsic_image_load:
53       case nir_intrinsic_image_size:
54       case nir_intrinsic_image_store:
55       case nir_intrinsic_image_deref_atomic:
56       case nir_intrinsic_image_deref_atomic_swap:
57       case nir_intrinsic_image_deref_load:
58       case nir_intrinsic_image_deref_size:
59       case nir_intrinsic_image_deref_store:
60          return nir_intrinsic_image_dim(intr) == GLSL_SAMPLER_DIM_CUBE;
61       default:
62          return false;
63       }
64    } else if (instr->type == nir_instr_type_deref) {
65       nir_deref_instr *deref = nir_instr_as_deref(instr);
66       return type_needs_lowering(deref->type, lower_samplers);
67    } else if (instr->type == nir_instr_type_tex && lower_samplers) {
68       nir_tex_instr *tex = nir_instr_as_tex(instr);
69 
70       if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
71          return false;
72 
73       switch (tex->op) {
74       case nir_texop_tex:
75       case nir_texop_txb:
76       case nir_texop_txd:
77       case nir_texop_txl:
78       case nir_texop_txs:
79       case nir_texop_lod:
80       case nir_texop_tg4:
81          break;
82       default:
83          return false;
84       }
85 
86       int sampler_deref = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
87       assert(sampler_deref >= 0);
88       nir_deref_instr *deref = nir_instr_as_deref(tex->src[sampler_deref].src.ssa->parent_instr);
89       nir_variable *cube = nir_deref_instr_get_variable(deref);
90       return glsl_base_type_is_integer(glsl_get_sampler_result_type(cube->type));
91    }
92 
93    return false;
94 }
95 
96 typedef struct {
97    bool image;
98    nir_def *rx;
99    nir_def *ry;
100    nir_def *rz;
101    nir_def *arx;
102    nir_def *ary;
103    nir_def *arz;
104    nir_def *array;
105 } coord_t;
106 
107 
108 /* This is taken from from sp_tex_sample:convert_cube */
109 static nir_def *
evaluate_face_x(nir_builder * b,coord_t * coord)110 evaluate_face_x(nir_builder *b, coord_t *coord)
111 {
112    nir_def *sign = nir_fsign(b, coord->rx);
113    nir_def *positive = nir_fge_imm(b, coord->rx, 0.0);
114    nir_def *ima = nir_fdiv(b, nir_imm_float(b, -0.5), coord->arx);
115 
116    nir_def *x = nir_fadd_imm(b, nir_fmul(b, nir_fmul(b, sign, ima), coord->rz), 0.5);
117    nir_def *y = nir_fadd_imm(b, nir_fmul(b, ima, coord->ry), 0.5);
118    nir_def *face = nir_bcsel(b, positive, nir_imm_float(b, 0.0), nir_imm_float(b, 1.0));
119 
120    if (coord->array)
121       face = nir_fadd(b, face, coord->array);
122 
123    return coord->image ?
124       nir_vec4(b, x,y, face, nir_undef(b, 1, 32)) :
125       nir_vec3(b, x,y, face);
126 }
127 
128 static nir_def *
evaluate_face_y(nir_builder * b,coord_t * coord)129 evaluate_face_y(nir_builder *b, coord_t *coord)
130 {
131    nir_def *sign = nir_fsign(b, coord->ry);
132    nir_def *positive = nir_fge_imm(b, coord->ry, 0.0);
133    nir_def *ima = nir_fdiv(b, nir_imm_float(b, 0.5), coord->ary);
134 
135    nir_def *x = nir_fadd_imm(b, nir_fmul(b, ima, coord->rx), 0.5);
136    nir_def *y = nir_fadd_imm(b, nir_fmul(b, nir_fmul(b, sign, ima), coord->rz), 0.5);
137    nir_def *face = nir_bcsel(b, positive, nir_imm_float(b, 2.0), nir_imm_float(b, 3.0));
138 
139    if (coord->array)
140       face = nir_fadd(b, face, coord->array);
141 
142    return coord->image ?
143       nir_vec4(b, x,y, face, nir_undef(b, 1, 32)) :
144       nir_vec3(b, x,y, face);
145 }
146 
147 static nir_def *
evaluate_face_z(nir_builder * b,coord_t * coord)148 evaluate_face_z(nir_builder *b, coord_t *coord)
149 {
150    nir_def *sign = nir_fsign(b, coord->rz);
151    nir_def *positive = nir_fge_imm(b, coord->rz, 0.0);
152    nir_def *ima = nir_fdiv(b, nir_imm_float(b, -0.5), coord->arz);
153 
154    nir_def *x = nir_fadd_imm(b, nir_fmul(b, nir_fmul(b, sign, ima), nir_fneg(b, coord->rx)), 0.5);
155    nir_def *y = nir_fadd_imm(b, nir_fmul(b, ima, coord->ry), 0.5);
156    nir_def *face = nir_bcsel(b, positive, nir_imm_float(b, 4.0), nir_imm_float(b, 5.0));
157 
158    if (coord->array)
159       face = nir_fadd(b, face, coord->array);
160 
161    return coord->image ?
162       nir_vec4(b, x,y, face, nir_undef(b, 1, 32)) :
163       nir_vec3(b, x,y, face);
164 }
165 
166 static nir_def *
create_array_tex_from_cube_tex(nir_builder * b,nir_tex_instr * tex,nir_def * coord,nir_texop op)167 create_array_tex_from_cube_tex(nir_builder *b, nir_tex_instr *tex, nir_def *coord, nir_texop op)
168 {
169    nir_tex_instr *array_tex;
170 
171    array_tex = nir_tex_instr_create(b->shader, tex->num_srcs);
172    array_tex->op = op;
173    array_tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
174    array_tex->is_array = true;
175    array_tex->is_shadow = tex->is_shadow;
176    array_tex->is_new_style_shadow = tex->is_new_style_shadow;
177    array_tex->texture_index = tex->texture_index;
178    array_tex->sampler_index = tex->sampler_index;
179    array_tex->dest_type = tex->dest_type;
180    array_tex->coord_components = 3;
181 
182    nir_src coord_src = nir_src_for_ssa(coord);
183    for (unsigned i = 0; i < tex->num_srcs; i++) {
184       nir_src *psrc = (tex->src[i].src_type == nir_tex_src_coord) ?
185                          &coord_src : &tex->src[i].src;
186 
187       array_tex->src[i].src = nir_src_for_ssa(psrc->ssa);
188       array_tex->src[i].src_type = tex->src[i].src_type;
189    }
190 
191    nir_def_init(&array_tex->instr, &array_tex->def,
192                 nir_tex_instr_dest_size(array_tex), 32);
193    nir_builder_instr_insert(b, &array_tex->instr);
194    return &array_tex->def;
195 }
196 
197 static nir_def *
handle_cube_edge(nir_builder * b,nir_def * x,nir_def * y,nir_def * face,nir_def * array_slice_cube_base,nir_def * tex_size)198 handle_cube_edge(nir_builder *b, nir_def *x, nir_def *y, nir_def *face, nir_def *array_slice_cube_base, nir_def *tex_size)
199 {
200    enum cube_remap
201    {
202       cube_remap_zero = 0,
203       cube_remap_x,
204       cube_remap_y,
205       cube_remap_tex_size,
206       cube_remap_tex_size_minus_x,
207       cube_remap_tex_size_minus_y,
208 
209       cube_remap_size,
210    };
211 
212    struct cube_remap_table
213    {
214       enum cube_remap remap_x;
215       enum cube_remap remap_y;
216       uint32_t        remap_face;
217    };
218 
219    static const struct cube_remap_table cube_remap_neg_x[6] =
220    {
221        {cube_remap_tex_size,         cube_remap_y,         4},
222        {cube_remap_tex_size,         cube_remap_y,         5},
223        {cube_remap_y,                cube_remap_zero,      1},
224        {cube_remap_tex_size_minus_y, cube_remap_tex_size,  1},
225        {cube_remap_tex_size,         cube_remap_y,         1},
226        {cube_remap_tex_size,         cube_remap_y,         0},
227    };
228 
229    static const struct cube_remap_table cube_remap_pos_x[6] =
230    {
231        {cube_remap_zero,             cube_remap_y,         5},
232        {cube_remap_zero,             cube_remap_y,         4},
233        {cube_remap_tex_size_minus_y, cube_remap_zero,      0},
234        {cube_remap_y,                cube_remap_tex_size,  0},
235        {cube_remap_zero,             cube_remap_y,         0},
236        {cube_remap_zero,             cube_remap_y,         1},
237    };
238 
239    static const struct cube_remap_table cube_remap_neg_y[6] =
240    {
241        {cube_remap_tex_size,         cube_remap_tex_size_minus_x, 2},
242        {cube_remap_zero,             cube_remap_x,                2},
243        {cube_remap_tex_size_minus_x, cube_remap_zero,             5},
244        {cube_remap_x,                cube_remap_tex_size,         4},
245        {cube_remap_x,                cube_remap_tex_size,         2},
246        {cube_remap_tex_size_minus_x, cube_remap_zero,             2},
247    };
248 
249    static const struct cube_remap_table cube_remap_pos_y[6] =
250    {
251        {cube_remap_tex_size,         cube_remap_x,                   3},
252        {cube_remap_zero,             cube_remap_tex_size_minus_x,    3},
253        {cube_remap_x,                cube_remap_zero,                4},
254        {cube_remap_tex_size_minus_x, cube_remap_tex_size,            5},
255        {cube_remap_x,                cube_remap_zero,                3},
256        {cube_remap_tex_size_minus_x, cube_remap_tex_size,            3},
257    };
258 
259    static const struct cube_remap_table* remap_tables[4] = {
260       cube_remap_neg_x,
261       cube_remap_pos_x,
262       cube_remap_neg_y,
263       cube_remap_pos_y
264    };
265 
266    nir_def *zero = nir_imm_int(b, 0);
267 
268    /* Doesn't matter since the texture is square */
269    tex_size = nir_channel(b, tex_size, 0);
270 
271    nir_def *x_on = nir_iand(b, nir_ige(b, x, zero), nir_ige(b, tex_size, x));
272    nir_def *y_on = nir_iand(b, nir_ige(b, y, zero), nir_ige(b, tex_size, y));
273    nir_def *one_on = nir_ixor(b, x_on, y_on);
274 
275    /* If the sample did not fall off the face in either dimension, then set output = input */
276    nir_def *x_result = x;
277    nir_def *y_result = y;
278    nir_def *face_result = face;
279 
280    /* otherwise, if the sample fell off the face in either the X or the Y direction, remap to the new face */
281    nir_def *remap_predicates[4] =
282    {
283       nir_iand(b, one_on, nir_ilt(b, x, zero)),
284       nir_iand(b, one_on, nir_ilt(b, tex_size, x)),
285       nir_iand(b, one_on, nir_ilt(b, y, zero)),
286       nir_iand(b, one_on, nir_ilt(b, tex_size, y)),
287    };
288 
289    nir_def *remap_array[cube_remap_size];
290 
291    remap_array[cube_remap_zero] = zero;
292    remap_array[cube_remap_x] = x;
293    remap_array[cube_remap_y] = y;
294    remap_array[cube_remap_tex_size] = tex_size;
295    remap_array[cube_remap_tex_size_minus_x] = nir_isub(b, tex_size, x);
296    remap_array[cube_remap_tex_size_minus_y] = nir_isub(b, tex_size, y);
297 
298    /* For each possible way the sample could have fallen off */
299    for (unsigned i = 0; i < 4; i++) {
300       const struct cube_remap_table* remap_table = remap_tables[i];
301 
302       /* For each possible original face */
303       for (unsigned j = 0; j < 6; j++) {
304          nir_def *predicate = nir_iand(b, remap_predicates[i], nir_ieq_imm(b, face, j));
305 
306          x_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_x], x_result);
307          y_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_y], y_result);
308          face_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_face], face_result);
309       }
310    }
311 
312    return nir_vec3(b, x_result, y_result, nir_iadd(b, face_result, array_slice_cube_base));
313 }
314 
315 static nir_def *
handle_cube_gather(nir_builder * b,nir_tex_instr * tex,nir_def * coord)316 handle_cube_gather(nir_builder *b, nir_tex_instr *tex, nir_def *coord)
317 {
318    nir_def *tex_size = nir_get_texture_size(b, tex);
319 
320    /* nir_get_texture_size puts the cursor before the tex op */
321    b->cursor = nir_after_instr(coord->parent_instr);
322 
323    nir_def *const_05 = nir_imm_float(b, 0.5f);
324    nir_def *texel_coords = nir_fmul(b, nir_trim_vector(b, coord, 2),
325                                         nir_i2f32(b, nir_trim_vector(b, tex_size, 2)));
326 
327    nir_def *x_orig = nir_channel(b, texel_coords, 0);
328    nir_def *y_orig = nir_channel(b, texel_coords, 1);
329 
330    nir_def *x_pos = nir_f2i32(b, nir_fadd(b, x_orig, const_05));
331    nir_def *x_neg = nir_f2i32(b, nir_fsub(b, x_orig, const_05));
332    nir_def *y_pos = nir_f2i32(b, nir_fadd(b, y_orig, const_05));
333    nir_def *y_neg = nir_f2i32(b, nir_fsub(b, y_orig, const_05));
334    nir_def *coords[4][2] = {
335       { x_neg, y_pos },
336       { x_pos, y_pos },
337       { x_pos, y_neg },
338       { x_neg, y_neg },
339    };
340 
341    nir_def *array_slice_2d = nir_f2i32(b, nir_channel(b, coord, 2));
342    nir_def *face = nir_imod_imm(b, array_slice_2d, 6);
343    nir_def *array_slice_cube_base = nir_isub(b, array_slice_2d, face);
344 
345    nir_def *channels[4];
346    for (unsigned i = 0; i < 4; ++i) {
347       nir_def *final_coord = handle_cube_edge(b, coords[i][0], coords[i][1], face, array_slice_cube_base, tex_size);
348       nir_def *sampled_val = create_array_tex_from_cube_tex(b, tex, final_coord, nir_texop_txf);
349       channels[i] = nir_channel(b, sampled_val, tex->component);
350    }
351 
352    return nir_vec(b, channels, 4);
353 }
354 
355 static nir_def *
lower_cube_coords(nir_builder * b,nir_def * coord,bool is_array,bool is_image)356 lower_cube_coords(nir_builder *b, nir_def *coord, bool is_array, bool is_image)
357 {
358    coord_t coords;
359    coords.image = is_image;
360    coords.rx = nir_channel(b, coord, 0);
361    coords.ry = nir_channel(b, coord, 1);
362    coords.rz = nir_channel(b, coord, 2);
363    coords.arx = nir_fabs(b, coords.rx);
364    coords.ary = nir_fabs(b, coords.ry);
365    coords.arz = nir_fabs(b, coords.rz);
366    coords.array = NULL;
367    if (is_array)
368       coords.array = nir_fmul_imm(b, nir_channel(b, coord, 3), 6.0f);
369 
370    nir_def *use_face_x = nir_iand(b,
371                                       nir_fge(b, coords.arx, coords.ary),
372                                       nir_fge(b, coords.arx, coords.arz));
373 
374    nir_if *use_face_x_if = nir_push_if(b, use_face_x);
375    nir_def *face_x_coord = evaluate_face_x(b, &coords);
376    nir_if *use_face_x_else = nir_push_else(b, use_face_x_if);
377 
378    nir_def *use_face_y = nir_iand(b,
379                                       nir_fge(b, coords.ary, coords.arx),
380                                       nir_fge(b, coords.ary, coords.arz));
381 
382    nir_if *use_face_y_if = nir_push_if(b, use_face_y);
383    nir_def *face_y_coord = evaluate_face_y(b, &coords);
384    nir_if *use_face_y_else = nir_push_else(b, use_face_y_if);
385 
386    nir_def *face_z_coord = evaluate_face_z(b, &coords);
387 
388    nir_pop_if(b, use_face_y_else);
389    nir_def *face_y_or_z_coord = nir_if_phi(b, face_y_coord, face_z_coord);
390    nir_pop_if(b, use_face_x_else);
391 
392    // This contains in xy the normalized sample coordinates, and in z the face index
393    nir_def *coord_and_face = nir_if_phi(b, face_x_coord, face_y_or_z_coord);
394 
395    return coord_and_face;
396 }
397 
398 static nir_def *
lower_cube_sample(nir_builder * b,nir_tex_instr * tex)399 lower_cube_sample(nir_builder *b, nir_tex_instr *tex)
400 {
401    int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
402    assert(coord_index >= 0);
403 
404    /* Evaluate the face and the xy coordinates for a 2D tex op */
405    nir_def *coord = tex->src[coord_index].src.ssa;
406    nir_def *coord_and_face = lower_cube_coords(b, coord, tex->is_array, false);
407 
408    if (tex->op == nir_texop_tg4)
409       return handle_cube_gather(b, tex, coord_and_face);
410    else
411       return create_array_tex_from_cube_tex(b, tex, coord_and_face, tex->op);
412 }
413 
414 static nir_def *
lower_cube_image_load_store_atomic(nir_builder * b,nir_intrinsic_instr * intr)415 lower_cube_image_load_store_atomic(nir_builder *b, nir_intrinsic_instr *intr)
416 {
417    b->cursor = nir_before_instr(&intr->instr);
418    nir_intrinsic_set_image_array(intr, true);
419    nir_intrinsic_set_image_dim(intr, GLSL_SAMPLER_DIM_2D);
420 
421    return NIR_LOWER_INSTR_PROGRESS;
422 }
423 
424 static nir_def *
lower_cube_txs(nir_builder * b,nir_tex_instr * tex)425 lower_cube_txs(nir_builder *b, nir_tex_instr *tex)
426 {
427    b->cursor = nir_after_instr(&tex->instr);
428    if (!tex->is_array)
429       return nir_trim_vector(b, &tex->def, 2);
430 
431    nir_def *array_dim = nir_channel(b, &tex->def, 2);
432    nir_def *cube_array_dim = nir_idiv(b, array_dim, nir_imm_int(b, 6));
433    return nir_vec3(b, nir_channel(b, &tex->def, 0),
434                       nir_channel(b, &tex->def, 1),
435                       cube_array_dim);
436 }
437 
438 static nir_def *
lower_cube_image_size(nir_builder * b,nir_intrinsic_instr * intr)439 lower_cube_image_size(nir_builder *b, nir_intrinsic_instr *intr)
440 {
441    b->cursor = nir_after_instr(&intr->instr);
442    if (!nir_intrinsic_image_array(intr))
443       return nir_trim_vector(b, &intr->def, 2);
444 
445    nir_def *array_dim = nir_channel(b, &intr->def, 2);
446    nir_def *cube_array_dim = nir_idiv(b, array_dim, nir_imm_int(b, 6));
447    return nir_vec3(b, nir_channel(b, &intr->def, 0),
448                       nir_channel(b, &intr->def, 1),
449                       cube_array_dim);
450 }
451 
452 static const struct glsl_type *
make_2darray_sampler_from_cubemap(const struct glsl_type * type)453 make_2darray_sampler_from_cubemap(const struct glsl_type *type)
454 {
455    return  glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ?
456             glsl_sampler_type(
457                GLSL_SAMPLER_DIM_2D,
458                false, true,
459                glsl_get_sampler_result_type(type)) : type;
460 }
461 
462 static const struct glsl_type *
make_2darray_image_from_cubemap(const struct glsl_type * type)463 make_2darray_image_from_cubemap(const struct glsl_type *type)
464 {
465    return  glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ?
466             glsl_image_type(
467                GLSL_SAMPLER_DIM_2D,
468                true,
469                glsl_get_sampler_result_type(type)) : type;
470 }
471 
472 static const struct glsl_type *
make_2darray_from_cubemap_with_array(const struct glsl_type * type,bool is_image)473 make_2darray_from_cubemap_with_array(const struct glsl_type *type, bool is_image)
474 {
475    if (glsl_type_is_array(type)) {
476       const struct glsl_type *new_type = glsl_without_array(type);
477       return new_type != type ? glsl_array_type(make_2darray_from_cubemap_with_array(glsl_without_array(type), is_image),
478                                                 glsl_get_length(type), 0) : type;
479    } else if (is_image)
480       return make_2darray_image_from_cubemap(type);
481    else
482       return make_2darray_sampler_from_cubemap(type);
483 }
484 
485 static nir_def *
lower_int_cubemap_to_array_tex(nir_builder * b,nir_tex_instr * tex)486 lower_int_cubemap_to_array_tex(nir_builder *b, nir_tex_instr *tex)
487 {
488    switch (tex->op) {
489    case nir_texop_tex:
490    case nir_texop_txb:
491    case nir_texop_txd:
492    case nir_texop_txl:
493    case nir_texop_lod:
494    case nir_texop_tg4:
495       return lower_cube_sample(b, tex);
496    case nir_texop_txs:
497       return lower_cube_txs(b, tex);
498    default:
499       unreachable("Unsupported cupe map texture operation");
500    }
501 }
502 
503 static nir_def *
lower_cube_image_intrinsic(nir_builder * b,nir_intrinsic_instr * intr)504 lower_cube_image_intrinsic(nir_builder *b, nir_intrinsic_instr *intr)
505 {
506    if (intr->intrinsic == nir_intrinsic_image_size ||
507       intr->intrinsic == nir_intrinsic_image_deref_size)
508       return lower_cube_image_size(b, intr);
509    else
510       return lower_cube_image_load_store_atomic(b, intr);
511 }
512 
513 static nir_def *
lower_cube_image_deref(nir_builder * b,nir_deref_instr * deref)514 lower_cube_image_deref(nir_builder *b, nir_deref_instr *deref)
515 {
516    deref->type = make_2darray_from_cubemap_with_array(
517       deref->type,
518       glsl_type_is_image(glsl_without_array(deref->type)));
519    return NIR_LOWER_INSTR_PROGRESS;
520 }
521 
522 static nir_def *
lower_int_cubmap_to_array_impl(nir_builder * b,nir_instr * instr,void * options)523 lower_int_cubmap_to_array_impl(nir_builder *b, nir_instr *instr,
524                                void *options)
525 {
526    bool lower_samplers = *(bool *)options;
527    if (instr->type == nir_instr_type_tex && lower_samplers)
528       return lower_int_cubemap_to_array_tex(b, nir_instr_as_tex(instr));
529    else if (instr->type == nir_instr_type_intrinsic)
530       return lower_cube_image_intrinsic(b, nir_instr_as_intrinsic(instr));
531    else if (instr->type == nir_instr_type_deref)
532       return lower_cube_image_deref(b, nir_instr_as_deref(instr));
533    return NULL;
534 }
535 
536 bool
dxil_nir_lower_int_cubemaps(nir_shader * s,bool lower_samplers)537 dxil_nir_lower_int_cubemaps(nir_shader *s, bool lower_samplers)
538 {
539    bool result =
540          nir_shader_lower_instructions(s,
541                                        lower_int_cubmap_to_array_filter,
542                                        lower_int_cubmap_to_array_impl,
543                                        &lower_samplers);
544 
545    if (result) {
546       nir_foreach_variable_with_modes_safe(var, s, nir_var_uniform | nir_var_image) {
547          if (!type_needs_lowering(var->type, lower_samplers))
548             continue;
549          bool is_image = glsl_type_is_image(glsl_without_array(var->type));
550          var->type = make_2darray_from_cubemap_with_array(var->type, is_image);
551       }
552    }
553    return result;
554 
555 }
556