2 * Copyright © 2020 Valve Corporation
3 * SPDX-License-Identifier: MIT
6 #include "tu_private.h"
7 #include "nir_builder.h"
9 /* Some a6xx variants cannot support a non-contiguous multiview mask. Instead,
10 * inside the shader something like this needs to be inserted:
12 * gl_Position = ((1ull << gl_ViewIndex) & view_mask) ? gl_Position : vec4(0.);
14 * Scan backwards until we find the gl_Position write (there should only be
18 lower_multiview_mask(nir_function_impl
*impl
, uint32_t mask
)
21 nir_builder_init(&b
, impl
);
23 nir_foreach_block_reverse(block
, impl
) {
24 nir_foreach_instr_reverse(instr
, block
) {
25 if (instr
->type
!= nir_instr_type_intrinsic
)
28 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
29 if (intrin
->intrinsic
!= nir_intrinsic_store_deref
)
32 nir_deref_instr
*deref
= nir_src_as_deref(intrin
->src
[0]);
33 if (deref
->mode
!= nir_var_shader_out
)
36 nir_variable
*var
= nir_deref_instr_get_variable(deref
);
37 if (var
->data
.location
!= VARYING_SLOT_POS
)
40 assert(intrin
->src
[1].is_ssa
);
41 nir_ssa_def
*orig_src
= intrin
->src
[1].ssa
;
42 b
.cursor
= nir_before_instr(instr
);
44 /* ((1ull << gl_ViewIndex) & mask) != 0 */
46 nir_i2b(&b
, nir_iand(&b
, nir_imm_int(&b
, mask
),
47 nir_ishl(&b
, nir_imm_int(&b
, 1),
48 nir_load_view_index(&b
))));
50 nir_ssa_def
*src
= nir_bcsel(&b
, cmp
, orig_src
, nir_imm_float(&b
, 0.));
51 nir_instr_rewrite_src(instr
, &intrin
->src
[1], nir_src_for_ssa(src
));
53 nir_metadata_preserve(impl
, nir_metadata_block_index
|
54 nir_metadata_dominance
);
59 nir_metadata_preserve(impl
, nir_metadata_all
);
64 tu_nir_lower_multiview(nir_shader
*nir
, uint32_t mask
, struct tu_device
*dev
)
66 nir_function_impl
*entrypoint
= nir_shader_get_entrypoint(nir
);
68 if (!dev
->physical_device
->supports_multiview_mask
&&
69 !util_is_power_of_two_or_zero(mask
+ 1)) {
70 return lower_multiview_mask(entrypoint
, mask
);
73 nir_metadata_preserve(entrypoint
, nir_metadata_all
);