1 /*
2 * Copyright © 2021 Valve Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 #include "ac_nir.h"
8 #include "ac_nir_helpers.h"
9
10 #include "nir_builder.h"
11
12 static void
gather_outputs(nir_builder * b,nir_function_impl * impl,ac_nir_prerast_out * out)13 gather_outputs(nir_builder *b, nir_function_impl *impl, ac_nir_prerast_out *out)
14 {
15 /* Assume:
16 * - the shader used nir_lower_io_to_temporaries
17 * - 64-bit outputs are lowered
18 * - no indirect indexing is present
19 */
20 nir_foreach_block (block, impl) {
21 nir_foreach_instr_safe (instr, block) {
22 if (instr->type != nir_instr_type_intrinsic)
23 continue;
24
25 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
26 if (intrin->intrinsic != nir_intrinsic_store_output)
27 continue;
28
29 ac_nir_gather_prerast_store_output_info(b, intrin, out);
30 nir_instr_remove(instr);
31 }
32 }
33 }
34
35 void
ac_nir_lower_legacy_vs(nir_shader * nir,enum amd_gfx_level gfx_level,uint32_t clip_cull_mask,const uint8_t * param_offsets,bool has_param_exports,bool export_primitive_id,bool disable_streamout,bool kill_pointsize,bool kill_layer,bool force_vrs)36 ac_nir_lower_legacy_vs(nir_shader *nir,
37 enum amd_gfx_level gfx_level,
38 uint32_t clip_cull_mask,
39 const uint8_t *param_offsets,
40 bool has_param_exports,
41 bool export_primitive_id,
42 bool disable_streamout,
43 bool kill_pointsize,
44 bool kill_layer,
45 bool force_vrs)
46 {
47 nir_function_impl *impl = nir_shader_get_entrypoint(nir);
48 nir_metadata preserved = nir_metadata_control_flow;
49
50 nir_builder b = nir_builder_at(nir_after_impl(impl));
51
52 ac_nir_prerast_out out = {0};
53 gather_outputs(&b, impl, &out);
54 b.cursor = nir_after_impl(impl);
55
56 if (export_primitive_id) {
57 /* When the primitive ID is read by FS, we must ensure that it's exported by the previous
58 * vertex stage because it's implicit for VS or TES (but required by the Vulkan spec for GS
59 * or MS).
60 */
61 out.outputs[VARYING_SLOT_PRIMITIVE_ID][0] = nir_load_primitive_id(&b);
62 out.infos[VARYING_SLOT_PRIMITIVE_ID].as_varying_mask = 0x1;
63
64 /* Update outputs_written to reflect that the pass added a new output. */
65 nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID);
66 }
67
68 if (!disable_streamout && nir->xfb_info) {
69 ac_nir_emit_legacy_streamout(&b, 0, ac_nir_get_sorted_xfb_info(nir), &out);
70 preserved = nir_metadata_none;
71 }
72
73 uint64_t export_outputs = nir->info.outputs_written | VARYING_BIT_POS;
74 if (kill_pointsize)
75 export_outputs &= ~VARYING_BIT_PSIZ;
76 if (kill_layer)
77 export_outputs &= ~VARYING_BIT_LAYER;
78
79 ac_nir_export_position(&b, gfx_level, clip_cull_mask, !has_param_exports,
80 force_vrs, true, export_outputs, &out, NULL);
81
82 if (has_param_exports) {
83 ac_nir_export_parameters(&b, param_offsets,
84 nir->info.outputs_written,
85 nir->info.outputs_written_16bit,
86 &out);
87 }
88
89 nir_metadata_preserve(impl, preserved);
90 }
91