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 "d3d12_nir_passes.h"
25 #include "d3d12_compiler.h"
26 #include "nir_builder.h"
27 #include "nir_builtin_builder.h"
28 #include "nir_format_convert.h"
29 #include "program/prog_instruction.h"
30 #include "dxil_nir.h"
31
32 /**
33 * Lower Y Flip:
34 *
35 * We can't do a Y flip simply by negating the viewport height,
36 * so we need to lower the flip into the NIR shader.
37 */
38
39 static nir_ssa_def *
get_state_var(nir_builder * b,enum d3d12_state_var var_enum,const char * var_name,const struct glsl_type * var_type,nir_variable ** out_var)40 get_state_var(nir_builder *b,
41 enum d3d12_state_var var_enum,
42 const char *var_name,
43 const struct glsl_type *var_type,
44 nir_variable **out_var)
45 {
46 const gl_state_index16 tokens[STATE_LENGTH] = { STATE_INTERNAL_DRIVER, var_enum };
47 if (*out_var == NULL) {
48 nir_variable *var = nir_variable_create(b->shader,
49 nir_var_uniform,
50 var_type,
51 var_name);
52
53 var->num_state_slots = 1;
54 var->state_slots = ralloc_array(var, nir_state_slot, 1);
55 memcpy(var->state_slots[0].tokens, tokens,
56 sizeof(var->state_slots[0].tokens));
57 var->data.how_declared = nir_var_hidden;
58 b->shader->num_uniforms++;
59 *out_var = var;
60 }
61 return nir_load_var(b, *out_var);
62 }
63
64 static void
lower_pos_write(nir_builder * b,struct nir_instr * instr,nir_variable ** flip)65 lower_pos_write(nir_builder *b, struct nir_instr *instr, nir_variable **flip)
66 {
67 if (instr->type != nir_instr_type_intrinsic)
68 return;
69
70 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
71 if (intr->intrinsic != nir_intrinsic_store_deref)
72 return;
73
74 nir_variable *var = nir_intrinsic_get_var(intr, 0);
75 if (var->data.mode != nir_var_shader_out ||
76 var->data.location != VARYING_SLOT_POS)
77 return;
78
79 b->cursor = nir_before_instr(&intr->instr);
80
81 nir_ssa_def *pos = nir_ssa_for_src(b, intr->src[1], 4);
82 nir_ssa_def *flip_y = get_state_var(b, D3D12_STATE_VAR_Y_FLIP, "d3d12_FlipY",
83 glsl_float_type(), flip);
84 nir_ssa_def *def = nir_vec4(b,
85 nir_channel(b, pos, 0),
86 nir_fmul(b, nir_channel(b, pos, 1), flip_y),
87 nir_channel(b, pos, 2),
88 nir_channel(b, pos, 3));
89 nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
90 }
91
92 void
d3d12_lower_yflip(nir_shader * nir)93 d3d12_lower_yflip(nir_shader *nir)
94 {
95 nir_variable *flip = NULL;
96
97 if (nir->info.stage != MESA_SHADER_VERTEX &&
98 nir->info.stage != MESA_SHADER_GEOMETRY)
99 return;
100
101 nir_foreach_function(function, nir) {
102 if (function->impl) {
103 nir_builder b;
104 nir_builder_init(&b, function->impl);
105
106 nir_foreach_block(block, function->impl) {
107 nir_foreach_instr_safe(instr, block) {
108 lower_pos_write(&b, instr, &flip);
109 }
110 }
111
112 nir_metadata_preserve(function->impl, nir_metadata_block_index |
113 nir_metadata_dominance);
114 }
115 }
116 }
117
118 static void
lower_load_face(nir_builder * b,struct nir_instr * instr,nir_variable * var)119 lower_load_face(nir_builder *b, struct nir_instr *instr, nir_variable *var)
120 {
121 if (instr->type != nir_instr_type_intrinsic)
122 return;
123
124 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
125 if (intr->intrinsic != nir_intrinsic_load_front_face)
126 return;
127
128 b->cursor = nir_before_instr(&intr->instr);
129
130 nir_ssa_def *load = nir_load_var(b, var);
131
132 nir_ssa_def_rewrite_uses(&intr->dest.ssa, load);
133 nir_instr_remove(instr);
134 }
135
136 void
d3d12_forward_front_face(nir_shader * nir)137 d3d12_forward_front_face(nir_shader *nir)
138 {
139 assert(nir->info.stage == MESA_SHADER_FRAGMENT);
140
141 nir_variable *var = nir_variable_create(nir, nir_var_shader_in,
142 glsl_bool_type(),
143 "gl_FrontFacing");
144 var->data.location = VARYING_SLOT_VAR12;
145 var->data.interpolation = INTERP_MODE_FLAT;
146
147
148 nir_foreach_function(function, nir) {
149 if (function->impl) {
150 nir_builder b;
151 nir_builder_init(&b, function->impl);
152
153 nir_foreach_block(block, function->impl) {
154 nir_foreach_instr_safe(instr, block) {
155 lower_load_face(&b, instr, var);
156 }
157 }
158
159 nir_metadata_preserve(function->impl, nir_metadata_block_index |
160 nir_metadata_dominance);
161 }
162 }
163 }
164
165 static void
lower_pos_read(nir_builder * b,struct nir_instr * instr,nir_variable ** depth_transform_var)166 lower_pos_read(nir_builder *b, struct nir_instr *instr,
167 nir_variable **depth_transform_var)
168 {
169 if (instr->type != nir_instr_type_intrinsic)
170 return;
171
172 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
173 if (intr->intrinsic != nir_intrinsic_load_deref)
174 return;
175
176 nir_variable *var = nir_intrinsic_get_var(intr, 0);
177 if (var->data.mode != nir_var_shader_in ||
178 var->data.location != VARYING_SLOT_POS)
179 return;
180
181 b->cursor = nir_after_instr(instr);
182
183 nir_ssa_def *pos = nir_instr_ssa_def(instr);
184 nir_ssa_def *depth = nir_channel(b, pos, 2);
185
186 assert(depth_transform_var);
187 nir_ssa_def *depth_transform = get_state_var(b, D3D12_STATE_VAR_DEPTH_TRANSFORM,
188 "d3d12_DepthTransform",
189 glsl_vec_type(2),
190 depth_transform_var);
191 depth = nir_fmad(b, depth, nir_channel(b, depth_transform, 0),
192 nir_channel(b, depth_transform, 1));
193
194 pos = nir_vector_insert_imm(b, pos, depth, 2);
195
196 assert(intr->dest.is_ssa);
197 nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, pos,
198 pos->parent_instr);
199 }
200
201 void
d3d12_lower_depth_range(nir_shader * nir)202 d3d12_lower_depth_range(nir_shader *nir)
203 {
204 assert(nir->info.stage == MESA_SHADER_FRAGMENT);
205 nir_variable *depth_transform = NULL;
206 nir_foreach_function(function, nir) {
207 if (function->impl) {
208 nir_builder b;
209 nir_builder_init(&b, function->impl);
210
211 nir_foreach_block(block, function->impl) {
212 nir_foreach_instr_safe(instr, block) {
213 lower_pos_read(&b, instr, &depth_transform);
214 }
215 }
216
217 nir_metadata_preserve(function->impl, nir_metadata_block_index |
218 nir_metadata_dominance);
219 }
220 }
221 }
222
223 static bool
is_color_output(nir_variable * var)224 is_color_output(nir_variable *var)
225 {
226 return (var->data.mode == nir_var_shader_out &&
227 (var->data.location == FRAG_RESULT_COLOR ||
228 var->data.location >= FRAG_RESULT_DATA0));
229 }
230
231 static void
lower_uint_color_write(nir_builder * b,struct nir_instr * instr,bool is_signed)232 lower_uint_color_write(nir_builder *b, struct nir_instr *instr, bool is_signed)
233 {
234 const unsigned NUM_BITS = 8;
235 const unsigned bits[4] = { NUM_BITS, NUM_BITS, NUM_BITS, NUM_BITS };
236
237 if (instr->type != nir_instr_type_intrinsic)
238 return;
239
240 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
241 if (intr->intrinsic != nir_intrinsic_store_deref)
242 return;
243
244 nir_variable *var = nir_intrinsic_get_var(intr, 0);
245 if (!is_color_output(var))
246 return;
247
248 b->cursor = nir_before_instr(&intr->instr);
249
250 nir_ssa_def *col = nir_ssa_for_src(b, intr->src[1], intr->num_components);
251 nir_ssa_def *def = is_signed ? nir_format_float_to_snorm(b, col, bits) :
252 nir_format_float_to_unorm(b, col, bits);
253 if (is_signed)
254 def = nir_bcsel(b, nir_ilt(b, def, nir_imm_int(b, 0)),
255 nir_iadd(b, def, nir_imm_int(b, 1 << NUM_BITS)),
256 def);
257 nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
258 }
259
260 void
d3d12_lower_uint_cast(nir_shader * nir,bool is_signed)261 d3d12_lower_uint_cast(nir_shader *nir, bool is_signed)
262 {
263 if (nir->info.stage != MESA_SHADER_FRAGMENT)
264 return;
265
266 nir_foreach_function(function, nir) {
267 if (function->impl) {
268 nir_builder b;
269 nir_builder_init(&b, function->impl);
270
271 nir_foreach_block(block, function->impl) {
272 nir_foreach_instr_safe(instr, block) {
273 lower_uint_color_write(&b, instr, is_signed);
274 }
275 }
276
277 nir_metadata_preserve(function->impl, nir_metadata_block_index |
278 nir_metadata_dominance);
279 }
280 }
281 }
282
283 static bool
lower_load_first_vertex(nir_builder * b,nir_instr * instr,nir_variable ** first_vertex)284 lower_load_first_vertex(nir_builder *b, nir_instr *instr, nir_variable **first_vertex)
285 {
286 if (instr->type != nir_instr_type_intrinsic)
287 return false;
288
289 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
290
291 if (intr->intrinsic != nir_intrinsic_load_first_vertex)
292 return false;
293
294 b->cursor = nir_before_instr(&intr->instr);
295
296 nir_ssa_def *load = get_state_var(b, D3D12_STATE_VAR_FIRST_VERTEX, "d3d12_FirstVertex",
297 glsl_uint_type(), first_vertex);
298 nir_ssa_def_rewrite_uses(&intr->dest.ssa, load);
299 nir_instr_remove(instr);
300
301 return true;
302 }
303
304 bool
d3d12_lower_load_first_vertex(struct nir_shader * nir)305 d3d12_lower_load_first_vertex(struct nir_shader *nir)
306 {
307 nir_variable *first_vertex = NULL;
308 bool progress = false;
309
310 if (nir->info.stage != MESA_SHADER_VERTEX)
311 return false;
312
313 nir_foreach_function(function, nir) {
314 if (function->impl) {
315 nir_builder b;
316 nir_builder_init(&b, function->impl);
317
318 nir_foreach_block(block, function->impl) {
319 nir_foreach_instr_safe(instr, block) {
320 progress |= lower_load_first_vertex(&b, instr, &first_vertex);
321 }
322 }
323
324 nir_metadata_preserve(function->impl, nir_metadata_block_index |
325 nir_metadata_dominance);
326 }
327 }
328 return progress;
329 }
330
331 static void
invert_depth(nir_builder * b,struct nir_instr * instr)332 invert_depth(nir_builder *b, struct nir_instr *instr)
333 {
334 if (instr->type != nir_instr_type_intrinsic)
335 return;
336
337 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
338 if (intr->intrinsic != nir_intrinsic_store_deref)
339 return;
340
341 nir_variable *var = nir_intrinsic_get_var(intr, 0);
342 if (var->data.mode != nir_var_shader_out ||
343 var->data.location != VARYING_SLOT_POS)
344 return;
345
346 b->cursor = nir_before_instr(&intr->instr);
347
348 nir_ssa_def *pos = nir_ssa_for_src(b, intr->src[1], 4);
349 nir_ssa_def *def = nir_vec4(b,
350 nir_channel(b, pos, 0),
351 nir_channel(b, pos, 1),
352 nir_fneg(b, nir_channel(b, pos, 2)),
353 nir_channel(b, pos, 3));
354 nir_instr_rewrite_src(&intr->instr, intr->src + 1, nir_src_for_ssa(def));
355 }
356
357 /* In OpenGL the windows space depth value z_w is evaluated according to "s * z_d + b"
358 * with "s + (far - near) / 2" (depth clip:minus_one_to_one) [OpenGL 3.3, 2.13.1].
359 * When we switch the far and near value to satisfy DirectX requirements we have
360 * to compensate by inverting "z_d' = -z_d" with this lowering pass.
361 */
362 void
d3d12_nir_invert_depth(nir_shader * shader)363 d3d12_nir_invert_depth(nir_shader *shader)
364 {
365 if (shader->info.stage != MESA_SHADER_VERTEX &&
366 shader->info.stage != MESA_SHADER_GEOMETRY)
367 return;
368
369 nir_foreach_function(function, shader) {
370 if (function->impl) {
371 nir_builder b;
372 nir_builder_init(&b, function->impl);
373
374 nir_foreach_block(block, function->impl) {
375 nir_foreach_instr_safe(instr, block) {
376 invert_depth(&b, instr);
377 }
378 }
379
380 nir_metadata_preserve(function->impl, nir_metadata_block_index |
381 nir_metadata_dominance);
382 }
383 }
384 }
385
386
387 /**
388 * Lower State Vars:
389 *
390 * All uniforms related to internal D3D12 variables are
391 * condensed into a UBO that is appended at the end of the
392 * current ones.
393 */
394
395 static unsigned
get_state_var_offset(struct d3d12_shader * shader,enum d3d12_state_var var)396 get_state_var_offset(struct d3d12_shader *shader, enum d3d12_state_var var)
397 {
398 for (unsigned i = 0; i < shader->num_state_vars; ++i) {
399 if (shader->state_vars[i].var == var)
400 return shader->state_vars[i].offset;
401 }
402
403 unsigned offset = shader->state_vars_size;
404 shader->state_vars[shader->num_state_vars].offset = offset;
405 shader->state_vars[shader->num_state_vars].var = var;
406 shader->state_vars_size += 4; /* Use 4-words slots no matter the variable size */
407 shader->num_state_vars++;
408
409 return offset;
410 }
411
412 static bool
lower_instr(nir_intrinsic_instr * instr,nir_builder * b,struct d3d12_shader * shader,unsigned binding)413 lower_instr(nir_intrinsic_instr *instr, nir_builder *b,
414 struct d3d12_shader *shader, unsigned binding)
415 {
416 nir_variable *variable = NULL;
417 nir_deref_instr *deref = NULL;
418
419 b->cursor = nir_before_instr(&instr->instr);
420
421 if (instr->intrinsic == nir_intrinsic_load_uniform) {
422 nir_foreach_variable_with_modes(var, b->shader, nir_var_uniform) {
423 if (var->data.driver_location == nir_intrinsic_base(instr)) {
424 variable = var;
425 break;
426 }
427 }
428 } else if (instr->intrinsic == nir_intrinsic_load_deref) {
429 deref = nir_src_as_deref(instr->src[0]);
430 variable = nir_intrinsic_get_var(instr, 0);
431 }
432
433 if (variable == NULL ||
434 variable->num_state_slots != 1 ||
435 variable->state_slots[0].tokens[0] != STATE_INTERNAL_DRIVER)
436 return false;
437
438 enum d3d12_state_var var = variable->state_slots[0].tokens[1];
439 nir_ssa_def *ubo_idx = nir_imm_int(b, binding);
440 nir_ssa_def *ubo_offset = nir_imm_int(b, get_state_var_offset(shader, var) * 4);
441 nir_ssa_def *load =
442 nir_load_ubo(b, instr->num_components, instr->dest.ssa.bit_size,
443 ubo_idx, ubo_offset,
444 .align_mul = instr->dest.ssa.bit_size / 8,
445 .align_offset = 0,
446 .range_base = 0,
447 .range = ~0,
448 );
449
450 nir_ssa_def_rewrite_uses(&instr->dest.ssa, load);
451
452 /* Remove the old load_* instruction and any parent derefs */
453 nir_instr_remove(&instr->instr);
454 for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) {
455 /* If anyone is using this deref, leave it alone */
456 assert(d->dest.is_ssa);
457 if (!list_is_empty(&d->dest.ssa.uses))
458 break;
459
460 nir_instr_remove(&d->instr);
461 }
462
463 return true;
464 }
465
466 bool
d3d12_lower_state_vars(nir_shader * nir,struct d3d12_shader * shader)467 d3d12_lower_state_vars(nir_shader *nir, struct d3d12_shader *shader)
468 {
469 bool progress = false;
470
471 /* The state var UBO is added after all the other UBOs if it already
472 * exists it will be replaced by using the same binding.
473 * In the event there are no other UBO's, use binding slot 1 to
474 * be consistent with other non-default UBO's */
475 unsigned binding = MAX2(nir->info.num_ubos, 1);
476
477 nir_foreach_variable_with_modes_safe(var, nir, nir_var_uniform) {
478 if (var->num_state_slots == 1 &&
479 var->state_slots[0].tokens[0] == STATE_INTERNAL_DRIVER) {
480 if (var->data.mode == nir_var_mem_ubo) {
481 binding = var->data.binding;
482 }
483 }
484 }
485
486 nir_foreach_function(function, nir) {
487 if (function->impl) {
488 nir_builder builder;
489 nir_builder_init(&builder, function->impl);
490 nir_foreach_block(block, function->impl) {
491 nir_foreach_instr_safe(instr, block) {
492 if (instr->type == nir_instr_type_intrinsic)
493 progress |= lower_instr(nir_instr_as_intrinsic(instr),
494 &builder,
495 shader,
496 binding);
497 }
498 }
499
500 nir_metadata_preserve(function->impl, nir_metadata_block_index |
501 nir_metadata_dominance);
502 }
503 }
504
505 if (progress) {
506 assert(shader->num_state_vars > 0);
507
508 shader->state_vars_used = true;
509
510 /* Remove state variables */
511 nir_foreach_variable_with_modes_safe(var, nir, nir_var_uniform) {
512 if (var->num_state_slots == 1 &&
513 var->state_slots[0].tokens[0] == STATE_INTERNAL_DRIVER) {
514 exec_node_remove(&var->node);
515 nir->num_uniforms--;
516 }
517 }
518
519 const gl_state_index16 tokens[STATE_LENGTH] = { STATE_INTERNAL_DRIVER };
520 const struct glsl_type *type = glsl_array_type(glsl_vec4_type(),
521 shader->state_vars_size / 4, 0);
522 nir_variable *ubo = nir_variable_create(nir, nir_var_mem_ubo, type,
523 "d3d12_state_vars");
524 if (binding >= nir->info.num_ubos)
525 nir->info.num_ubos = binding + 1;
526 ubo->data.binding = binding;
527 ubo->num_state_slots = 1;
528 ubo->state_slots = ralloc_array(ubo, nir_state_slot, 1);
529 memcpy(ubo->state_slots[0].tokens, tokens,
530 sizeof(ubo->state_slots[0].tokens));
531
532 struct glsl_struct_field field = {
533 .type = type,
534 .name = "data",
535 .location = -1,
536 };
537 ubo->interface_type =
538 glsl_interface_type(&field, 1, GLSL_INTERFACE_PACKING_STD430,
539 false, "__d3d12_state_vars_interface");
540 }
541
542 return progress;
543 }
544
545 void
d3d12_add_missing_dual_src_target(struct nir_shader * s,unsigned missing_mask)546 d3d12_add_missing_dual_src_target(struct nir_shader *s,
547 unsigned missing_mask)
548 {
549 assert(missing_mask != 0);
550 nir_builder b;
551 nir_function_impl *impl = nir_shader_get_entrypoint(s);
552 nir_builder_init(&b, impl);
553 b.cursor = nir_before_cf_list(&impl->body);
554
555 nir_ssa_def *zero = nir_imm_zero(&b, 4, 32);
556 for (unsigned i = 0; i < 2; ++i) {
557
558 if (!(missing_mask & (1u << i)))
559 continue;
560
561 const char *name = i == 0 ? "gl_FragData[0]" :
562 "gl_SecondaryFragDataEXT[0]";
563 nir_variable *out = nir_variable_create(s, nir_var_shader_out,
564 glsl_vec4_type(), name);
565 out->data.location = FRAG_RESULT_DATA0;
566 out->data.driver_location = i;
567 out->data.index = i;
568
569 nir_store_var(&b, out, zero, 0xf);
570 }
571 nir_metadata_preserve(impl, nir_metadata_block_index |
572 nir_metadata_dominance);
573 }
574
575 static bool
fix_io_uint_type(struct nir_shader * s,nir_variable_mode modes,int slot)576 fix_io_uint_type(struct nir_shader *s, nir_variable_mode modes, int slot)
577 {
578 nir_variable *fixed_var = NULL;
579 nir_foreach_variable_with_modes(var, s, modes) {
580 if (var->data.location == slot) {
581 var->type = glsl_uint_type();
582 fixed_var = var;
583 break;
584 }
585 }
586
587 assert(fixed_var);
588
589 nir_foreach_function(function, s) {
590 if (function->impl) {
591 nir_foreach_block(block, function->impl) {
592 nir_foreach_instr_safe(instr, block) {
593 if (instr->type == nir_instr_type_deref) {
594 nir_deref_instr *deref = nir_instr_as_deref(instr);
595 if (deref->var == fixed_var)
596 deref->type = fixed_var->type;
597 }
598 }
599 }
600 }
601 }
602 return true;
603 }
604
605 bool
d3d12_fix_io_uint_type(struct nir_shader * s,uint64_t in_mask,uint64_t out_mask)606 d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask)
607 {
608 if (!(s->info.outputs_written & out_mask) &&
609 !(s->info.inputs_read & in_mask))
610 return false;
611
612 bool progress = false;
613
614 while (in_mask) {
615 int slot = u_bit_scan64(&in_mask);
616 progress |= (s->info.inputs_read & (1ull << slot)) &&
617 fix_io_uint_type(s, nir_var_shader_in, slot);
618 }
619
620 while (out_mask) {
621 int slot = u_bit_scan64(&out_mask);
622 progress |= (s->info.outputs_written & (1ull << slot)) &&
623 fix_io_uint_type(s, nir_var_shader_out, slot);
624 }
625
626 return progress;
627 }
628
629 static bool
lower_load_ubo_packed_filter(const nir_instr * instr,UNUSED const void * _options)630 lower_load_ubo_packed_filter(const nir_instr *instr,
631 UNUSED const void *_options) {
632 if (instr->type != nir_instr_type_intrinsic)
633 return false;
634
635 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
636
637 return intr->intrinsic == nir_intrinsic_load_ubo;
638 }
639
640 static nir_ssa_def *
lower_load_ubo_packed_impl(nir_builder * b,nir_instr * instr,UNUSED void * _options)641 lower_load_ubo_packed_impl(nir_builder *b, nir_instr *instr,
642 UNUSED void *_options) {
643 nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
644
645 nir_ssa_def *buffer = intr->src[0].ssa;
646 nir_ssa_def *offset = intr->src[1].ssa;
647
648 nir_ssa_def *result =
649 build_load_ubo_dxil(b, buffer,
650 offset,
651 nir_dest_num_components(intr->dest),
652 nir_dest_bit_size(intr->dest));
653 return result;
654 }
655
656 bool
nir_lower_packed_ubo_loads(nir_shader * nir)657 nir_lower_packed_ubo_loads(nir_shader *nir) {
658 return nir_shader_lower_instructions(nir,
659 lower_load_ubo_packed_filter,
660 lower_load_ubo_packed_impl,
661 NULL);
662 }
663
664 void
d3d12_lower_primitive_id(nir_shader * shader)665 d3d12_lower_primitive_id(nir_shader *shader)
666 {
667 nir_builder b;
668 nir_function_impl *impl = nir_shader_get_entrypoint(shader);
669 nir_ssa_def *primitive_id;
670 nir_builder_init(&b, impl);
671
672 nir_variable *primitive_id_var = nir_variable_create(shader, nir_var_shader_out,
673 glsl_uint_type(), "primitive_id");
674 primitive_id_var->data.location = VARYING_SLOT_PRIMITIVE_ID;
675 primitive_id_var->data.interpolation = INTERP_MODE_FLAT;
676
677 nir_foreach_block(block, impl) {
678 b.cursor = nir_before_block(block);
679 primitive_id = nir_load_primitive_id(&b);
680
681 nir_foreach_instr_safe(instr, block) {
682 if (instr->type != nir_instr_type_intrinsic ||
683 nir_instr_as_intrinsic(instr)->intrinsic != nir_intrinsic_emit_vertex)
684 continue;
685
686 b.cursor = nir_before_instr(instr);
687 nir_store_var(&b, primitive_id_var, primitive_id, 0x1);
688 }
689 }
690
691 nir_metadata_preserve(impl, nir_metadata_none);
692 }
693
694 static void
lower_triangle_strip_store(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * vertex_count_var,nir_variable ** varyings)695 lower_triangle_strip_store(nir_builder *b, nir_intrinsic_instr *intr,
696 nir_variable *vertex_count_var,
697 nir_variable **varyings)
698 {
699 /**
700 * tmp_varying[slot][min(vertex_count, 2)] = src
701 */
702 nir_ssa_def *vertex_count = nir_load_var(b, vertex_count_var);
703 nir_ssa_def *index = nir_imin(b, vertex_count, nir_imm_int(b, 2));
704 nir_variable *var = nir_intrinsic_get_var(intr, 0);
705
706 if (var->data.mode != nir_var_shader_out)
707 return;
708
709 nir_deref_instr *deref = nir_build_deref_array(b, nir_build_deref_var(b, varyings[var->data.location]), index);
710 nir_ssa_def *value = nir_ssa_for_src(b, intr->src[1], intr->num_components);
711 nir_store_deref(b, deref, value, 0xf);
712 nir_instr_remove(&intr->instr);
713 }
714
715 static void
lower_triangle_strip_emit_vertex(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * vertex_count_var,nir_variable ** varyings,nir_variable ** out_varyings)716 lower_triangle_strip_emit_vertex(nir_builder *b, nir_intrinsic_instr *intr,
717 nir_variable *vertex_count_var,
718 nir_variable **varyings,
719 nir_variable **out_varyings)
720 {
721 // TODO xfb + flat shading + last_pv
722 /**
723 * if (vertex_count >= 2) {
724 * for (i = 0; i < 3; i++) {
725 * foreach(slot)
726 * out[slot] = tmp_varying[slot][i];
727 * EmitVertex();
728 * }
729 * EndPrimitive();
730 * foreach(slot)
731 * tmp_varying[slot][vertex_count % 2] = tmp_varying[slot][2];
732 * }
733 * vertex_count++;
734 */
735
736 nir_ssa_def *two = nir_imm_int(b, 2);
737 nir_ssa_def *vertex_count = nir_load_var(b, vertex_count_var);
738 nir_ssa_def *count_cmp = nir_uge(b, vertex_count, two);
739 nir_if *count_check = nir_push_if(b, count_cmp);
740
741 for (int j = 0; j < 3; ++j) {
742 for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
743 if (!varyings[i])
744 continue;
745 nir_copy_deref(b, nir_build_deref_var(b, out_varyings[i]),
746 nir_build_deref_array_imm(b, nir_build_deref_var(b, varyings[i]), j));
747 }
748 nir_emit_vertex(b, 0);
749 }
750
751 for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
752 if (!varyings[i])
753 continue;
754 nir_copy_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, varyings[i]), nir_umod(b, vertex_count, two)),
755 nir_build_deref_array(b, nir_build_deref_var(b, varyings[i]), two));
756 }
757
758 nir_end_primitive(b, .stream_id = 0);
759
760 nir_pop_if(b, count_check);
761
762 vertex_count = nir_iadd(b, vertex_count, nir_imm_int(b, 1));
763 nir_store_var(b, vertex_count_var, vertex_count, 0x1);
764
765 nir_instr_remove(&intr->instr);
766 }
767
768 static void
lower_triangle_strip_end_primitive(nir_builder * b,nir_intrinsic_instr * intr,nir_variable * vertex_count_var)769 lower_triangle_strip_end_primitive(nir_builder *b, nir_intrinsic_instr *intr,
770 nir_variable *vertex_count_var)
771 {
772 /**
773 * vertex_count = 0;
774 */
775 nir_store_var(b, vertex_count_var, nir_imm_int(b, 0), 0x1);
776 nir_instr_remove(&intr->instr);
777 }
778
779 void
d3d12_lower_triangle_strip(nir_shader * shader)780 d3d12_lower_triangle_strip(nir_shader *shader)
781 {
782 nir_builder b;
783 nir_function_impl *impl = nir_shader_get_entrypoint(shader);
784 nir_variable *tmp_vars[VARYING_SLOT_MAX] = {0};
785 nir_variable *out_vars[VARYING_SLOT_MAX] = {0};
786 nir_builder_init(&b, impl);
787
788 shader->info.gs.vertices_out = (shader->info.gs.vertices_out - 2) * 3;
789
790 nir_variable *vertex_count_var =
791 nir_local_variable_create(impl, glsl_uint_type(), "vertex_count");
792
793 nir_block *first = nir_start_block(impl);
794 b.cursor = nir_before_block(first);
795 nir_foreach_variable_with_modes(var, shader, nir_var_shader_out) {
796 const struct glsl_type *type = glsl_array_type(var->type, 3, 0);
797 tmp_vars[var->data.location] = nir_local_variable_create(impl, type, "tmp_var");
798 out_vars[var->data.location] = var;
799 }
800 nir_store_var(&b, vertex_count_var, nir_imm_int(&b, 0), 1);
801
802 nir_foreach_block(block, impl) {
803 nir_foreach_instr_safe(instr, block) {
804 if (instr->type != nir_instr_type_intrinsic)
805 continue;
806
807 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
808 switch (intrin->intrinsic) {
809 case nir_intrinsic_store_deref:
810 b.cursor = nir_before_instr(instr);
811 lower_triangle_strip_store(&b, intrin, vertex_count_var, tmp_vars);
812 break;
813 case nir_intrinsic_emit_vertex_with_counter:
814 case nir_intrinsic_emit_vertex:
815 b.cursor = nir_before_instr(instr);
816 lower_triangle_strip_emit_vertex(&b, intrin, vertex_count_var,
817 tmp_vars, out_vars);
818 break;
819 case nir_intrinsic_end_primitive:
820 case nir_intrinsic_end_primitive_with_counter:
821 b.cursor = nir_before_instr(instr);
822 lower_triangle_strip_end_primitive(&b, intrin, vertex_count_var);
823 break;
824 default:
825 break;
826 }
827 }
828 }
829
830 nir_metadata_preserve(impl, nir_metadata_none);
831 NIR_PASS_V(shader, nir_lower_var_copies);
832 }
833