1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 * Copyright © 2023 Valve Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * IN THE SOFTWARE.
24 */
25
26 #include "ac_nir.h"
27 #include "nir.h"
28 #include "nir_builder.h"
29 #include "radv_nir.h"
30 #include "radv_private.h"
31 #include "radv_shader.h"
32
33 static int
type_size_vec4(const struct glsl_type * type,bool bindless)34 type_size_vec4(const struct glsl_type *type, bool bindless)
35 {
36 return glsl_count_attribute_slots(type, false);
37 }
38
39 void
radv_nir_lower_io_to_scalar_early(nir_shader * nir,nir_variable_mode mask)40 radv_nir_lower_io_to_scalar_early(nir_shader *nir, nir_variable_mode mask)
41 {
42 bool progress = false;
43
44 NIR_PASS(progress, nir, nir_lower_io_to_scalar_early, mask);
45 if (progress) {
46 /* Optimize the new vector code and then remove dead vars */
47 NIR_PASS(_, nir, nir_copy_prop);
48 NIR_PASS(_, nir, nir_opt_shrink_vectors);
49
50 if (mask & nir_var_shader_out) {
51 /* Optimize swizzled movs of load_const for nir_link_opt_varyings's constant propagation. */
52 NIR_PASS(_, nir, nir_opt_constant_folding);
53
54 /* For nir_link_opt_varyings's duplicate input opt */
55 NIR_PASS(_, nir, nir_opt_cse);
56 }
57
58 /* Run copy-propagation to help remove dead output variables (some shaders have useless copies
59 * to/from an output), so compaction later will be more effective.
60 *
61 * This will have been done earlier but it might not have worked because the outputs were
62 * vector.
63 */
64 if (nir->info.stage == MESA_SHADER_TESS_CTRL)
65 NIR_PASS(_, nir, nir_opt_copy_prop_vars);
66
67 NIR_PASS(_, nir, nir_opt_dce);
68 NIR_PASS(_, nir, nir_remove_dead_variables, nir_var_function_temp | nir_var_shader_in | nir_var_shader_out, NULL);
69 }
70 }
71
72 void
radv_nir_lower_io(struct radv_device * device,nir_shader * nir)73 radv_nir_lower_io(struct radv_device *device, nir_shader *nir)
74 {
75 if (nir->info.stage == MESA_SHADER_FRAGMENT) {
76 nir_assign_io_var_locations(nir, nir_var_shader_in, &nir->num_inputs, MESA_SHADER_FRAGMENT);
77 }
78
79 if (nir->info.stage == MESA_SHADER_VERTEX) {
80 NIR_PASS(_, nir, nir_lower_io, nir_var_shader_in, type_size_vec4, 0);
81 NIR_PASS(_, nir, nir_lower_io, nir_var_shader_out, type_size_vec4, nir_lower_io_lower_64bit_to_32);
82 } else {
83 NIR_PASS(_, nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out, type_size_vec4,
84 nir_lower_io_lower_64bit_to_32);
85 }
86
87 /* This pass needs actual constants */
88 NIR_PASS(_, nir, nir_opt_constant_folding);
89
90 NIR_PASS(_, nir, nir_io_add_const_offset_to_base, nir_var_shader_in | nir_var_shader_out);
91
92 if (device->physical_device->use_ngg_streamout && nir->xfb_info) {
93 NIR_PASS_V(nir, nir_io_add_intrinsic_xfb_info);
94
95 /* The total number of shader outputs is required for computing the pervertex LDS size for
96 * VS/TES when lowering NGG streamout.
97 */
98 nir_assign_io_var_locations(nir, nir_var_shader_out, &nir->num_outputs, nir->info.stage);
99 }
100 }
101
102 /* IO slot layout for stages that aren't linked. */
103 enum {
104 RADV_IO_SLOT_POS = 0,
105 RADV_IO_SLOT_CLIP_DIST0,
106 RADV_IO_SLOT_CLIP_DIST1,
107 RADV_IO_SLOT_PSIZ,
108 RADV_IO_SLOT_VAR0, /* 0..31 */
109 };
110
111 static unsigned
radv_map_io_driver_location(unsigned semantic)112 radv_map_io_driver_location(unsigned semantic)
113 {
114 if ((semantic >= VARYING_SLOT_PATCH0 && semantic < VARYING_SLOT_TESS_MAX) ||
115 semantic == VARYING_SLOT_TESS_LEVEL_INNER || semantic == VARYING_SLOT_TESS_LEVEL_OUTER)
116 return ac_shader_io_get_unique_index_patch(semantic);
117
118 switch (semantic) {
119 case VARYING_SLOT_POS:
120 return RADV_IO_SLOT_POS;
121 case VARYING_SLOT_CLIP_DIST0:
122 return RADV_IO_SLOT_CLIP_DIST0;
123 case VARYING_SLOT_CLIP_DIST1:
124 return RADV_IO_SLOT_CLIP_DIST1;
125 case VARYING_SLOT_PSIZ:
126 return RADV_IO_SLOT_PSIZ;
127 default:
128 assert(semantic >= VARYING_SLOT_VAR0 && semantic <= VARYING_SLOT_VAR31);
129 return RADV_IO_SLOT_VAR0 + (semantic - VARYING_SLOT_VAR0);
130 }
131 }
132
133 bool
radv_nir_lower_io_to_mem(struct radv_device * device,struct radv_shader_stage * stage)134 radv_nir_lower_io_to_mem(struct radv_device *device, struct radv_shader_stage *stage)
135 {
136 const struct radv_shader_info *info = &stage->info;
137 ac_nir_map_io_driver_location map_input = info->inputs_linked ? NULL : radv_map_io_driver_location;
138 ac_nir_map_io_driver_location map_output = info->outputs_linked ? NULL : radv_map_io_driver_location;
139 nir_shader *nir = stage->nir;
140
141 if (nir->info.stage == MESA_SHADER_VERTEX) {
142 if (info->vs.as_ls) {
143 NIR_PASS_V(nir, ac_nir_lower_ls_outputs_to_mem, map_output, info->vs.tcs_in_out_eq,
144 info->vs.tcs_temp_only_input_mask);
145 return true;
146 } else if (info->vs.as_es) {
147 NIR_PASS_V(nir, ac_nir_lower_es_outputs_to_mem, map_output, device->physical_device->rad_info.gfx_level,
148 info->esgs_itemsize);
149 return true;
150 }
151 } else if (nir->info.stage == MESA_SHADER_TESS_CTRL) {
152 NIR_PASS_V(nir, ac_nir_lower_hs_inputs_to_mem, map_input, info->vs.tcs_in_out_eq);
153 NIR_PASS_V(nir, ac_nir_lower_hs_outputs_to_mem, map_output, device->physical_device->rad_info.gfx_level,
154 info->tcs.tes_reads_tess_factors, info->tcs.tes_inputs_read, info->tcs.tes_patch_inputs_read,
155 info->tcs.num_linked_outputs, info->tcs.num_linked_patch_outputs, info->wave_size, false, false,
156 !info->has_epilog);
157
158 return true;
159 } else if (nir->info.stage == MESA_SHADER_TESS_EVAL) {
160 NIR_PASS_V(nir, ac_nir_lower_tes_inputs_to_mem, map_input);
161
162 if (info->tes.as_es) {
163 NIR_PASS_V(nir, ac_nir_lower_es_outputs_to_mem, map_output, device->physical_device->rad_info.gfx_level,
164 info->esgs_itemsize);
165 }
166
167 return true;
168 } else if (nir->info.stage == MESA_SHADER_GEOMETRY) {
169 NIR_PASS_V(nir, ac_nir_lower_gs_inputs_to_mem, map_input, device->physical_device->rad_info.gfx_level, false);
170 return true;
171 } else if (nir->info.stage == MESA_SHADER_TASK) {
172 ac_nir_lower_task_outputs_to_mem(nir, AC_TASK_PAYLOAD_ENTRY_BYTES, device->physical_device->task_info.num_entries,
173 info->cs.has_query);
174 return true;
175 } else if (nir->info.stage == MESA_SHADER_MESH) {
176 ac_nir_lower_mesh_inputs_to_mem(nir, AC_TASK_PAYLOAD_ENTRY_BYTES, device->physical_device->task_info.num_entries);
177 return true;
178 }
179
180 return false;
181 }
182