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)30 type_needs_lowering(const struct glsl_type *type)
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 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_add:
51 case nir_intrinsic_image_atomic_and:
52 case nir_intrinsic_image_atomic_comp_swap:
53 case nir_intrinsic_image_atomic_dec_wrap:
54 case nir_intrinsic_image_atomic_exchange:
55 case nir_intrinsic_image_atomic_fadd:
56 case nir_intrinsic_image_atomic_fmax:
57 case nir_intrinsic_image_atomic_fmin:
58 case nir_intrinsic_image_atomic_imax:
59 case nir_intrinsic_image_atomic_imin:
60 case nir_intrinsic_image_atomic_inc_wrap:
61 case nir_intrinsic_image_atomic_or:
62 case nir_intrinsic_image_atomic_umax:
63 case nir_intrinsic_image_atomic_umin:
64 case nir_intrinsic_image_atomic_xor:
65 case nir_intrinsic_image_load:
66 case nir_intrinsic_image_size:
67 case nir_intrinsic_image_store:
68 case nir_intrinsic_image_deref_atomic_add:
69 case nir_intrinsic_image_deref_atomic_and:
70 case nir_intrinsic_image_deref_atomic_comp_swap:
71 case nir_intrinsic_image_deref_atomic_dec_wrap:
72 case nir_intrinsic_image_deref_atomic_exchange:
73 case nir_intrinsic_image_deref_atomic_fadd:
74 case nir_intrinsic_image_deref_atomic_fmax:
75 case nir_intrinsic_image_deref_atomic_fmin:
76 case nir_intrinsic_image_deref_atomic_imax:
77 case nir_intrinsic_image_deref_atomic_imin:
78 case nir_intrinsic_image_deref_atomic_inc_wrap:
79 case nir_intrinsic_image_deref_atomic_or:
80 case nir_intrinsic_image_deref_atomic_umax:
81 case nir_intrinsic_image_deref_atomic_umin:
82 case nir_intrinsic_image_deref_atomic_xor:
83 case nir_intrinsic_image_deref_load:
84 case nir_intrinsic_image_deref_size:
85 case nir_intrinsic_image_deref_store:
86 return nir_intrinsic_image_dim(intr) == GLSL_SAMPLER_DIM_CUBE;
87 default:
88 return false;
89 }
90 } else if (instr->type == nir_instr_type_deref) {
91 nir_deref_instr *deref = nir_instr_as_deref(instr);
92 return type_needs_lowering(deref->type);
93 } else if (instr->type == nir_instr_type_tex && lower_samplers) {
94 nir_tex_instr *tex = nir_instr_as_tex(instr);
95
96 if (tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE)
97 return false;
98
99 switch (tex->op) {
100 case nir_texop_tex:
101 case nir_texop_txb:
102 case nir_texop_txd:
103 case nir_texop_txl:
104 case nir_texop_txs:
105 case nir_texop_lod:
106 case nir_texop_tg4:
107 break;
108 default:
109 return false;
110 }
111
112 int sampler_deref = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref);
113 assert(sampler_deref >= 0);
114 nir_deref_instr *deref = nir_instr_as_deref(tex->src[sampler_deref].src.ssa->parent_instr);
115 nir_variable *cube = nir_deref_instr_get_variable(deref);
116 return glsl_base_type_is_integer(glsl_get_sampler_result_type(cube->type));
117 }
118
119 return false;
120 }
121
122 typedef struct {
123 bool image;
124 nir_ssa_def *rx;
125 nir_ssa_def *ry;
126 nir_ssa_def *rz;
127 nir_ssa_def *arx;
128 nir_ssa_def *ary;
129 nir_ssa_def *arz;
130 nir_ssa_def *array;
131 } coord_t;
132
133
134 /* This is taken from from sp_tex_sample:convert_cube */
135 static nir_ssa_def *
evaluate_face_x(nir_builder * b,coord_t * coord)136 evaluate_face_x(nir_builder *b, coord_t *coord)
137 {
138 nir_ssa_def *sign = nir_fsign(b, coord->rx);
139 nir_ssa_def *positive = nir_fge(b, coord->rx, nir_imm_float(b, 0.0));
140 nir_ssa_def *ima = nir_fdiv(b, nir_imm_float(b, -0.5), coord->arx);
141
142 nir_ssa_def *x = nir_fadd(b, nir_fmul(b, nir_fmul(b, sign, ima), coord->rz), nir_imm_float(b, 0.5));
143 nir_ssa_def *y = nir_fadd(b, nir_fmul(b, ima, coord->ry), nir_imm_float(b, 0.5));
144 nir_ssa_def *face = nir_bcsel(b, positive, nir_imm_float(b, 0.0), nir_imm_float(b, 1.0));
145
146 if (coord->array)
147 face = nir_fadd(b, face, coord->array);
148
149 return coord->image ?
150 nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) :
151 nir_vec3(b, x,y, face);
152 }
153
154 static nir_ssa_def *
evaluate_face_y(nir_builder * b,coord_t * coord)155 evaluate_face_y(nir_builder *b, coord_t *coord)
156 {
157 nir_ssa_def *sign = nir_fsign(b, coord->ry);
158 nir_ssa_def *positive = nir_fge(b, coord->ry, nir_imm_float(b, 0.0));
159 nir_ssa_def *ima = nir_fdiv(b, nir_imm_float(b, 0.5), coord->ary);
160
161 nir_ssa_def *x = nir_fadd(b, nir_fmul(b, ima, coord->rx), nir_imm_float(b, 0.5));
162 nir_ssa_def *y = nir_fadd(b, nir_fmul(b, nir_fmul(b, sign, ima), coord->rz), nir_imm_float(b, 0.5));
163 nir_ssa_def *face = nir_bcsel(b, positive, nir_imm_float(b, 2.0), nir_imm_float(b, 3.0));
164
165 if (coord->array)
166 face = nir_fadd(b, face, coord->array);
167
168 return coord->image ?
169 nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) :
170 nir_vec3(b, x,y, face);
171 }
172
173 static nir_ssa_def *
evaluate_face_z(nir_builder * b,coord_t * coord)174 evaluate_face_z(nir_builder *b, coord_t *coord)
175 {
176 nir_ssa_def *sign = nir_fsign(b, coord->rz);
177 nir_ssa_def *positive = nir_fge(b, coord->rz, nir_imm_float(b, 0.0));
178 nir_ssa_def *ima = nir_fdiv(b, nir_imm_float(b, -0.5), coord->arz);
179
180 nir_ssa_def *x = nir_fadd(b, nir_fmul(b, nir_fmul(b, sign, ima), nir_fneg(b, coord->rx)), nir_imm_float(b, 0.5));
181 nir_ssa_def *y = nir_fadd(b, nir_fmul(b, ima, coord->ry), nir_imm_float(b, 0.5));
182 nir_ssa_def *face = nir_bcsel(b, positive, nir_imm_float(b, 4.0), nir_imm_float(b, 5.0));
183
184 if (coord->array)
185 face = nir_fadd(b, face, coord->array);
186
187 return coord->image ?
188 nir_vec4(b, x,y, face, nir_ssa_undef(b, 1, 32)) :
189 nir_vec3(b, x,y, face);
190 }
191
192 static nir_ssa_def *
create_array_tex_from_cube_tex(nir_builder * b,nir_tex_instr * tex,nir_ssa_def * coord,nir_texop op)193 create_array_tex_from_cube_tex(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *coord, nir_texop op)
194 {
195 nir_tex_instr *array_tex;
196
197 array_tex = nir_tex_instr_create(b->shader, tex->num_srcs);
198 array_tex->op = op;
199 array_tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
200 array_tex->is_array = true;
201 array_tex->is_shadow = tex->is_shadow;
202 array_tex->is_new_style_shadow = tex->is_new_style_shadow;
203 array_tex->texture_index = tex->texture_index;
204 array_tex->sampler_index = tex->sampler_index;
205 array_tex->dest_type = tex->dest_type;
206 array_tex->coord_components = 3;
207
208 nir_src coord_src = nir_src_for_ssa(coord);
209 for (unsigned i = 0; i < tex->num_srcs; i++) {
210 nir_src *psrc = (tex->src[i].src_type == nir_tex_src_coord) ?
211 &coord_src : &tex->src[i].src;
212
213 nir_src_copy(&array_tex->src[i].src, psrc);
214 array_tex->src[i].src_type = tex->src[i].src_type;
215 }
216
217 nir_ssa_dest_init(&array_tex->instr, &array_tex->dest,
218 nir_tex_instr_dest_size(array_tex), 32, NULL);
219 nir_builder_instr_insert(b, &array_tex->instr);
220 return &array_tex->dest.ssa;
221 }
222
223 static nir_ssa_def *
handle_cube_edge(nir_builder * b,nir_ssa_def * x,nir_ssa_def * y,nir_ssa_def * face,nir_ssa_def * array_slice_cube_base,nir_ssa_def * tex_size)224 handle_cube_edge(nir_builder *b, nir_ssa_def *x, nir_ssa_def *y, nir_ssa_def *face, nir_ssa_def *array_slice_cube_base, nir_ssa_def *tex_size)
225 {
226 enum cube_remap
227 {
228 cube_remap_zero = 0,
229 cube_remap_x,
230 cube_remap_y,
231 cube_remap_tex_size,
232 cube_remap_tex_size_minus_x,
233 cube_remap_tex_size_minus_y,
234
235 cube_remap_size,
236 };
237
238 struct cube_remap_table
239 {
240 enum cube_remap remap_x;
241 enum cube_remap remap_y;
242 uint32_t remap_face;
243 };
244
245 static const struct cube_remap_table cube_remap_neg_x[6] =
246 {
247 {cube_remap_tex_size, cube_remap_y, 4},
248 {cube_remap_tex_size, cube_remap_y, 5},
249 {cube_remap_y, cube_remap_zero, 1},
250 {cube_remap_tex_size_minus_y, cube_remap_tex_size, 1},
251 {cube_remap_tex_size, cube_remap_y, 1},
252 {cube_remap_tex_size, cube_remap_y, 0},
253 };
254
255 static const struct cube_remap_table cube_remap_pos_x[6] =
256 {
257 {cube_remap_zero, cube_remap_y, 5},
258 {cube_remap_zero, cube_remap_y, 4},
259 {cube_remap_tex_size_minus_y, cube_remap_zero, 0},
260 {cube_remap_y, cube_remap_tex_size, 0},
261 {cube_remap_zero, cube_remap_y, 0},
262 {cube_remap_zero, cube_remap_y, 1},
263 };
264
265 static const struct cube_remap_table cube_remap_neg_y[6] =
266 {
267 {cube_remap_tex_size, cube_remap_tex_size_minus_x, 2},
268 {cube_remap_zero, cube_remap_x, 2},
269 {cube_remap_tex_size_minus_x, cube_remap_zero, 5},
270 {cube_remap_x, cube_remap_tex_size, 4},
271 {cube_remap_x, cube_remap_tex_size, 2},
272 {cube_remap_tex_size_minus_x, cube_remap_zero, 2},
273 };
274
275 static const struct cube_remap_table cube_remap_pos_y[6] =
276 {
277 {cube_remap_tex_size, cube_remap_x, 3},
278 {cube_remap_zero, cube_remap_tex_size_minus_x, 3},
279 {cube_remap_x, cube_remap_zero, 4},
280 {cube_remap_tex_size_minus_x, cube_remap_tex_size, 5},
281 {cube_remap_x, cube_remap_zero, 3},
282 {cube_remap_tex_size_minus_x, cube_remap_tex_size, 3},
283 };
284
285 static const struct cube_remap_table* remap_tables[4] = {
286 cube_remap_neg_x,
287 cube_remap_pos_x,
288 cube_remap_neg_y,
289 cube_remap_pos_y
290 };
291
292 nir_ssa_def *zero = nir_imm_int(b, 0);
293
294 /* Doesn't matter since the texture is square */
295 tex_size = nir_channel(b, tex_size, 0);
296
297 nir_ssa_def *x_on = nir_iand(b, nir_ige(b, x, zero), nir_ige(b, tex_size, x));
298 nir_ssa_def *y_on = nir_iand(b, nir_ige(b, y, zero), nir_ige(b, tex_size, y));
299 nir_ssa_def *one_on = nir_ixor(b, x_on, y_on);
300
301 /* If the sample did not fall off the face in either dimension, then set output = input */
302 nir_ssa_def *x_result = x;
303 nir_ssa_def *y_result = y;
304 nir_ssa_def *face_result = face;
305
306 /* otherwise, if the sample fell off the face in either the X or the Y direction, remap to the new face */
307 nir_ssa_def *remap_predicates[4] =
308 {
309 nir_iand(b, one_on, nir_ilt(b, x, zero)),
310 nir_iand(b, one_on, nir_ilt(b, tex_size, x)),
311 nir_iand(b, one_on, nir_ilt(b, y, zero)),
312 nir_iand(b, one_on, nir_ilt(b, tex_size, y)),
313 };
314
315 nir_ssa_def *remap_array[cube_remap_size];
316
317 remap_array[cube_remap_zero] = zero;
318 remap_array[cube_remap_x] = x;
319 remap_array[cube_remap_y] = y;
320 remap_array[cube_remap_tex_size] = tex_size;
321 remap_array[cube_remap_tex_size_minus_x] = nir_isub(b, tex_size, x);
322 remap_array[cube_remap_tex_size_minus_y] = nir_isub(b, tex_size, y);
323
324 /* For each possible way the sample could have fallen off */
325 for (unsigned i = 0; i < 4; i++) {
326 const struct cube_remap_table* remap_table = remap_tables[i];
327
328 /* For each possible original face */
329 for (unsigned j = 0; j < 6; j++) {
330 nir_ssa_def *predicate = nir_iand(b, remap_predicates[i], nir_ieq(b, face, nir_imm_int(b, j)));
331
332 x_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_x], x_result);
333 y_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_y], y_result);
334 face_result = nir_bcsel(b, predicate, remap_array[remap_table[j].remap_face], face_result);
335 }
336 }
337
338 return nir_vec3(b, x_result, y_result, nir_iadd(b, face_result, array_slice_cube_base));
339 }
340
341 static nir_ssa_def *
handle_cube_gather(nir_builder * b,nir_tex_instr * tex,nir_ssa_def * coord)342 handle_cube_gather(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *coord)
343 {
344 nir_ssa_def *tex_size = nir_get_texture_size(b, tex);
345
346 /* nir_get_texture_size puts the cursor before the tex op */
347 b->cursor = nir_after_instr(coord->parent_instr);
348
349 nir_ssa_def *const_05 = nir_imm_float(b, 0.5f);
350 nir_ssa_def *texel_coords = nir_fmul(b, nir_channels(b, coord, 3),
351 nir_i2f32(b, nir_channels(b, tex_size, 3)));
352
353 nir_ssa_def *x_orig = nir_channel(b, texel_coords, 0);
354 nir_ssa_def *y_orig = nir_channel(b, texel_coords, 1);
355
356 nir_ssa_def *x_pos = nir_f2i32(b, nir_fadd(b, x_orig, const_05));
357 nir_ssa_def *x_neg = nir_f2i32(b, nir_fsub(b, x_orig, const_05));
358 nir_ssa_def *y_pos = nir_f2i32(b, nir_fadd(b, y_orig, const_05));
359 nir_ssa_def *y_neg = nir_f2i32(b, nir_fsub(b, y_orig, const_05));
360 nir_ssa_def *coords[4][2] = {
361 { x_neg, y_pos },
362 { x_pos, y_pos },
363 { x_pos, y_neg },
364 { x_neg, y_neg },
365 };
366
367 nir_ssa_def *array_slice_2d = nir_f2i32(b, nir_channel(b, coord, 2));
368 nir_ssa_def *face = nir_imod(b, array_slice_2d, nir_imm_int(b, 6));
369 nir_ssa_def *array_slice_cube_base = nir_isub(b, array_slice_2d, face);
370
371 nir_ssa_def *channels[4];
372 for (unsigned i = 0; i < 4; ++i) {
373 nir_ssa_def *final_coord = handle_cube_edge(b, coords[i][0], coords[i][1], face, array_slice_cube_base, tex_size);
374 nir_ssa_def *sampled_val = create_array_tex_from_cube_tex(b, tex, final_coord, nir_texop_txf);
375 channels[i] = nir_channel(b, sampled_val, tex->component);
376 }
377
378 return nir_vec(b, channels, 4);
379 }
380
381 static nir_ssa_def *
lower_cube_coords(nir_builder * b,nir_ssa_def * coord,bool is_array,bool is_image)382 lower_cube_coords(nir_builder *b, nir_ssa_def *coord, bool is_array, bool is_image)
383 {
384 coord_t coords;
385 coords.image = is_image;
386 coords.rx = nir_channel(b, coord, 0);
387 coords.ry = nir_channel(b, coord, 1);
388 coords.rz = nir_channel(b, coord, 2);
389 coords.arx = nir_fabs(b, coords.rx);
390 coords.ary = nir_fabs(b, coords.ry);
391 coords.arz = nir_fabs(b, coords.rz);
392 coords.array = NULL;
393 if (is_array)
394 coords.array = nir_fmul(b, nir_channel(b, coord, 3), nir_imm_float(b, 6.0f));
395
396 nir_ssa_def *use_face_x = nir_iand(b,
397 nir_fge(b, coords.arx, coords.ary),
398 nir_fge(b, coords.arx, coords.arz));
399
400 nir_if *use_face_x_if = nir_push_if(b, use_face_x);
401 nir_ssa_def *face_x_coord = evaluate_face_x(b, &coords);
402 nir_if *use_face_x_else = nir_push_else(b, use_face_x_if);
403
404 nir_ssa_def *use_face_y = nir_iand(b,
405 nir_fge(b, coords.ary, coords.arx),
406 nir_fge(b, coords.ary, coords.arz));
407
408 nir_if *use_face_y_if = nir_push_if(b, use_face_y);
409 nir_ssa_def *face_y_coord = evaluate_face_y(b, &coords);
410 nir_if *use_face_y_else = nir_push_else(b, use_face_y_if);
411
412 nir_ssa_def *face_z_coord = evaluate_face_z(b, &coords);
413
414 nir_pop_if(b, use_face_y_else);
415 nir_ssa_def *face_y_or_z_coord = nir_if_phi(b, face_y_coord, face_z_coord);
416 nir_pop_if(b, use_face_x_else);
417
418 // This contains in xy the normalized sample coordinates, and in z the face index
419 nir_ssa_def *coord_and_face = nir_if_phi(b, face_x_coord, face_y_or_z_coord);
420
421 return coord_and_face;
422 }
423
424 static nir_ssa_def *
lower_cube_sample(nir_builder * b,nir_tex_instr * tex)425 lower_cube_sample(nir_builder *b, nir_tex_instr *tex)
426 {
427 int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
428 assert(coord_index >= 0);
429
430 /* Evaluate the face and the xy coordinates for a 2D tex op */
431 nir_ssa_def *coord = tex->src[coord_index].src.ssa;
432 nir_ssa_def *coord_and_face = lower_cube_coords(b, coord, tex->is_array, false);
433
434 if (tex->op == nir_texop_tg4)
435 return handle_cube_gather(b, tex, coord_and_face);
436 else
437 return create_array_tex_from_cube_tex(b, tex, coord_and_face, tex->op);
438 }
439
440 static nir_ssa_def *
lower_cube_image_load_store_atomic(nir_builder * b,nir_intrinsic_instr * intr)441 lower_cube_image_load_store_atomic(nir_builder *b, nir_intrinsic_instr *intr)
442 {
443 b->cursor = nir_before_instr(&intr->instr);
444 nir_intrinsic_set_image_array(intr, true);
445 nir_intrinsic_set_image_dim(intr, GLSL_SAMPLER_DIM_2D);
446
447 return NIR_LOWER_INSTR_PROGRESS;
448 }
449
450 static nir_ssa_def *
lower_cube_txs(nir_builder * b,nir_tex_instr * tex)451 lower_cube_txs(nir_builder *b, nir_tex_instr *tex)
452 {
453 b->cursor = nir_after_instr(&tex->instr);
454 if (!tex->is_array)
455 return nir_channels(b, &tex->dest.ssa, 3);
456
457 nir_ssa_def *array_dim = nir_channel(b, &tex->dest.ssa, 2);
458 nir_ssa_def *cube_array_dim = nir_idiv(b, array_dim, nir_imm_int(b, 6));
459 return nir_vec3(b, nir_channel(b, &tex->dest.ssa, 0),
460 nir_channel(b, &tex->dest.ssa, 1),
461 cube_array_dim);
462 }
463
464 static nir_ssa_def *
lower_cube_image_size(nir_builder * b,nir_intrinsic_instr * intr)465 lower_cube_image_size(nir_builder *b, nir_intrinsic_instr *intr)
466 {
467 b->cursor = nir_after_instr(&intr->instr);
468 if (!nir_intrinsic_image_array(intr))
469 return nir_channels(b, &intr->dest.ssa, 3);
470
471 nir_ssa_def *array_dim = nir_channel(b, &intr->dest.ssa, 2);
472 nir_ssa_def *cube_array_dim = nir_idiv(b, array_dim, nir_imm_int(b, 6));
473 return nir_vec3(b, nir_channel(b, &intr->dest.ssa, 0),
474 nir_channel(b, &intr->dest.ssa, 1),
475 cube_array_dim);
476 }
477
478 static const struct glsl_type *
make_2darray_sampler_from_cubemap(const struct glsl_type * type)479 make_2darray_sampler_from_cubemap(const struct glsl_type *type)
480 {
481 return glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ?
482 glsl_sampler_type(
483 GLSL_SAMPLER_DIM_2D,
484 false, true,
485 glsl_get_sampler_result_type(type)) : type;
486 }
487
488 static const struct glsl_type *
make_2darray_image_from_cubemap(const struct glsl_type * type)489 make_2darray_image_from_cubemap(const struct glsl_type *type)
490 {
491 return glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE ?
492 glsl_image_type(
493 GLSL_SAMPLER_DIM_2D,
494 true,
495 glsl_get_sampler_result_type(type)) : type;
496 }
497
498 static const struct glsl_type *
make_2darray_from_cubemap_with_array(const struct glsl_type * type,bool is_image)499 make_2darray_from_cubemap_with_array(const struct glsl_type *type, bool is_image)
500 {
501 if (glsl_type_is_array(type)) {
502 const struct glsl_type *new_type = glsl_without_array(type);
503 return new_type != type ? glsl_array_type(make_2darray_from_cubemap_with_array(glsl_without_array(type), is_image),
504 glsl_get_length(type), 0) : type;
505 } else if (is_image)
506 return make_2darray_image_from_cubemap(type);
507 else
508 return make_2darray_sampler_from_cubemap(type);
509 }
510
511 static nir_ssa_def *
lower_int_cubemap_to_array_tex(nir_builder * b,nir_tex_instr * tex)512 lower_int_cubemap_to_array_tex(nir_builder *b, nir_tex_instr *tex)
513 {
514 switch (tex->op) {
515 case nir_texop_tex:
516 case nir_texop_txb:
517 case nir_texop_txd:
518 case nir_texop_txl:
519 case nir_texop_lod:
520 case nir_texop_tg4:
521 return lower_cube_sample(b, tex);
522 case nir_texop_txs:
523 return lower_cube_txs(b, tex);
524 default:
525 unreachable("Unsupported cupe map texture operation");
526 }
527 }
528
529 static nir_ssa_def *
lower_cube_image_intrinsic(nir_builder * b,nir_intrinsic_instr * intr)530 lower_cube_image_intrinsic(nir_builder *b, nir_intrinsic_instr *intr)
531 {
532 if (intr->intrinsic == nir_intrinsic_image_size ||
533 intr->intrinsic == nir_intrinsic_image_deref_size)
534 return lower_cube_image_size(b, intr);
535 else
536 return lower_cube_image_load_store_atomic(b, intr);
537 }
538
539 static nir_ssa_def *
lower_cube_image_deref(nir_builder * b,nir_deref_instr * deref)540 lower_cube_image_deref(nir_builder *b, nir_deref_instr *deref)
541 {
542 deref->type = make_2darray_from_cubemap_with_array(
543 deref->type,
544 glsl_type_is_image(glsl_without_array(deref->type)));
545 return NIR_LOWER_INSTR_PROGRESS;
546 }
547
548 static nir_ssa_def *
lower_int_cubmap_to_array_impl(nir_builder * b,nir_instr * instr,void * options)549 lower_int_cubmap_to_array_impl(nir_builder *b, nir_instr *instr,
550 void *options)
551 {
552 bool lower_samplers = *(bool *)options;
553 if (instr->type == nir_instr_type_tex && lower_samplers)
554 return lower_int_cubemap_to_array_tex(b, nir_instr_as_tex(instr));
555 else if (instr->type == nir_instr_type_intrinsic)
556 return lower_cube_image_intrinsic(b, nir_instr_as_intrinsic(instr));
557 else if (instr->type == nir_instr_type_deref)
558 return lower_cube_image_deref(b, nir_instr_as_deref(instr));
559 return NULL;
560 }
561
562 bool
dxil_nir_lower_int_cubemaps(nir_shader * s,bool lower_samplers)563 dxil_nir_lower_int_cubemaps(nir_shader *s, bool lower_samplers)
564 {
565 bool result =
566 nir_shader_lower_instructions(s,
567 lower_int_cubmap_to_array_filter,
568 lower_int_cubmap_to_array_impl,
569 &lower_samplers);
570
571 if (result) {
572 nir_foreach_variable_with_modes_safe(var, s, nir_var_uniform | nir_var_image) {
573 if (!type_needs_lowering(var->type))
574 continue;
575 bool is_image = glsl_type_is_image(glsl_without_array(var->type));
576 var->type = make_2darray_from_cubemap_with_array(var->type, is_image);
577 }
578 }
579 return result;
580
581 }
582