Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_nir_passes.c
4570 views
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
static bool
546
lower_bool_input_filter(const nir_instr *instr,
547
UNUSED const void *_options)
548
{
549
if (instr->type != nir_instr_type_intrinsic)
550
return false;
551
552
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
553
if (intr->intrinsic == nir_intrinsic_load_front_face)
554
return true;
555
556
if (intr->intrinsic == nir_intrinsic_load_deref) {
557
nir_deref_instr *deref = nir_instr_as_deref(intr->src[0].ssa->parent_instr);
558
nir_variable *var = nir_deref_instr_get_variable(deref);
559
return var->data.mode == nir_var_shader_in &&
560
glsl_get_base_type(var->type) == GLSL_TYPE_BOOL;
561
}
562
563
return false;
564
}
565
566
static nir_ssa_def *
567
lower_bool_input_impl(nir_builder *b, nir_instr *instr,
568
UNUSED void *_options)
569
{
570
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
571
572
if (intr->intrinsic == nir_intrinsic_load_deref) {
573
nir_deref_instr *deref = nir_instr_as_deref(intr->src[0].ssa->parent_instr);
574
nir_variable *var = nir_deref_instr_get_variable(deref);
575
576
/* rewrite var->type */
577
var->type = glsl_vector_type(GLSL_TYPE_UINT,
578
glsl_get_vector_elements(var->type));
579
deref->type = var->type;
580
}
581
582
intr->dest.ssa.bit_size = 32;
583
return nir_i2b1(b, &intr->dest.ssa);
584
}
585
586
bool
587
d3d12_lower_bool_input(struct nir_shader *s)
588
{
589
return nir_shader_lower_instructions(s, lower_bool_input_filter,
590
lower_bool_input_impl, NULL);
591
}
592
593
void
594
d3d12_add_missing_dual_src_target(struct nir_shader *s,
595
unsigned missing_mask)
596
{
597
assert(missing_mask != 0);
598
nir_builder b;
599
nir_function_impl *impl = nir_shader_get_entrypoint(s);
600
nir_builder_init(&b, impl);
601
b.cursor = nir_before_cf_list(&impl->body);
602
603
nir_ssa_def *zero = nir_imm_zero(&b, 4, 32);
604
for (unsigned i = 0; i < 2; ++i) {
605
606
if (!(missing_mask & (1u << i)))
607
continue;
608
609
const char *name = i == 0 ? "gl_FragData[0]" :
610
"gl_SecondaryFragDataEXT[0]";
611
nir_variable *out = nir_variable_create(s, nir_var_shader_out,
612
glsl_vec4_type(), name);
613
out->data.location = FRAG_RESULT_DATA0;
614
out->data.driver_location = i;
615
out->data.index = i;
616
617
nir_store_var(&b, out, zero, 0xf);
618
}
619
nir_metadata_preserve(impl, nir_metadata_block_index |
620
nir_metadata_dominance);
621
}
622
623
static bool
624
fix_io_uint_type(struct nir_shader *s, nir_variable_mode modes, int slot)
625
{
626
nir_variable *fixed_var = NULL;
627
nir_foreach_variable_with_modes(var, s, modes) {
628
if (var->data.location == slot) {
629
var->type = glsl_uint_type();
630
fixed_var = var;
631
break;
632
}
633
}
634
635
assert(fixed_var);
636
637
nir_foreach_function(function, s) {
638
if (function->impl) {
639
nir_foreach_block(block, function->impl) {
640
nir_foreach_instr_safe(instr, block) {
641
if (instr->type == nir_instr_type_deref) {
642
nir_deref_instr *deref = nir_instr_as_deref(instr);
643
if (deref->var == fixed_var)
644
deref->type = fixed_var->type;
645
}
646
}
647
}
648
}
649
}
650
return true;
651
}
652
653
bool
654
d3d12_fix_io_uint_type(struct nir_shader *s, uint64_t in_mask, uint64_t out_mask)
655
{
656
if (!(s->info.outputs_written & out_mask) &&
657
!(s->info.inputs_read & in_mask))
658
return false;
659
660
bool progress = false;
661
662
while (in_mask) {
663
int slot = u_bit_scan64(&in_mask);
664
progress |= (s->info.inputs_read & (1ull << slot)) &&
665
fix_io_uint_type(s, nir_var_shader_in, slot);
666
}
667
668
while (out_mask) {
669
int slot = u_bit_scan64(&out_mask);
670
progress |= (s->info.outputs_written & (1ull << slot)) &&
671
fix_io_uint_type(s, nir_var_shader_out, slot);
672
}
673
674
return progress;
675
}
676
677
static bool
678
lower_load_ubo_packed_filter(const nir_instr *instr,
679
UNUSED const void *_options) {
680
if (instr->type != nir_instr_type_intrinsic)
681
return false;
682
683
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
684
685
return intr->intrinsic == nir_intrinsic_load_ubo;
686
}
687
688
static nir_ssa_def *
689
lower_load_ubo_packed_impl(nir_builder *b, nir_instr *instr,
690
UNUSED void *_options) {
691
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
692
693
nir_ssa_def *buffer = intr->src[0].ssa;
694
nir_ssa_def *offset = intr->src[1].ssa;
695
696
nir_ssa_def *result =
697
build_load_ubo_dxil(b, buffer,
698
offset,
699
nir_dest_num_components(intr->dest),
700
nir_dest_bit_size(intr->dest));
701
return result;
702
}
703
704
bool
705
nir_lower_packed_ubo_loads(nir_shader *nir) {
706
return nir_shader_lower_instructions(nir,
707
lower_load_ubo_packed_filter,
708
lower_load_ubo_packed_impl,
709
NULL);
710
}
711
712
void
713
d3d12_lower_primitive_id(nir_shader *shader)
714
{
715
nir_builder b;
716
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
717
nir_ssa_def *primitive_id;
718
nir_builder_init(&b, impl);
719
720
nir_variable *primitive_id_var = nir_variable_create(shader, nir_var_shader_out,
721
glsl_uint_type(), "primitive_id");
722
primitive_id_var->data.location = VARYING_SLOT_PRIMITIVE_ID;
723
primitive_id_var->data.interpolation = INTERP_MODE_FLAT;
724
725
nir_foreach_block(block, impl) {
726
b.cursor = nir_before_block(block);
727
primitive_id = nir_load_primitive_id(&b);
728
729
nir_foreach_instr_safe(instr, block) {
730
if (instr->type != nir_instr_type_intrinsic ||
731
nir_instr_as_intrinsic(instr)->intrinsic != nir_intrinsic_emit_vertex)
732
continue;
733
734
b.cursor = nir_before_instr(instr);
735
nir_store_var(&b, primitive_id_var, primitive_id, 0x1);
736
}
737
}
738
739
nir_metadata_preserve(impl, 0);
740
}
741
742
static void
743
lower_triangle_strip_store(nir_builder *b, nir_intrinsic_instr *intr,
744
nir_variable *vertex_count_var,
745
nir_variable **varyings)
746
{
747
/**
748
* tmp_varying[slot][min(vertex_count, 2)] = src
749
*/
750
nir_ssa_def *vertex_count = nir_load_var(b, vertex_count_var);
751
nir_ssa_def *index = nir_imin(b, vertex_count, nir_imm_int(b, 2));
752
nir_variable *var = nir_intrinsic_get_var(intr, 0);
753
754
if (var->data.mode != nir_var_shader_out)
755
return;
756
757
nir_deref_instr *deref = nir_build_deref_array(b, nir_build_deref_var(b, varyings[var->data.location]), index);
758
nir_ssa_def *value = nir_ssa_for_src(b, intr->src[1], intr->num_components);
759
nir_store_deref(b, deref, value, 0xf);
760
nir_instr_remove(&intr->instr);
761
}
762
763
static void
764
lower_triangle_strip_emit_vertex(nir_builder *b, nir_intrinsic_instr *intr,
765
nir_variable *vertex_count_var,
766
nir_variable **varyings,
767
nir_variable **out_varyings)
768
{
769
// TODO xfb + flat shading + last_pv
770
/**
771
* if (vertex_count >= 2) {
772
* for (i = 0; i < 3; i++) {
773
* foreach(slot)
774
* out[slot] = tmp_varying[slot][i];
775
* EmitVertex();
776
* }
777
* EndPrimitive();
778
* foreach(slot)
779
* tmp_varying[slot][vertex_count % 2] = tmp_varying[slot][2];
780
* }
781
* vertex_count++;
782
*/
783
784
nir_ssa_def *two = nir_imm_int(b, 2);
785
nir_ssa_def *vertex_count = nir_load_var(b, vertex_count_var);
786
nir_ssa_def *count_cmp = nir_uge(b, vertex_count, two);
787
nir_if *count_check = nir_push_if(b, count_cmp);
788
789
for (int j = 0; j < 3; ++j) {
790
for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
791
if (!varyings[i])
792
continue;
793
nir_copy_deref(b, nir_build_deref_var(b, out_varyings[i]),
794
nir_build_deref_array_imm(b, nir_build_deref_var(b, varyings[i]), j));
795
}
796
nir_emit_vertex(b, 0);
797
}
798
799
for (int i = 0; i < VARYING_SLOT_MAX; ++i) {
800
if (!varyings[i])
801
continue;
802
nir_copy_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, varyings[i]), nir_umod(b, vertex_count, two)),
803
nir_build_deref_array(b, nir_build_deref_var(b, varyings[i]), two));
804
}
805
806
nir_end_primitive(b, .stream_id = 0);
807
808
nir_pop_if(b, count_check);
809
810
vertex_count = nir_iadd(b, vertex_count, nir_imm_int(b, 1));
811
nir_store_var(b, vertex_count_var, vertex_count, 0x1);
812
813
nir_instr_remove(&intr->instr);
814
}
815
816
static void
817
lower_triangle_strip_end_primitive(nir_builder *b, nir_intrinsic_instr *intr,
818
nir_variable *vertex_count_var)
819
{
820
/**
821
* vertex_count = 0;
822
*/
823
nir_store_var(b, vertex_count_var, nir_imm_int(b, 0), 0x1);
824
nir_instr_remove(&intr->instr);
825
}
826
827
void
828
d3d12_lower_triangle_strip(nir_shader *shader)
829
{
830
nir_builder b;
831
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
832
nir_variable *tmp_vars[VARYING_SLOT_MAX] = {0};
833
nir_variable *out_vars[VARYING_SLOT_MAX] = {0};
834
nir_builder_init(&b, impl);
835
836
shader->info.gs.vertices_out = (shader->info.gs.vertices_out - 2) * 3;
837
838
nir_variable *vertex_count_var =
839
nir_local_variable_create(impl, glsl_uint_type(), "vertex_count");
840
841
nir_block *first = nir_start_block(impl);
842
b.cursor = nir_before_block(first);
843
nir_foreach_variable_with_modes(var, shader, nir_var_shader_out) {
844
const struct glsl_type *type = glsl_array_type(var->type, 3, 0);
845
tmp_vars[var->data.location] = nir_local_variable_create(impl, type, "tmp_var");
846
out_vars[var->data.location] = var;
847
}
848
nir_store_var(&b, vertex_count_var, nir_imm_int(&b, 0), 1);
849
850
nir_foreach_block(block, impl) {
851
nir_foreach_instr_safe(instr, block) {
852
if (instr->type != nir_instr_type_intrinsic)
853
continue;
854
855
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
856
switch (intrin->intrinsic) {
857
case nir_intrinsic_store_deref:
858
b.cursor = nir_before_instr(instr);
859
lower_triangle_strip_store(&b, intrin, vertex_count_var, tmp_vars);
860
break;
861
case nir_intrinsic_emit_vertex_with_counter:
862
case nir_intrinsic_emit_vertex:
863
b.cursor = nir_before_instr(instr);
864
lower_triangle_strip_emit_vertex(&b, intrin, vertex_count_var,
865
tmp_vars, out_vars);
866
break;
867
case nir_intrinsic_end_primitive:
868
case nir_intrinsic_end_primitive_with_counter:
869
b.cursor = nir_before_instr(instr);
870
lower_triangle_strip_end_primitive(&b, intrin, vertex_count_var);
871
break;
872
default:
873
break;
874
}
875
}
876
}
877
878
nir_metadata_preserve(impl, 0);
879
NIR_PASS_V(shader, nir_lower_var_copies);
880
}
881
882