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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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