• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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