1 /*
2 * Copyright (c) 2017 Lima Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25 #include <err.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "main/mtypes.h"
30
31 #include "compiler/glsl/standalone.h"
32 #include "compiler/glsl/glsl_to_nir.h"
33 #include "compiler/glsl/gl_nir.h"
34 #include "compiler/nir_types.h"
35
36 #include "lima_context.h"
37 #include "lima_program.h"
38 #include "ir/lima_ir.h"
39 #include "standalone/glsl.h"
40
41 static void
print_usage(void)42 print_usage(void)
43 {
44 printf("Usage: lima_compiler [OPTIONS]... FILE\n");
45 printf(" --help - show this message\n");
46 }
47
48 static void
insert_sorted(struct exec_list * var_list,nir_variable * new_var)49 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
50 {
51 nir_foreach_variable_in_list(var, var_list) {
52 if (var->data.location > new_var->data.location &&
53 new_var->data.location >= 0) {
54 exec_node_insert_node_before(&var->node, &new_var->node);
55 return;
56 }
57 }
58 exec_list_push_tail(var_list, &new_var->node);
59 }
60
61 static void
sort_varyings(nir_shader * nir,nir_variable_mode mode)62 sort_varyings(nir_shader *nir, nir_variable_mode mode)
63 {
64 struct exec_list new_list;
65 exec_list_make_empty(&new_list);
66 nir_foreach_variable_with_modes_safe(var, nir, mode) {
67 exec_node_remove(&var->node);
68 insert_sorted(&new_list, var);
69 }
70 exec_list_append(&nir->variables, &new_list);
71 }
72
73 static void
fixup_varying_slots(nir_shader * nir,nir_variable_mode mode)74 fixup_varying_slots(nir_shader *nir, nir_variable_mode mode)
75 {
76 nir_foreach_variable_with_modes(var, nir, mode) {
77 if (var->data.location >= VARYING_SLOT_VAR0) {
78 var->data.location += 9;
79 } else if ((var->data.location >= VARYING_SLOT_TEX0) &&
80 (var->data.location <= VARYING_SLOT_TEX7)) {
81 var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
82 }
83 }
84 }
85
86 static nir_shader *
load_glsl(unsigned num_files,char * const * files,gl_shader_stage stage)87 load_glsl(unsigned num_files, char* const* files, gl_shader_stage stage)
88 {
89 static const struct standalone_options options = {
90 .glsl_version = 110,
91 .do_link = false,
92 };
93 unsigned shader = 0;
94 switch (stage) {
95 case MESA_SHADER_FRAGMENT:
96 shader = PIPE_SHADER_FRAGMENT;
97 break;
98 case MESA_SHADER_VERTEX:
99 shader = PIPE_SHADER_VERTEX;
100 break;
101 default:
102 unreachable("bad stage");
103 }
104 struct gl_shader_program *prog;
105 const nir_shader_compiler_options *nir_options =
106 lima_program_get_compiler_options(shader);
107 static struct gl_context local_ctx;
108
109 prog = standalone_compile_shader(&options, num_files, files, &local_ctx);
110 if (!prog)
111 errx(1, "couldn't parse `%s'", files[0]);
112
113 lima_do_glsl_optimizations(prog->_LinkedShaders[stage]->ir);
114
115 nir_shader *nir = glsl_to_nir(&local_ctx.Const, prog, stage, nir_options);
116
117 /* required NIR passes: */
118 if (nir_options->lower_all_io_to_temps ||
119 nir->info.stage == MESA_SHADER_VERTEX ||
120 nir->info.stage == MESA_SHADER_GEOMETRY) {
121 NIR_PASS_V(nir, nir_lower_io_to_temporaries,
122 nir_shader_get_entrypoint(nir),
123 true, true);
124 } else if (nir->info.stage == MESA_SHADER_FRAGMENT) {
125 NIR_PASS_V(nir, nir_lower_io_to_temporaries,
126 nir_shader_get_entrypoint(nir),
127 true, false);
128 }
129
130 NIR_PASS_V(nir, nir_lower_global_vars_to_local);
131 NIR_PASS_V(nir, nir_split_var_copies);
132 NIR_PASS_V(nir, nir_lower_var_copies);
133
134 NIR_PASS_V(nir, nir_split_var_copies);
135 NIR_PASS_V(nir, nir_lower_var_copies);
136 nir_print_shader(nir, stdout);
137 NIR_PASS_V(nir, gl_nir_lower_atomics, prog, true);
138 NIR_PASS_V(nir, nir_lower_atomics_to_ssbo, 0);
139 nir_print_shader(nir, stdout);
140
141 switch (stage) {
142 case MESA_SHADER_VERTEX:
143 nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs,
144 st_glsl_type_size);
145
146 /* Re-lower global vars, to deal with any dead VS inputs. */
147 NIR_PASS_V(nir, nir_lower_global_vars_to_local);
148
149 sort_varyings(nir, nir_var_shader_out);
150 nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs,
151 st_glsl_type_size);
152 fixup_varying_slots(nir, nir_var_shader_out);
153 break;
154 case MESA_SHADER_FRAGMENT:
155 sort_varyings(nir, nir_var_shader_in);
156 nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs,
157 st_glsl_type_size);
158 fixup_varying_slots(nir, nir_var_shader_in);
159 nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs,
160 st_glsl_type_size);
161 break;
162 default:
163 errx(1, "unhandled shader stage: %d", stage);
164 }
165
166 nir_assign_var_locations(nir, nir_var_uniform,
167 &nir->num_uniforms,
168 st_glsl_type_size);
169
170 NIR_PASS_V(nir, nir_lower_system_values);
171 NIR_PASS_V(nir, nir_lower_frexp);
172 NIR_PASS_V(nir, gl_nir_lower_samplers, prog);
173
174 return nir;
175 }
176
177 int
main(int argc,char ** argv)178 main(int argc, char **argv)
179 {
180 int n;
181
182 lima_debug = LIMA_DEBUG_GP | LIMA_DEBUG_PP;
183
184 if (argc < 2) {
185 print_usage();
186 return 1;
187 }
188
189 for (n = 1; n < argc; n++) {
190 if (!strcmp(argv[n], "--help")) {
191 print_usage();
192 return 1;
193 }
194
195 break;
196 }
197
198 char *filename[10] = {0};
199 filename[0] = argv[n];
200
201 char *ext = rindex(filename[0], '.');
202 unsigned stage = 0;
203
204 if (!strcmp(ext, ".frag")) {
205 stage = MESA_SHADER_FRAGMENT;
206 }
207 else if (!strcmp(ext, ".vert")) {
208 stage = MESA_SHADER_VERTEX;
209 }
210 else {
211 print_usage();
212 return -1;
213 }
214
215 struct nir_lower_tex_options tex_options = {
216 .lower_txp = ~0u,
217 .lower_invalid_implicit_lod = true,
218 };
219
220 nir_shader *nir = load_glsl(1, filename, stage);
221
222 switch (stage) {
223 case MESA_SHADER_VERTEX:
224 lima_program_optimize_vs_nir(nir);
225
226 nir_print_shader(nir, stdout);
227
228 struct lima_vs_compiled_shader *vs = ralloc(nir, struct lima_vs_compiled_shader);
229 gpir_compile_nir(vs, nir, NULL);
230 break;
231 case MESA_SHADER_FRAGMENT:
232 lima_program_optimize_fs_nir(nir, &tex_options);
233
234 nir_print_shader(nir, stdout);
235
236 struct lima_fs_compiled_shader *so = rzalloc(NULL, struct lima_fs_compiled_shader);
237 struct ra_regs *ra = ppir_regalloc_init(NULL);
238 ppir_compile_nir(so, nir, ra, NULL);
239 break;
240 default:
241 errx(1, "unhandled shader stage: %d", stage);
242 }
243
244 ralloc_free(nir);
245 return 0;
246 }
247