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