• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
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, sublicense,
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 next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * 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 NONINFRINGEMENT.  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 FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/mman.h>
30 #include <fcntl.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <err.h>
35 
36 #include "tgsi/tgsi_parse.h"
37 #include "tgsi/tgsi_text.h"
38 #include "tgsi/tgsi_dump.h"
39 
40 #include "freedreno_util.h"
41 
42 #include "ir3_compiler.h"
43 #include "ir3_nir.h"
44 #include "instr-a3xx.h"
45 #include "ir3.h"
46 
47 #include "compiler/glsl/standalone.h"
48 #include "compiler/glsl/glsl_to_nir.h"
49 #include "compiler/nir_types.h"
50 
dump_info(struct ir3_shader_variant * so,const char * str)51 static void dump_info(struct ir3_shader_variant *so, const char *str)
52 {
53 	uint32_t *bin;
54 	const char *type = ir3_shader_stage(so->shader);
55 	bin = ir3_shader_assemble(so, so->shader->compiler->gpu_id);
56 	debug_printf("; %s: %s\n", type, str);
57 	ir3_shader_disasm(so, bin);
58 	free(bin);
59 }
60 
61 static void
insert_sorted(struct exec_list * var_list,nir_variable * new_var)62 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
63 {
64 	nir_foreach_variable(var, var_list) {
65 		if (var->data.location > new_var->data.location) {
66 			exec_node_insert_node_before(&var->node, &new_var->node);
67 			return;
68 		}
69 	}
70 	exec_list_push_tail(var_list, &new_var->node);
71 }
72 
73 static void
sort_varyings(struct exec_list * var_list)74 sort_varyings(struct exec_list *var_list)
75 {
76 	struct exec_list new_list;
77 	exec_list_make_empty(&new_list);
78 	nir_foreach_variable_safe(var, var_list) {
79 		exec_node_remove(&var->node);
80 		insert_sorted(&new_list, var);
81 	}
82 	exec_list_move_nodes_to(&new_list, var_list);
83 }
84 
85 static void
fixup_varying_slots(struct exec_list * var_list)86 fixup_varying_slots(struct exec_list *var_list)
87 {
88 	nir_foreach_variable(var, var_list) {
89 		if (var->data.location >= VARYING_SLOT_VAR0) {
90 			var->data.location += 9;
91 		} else if ((var->data.location >= VARYING_SLOT_TEX0) &&
92 				(var->data.location <= VARYING_SLOT_TEX7)) {
93 			var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
94 		}
95 	}
96 }
97 
98 static struct ir3_compiler *compiler;
99 
100 static nir_shader *
load_glsl(unsigned num_files,char * const * files,gl_shader_stage stage)101 load_glsl(unsigned num_files, char* const* files, gl_shader_stage stage)
102 {
103 	static const struct standalone_options options = {
104 			.glsl_version = 140,
105 			.do_link = true,
106 	};
107 	struct gl_shader_program *prog;
108 
109 	prog = standalone_compile_shader(&options, num_files, files);
110 	if (!prog)
111 		errx(1, "couldn't parse `%s'", files[0]);
112 
113 	nir_shader *nir = glsl_to_nir(prog, stage, ir3_get_compiler_options(compiler));
114 
115 	/* required NIR passes: */
116 	/* TODO cmdline args for some of the conditional lowering passes? */
117 
118 	NIR_PASS_V(nir, nir_lower_io_to_temporaries,
119 			nir_shader_get_entrypoint(nir),
120 			true, true);
121 	NIR_PASS_V(nir, nir_lower_global_vars_to_local);
122 	NIR_PASS_V(nir, nir_split_var_copies);
123 	NIR_PASS_V(nir, nir_lower_var_copies);
124 
125 	NIR_PASS_V(nir, nir_split_var_copies);
126 	NIR_PASS_V(nir, nir_lower_var_copies);
127 	NIR_PASS_V(nir, nir_lower_io_types);
128 
129 	switch (stage) {
130 	case MESA_SHADER_VERTEX:
131 		nir_assign_var_locations(&nir->inputs,
132 				&nir->num_inputs,
133 				ir3_glsl_type_size);
134 
135 		/* Re-lower global vars, to deal with any dead VS inputs. */
136 		NIR_PASS_V(nir, nir_lower_global_vars_to_local);
137 
138 		sort_varyings(&nir->outputs);
139 		nir_assign_var_locations(&nir->outputs,
140 				&nir->num_outputs,
141 				ir3_glsl_type_size);
142 		fixup_varying_slots(&nir->outputs);
143 		break;
144 	case MESA_SHADER_FRAGMENT:
145 		sort_varyings(&nir->inputs);
146 		nir_assign_var_locations(&nir->inputs,
147 				&nir->num_inputs,
148 				ir3_glsl_type_size);
149 		fixup_varying_slots(&nir->inputs);
150 		nir_assign_var_locations(&nir->outputs,
151 				&nir->num_outputs,
152 				ir3_glsl_type_size);
153 		break;
154 	default:
155 		errx(1, "unhandled shader stage: %d", stage);
156 	}
157 
158 	nir_assign_var_locations(&nir->uniforms,
159 			&nir->num_uniforms,
160 			ir3_glsl_type_size);
161 
162 	NIR_PASS_V(nir, nir_lower_system_values);
163 	NIR_PASS_V(nir, nir_lower_io, nir_var_all, ir3_glsl_type_size, 0);
164 	NIR_PASS_V(nir, nir_lower_samplers, prog);
165 
166 	return nir;
167 }
168 
169 static int
read_file(const char * filename,void ** ptr,size_t * size)170 read_file(const char *filename, void **ptr, size_t *size)
171 {
172 	int fd, ret;
173 	struct stat st;
174 
175 	*ptr = MAP_FAILED;
176 
177 	fd = open(filename, O_RDONLY);
178 	if (fd == -1) {
179 		warnx("couldn't open `%s'", filename);
180 		return 1;
181 	}
182 
183 	ret = fstat(fd, &st);
184 	if (ret)
185 		errx(1, "couldn't stat `%s'", filename);
186 
187 	*size = st.st_size;
188 	*ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
189 	if (*ptr == MAP_FAILED)
190 		errx(1, "couldn't map `%s'", filename);
191 
192 	close(fd);
193 
194 	return 0;
195 }
196 
print_usage(void)197 static void print_usage(void)
198 {
199 	printf("Usage: ir3_compiler [OPTIONS]... <file.tgsi | (file.vert | file.frag)*>\n");
200 	printf("    --verbose         - verbose compiler/debug messages\n");
201 	printf("    --binning-pass    - generate binning pass shader (VERT)\n");
202 	printf("    --color-two-side  - emulate two-sided color (FRAG)\n");
203 	printf("    --half-precision  - use half-precision\n");
204 	printf("    --saturate-s MASK - bitmask of samplers to saturate S coord\n");
205 	printf("    --saturate-t MASK - bitmask of samplers to saturate T coord\n");
206 	printf("    --saturate-r MASK - bitmask of samplers to saturate R coord\n");
207 	printf("    --astc-srgb MASK  - bitmask of samplers to enable astc-srgb workaround\n");
208 	printf("    --stream-out      - enable stream-out (aka transform feedback)\n");
209 	printf("    --ucp MASK        - bitmask of enabled user-clip-planes\n");
210 	printf("    --gpu GPU_ID      - specify gpu-id (default 320)\n");
211 	printf("    --help            - show this message\n");
212 }
213 
main(int argc,char ** argv)214 int main(int argc, char **argv)
215 {
216 	int ret = 0, n = 1;
217 	char *filenames[2];
218 	int num_files = 0;
219 	unsigned stage = 0;
220 	struct ir3_shader_variant v;
221 	struct ir3_shader s;
222 	struct ir3_shader_key key = {};
223 	/* TODO cmdline option to target different gpus: */
224 	unsigned gpu_id = 320;
225 	const char *info;
226 	void *ptr;
227 	size_t size;
228 
229 	memset(&s, 0, sizeof(s));
230 	memset(&v, 0, sizeof(v));
231 
232 	/* cmdline args which impact shader variant get spit out in a
233 	 * comment on the first line..  a quick/dirty way to preserve
234 	 * that info so when ir3test recompiles the shader with a new
235 	 * compiler version, we use the same shader-key settings:
236 	 */
237 	debug_printf("; options:");
238 
239 	while (n < argc) {
240 		if (!strcmp(argv[n], "--verbose")) {
241 			fd_mesa_debug |= FD_DBG_MSGS | FD_DBG_OPTMSGS | FD_DBG_DISASM;
242 			n++;
243 			continue;
244 		}
245 
246 		if (!strcmp(argv[n], "--binning-pass")) {
247 			debug_printf(" %s", argv[n]);
248 			key.binning_pass = true;
249 			n++;
250 			continue;
251 		}
252 
253 		if (!strcmp(argv[n], "--color-two-side")) {
254 			debug_printf(" %s", argv[n]);
255 			key.color_two_side = true;
256 			n++;
257 			continue;
258 		}
259 
260 		if (!strcmp(argv[n], "--half-precision")) {
261 			debug_printf(" %s", argv[n]);
262 			key.half_precision = true;
263 			n++;
264 			continue;
265 		}
266 
267 		if (!strcmp(argv[n], "--saturate-s")) {
268 			debug_printf(" %s %s", argv[n], argv[n+1]);
269 			key.vsaturate_s = key.fsaturate_s = strtol(argv[n+1], NULL, 0);
270 			n += 2;
271 			continue;
272 		}
273 
274 		if (!strcmp(argv[n], "--saturate-t")) {
275 			debug_printf(" %s %s", argv[n], argv[n+1]);
276 			key.vsaturate_t = key.fsaturate_t = strtol(argv[n+1], NULL, 0);
277 			n += 2;
278 			continue;
279 		}
280 
281 		if (!strcmp(argv[n], "--saturate-r")) {
282 			debug_printf(" %s %s", argv[n], argv[n+1]);
283 			key.vsaturate_r = key.fsaturate_r = strtol(argv[n+1], NULL, 0);
284 			n += 2;
285 			continue;
286 		}
287 
288 		if (!strcmp(argv[n], "--astc-srgb")) {
289 			debug_printf(" %s %s", argv[n], argv[n+1]);
290 			key.vastc_srgb = key.fastc_srgb = strtol(argv[n+1], NULL, 0);
291 			n += 2;
292 			continue;
293 		}
294 
295 		if (!strcmp(argv[n], "--stream-out")) {
296 			struct pipe_stream_output_info *so = &s.stream_output;
297 			debug_printf(" %s", argv[n]);
298 			/* TODO more dynamic config based on number of outputs, etc
299 			 * rather than just hard-code for first output:
300 			 */
301 			so->num_outputs = 1;
302 			so->stride[0] = 4;
303 			so->output[0].register_index = 0;
304 			so->output[0].start_component = 0;
305 			so->output[0].num_components = 4;
306 			so->output[0].output_buffer = 0;
307 			so->output[0].dst_offset = 2;
308 			so->output[0].stream = 0;
309 			n++;
310 			continue;
311 		}
312 
313 		if (!strcmp(argv[n], "--ucp")) {
314 			debug_printf(" %s %s", argv[n], argv[n+1]);
315 			key.ucp_enables = strtol(argv[n+1], NULL, 0);
316 			n += 2;
317 			continue;
318 		}
319 
320 		if (!strcmp(argv[n], "--gpu")) {
321 			debug_printf(" %s %s", argv[n], argv[n+1]);
322 			gpu_id = strtol(argv[n+1], NULL, 0);
323 			n += 2;
324 			continue;
325 		}
326 
327 		if (!strcmp(argv[n], "--help")) {
328 			print_usage();
329 			return 0;
330 		}
331 
332 		break;
333 	}
334 	debug_printf("\n");
335 
336 	while (n < argc) {
337 		char *filename = argv[n];
338 		char *ext = rindex(filename, '.');
339 
340 		if (strcmp(ext, ".tgsi") == 0) {
341 			if (num_files != 0)
342 				errx(1, "in TGSI mode, only a single file may be specified");
343 			s.from_tgsi = true;
344 		} else if (strcmp(ext, ".frag") == 0) {
345 			if (s.from_tgsi)
346 				errx(1, "cannot mix GLSL and TGSI");
347 			if (num_files >= ARRAY_SIZE(filenames))
348 				errx(1, "too many GLSL files");
349 			stage = MESA_SHADER_FRAGMENT;
350 		} else if (strcmp(ext, ".vert") == 0) {
351 			if (s.from_tgsi)
352 				errx(1, "cannot mix GLSL and TGSI");
353 			if (num_files >= ARRAY_SIZE(filenames))
354 				errx(1, "too many GLSL files");
355 			stage = MESA_SHADER_VERTEX;
356 		} else {
357 			print_usage();
358 			return -1;
359 		}
360 
361 		filenames[num_files++] = filename;
362 
363 		n++;
364 	}
365 
366 	nir_shader *nir;
367 
368 	compiler = ir3_compiler_create(NULL, gpu_id);
369 
370 	if (s.from_tgsi) {
371 		struct tgsi_token toks[65536];
372 
373 		ret = read_file(filenames[0], &ptr, &size);
374 		if (ret) {
375 			print_usage();
376 			return ret;
377 		}
378 
379 		if (fd_mesa_debug & FD_DBG_OPTMSGS)
380 			debug_printf("%s\n", (char *)ptr);
381 
382 		if (!tgsi_text_translate(ptr, toks, ARRAY_SIZE(toks)))
383 			errx(1, "could not parse `%s'", filenames[0]);
384 
385 		if (fd_mesa_debug & FD_DBG_OPTMSGS)
386 			tgsi_dump(toks, 0);
387 
388 		nir = ir3_tgsi_to_nir(toks);
389 	} else if (num_files > 0) {
390 		nir = load_glsl(num_files, filenames, stage);
391 	} else {
392 		print_usage();
393 		return -1;
394 	}
395 
396 	s.compiler = compiler;
397 	s.nir = ir3_optimize_nir(&s, nir, NULL);
398 
399 	v.key = key;
400 	v.shader = &s;
401 
402 	switch (nir->info.stage) {
403 	case MESA_SHADER_FRAGMENT:
404 		s.type = v.type = SHADER_FRAGMENT;
405 		break;
406 	case MESA_SHADER_VERTEX:
407 		s.type = v.type = SHADER_VERTEX;
408 		break;
409 	case MESA_SHADER_COMPUTE:
410 		s.type = v.type = SHADER_COMPUTE;
411 		break;
412 	default:
413 		errx(1, "unhandled shader stage: %d", nir->info.stage);
414 	}
415 
416 	info = "NIR compiler";
417 	ret = ir3_compile_shader_nir(s.compiler, &v);
418 	if (ret) {
419 		fprintf(stderr, "compiler failed!\n");
420 		return ret;
421 	}
422 	dump_info(&v, info);
423 }
424