• 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 #include <getopt.h>
36 
37 #include "nir/tgsi_to_nir.h"
38 #include "tgsi/tgsi_parse.h"
39 #include "tgsi/tgsi_text.h"
40 #include "tgsi/tgsi_dump.h"
41 
42 #include "ir3/ir3_compiler.h"
43 #include "ir3/ir3_gallium.h"
44 #include "ir3/ir3_nir.h"
45 #include "ir3/instr-a3xx.h"
46 #include "ir3/ir3.h"
47 
48 #include "main/mtypes.h"
49 
50 #include "compiler/glsl/standalone.h"
51 #include "compiler/glsl/glsl_to_nir.h"
52 #include "compiler/glsl/gl_nir.h"
53 #include "compiler/nir_types.h"
54 #include "compiler/spirv/nir_spirv.h"
55 
56 #include "pipe/p_context.h"
57 
58 static void
dump_info(struct ir3_shader_variant * so,const char * str)59 dump_info(struct ir3_shader_variant *so, const char *str)
60 {
61 	uint32_t *bin;
62 	const char *type = ir3_shader_stage(so);
63 	bin = ir3_shader_assemble(so);
64 	printf("; %s: %s\n", type, str);
65 	ir3_shader_disasm(so, bin, stdout);
66 }
67 
68 static void
insert_sorted(struct exec_list * var_list,nir_variable * new_var)69 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
70 {
71 	nir_foreach_variable_in_list(var, var_list) {
72 		if (var->data.location > new_var->data.location) {
73 			exec_node_insert_node_before(&var->node, &new_var->node);
74 			return;
75 		}
76 	}
77 	exec_list_push_tail(var_list, &new_var->node);
78 }
79 
80 static void
sort_varyings(nir_shader * nir,nir_variable_mode mode)81 sort_varyings(nir_shader *nir, nir_variable_mode mode)
82 {
83 	struct exec_list new_list;
84 	exec_list_make_empty(&new_list);
85 	nir_foreach_variable_with_modes_safe(var, nir, mode) {
86 		exec_node_remove(&var->node);
87 		insert_sorted(&new_list, var);
88 	}
89 	exec_list_append(&nir->variables, &new_list);
90 }
91 
92 static void
fixup_varying_slots(nir_shader * nir,nir_variable_mode mode)93 fixup_varying_slots(nir_shader *nir, nir_variable_mode mode)
94 {
95 	nir_foreach_variable_with_modes(var, nir, mode) {
96 		if (var->data.location >= VARYING_SLOT_VAR0) {
97 			var->data.location += 9;
98 		} else if ((var->data.location >= VARYING_SLOT_TEX0) &&
99 				(var->data.location <= VARYING_SLOT_TEX7)) {
100 			var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
101 		}
102 	}
103 }
104 
105 static struct ir3_compiler *compiler;
106 
107 static nir_shader *
load_glsl(unsigned num_files,char * const * files,gl_shader_stage stage)108 load_glsl(unsigned num_files, char* const* files, gl_shader_stage stage)
109 {
110 	static const struct standalone_options options = {
111 			.glsl_version = 310,
112 			.do_link = true,
113 			.lower_precision = true,
114 	};
115 	struct gl_shader_program *prog;
116 	const nir_shader_compiler_options *nir_options =
117 			ir3_get_compiler_options(compiler);
118 	static struct gl_context local_ctx;
119 
120 	prog = standalone_compile_shader(&options, num_files, files, &local_ctx);
121 	if (!prog)
122 		errx(1, "couldn't parse `%s'", files[0]);
123 
124 	nir_shader *nir = glsl_to_nir(&local_ctx, prog, stage, nir_options);
125 
126 	/* required NIR passes: */
127 	if (nir_options->lower_all_io_to_temps ||
128 			nir->info.stage == MESA_SHADER_VERTEX ||
129 			nir->info.stage == MESA_SHADER_GEOMETRY) {
130 		NIR_PASS_V(nir, nir_lower_io_to_temporaries,
131 				nir_shader_get_entrypoint(nir),
132 				true, true);
133 	} else if (nir->info.stage == MESA_SHADER_FRAGMENT) {
134 		NIR_PASS_V(nir, nir_lower_io_to_temporaries,
135 				nir_shader_get_entrypoint(nir),
136 				true, false);
137 	}
138 
139 	NIR_PASS_V(nir, nir_lower_global_vars_to_local);
140 	NIR_PASS_V(nir, nir_split_var_copies);
141 	NIR_PASS_V(nir, nir_lower_var_copies);
142 
143 	NIR_PASS_V(nir, nir_split_var_copies);
144 	NIR_PASS_V(nir, nir_lower_var_copies);
145 	nir_print_shader(nir, stdout);
146 	NIR_PASS_V(nir, gl_nir_lower_atomics, prog, true);
147 	NIR_PASS_V(nir, gl_nir_lower_buffers, prog);
148 	NIR_PASS_V(nir, nir_lower_atomics_to_ssbo);
149 	nir_print_shader(nir, stdout);
150 
151 	switch (stage) {
152 	case MESA_SHADER_VERTEX:
153 		nir_assign_var_locations(nir, nir_var_shader_in,
154 				&nir->num_inputs,
155 				ir3_glsl_type_size);
156 
157 		/* Re-lower global vars, to deal with any dead VS inputs. */
158 		NIR_PASS_V(nir, nir_lower_global_vars_to_local);
159 
160 		sort_varyings(nir, nir_var_shader_out);
161 		nir_assign_var_locations(nir, nir_var_shader_out,
162 				&nir->num_outputs,
163 				ir3_glsl_type_size);
164 		fixup_varying_slots(nir, nir_var_shader_out);
165 		break;
166 	case MESA_SHADER_FRAGMENT:
167 		sort_varyings(nir, nir_var_shader_in);
168 		nir_assign_var_locations(nir, nir_var_shader_in,
169 				&nir->num_inputs,
170 				ir3_glsl_type_size);
171 		fixup_varying_slots(nir, nir_var_shader_in);
172 		nir_assign_var_locations(nir, nir_var_shader_out,
173 				&nir->num_outputs,
174 				ir3_glsl_type_size);
175 		break;
176 	case MESA_SHADER_COMPUTE:
177 	case MESA_SHADER_KERNEL:
178 		break;
179 	default:
180 		errx(1, "unhandled shader stage: %d", stage);
181 	}
182 
183 	nir_assign_var_locations(nir, nir_var_uniform,
184 			&nir->num_uniforms,
185 			ir3_glsl_type_size);
186 
187 	NIR_PASS_V(nir, nir_lower_system_values);
188 	NIR_PASS_V(nir, nir_lower_compute_system_values, NULL);
189 
190 	NIR_PASS_V(nir, nir_lower_frexp);
191 	NIR_PASS_V(nir, nir_lower_io,
192 	           nir_var_shader_in | nir_var_shader_out | nir_var_uniform,
193 	           ir3_glsl_type_size, (nir_lower_io_options)0);
194 	NIR_PASS_V(nir, gl_nir_lower_samplers, prog);
195 
196 	return nir;
197 }
198 
199 static int
read_file(const char * filename,void ** ptr,size_t * size)200 read_file(const char *filename, void **ptr, size_t *size)
201 {
202 	int fd, ret;
203 	struct stat st;
204 
205 	*ptr = MAP_FAILED;
206 
207 	fd = open(filename, O_RDONLY);
208 	if (fd == -1) {
209 		warnx("couldn't open `%s'", filename);
210 		return 1;
211 	}
212 
213 	ret = fstat(fd, &st);
214 	if (ret)
215 		errx(1, "couldn't stat `%s'", filename);
216 
217 	*size = st.st_size;
218 	*ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
219 	if (*ptr == MAP_FAILED)
220 		errx(1, "couldn't map `%s'", filename);
221 
222 	close(fd);
223 
224 	return 0;
225 }
226 
debug_func(void * priv,enum nir_spirv_debug_level level,size_t spirv_offset,const char * message)227 static void debug_func(void *priv, enum nir_spirv_debug_level level,
228 		size_t spirv_offset, const char *message)
229 {
230 //	printf("%s\n", message);
231 }
232 
233 static nir_shader *
load_spirv(const char * filename,const char * entry,gl_shader_stage stage)234 load_spirv(const char *filename, const char *entry, gl_shader_stage stage)
235 {
236 	const struct spirv_to_nir_options spirv_options = {
237 		/* these caps are just make-believe */
238 		.caps = {
239 			.draw_parameters = true,
240 			.float64 = true,
241 			.image_read_without_format = true,
242 			.image_write_without_format = true,
243 			.int64 = true,
244 			.variable_pointers = true,
245 		},
246 		.debug = {
247 			.func = debug_func,
248 		}
249 	};
250 	nir_shader *nir;
251 	void *buf;
252 	size_t size;
253 
254 	read_file(filename, &buf, &size);
255 
256 	nir = spirv_to_nir(buf, size / 4,
257 			NULL, 0, /* spec_entries */
258 			stage, entry,
259 			&spirv_options,
260 			ir3_get_compiler_options(compiler));
261 
262 	nir_print_shader(nir, stdout);
263 
264 	return nir;
265 }
266 
267 static const char *shortopts = "g:hv";
268 
269 static const struct option longopts[] = {
270 	{ "gpu",            required_argument, 0, 'g' },
271 	{ "help",           no_argument,       0, 'h' },
272 	{ "verbose",        no_argument,       0, 'v' },
273 };
274 
275 static void
print_usage(void)276 print_usage(void)
277 {
278 	printf("Usage: ir3_compiler [OPTIONS]... <file.tgsi | file.spv entry_point | (file.vert | file.frag)*>\n");
279 	printf("    -g, --gpu GPU_ID - specify gpu-id (default 320)\n");
280 	printf("    -h, --help       - show this message\n");
281 	printf("    -v, --verbose    - verbose compiler/debug messages\n");
282 }
283 
284 int
main(int argc,char ** argv)285 main(int argc, char **argv)
286 {
287 	int ret = 0, opt;
288 	char *filenames[2];
289 	int num_files = 0;
290 	unsigned stage = 0;
291 	struct ir3_shader_key key = {};
292 	unsigned gpu_id = 320;
293 	const char *info;
294 	const char *spirv_entry = NULL;
295 	void *ptr;
296 	bool from_tgsi = false;
297 	size_t size;
298 
299 	while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) != -1) {
300 		switch (opt) {
301 		case 'g':
302 			gpu_id = strtol(optarg, NULL, 0);
303 			break;
304 		case 'v':
305 			ir3_shader_debug |= IR3_DBG_OPTMSGS | IR3_DBG_DISASM;
306 			break;
307 		default:
308 			printf("unrecognized arg: %c\n", opt);
309 			/* fallthrough */
310 		case 'h':
311 			print_usage();
312 			return 0;
313 		}
314 	}
315 
316 	if (optind >= argc) {
317 		fprintf(stderr, "no file specified!\n");
318 		print_usage();
319 		return 0;
320 	}
321 
322 	unsigned n = optind;
323 	while (n < argc) {
324 		char *filename = argv[n];
325 		char *ext = strrchr(filename, '.');
326 
327 		if (strcmp(ext, ".tgsi") == 0) {
328 			if (num_files != 0)
329 				errx(1, "in TGSI mode, only a single file may be specified");
330 			from_tgsi = true;
331 		} else if (strcmp(ext, ".spv") == 0) {
332 			if (num_files != 0)
333 				errx(1, "in SPIR-V mode, only a single file may be specified");
334 			stage = MESA_SHADER_COMPUTE;
335 			filenames[num_files++] = filename;
336 			n++;
337 			if (n == argc)
338 				errx(1, "in SPIR-V mode, an entry point must be specified");
339 			spirv_entry = argv[n];
340 			n++;
341 		} else if (strcmp(ext, ".comp") == 0) {
342 			if (from_tgsi || spirv_entry)
343 				errx(1, "cannot mix GLSL/TGSI/SPIRV");
344 			if (num_files >= ARRAY_SIZE(filenames))
345 				errx(1, "too many GLSL files");
346 			stage = MESA_SHADER_COMPUTE;
347 		} else if (strcmp(ext, ".frag") == 0) {
348 			if (from_tgsi || spirv_entry)
349 				errx(1, "cannot mix GLSL/TGSI/SPIRV");
350 			if (num_files >= ARRAY_SIZE(filenames))
351 				errx(1, "too many GLSL files");
352 			stage = MESA_SHADER_FRAGMENT;
353 		} else if (strcmp(ext, ".vert") == 0) {
354 			if (from_tgsi)
355 				errx(1, "cannot mix GLSL and TGSI");
356 			if (num_files >= ARRAY_SIZE(filenames))
357 				errx(1, "too many GLSL files");
358 			stage = MESA_SHADER_VERTEX;
359 		} else {
360 			print_usage();
361 			return -1;
362 		}
363 
364 		filenames[num_files++] = filename;
365 
366 		n++;
367 	}
368 
369 	nir_shader *nir;
370 
371 	compiler = ir3_compiler_create(NULL, gpu_id);
372 
373 	if (from_tgsi) {
374 		struct tgsi_token toks[65536];
375 		const nir_shader_compiler_options *nir_options =
376 			ir3_get_compiler_options(compiler);
377 
378 		ret = read_file(filenames[0], &ptr, &size);
379 		if (ret) {
380 			print_usage();
381 			return ret;
382 		}
383 
384 		if (ir3_shader_debug & IR3_DBG_OPTMSGS)
385 			printf("%s\n", (char *)ptr);
386 
387 		if (!tgsi_text_translate(ptr, toks, ARRAY_SIZE(toks)))
388 			errx(1, "could not parse `%s'", filenames[0]);
389 
390 		if (ir3_shader_debug & IR3_DBG_OPTMSGS)
391 			tgsi_dump(toks, 0);
392 
393 		nir = tgsi_to_nir_noscreen(toks, nir_options);
394 		NIR_PASS_V(nir, nir_lower_global_vars_to_local);
395 	} else if (spirv_entry) {
396 		nir = load_spirv(filenames[0], spirv_entry, stage);
397 
398 		NIR_PASS_V(nir, nir_lower_io,
399 		           nir_var_shader_in | nir_var_shader_out,
400 		           ir3_glsl_type_size, (nir_lower_io_options)0);
401 
402 		/* TODO do this somewhere else */
403 		nir_lower_int64(nir);
404 		nir_lower_system_values(nir);
405 		nir_lower_compute_system_values(nir, NULL);
406 	} else if (num_files > 0) {
407 		nir = load_glsl(num_files, filenames, stage);
408 	} else {
409 		print_usage();
410 		return -1;
411 	}
412 
413 	ir3_finalize_nir(compiler, nir);
414 	ir3_nir_post_finalize(compiler, nir);
415 
416 	struct ir3_shader *shader = rzalloc_size(NULL, sizeof(*shader));
417 	shader->compiler = compiler;
418 	shader->type = stage;
419 	shader->nir = nir;
420 
421 	struct ir3_shader_variant *v = rzalloc_size(shader, sizeof(*v));
422 	v->type = shader->type;
423 	v->shader = shader;
424 	v->key = key;
425 	v->const_state = rzalloc_size(v, sizeof(*v->const_state));
426 
427 	shader->variants = v;
428 	shader->variant_count = 1;
429 
430 	ir3_nir_lower_variant(v, nir);
431 
432 	info = "NIR compiler";
433 	ret = ir3_compile_shader_nir(compiler, v);
434 	if (ret) {
435 		fprintf(stderr, "compiler failed!\n");
436 		return ret;
437 	}
438 	dump_info(v, info);
439 
440 	return 0;
441 }
442