xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/rogue_nir.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
5*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
6*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
7*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
9*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/nir_spirv.h"
25*61046927SAndroid Build Coastguard Worker #include "nir/nir.h"
26*61046927SAndroid Build Coastguard Worker #include "rogue.h"
27*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker /**
32*61046927SAndroid Build Coastguard Worker  * \file rogue_nir.c
33*61046927SAndroid Build Coastguard Worker  *
34*61046927SAndroid Build Coastguard Worker  * \brief Contains SPIR-V and NIR-specific functions.
35*61046927SAndroid Build Coastguard Worker  */
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker /**
38*61046927SAndroid Build Coastguard Worker  * \brief SPIR-V to NIR compilation options.
39*61046927SAndroid Build Coastguard Worker  */
40*61046927SAndroid Build Coastguard Worker static const struct spirv_to_nir_options spirv_options = {
41*61046927SAndroid Build Coastguard Worker    .environment = NIR_SPIRV_VULKAN,
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker    /* Buffer address: (descriptor_set, binding), offset. */
44*61046927SAndroid Build Coastguard Worker    .ubo_addr_format = nir_address_format_64bit_global,
45*61046927SAndroid Build Coastguard Worker };
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker static const nir_shader_compiler_options nir_options = {
48*61046927SAndroid Build Coastguard Worker    .fuse_ffma32 = true,
49*61046927SAndroid Build Coastguard Worker };
50*61046927SAndroid Build Coastguard Worker 
rogue_glsl_type_size(const struct glsl_type * type,bool bindless)51*61046927SAndroid Build Coastguard Worker static int rogue_glsl_type_size(const struct glsl_type *type, bool bindless)
52*61046927SAndroid Build Coastguard Worker {
53*61046927SAndroid Build Coastguard Worker    return glsl_count_attribute_slots(type, false);
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker /**
57*61046927SAndroid Build Coastguard Worker  * \brief Applies optimizations and passes required to lower the NIR shader into
58*61046927SAndroid Build Coastguard Worker  * a form suitable for lowering to Rogue IR.
59*61046927SAndroid Build Coastguard Worker  *
60*61046927SAndroid Build Coastguard Worker  * \param[in] ctx Shared multi-stage build context.
61*61046927SAndroid Build Coastguard Worker  * \param[in] shader Rogue shader.
62*61046927SAndroid Build Coastguard Worker  * \param[in] stage Shader stage.
63*61046927SAndroid Build Coastguard Worker  */
rogue_nir_passes(struct rogue_build_ctx * ctx,nir_shader * nir,gl_shader_stage stage)64*61046927SAndroid Build Coastguard Worker static void rogue_nir_passes(struct rogue_build_ctx *ctx,
65*61046927SAndroid Build Coastguard Worker                              nir_shader *nir,
66*61046927SAndroid Build Coastguard Worker                              gl_shader_stage stage)
67*61046927SAndroid Build Coastguard Worker {
68*61046927SAndroid Build Coastguard Worker    bool progress;
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker #if !defined(NDEBUG)
71*61046927SAndroid Build Coastguard Worker    bool nir_debug_print_shader_prev = nir_debug_print_shader[nir->info.stage];
72*61046927SAndroid Build Coastguard Worker    nir_debug_print_shader[nir->info.stage] = ROGUE_DEBUG(NIR_PASSES);
73*61046927SAndroid Build Coastguard Worker #endif /* !defined(NDEBUG) */
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    nir_validate_shader(nir, "after spirv_to_nir");
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_vars_to_ssa);
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    /* Splitting. */
80*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_split_var_copies);
81*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_split_per_member_structs);
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    /* Replace references to I/O variables with intrinsics. */
84*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir,
85*61046927SAndroid Build Coastguard Worker               nir_lower_io,
86*61046927SAndroid Build Coastguard Worker               nir_var_shader_in | nir_var_shader_out,
87*61046927SAndroid Build Coastguard Worker               rogue_glsl_type_size,
88*61046927SAndroid Build Coastguard Worker               (nir_lower_io_options)0);
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    /* Load inputs to scalars (single registers later). */
91*61046927SAndroid Build Coastguard Worker    /* TODO: Fitrp can process multiple frag inputs at once, scalarise I/O. */
92*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_io_to_scalar, nir_var_shader_in, NULL, NULL);
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    /* Optimize GL access qualifiers. */
95*61046927SAndroid Build Coastguard Worker    const nir_opt_access_options opt_access_options = {
96*61046927SAndroid Build Coastguard Worker       .is_vulkan = true,
97*61046927SAndroid Build Coastguard Worker    };
98*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_opt_access, &opt_access_options);
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker    /* Apply PFO code to the fragment shader output. */
101*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_FRAGMENT)
102*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, rogue_nir_pfo);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    /* Load outputs to scalars (single registers later). */
105*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_io_to_scalar, nir_var_shader_out, NULL, NULL);
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    /* Lower ALU operations to scalars. */
108*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_alu_to_scalar, NULL, NULL);
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    /* Lower load_consts to scalars. */
111*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_load_const_to_scalar);
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    /* Additional I/O lowering. */
114*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir,
115*61046927SAndroid Build Coastguard Worker               nir_lower_explicit_io,
116*61046927SAndroid Build Coastguard Worker               nir_var_mem_ubo,
117*61046927SAndroid Build Coastguard Worker               spirv_options.ubo_addr_format);
118*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_lower_io_to_scalar, nir_var_mem_ubo, NULL, NULL);
119*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, rogue_nir_lower_io);
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker    /* Algebraic opts. */
122*61046927SAndroid Build Coastguard Worker    do {
123*61046927SAndroid Build Coastguard Worker       progress = false;
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_copy_prop);
126*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_cse);
127*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_algebraic);
128*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_constant_folding);
129*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_dce);
130*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_opt_gcm, false);
131*61046927SAndroid Build Coastguard Worker    } while (progress);
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    /* Late algebraic opts. */
134*61046927SAndroid Build Coastguard Worker    do {
135*61046927SAndroid Build Coastguard Worker       progress = false;
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_opt_algebraic_late);
138*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_opt_constant_folding);
139*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_copy_prop);
140*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_opt_dce);
141*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_opt_cse);
142*61046927SAndroid Build Coastguard Worker    } while (progress);
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    /* Remove unused constant registers. */
145*61046927SAndroid Build Coastguard Worker    NIR_PASS_V(nir, nir_opt_dce);
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker    /* Move loads to just before they're needed. */
148*61046927SAndroid Build Coastguard Worker    /* Disabled for now since we want to try and keep them vectorised and group
149*61046927SAndroid Build Coastguard Worker     * them. */
150*61046927SAndroid Build Coastguard Worker    /* TODO: Investigate this further. */
151*61046927SAndroid Build Coastguard Worker    /* NIR_PASS_V(nir, nir_opt_move, nir_move_load_ubo | nir_move_load_input); */
152*61046927SAndroid Build Coastguard Worker 
153*61046927SAndroid Build Coastguard Worker    /* TODO: Re-enable scheduling after register pressure tweaks. */
154*61046927SAndroid Build Coastguard Worker #if 0
155*61046927SAndroid Build Coastguard Worker 	/* Instruction scheduling. */
156*61046927SAndroid Build Coastguard Worker 	struct nir_schedule_options schedule_options = {
157*61046927SAndroid Build Coastguard Worker 		.threshold = ROGUE_MAX_REG_TEMP / 2,
158*61046927SAndroid Build Coastguard Worker 	};
159*61046927SAndroid Build Coastguard Worker 	NIR_PASS_V(nir, nir_schedule, &schedule_options);
160*61046927SAndroid Build Coastguard Worker #endif
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    /* Assign I/O locations. */
163*61046927SAndroid Build Coastguard Worker    nir_assign_io_var_locations(nir,
164*61046927SAndroid Build Coastguard Worker                                nir_var_shader_in,
165*61046927SAndroid Build Coastguard Worker                                &nir->num_inputs,
166*61046927SAndroid Build Coastguard Worker                                nir->info.stage);
167*61046927SAndroid Build Coastguard Worker    nir_assign_io_var_locations(nir,
168*61046927SAndroid Build Coastguard Worker                                nir_var_shader_out,
169*61046927SAndroid Build Coastguard Worker                                &nir->num_outputs,
170*61046927SAndroid Build Coastguard Worker                                nir->info.stage);
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker    /* Renumber SSA defs. */
173*61046927SAndroid Build Coastguard Worker    nir_index_ssa_defs(nir_shader_get_entrypoint(nir));
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker    /* Gather info into nir shader struct. */
176*61046927SAndroid Build Coastguard Worker    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    /* Clean-up after passes. */
179*61046927SAndroid Build Coastguard Worker    nir_sweep(nir);
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    nir_validate_shader(nir, "after passes");
182*61046927SAndroid Build Coastguard Worker    if (ROGUE_DEBUG(NIR)) {
183*61046927SAndroid Build Coastguard Worker       fputs("after passes\n", stdout);
184*61046927SAndroid Build Coastguard Worker       nir_print_shader(nir, stdout);
185*61046927SAndroid Build Coastguard Worker    }
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker #if !defined(NDEBUG)
188*61046927SAndroid Build Coastguard Worker    nir_debug_print_shader[nir->info.stage] = nir_debug_print_shader_prev;
189*61046927SAndroid Build Coastguard Worker #endif /* !defined(NDEBUG) */
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker /**
193*61046927SAndroid Build Coastguard Worker  * \brief Converts a SPIR-V shader to NIR.
194*61046927SAndroid Build Coastguard Worker  *
195*61046927SAndroid Build Coastguard Worker  * \param[in] ctx Shared multi-stage build context.
196*61046927SAndroid Build Coastguard Worker  * \param[in] entry Shader entry-point function name.
197*61046927SAndroid Build Coastguard Worker  * \param[in] stage Shader stage.
198*61046927SAndroid Build Coastguard Worker  * \param[in] spirv_size SPIR-V data length in DWORDs.
199*61046927SAndroid Build Coastguard Worker  * \param[in] spirv_data SPIR-V data.
200*61046927SAndroid Build Coastguard Worker  * \param[in] num_spec Number of SPIR-V specializations.
201*61046927SAndroid Build Coastguard Worker  * \param[in] spec SPIR-V specializations.
202*61046927SAndroid Build Coastguard Worker  * \return A nir_shader* if successful, or NULL if unsuccessful.
203*61046927SAndroid Build Coastguard Worker  */
204*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_spirv_to_nir(rogue_build_ctx * ctx,gl_shader_stage stage,const char * entry,unsigned spirv_size,const uint32_t * spirv_data,unsigned num_spec,struct nir_spirv_specialization * spec)205*61046927SAndroid Build Coastguard Worker nir_shader *rogue_spirv_to_nir(rogue_build_ctx *ctx,
206*61046927SAndroid Build Coastguard Worker                                gl_shader_stage stage,
207*61046927SAndroid Build Coastguard Worker                                const char *entry,
208*61046927SAndroid Build Coastguard Worker                                unsigned spirv_size,
209*61046927SAndroid Build Coastguard Worker                                const uint32_t *spirv_data,
210*61046927SAndroid Build Coastguard Worker                                unsigned num_spec,
211*61046927SAndroid Build Coastguard Worker                                struct nir_spirv_specialization *spec)
212*61046927SAndroid Build Coastguard Worker {
213*61046927SAndroid Build Coastguard Worker    nir_shader *nir;
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker    nir = spirv_to_nir(spirv_data,
216*61046927SAndroid Build Coastguard Worker                       spirv_size,
217*61046927SAndroid Build Coastguard Worker                       spec,
218*61046927SAndroid Build Coastguard Worker                       num_spec,
219*61046927SAndroid Build Coastguard Worker                       stage,
220*61046927SAndroid Build Coastguard Worker                       entry,
221*61046927SAndroid Build Coastguard Worker                       &spirv_options,
222*61046927SAndroid Build Coastguard Worker                       &nir_options);
223*61046927SAndroid Build Coastguard Worker    if (!nir)
224*61046927SAndroid Build Coastguard Worker       return NULL;
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker    ralloc_steal(ctx, nir);
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    /* Apply passes. */
229*61046927SAndroid Build Coastguard Worker    rogue_nir_passes(ctx, nir, stage);
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker    /* Collect I/O data to pass back to the driver. */
232*61046927SAndroid Build Coastguard Worker    rogue_collect_io_data(ctx, nir);
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    return nir;
235*61046927SAndroid Build Coastguard Worker }
236