spirv2nir.c revision 7ec681f3
101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2015 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg * 2301e04c3fSmrg * Authors: 2401e04c3fSmrg * Jason Ekstrand (jason@jlekstrand.net) 2501e04c3fSmrg * 2601e04c3fSmrg */ 2701e04c3fSmrg 2801e04c3fSmrg/* 2901e04c3fSmrg * A simple executable that opens a SPIR-V shader, converts it to NIR, and 3001e04c3fSmrg * dumps out the result. This should be useful for testing the 3101e04c3fSmrg * spirv_to_nir code. 3201e04c3fSmrg */ 3301e04c3fSmrg 3401e04c3fSmrg#include "spirv/nir_spirv.h" 3501e04c3fSmrg 3601e04c3fSmrg#include <sys/mman.h> 3701e04c3fSmrg#include <sys/types.h> 3801e04c3fSmrg#include <fcntl.h> 3901e04c3fSmrg#include <unistd.h> 4001e04c3fSmrg#include <stdio.h> 4101e04c3fSmrg#include <errno.h> 4201e04c3fSmrg#include <string.h> 437ec681f3Smrg#include <getopt.h> 4401e04c3fSmrg 4501e04c3fSmrg#define WORD_SIZE 4 4601e04c3fSmrg 477ec681f3Smrgstatic gl_shader_stage 487ec681f3Smrgstage_to_enum(char *stage) 497ec681f3Smrg{ 507ec681f3Smrg if (!strcmp(stage, "vertex")) 517ec681f3Smrg return MESA_SHADER_VERTEX; 527ec681f3Smrg else if (!strcmp(stage, "tess-ctrl")) 537ec681f3Smrg return MESA_SHADER_TESS_CTRL; 547ec681f3Smrg else if (!strcmp(stage, "tess-eval")) 557ec681f3Smrg return MESA_SHADER_TESS_EVAL; 567ec681f3Smrg else if (!strcmp(stage, "geometry")) 577ec681f3Smrg return MESA_SHADER_GEOMETRY; 587ec681f3Smrg else if (!strcmp(stage, "fragment")) 597ec681f3Smrg return MESA_SHADER_FRAGMENT; 607ec681f3Smrg else if (!strcmp(stage, "compute")) 617ec681f3Smrg return MESA_SHADER_COMPUTE; 627ec681f3Smrg else if (!strcmp(stage, "kernel")) 637ec681f3Smrg return MESA_SHADER_KERNEL; 647ec681f3Smrg else if (!strcmp(stage, "task")) 657ec681f3Smrg return MESA_SHADER_TASK; 667ec681f3Smrg else if (!strcmp(stage, "mesh")) 677ec681f3Smrg return MESA_SHADER_MESH; 687ec681f3Smrg else 697ec681f3Smrg return MESA_SHADER_NONE; 707ec681f3Smrg} 717ec681f3Smrg 727ec681f3Smrgstatic void 737ec681f3Smrgprint_usage(char *exec_name, FILE *f) 747ec681f3Smrg{ 757ec681f3Smrg fprintf(f, 767ec681f3Smrg"Usage: %s [options] file\n" 777ec681f3Smrg"Options:\n" 787ec681f3Smrg" -h --help Print this help.\n" 797ec681f3Smrg" -s, --stage <stage> Specify the shader stage. Valid stages are:\n" 807ec681f3Smrg" vertex, tess-ctrl, tess-eval, geometry, fragment,\n" 817ec681f3Smrg" task, mesh, compute, and kernel (OpenCL-style compute).\n" 827ec681f3Smrg" -e, --entry <name> Specify the entry-point name.\n" 837ec681f3Smrg" -g, --opengl Use OpenGL environment instead of Vulkan for\n" 847ec681f3Smrg" graphics stages.\n" 857ec681f3Smrg , exec_name); 867ec681f3Smrg} 877ec681f3Smrg 8801e04c3fSmrgint main(int argc, char **argv) 8901e04c3fSmrg{ 907ec681f3Smrg gl_shader_stage shader_stage = MESA_SHADER_FRAGMENT; 917ec681f3Smrg char *entry_point = "main"; 927ec681f3Smrg int ch; 937ec681f3Smrg enum nir_spirv_execution_environment env = NIR_SPIRV_VULKAN; 947ec681f3Smrg 957ec681f3Smrg static struct option long_options[] = 967ec681f3Smrg { 977ec681f3Smrg {"help", no_argument, 0, 'h'}, 987ec681f3Smrg {"stage", required_argument, 0, 's'}, 997ec681f3Smrg {"entry", required_argument, 0, 'e'}, 1007ec681f3Smrg {"opengl", no_argument, 0, 'g'}, 1017ec681f3Smrg {0, 0, 0, 0} 1027ec681f3Smrg }; 1037ec681f3Smrg 1047ec681f3Smrg while ((ch = getopt_long(argc, argv, "hs:e:g", long_options, NULL)) != -1) 1057ec681f3Smrg { 1067ec681f3Smrg switch (ch) 1077ec681f3Smrg { 1087ec681f3Smrg case 'h': 1097ec681f3Smrg print_usage(argv[0], stdout); 1107ec681f3Smrg return 0; 1117ec681f3Smrg case 's': 1127ec681f3Smrg shader_stage = stage_to_enum(optarg); 1137ec681f3Smrg if (shader_stage == MESA_SHADER_NONE) 1147ec681f3Smrg { 1157ec681f3Smrg fprintf(stderr, "Unknown stage \"%s\"\n", optarg); 1167ec681f3Smrg print_usage(argv[0], stderr); 1177ec681f3Smrg return 1; 1187ec681f3Smrg } 1197ec681f3Smrg break; 1207ec681f3Smrg case 'e': 1217ec681f3Smrg entry_point = optarg; 1227ec681f3Smrg break; 1237ec681f3Smrg case 'g': 1247ec681f3Smrg env = NIR_SPIRV_OPENGL; 1257ec681f3Smrg break; 1267ec681f3Smrg default: 1277ec681f3Smrg fprintf(stderr, "Unrecognized option \"%s\".\n", optarg); 1287ec681f3Smrg print_usage(argv[0], stderr); 1297ec681f3Smrg return 1; 1307ec681f3Smrg } 1317ec681f3Smrg } 1327ec681f3Smrg 1337ec681f3Smrg const char *filename = argv[optind]; 1347ec681f3Smrg int fd = open(filename, O_RDONLY); 13501e04c3fSmrg if (fd < 0) 13601e04c3fSmrg { 1377ec681f3Smrg fprintf(stderr, "Failed to open %s\n", filename); 13801e04c3fSmrg return 1; 13901e04c3fSmrg } 14001e04c3fSmrg 14101e04c3fSmrg off_t len = lseek(fd, 0, SEEK_END); 14201e04c3fSmrg if (len % WORD_SIZE != 0) 14301e04c3fSmrg { 14401e04c3fSmrg fprintf(stderr, "File length isn't a multiple of the word size\n"); 14501e04c3fSmrg fprintf(stderr, "Are you sure this is a valid SPIR-V shader?\n"); 14601e04c3fSmrg close(fd); 14701e04c3fSmrg return 1; 14801e04c3fSmrg } 14901e04c3fSmrg 15001e04c3fSmrg size_t word_count = len / WORD_SIZE; 15101e04c3fSmrg 15201e04c3fSmrg const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 15301e04c3fSmrg if (map == MAP_FAILED) 15401e04c3fSmrg { 15501e04c3fSmrg fprintf(stderr, "Failed to mmap the file: errno=%d, %s\n", 15601e04c3fSmrg errno, strerror(errno)); 15701e04c3fSmrg close(fd); 15801e04c3fSmrg return 1; 15901e04c3fSmrg } 16001e04c3fSmrg 1617ec681f3Smrg glsl_type_singleton_init_or_ref(); 1627ec681f3Smrg 1637ec681f3Smrg struct spirv_to_nir_options spirv_opts = { 1647ec681f3Smrg .environment = env, 1657ec681f3Smrg .use_deref_buffer_array_length = env == NIR_SPIRV_OPENGL, 1667ec681f3Smrg }; 1677ec681f3Smrg 1687ec681f3Smrg if (shader_stage == MESA_SHADER_KERNEL) { 1697ec681f3Smrg spirv_opts.environment = NIR_SPIRV_OPENCL; 1707ec681f3Smrg spirv_opts.caps.address = true; 1717ec681f3Smrg spirv_opts.caps.float64 = true; 1727ec681f3Smrg spirv_opts.caps.int8 = true; 1737ec681f3Smrg spirv_opts.caps.int16 = true; 1747ec681f3Smrg spirv_opts.caps.int64 = true; 1757ec681f3Smrg spirv_opts.caps.kernel = true; 1767ec681f3Smrg } 1777ec681f3Smrg 1787ec681f3Smrg nir_shader *nir = spirv_to_nir(map, word_count, NULL, 0, 1797ec681f3Smrg shader_stage, entry_point, 1807ec681f3Smrg &spirv_opts, NULL); 1817ec681f3Smrg 1827ec681f3Smrg if (nir) 1837ec681f3Smrg nir_print_shader(nir, stderr); 1847ec681f3Smrg else 1857ec681f3Smrg fprintf(stderr, "SPIRV to NIR compilation failed\n"); 18601e04c3fSmrg 1877ec681f3Smrg glsl_type_singleton_decref(); 18801e04c3fSmrg 18901e04c3fSmrg return 0; 19001e04c3fSmrg} 191