1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Jason Ekstrand (jason@jlekstrand.net) 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/* 29bf215546Sopenharmony_ci * A simple executable that opens a SPIR-V shader, converts it to NIR, and 30bf215546Sopenharmony_ci * dumps out the result. This should be useful for testing the 31bf215546Sopenharmony_ci * spirv_to_nir code. 32bf215546Sopenharmony_ci */ 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "spirv/nir_spirv.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include <sys/mman.h> 37bf215546Sopenharmony_ci#include <sys/types.h> 38bf215546Sopenharmony_ci#include <fcntl.h> 39bf215546Sopenharmony_ci#include <unistd.h> 40bf215546Sopenharmony_ci#include <stdio.h> 41bf215546Sopenharmony_ci#include <errno.h> 42bf215546Sopenharmony_ci#include <string.h> 43bf215546Sopenharmony_ci#include <getopt.h> 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#define WORD_SIZE 4 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic gl_shader_stage 48bf215546Sopenharmony_cistage_to_enum(char *stage) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci if (!strcmp(stage, "vertex")) 51bf215546Sopenharmony_ci return MESA_SHADER_VERTEX; 52bf215546Sopenharmony_ci else if (!strcmp(stage, "tess-ctrl")) 53bf215546Sopenharmony_ci return MESA_SHADER_TESS_CTRL; 54bf215546Sopenharmony_ci else if (!strcmp(stage, "tess-eval")) 55bf215546Sopenharmony_ci return MESA_SHADER_TESS_EVAL; 56bf215546Sopenharmony_ci else if (!strcmp(stage, "geometry")) 57bf215546Sopenharmony_ci return MESA_SHADER_GEOMETRY; 58bf215546Sopenharmony_ci else if (!strcmp(stage, "fragment")) 59bf215546Sopenharmony_ci return MESA_SHADER_FRAGMENT; 60bf215546Sopenharmony_ci else if (!strcmp(stage, "compute")) 61bf215546Sopenharmony_ci return MESA_SHADER_COMPUTE; 62bf215546Sopenharmony_ci else if (!strcmp(stage, "kernel")) 63bf215546Sopenharmony_ci return MESA_SHADER_KERNEL; 64bf215546Sopenharmony_ci else if (!strcmp(stage, "task")) 65bf215546Sopenharmony_ci return MESA_SHADER_TASK; 66bf215546Sopenharmony_ci else if (!strcmp(stage, "mesh")) 67bf215546Sopenharmony_ci return MESA_SHADER_MESH; 68bf215546Sopenharmony_ci else 69bf215546Sopenharmony_ci return MESA_SHADER_NONE; 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_cistatic void 73bf215546Sopenharmony_ciprint_usage(char *exec_name, FILE *f) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci fprintf(f, 76bf215546Sopenharmony_ci"Usage: %s [options] file\n" 77bf215546Sopenharmony_ci"Options:\n" 78bf215546Sopenharmony_ci" -h --help Print this help.\n" 79bf215546Sopenharmony_ci" -s, --stage <stage> Specify the shader stage. Valid stages are:\n" 80bf215546Sopenharmony_ci" vertex, tess-ctrl, tess-eval, geometry, fragment,\n" 81bf215546Sopenharmony_ci" task, mesh, compute, and kernel (OpenCL-style compute).\n" 82bf215546Sopenharmony_ci" -e, --entry <name> Specify the entry-point name.\n" 83bf215546Sopenharmony_ci" -g, --opengl Use OpenGL environment instead of Vulkan for\n" 84bf215546Sopenharmony_ci" graphics stages.\n" 85bf215546Sopenharmony_ci , exec_name); 86bf215546Sopenharmony_ci} 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ciint main(int argc, char **argv) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci gl_shader_stage shader_stage = MESA_SHADER_FRAGMENT; 91bf215546Sopenharmony_ci char *entry_point = "main"; 92bf215546Sopenharmony_ci int ch; 93bf215546Sopenharmony_ci enum nir_spirv_execution_environment env = NIR_SPIRV_VULKAN; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci static struct option long_options[] = 96bf215546Sopenharmony_ci { 97bf215546Sopenharmony_ci {"help", no_argument, 0, 'h'}, 98bf215546Sopenharmony_ci {"stage", required_argument, 0, 's'}, 99bf215546Sopenharmony_ci {"entry", required_argument, 0, 'e'}, 100bf215546Sopenharmony_ci {"opengl", no_argument, 0, 'g'}, 101bf215546Sopenharmony_ci {0, 0, 0, 0} 102bf215546Sopenharmony_ci }; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci while ((ch = getopt_long(argc, argv, "hs:e:g", long_options, NULL)) != -1) 105bf215546Sopenharmony_ci { 106bf215546Sopenharmony_ci switch (ch) 107bf215546Sopenharmony_ci { 108bf215546Sopenharmony_ci case 'h': 109bf215546Sopenharmony_ci print_usage(argv[0], stdout); 110bf215546Sopenharmony_ci return 0; 111bf215546Sopenharmony_ci case 's': 112bf215546Sopenharmony_ci shader_stage = stage_to_enum(optarg); 113bf215546Sopenharmony_ci if (shader_stage == MESA_SHADER_NONE) 114bf215546Sopenharmony_ci { 115bf215546Sopenharmony_ci fprintf(stderr, "Unknown stage \"%s\"\n", optarg); 116bf215546Sopenharmony_ci print_usage(argv[0], stderr); 117bf215546Sopenharmony_ci return 1; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci break; 120bf215546Sopenharmony_ci case 'e': 121bf215546Sopenharmony_ci entry_point = optarg; 122bf215546Sopenharmony_ci break; 123bf215546Sopenharmony_ci case 'g': 124bf215546Sopenharmony_ci env = NIR_SPIRV_OPENGL; 125bf215546Sopenharmony_ci break; 126bf215546Sopenharmony_ci default: 127bf215546Sopenharmony_ci fprintf(stderr, "Unrecognized option \"%s\".\n", optarg); 128bf215546Sopenharmony_ci print_usage(argv[0], stderr); 129bf215546Sopenharmony_ci return 1; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci const char *filename = argv[optind]; 134bf215546Sopenharmony_ci int fd = open(filename, O_RDONLY); 135bf215546Sopenharmony_ci if (fd < 0) 136bf215546Sopenharmony_ci { 137bf215546Sopenharmony_ci fprintf(stderr, "Failed to open %s\n", filename); 138bf215546Sopenharmony_ci return 1; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci off_t len = lseek(fd, 0, SEEK_END); 142bf215546Sopenharmony_ci if (len % WORD_SIZE != 0) 143bf215546Sopenharmony_ci { 144bf215546Sopenharmony_ci fprintf(stderr, "File length isn't a multiple of the word size\n"); 145bf215546Sopenharmony_ci fprintf(stderr, "Are you sure this is a valid SPIR-V shader?\n"); 146bf215546Sopenharmony_ci close(fd); 147bf215546Sopenharmony_ci return 1; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci size_t word_count = len / WORD_SIZE; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); 153bf215546Sopenharmony_ci if (map == MAP_FAILED) 154bf215546Sopenharmony_ci { 155bf215546Sopenharmony_ci fprintf(stderr, "Failed to mmap the file: errno=%d, %s\n", 156bf215546Sopenharmony_ci errno, strerror(errno)); 157bf215546Sopenharmony_ci close(fd); 158bf215546Sopenharmony_ci return 1; 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci glsl_type_singleton_init_or_ref(); 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci struct spirv_to_nir_options spirv_opts = { 164bf215546Sopenharmony_ci .environment = env, 165bf215546Sopenharmony_ci .use_deref_buffer_array_length = env == NIR_SPIRV_OPENGL, 166bf215546Sopenharmony_ci }; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if (shader_stage == MESA_SHADER_KERNEL) { 169bf215546Sopenharmony_ci spirv_opts.environment = NIR_SPIRV_OPENCL; 170bf215546Sopenharmony_ci spirv_opts.caps.address = true; 171bf215546Sopenharmony_ci spirv_opts.caps.float64 = true; 172bf215546Sopenharmony_ci spirv_opts.caps.int8 = true; 173bf215546Sopenharmony_ci spirv_opts.caps.int16 = true; 174bf215546Sopenharmony_ci spirv_opts.caps.int64 = true; 175bf215546Sopenharmony_ci spirv_opts.caps.kernel = true; 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci nir_shader *nir = spirv_to_nir(map, word_count, NULL, 0, 179bf215546Sopenharmony_ci shader_stage, entry_point, 180bf215546Sopenharmony_ci &spirv_opts, NULL); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (nir) 183bf215546Sopenharmony_ci nir_print_shader(nir, stderr); 184bf215546Sopenharmony_ci else 185bf215546Sopenharmony_ci fprintf(stderr, "SPIRV to NIR compilation failed\n"); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci glsl_type_singleton_decref(); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci return 0; 190bf215546Sopenharmony_ci} 191