1/* 2 * Copyright © 2015 Intel Corporation 3 * Copyright © Microsoft Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25/* 26 * A simple executable that opens a SPIR-V shader, converts it to DXIL via 27 * NIR, and dumps out the result. This should be useful for testing the 28 * nir_to_dxil code. Based on spirv2nir.c. 29 */ 30 31#include "nir_to_dxil.h" 32#include "dxil_validation.h" 33#include "spirv/nir_spirv.h" 34#include "spirv_to_dxil.h" 35 36#include "util/os_file.h" 37#include <errno.h> 38#include <getopt.h> 39#include <stdio.h> 40#include <string.h> 41 42#define WORD_SIZE 4 43 44static gl_shader_stage 45stage_to_enum(char *stage) 46{ 47 if (!strcmp(stage, "vertex")) 48 return MESA_SHADER_VERTEX; 49 else if (!strcmp(stage, "tess-ctrl")) 50 return MESA_SHADER_TESS_CTRL; 51 else if (!strcmp(stage, "tess-eval")) 52 return MESA_SHADER_TESS_EVAL; 53 else if (!strcmp(stage, "geometry")) 54 return MESA_SHADER_GEOMETRY; 55 else if (!strcmp(stage, "fragment")) 56 return MESA_SHADER_FRAGMENT; 57 else if (!strcmp(stage, "compute")) 58 return MESA_SHADER_COMPUTE; 59 else if (!strcmp(stage, "kernel")) 60 return MESA_SHADER_KERNEL; 61 else 62 return MESA_SHADER_NONE; 63} 64 65int 66main(int argc, char **argv) 67{ 68 gl_shader_stage shader_stage = MESA_SHADER_FRAGMENT; 69 char *entry_point = "main"; 70 char *output_file = ""; 71 int ch; 72 bool validate = false, debug = false; 73 74 static struct option long_options[] = { 75 {"stage", required_argument, 0, 's'}, 76 {"entry", required_argument, 0, 'e'}, 77 {"output", required_argument, 0, 'o'}, 78 {"validate", no_argument, 0, 'v'}, 79 {"debug", no_argument, 0, 'd'}, 80 {0, 0, 0, 0}}; 81 82 83 while ((ch = getopt_long(argc, argv, "s:e:o:vd", long_options, NULL)) != 84 -1) { 85 switch(ch) 86 { 87 case 's': 88 shader_stage = stage_to_enum(optarg); 89 if (shader_stage == MESA_SHADER_NONE) { 90 fprintf(stderr, "Unknown stage %s\n", optarg); 91 return 1; 92 } 93 break; 94 case 'e': 95 entry_point = optarg; 96 break; 97 case 'o': 98 output_file = optarg; 99 break; 100 case 'v': 101 validate = true; 102 break; 103 case 'd': 104 debug = true; 105 break; 106 default: 107 fprintf(stderr, "Unrecognized option.\n"); 108 return 1; 109 } 110 } 111 112 if (optind != argc - 1) { 113 if (optind < argc) 114 fprintf(stderr, "Please specify only one input file."); 115 else 116 fprintf(stderr, "Please specify an input file."); 117 return 1; 118 } 119 120 const char *filename = argv[optind]; 121 size_t file_size; 122 char *file_contents = os_read_file(filename, &file_size); 123 if (!file_contents) { 124 fprintf(stderr, "Failed to open %s\n", filename); 125 return 1; 126 } 127 128 if (file_size % WORD_SIZE != 0) { 129 fprintf(stderr, "%s size == %zu is not a multiple of %d\n", filename, 130 file_size, WORD_SIZE); 131 return 1; 132 } 133 134 size_t word_count = file_size / WORD_SIZE; 135 136 struct dxil_spirv_runtime_conf conf; 137 memset(&conf, 0, sizeof(conf)); 138 conf.runtime_data_cbv.base_shader_register = 0; 139 conf.runtime_data_cbv.register_space = 31; 140 conf.zero_based_vertex_instance_id = true; 141 142 struct dxil_spirv_debug_options dbg_opts = { 143 .dump_nir = debug, 144 }; 145 146 struct dxil_spirv_object obj; 147 memset(&obj, 0, sizeof(obj)); 148 if (spirv_to_dxil((uint32_t *)file_contents, word_count, NULL, 0, 149 (dxil_spirv_shader_stage)shader_stage, entry_point, 150 &dbg_opts, &conf, &obj)) { 151 152 if (validate && !validate_dxil(&obj)) { 153 fprintf(stderr, "Failed to validate DXIL\n"); 154 spirv_to_dxil_free(&obj); 155 free(file_contents); 156 return 1; 157 } 158 159 FILE *file = fopen(output_file, "wb"); 160 if (!file) { 161 fprintf(stderr, "Failed to open %s, %s\n", output_file, 162 strerror(errno)); 163 spirv_to_dxil_free(&obj); 164 free(file_contents); 165 return 1; 166 } 167 168 fwrite(obj.binary.buffer, sizeof(char), obj.binary.size, file); 169 fclose(file); 170 spirv_to_dxil_free(&obj); 171 } else { 172 fprintf(stderr, "Compilation failed\n"); 173 return 1; 174 } 175 176 free(file_contents); 177 178 return 0; 179} 180