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 <err.h> 28#include <fcntl.h> 29#include <getopt.h> 30#include <stdint.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <sys/mman.h> 34#include <sys/stat.h> 35#include <sys/types.h> 36 37#include "nir/tgsi_to_nir.h" 38#include "tgsi/tgsi_dump.h" 39#include "tgsi/tgsi_parse.h" 40#include "tgsi/tgsi_text.h" 41 42#include "ir3/instr-a3xx.h" 43#include "ir3/ir3.h" 44#include "ir3/ir3_compiler.h" 45#include "ir3/ir3_gallium.h" 46#include "ir3/ir3_nir.h" 47 48#include "main/mtypes.h" 49 50#include "compiler/glsl/gl_nir.h" 51#include "compiler/glsl/glsl_to_nir.h" 52#include "compiler/glsl/standalone.h" 53#include "compiler/nir_types.h" 54#include "compiler/spirv/nir_spirv.h" 55 56#include "pipe/p_context.h" 57 58static void 59dump_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 68static void 69insert_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 80static void 81sort_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 92static void 93fixup_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 105static struct ir3_compiler *compiler; 106 107static nir_shader * 108load_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.Const, 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), true, true); 132 } else if (nir->info.stage == MESA_SHADER_FRAGMENT) { 133 NIR_PASS_V(nir, nir_lower_io_to_temporaries, 134 nir_shader_get_entrypoint(nir), true, false); 135 } 136 137 NIR_PASS_V(nir, nir_lower_global_vars_to_local); 138 NIR_PASS_V(nir, nir_split_var_copies); 139 NIR_PASS_V(nir, nir_lower_var_copies); 140 141 NIR_PASS_V(nir, nir_split_var_copies); 142 NIR_PASS_V(nir, nir_lower_var_copies); 143 nir_print_shader(nir, stdout); 144 NIR_PASS_V(nir, gl_nir_lower_atomics, prog, true); 145 NIR_PASS_V(nir, gl_nir_lower_buffers, prog); 146 NIR_PASS_V(nir, nir_lower_atomics_to_ssbo, 0); 147 nir_print_shader(nir, stdout); 148 149 switch (stage) { 150 case MESA_SHADER_VERTEX: 151 nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs, 152 ir3_glsl_type_size); 153 154 /* Re-lower global vars, to deal with any dead VS inputs. */ 155 NIR_PASS_V(nir, nir_lower_global_vars_to_local); 156 157 sort_varyings(nir, nir_var_shader_out); 158 nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs, 159 ir3_glsl_type_size); 160 fixup_varying_slots(nir, nir_var_shader_out); 161 break; 162 case MESA_SHADER_FRAGMENT: 163 sort_varyings(nir, nir_var_shader_in); 164 nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs, 165 ir3_glsl_type_size); 166 fixup_varying_slots(nir, nir_var_shader_in); 167 nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs, 168 ir3_glsl_type_size); 169 break; 170 case MESA_SHADER_COMPUTE: 171 case MESA_SHADER_KERNEL: 172 break; 173 default: 174 errx(1, "unhandled shader stage: %d", stage); 175 } 176 177 nir_assign_var_locations(nir, nir_var_uniform, &nir->num_uniforms, 178 ir3_glsl_type_size); 179 180 NIR_PASS_V(nir, nir_lower_system_values); 181 NIR_PASS_V(nir, nir_lower_compute_system_values, NULL); 182 183 NIR_PASS_V(nir, nir_lower_frexp); 184 NIR_PASS_V(nir, nir_lower_io, 185 nir_var_shader_in | nir_var_shader_out | nir_var_uniform, 186 ir3_glsl_type_size, (nir_lower_io_options)0); 187 NIR_PASS_V(nir, gl_nir_lower_samplers, prog); 188 189 return nir; 190} 191 192static int 193read_file(const char *filename, void **ptr, size_t *size) 194{ 195 int fd, ret; 196 struct stat st; 197 198 *ptr = MAP_FAILED; 199 200 fd = open(filename, O_RDONLY); 201 if (fd == -1) { 202 warnx("couldn't open `%s'", filename); 203 return 1; 204 } 205 206 ret = fstat(fd, &st); 207 if (ret) 208 errx(1, "couldn't stat `%s'", filename); 209 210 *size = st.st_size; 211 *ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); 212 if (*ptr == MAP_FAILED) 213 errx(1, "couldn't map `%s'", filename); 214 215 close(fd); 216 217 return 0; 218} 219 220static void 221debug_func(void *priv, enum nir_spirv_debug_level level, size_t spirv_offset, 222 const char *message) 223{ 224 // printf("%s\n", message); 225} 226 227static nir_shader * 228load_spirv(const char *filename, const char *entry, gl_shader_stage stage) 229{ 230 const struct spirv_to_nir_options spirv_options = { 231 /* these caps are just make-believe */ 232 .caps = { 233 .draw_parameters = true, 234 .float64 = true, 235 .image_read_without_format = true, 236 .image_write_without_format = true, 237 .int64 = true, 238 .variable_pointers = true, 239 }, 240 .debug = { 241 .func = debug_func, 242 } 243 }; 244 nir_shader *nir; 245 void *buf; 246 size_t size; 247 248 read_file(filename, &buf, &size); 249 250 nir = spirv_to_nir(buf, size / 4, NULL, 0, /* spec_entries */ 251 stage, entry, &spirv_options, 252 ir3_get_compiler_options(compiler)); 253 254 const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = { 255 .frag_coord = true, 256 .point_coord = true, 257 }; 258 NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings); 259 260 nir_print_shader(nir, stdout); 261 262 return nir; 263} 264 265static const char *shortopts = "g:hv"; 266 267static const struct option longopts[] = { 268 {"gpu", required_argument, 0, 'g'}, 269 {"help", no_argument, 0, 'h'}, 270 {"verbose", no_argument, 0, 'v'}, 271}; 272 273static void 274print_usage(void) 275{ 276 printf("Usage: ir3_compiler [OPTIONS]... <file.tgsi | file.spv entry_point " 277 "| (file.vert | file.frag)*>\n"); 278 printf(" -g, --gpu GPU_ID - specify gpu-id (default 320)\n"); 279 printf(" -h, --help - show this message\n"); 280 printf(" -v, --verbose - verbose compiler/debug messages\n"); 281} 282 283int 284main(int argc, char **argv) 285{ 286 int ret = 0, opt; 287 char *filenames[2]; 288 int num_files = 0; 289 unsigned stage = 0; 290 struct ir3_shader_key key = {}; 291 unsigned gpu_id = 320; 292 const char *info; 293 const char *spirv_entry = NULL; 294 void *ptr; 295 bool from_tgsi = false; 296 size_t size; 297 298 while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) != 299 -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 struct fd_dev_id dev_id = { 372 .gpu_id = gpu_id, 373 }; 374 compiler = ir3_compiler_create(NULL, &dev_id, 375 &(struct ir3_compiler_options) {}); 376 377 if (from_tgsi) { 378 struct tgsi_token toks[65536]; 379 const nir_shader_compiler_options *nir_options = 380 ir3_get_compiler_options(compiler); 381 382 ret = read_file(filenames[0], &ptr, &size); 383 if (ret) { 384 print_usage(); 385 return ret; 386 } 387 388 if (ir3_shader_debug & IR3_DBG_OPTMSGS) 389 printf("%s\n", (char *)ptr); 390 391 if (!tgsi_text_translate(ptr, toks, ARRAY_SIZE(toks))) 392 errx(1, "could not parse `%s'", filenames[0]); 393 394 if (ir3_shader_debug & IR3_DBG_OPTMSGS) 395 tgsi_dump(toks, 0); 396 397 nir = tgsi_to_nir_noscreen(toks, nir_options); 398 NIR_PASS_V(nir, nir_lower_global_vars_to_local); 399 } else if (spirv_entry) { 400 nir = load_spirv(filenames[0], spirv_entry, stage); 401 402 NIR_PASS_V(nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out, 403 ir3_glsl_type_size, (nir_lower_io_options)0); 404 405 /* TODO do this somewhere else */ 406 nir_lower_int64(nir); 407 nir_lower_system_values(nir); 408 nir_lower_compute_system_values(nir, NULL); 409 } else if (num_files > 0) { 410 nir = load_glsl(num_files, filenames, stage); 411 } else { 412 print_usage(); 413 return -1; 414 } 415 416 ir3_nir_lower_io_to_temporaries(nir); 417 ir3_finalize_nir(compiler, nir); 418 419 struct ir3_shader *shader = rzalloc_size(NULL, sizeof(*shader)); 420 shader->compiler = compiler; 421 shader->type = stage; 422 shader->nir = nir; 423 424 ir3_nir_post_finalize(shader); 425 426 struct ir3_shader_variant *v = rzalloc_size(shader, sizeof(*v)); 427 v->type = shader->type; 428 v->compiler = compiler; 429 v->key = key; 430 v->const_state = rzalloc_size(v, sizeof(*v->const_state)); 431 432 shader->variants = v; 433 shader->variant_count = 1; 434 435 ir3_nir_lower_variant(v, nir); 436 437 info = "NIR compiler"; 438 ret = ir3_compile_shader_nir(compiler, shader, v); 439 if (ret) { 440 fprintf(stderr, "compiler failed!\n"); 441 return ret; 442 } 443 dump_info(v, info); 444 445 return 0; 446} 447