17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2015 Intel Corporation
37ec681f3Smrg * Copyright © Microsoft Corporation
47ec681f3Smrg *
57ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
67ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
77ec681f3Smrg * to deal in the Software without restriction, including without limitation
87ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
97ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
107ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
117ec681f3Smrg *
127ec681f3Smrg * The above copyright notice and this permission notice (including the next
137ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
147ec681f3Smrg * Software.
157ec681f3Smrg *
167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
197ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
217ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
227ec681f3Smrg * IN THE SOFTWARE.
237ec681f3Smrg */
247ec681f3Smrg
257ec681f3Smrg/*
267ec681f3Smrg * A simple executable that opens a SPIR-V shader, converts it to DXIL via
277ec681f3Smrg * NIR, and dumps out the result.  This should be useful for testing the
287ec681f3Smrg * nir_to_dxil code.  Based on spirv2nir.c.
297ec681f3Smrg */
307ec681f3Smrg
317ec681f3Smrg#include "nir_to_dxil.h"
327ec681f3Smrg#include "spirv/nir_spirv.h"
337ec681f3Smrg#include "spirv_to_dxil.h"
347ec681f3Smrg
357ec681f3Smrg#include "util/os_file.h"
367ec681f3Smrg#include <errno.h>
377ec681f3Smrg#include <getopt.h>
387ec681f3Smrg#include <stdio.h>
397ec681f3Smrg#include <string.h>
407ec681f3Smrg
417ec681f3Smrg#define WORD_SIZE 4
427ec681f3Smrg
437ec681f3Smrgstatic gl_shader_stage
447ec681f3Smrgstage_to_enum(char *stage)
457ec681f3Smrg{
467ec681f3Smrg   if (!strcmp(stage, "vertex"))
477ec681f3Smrg      return MESA_SHADER_VERTEX;
487ec681f3Smrg   else if (!strcmp(stage, "tess-ctrl"))
497ec681f3Smrg      return MESA_SHADER_TESS_CTRL;
507ec681f3Smrg   else if (!strcmp(stage, "tess-eval"))
517ec681f3Smrg      return MESA_SHADER_TESS_EVAL;
527ec681f3Smrg   else if (!strcmp(stage, "geometry"))
537ec681f3Smrg      return MESA_SHADER_GEOMETRY;
547ec681f3Smrg   else if (!strcmp(stage, "fragment"))
557ec681f3Smrg      return MESA_SHADER_FRAGMENT;
567ec681f3Smrg   else if (!strcmp(stage, "compute"))
577ec681f3Smrg      return MESA_SHADER_COMPUTE;
587ec681f3Smrg   else if (!strcmp(stage, "kernel"))
597ec681f3Smrg      return MESA_SHADER_KERNEL;
607ec681f3Smrg   else
617ec681f3Smrg      return MESA_SHADER_NONE;
627ec681f3Smrg}
637ec681f3Smrg
647ec681f3Smrgint
657ec681f3Smrgmain(int argc, char **argv)
667ec681f3Smrg{
677ec681f3Smrg   gl_shader_stage shader_stage = MESA_SHADER_FRAGMENT;
687ec681f3Smrg   char *entry_point = "main";
697ec681f3Smrg   char *output_file = "";
707ec681f3Smrg   int ch;
717ec681f3Smrg
727ec681f3Smrg   static struct option long_options[] = {
737ec681f3Smrg      {"stage", required_argument, 0, 's'},
747ec681f3Smrg      {"entry", required_argument, 0, 'e'},
757ec681f3Smrg      {"output", required_argument, 0, 'o'},
767ec681f3Smrg      {0, 0, 0, 0}};
777ec681f3Smrg
787ec681f3Smrg   while ((ch = getopt_long(argc, argv, "s:e:o:", long_options, NULL)) !=
797ec681f3Smrg          -1) {
807ec681f3Smrg      switch (ch) {
817ec681f3Smrg      case 's':
827ec681f3Smrg         shader_stage = stage_to_enum(optarg);
837ec681f3Smrg         if (shader_stage == MESA_SHADER_NONE) {
847ec681f3Smrg            fprintf(stderr, "Unknown stage %s\n", optarg);
857ec681f3Smrg            return 1;
867ec681f3Smrg         }
877ec681f3Smrg         break;
887ec681f3Smrg      case 'e':
897ec681f3Smrg         entry_point = optarg;
907ec681f3Smrg         break;
917ec681f3Smrg      case 'o':
927ec681f3Smrg         output_file = optarg;
937ec681f3Smrg         break;
947ec681f3Smrg      default:
957ec681f3Smrg         fprintf(stderr, "Unrecognized option.\n");
967ec681f3Smrg         return 1;
977ec681f3Smrg      }
987ec681f3Smrg   }
997ec681f3Smrg
1007ec681f3Smrg   if (optind != argc - 1) {
1017ec681f3Smrg      if (optind < argc)
1027ec681f3Smrg         fprintf(stderr, "Please specify only one input file.");
1037ec681f3Smrg      else
1047ec681f3Smrg         fprintf(stderr, "Please specify an input file.");
1057ec681f3Smrg      return 1;
1067ec681f3Smrg   }
1077ec681f3Smrg
1087ec681f3Smrg   const char *filename = argv[optind];
1097ec681f3Smrg   size_t file_size;
1107ec681f3Smrg   char *file_contents = os_read_file(filename, &file_size);
1117ec681f3Smrg   if (!file_contents) {
1127ec681f3Smrg      fprintf(stderr, "Failed to open %s\n", filename);
1137ec681f3Smrg      return 1;
1147ec681f3Smrg   }
1157ec681f3Smrg
1167ec681f3Smrg   if (file_size % WORD_SIZE != 0) {
1177ec681f3Smrg      fprintf(stderr, "%s size == %zu is not a multiple of %d\n", filename,
1187ec681f3Smrg              file_size, WORD_SIZE);
1197ec681f3Smrg      return 1;
1207ec681f3Smrg   }
1217ec681f3Smrg
1227ec681f3Smrg   size_t word_count = file_size / WORD_SIZE;
1237ec681f3Smrg
1247ec681f3Smrg   struct dxil_spirv_runtime_conf conf;
1257ec681f3Smrg   memset(&conf, 0, sizeof(conf));
1267ec681f3Smrg   conf.runtime_data_cbv.base_shader_register = 0;
1277ec681f3Smrg   conf.runtime_data_cbv.register_space = 31;
1287ec681f3Smrg   conf.zero_based_vertex_instance_id = true;
1297ec681f3Smrg
1307ec681f3Smrg   struct dxil_spirv_object obj;
1317ec681f3Smrg   memset(&obj, 0, sizeof(obj));
1327ec681f3Smrg   if (spirv_to_dxil((uint32_t *)file_contents, word_count, NULL, 0,
1337ec681f3Smrg                     (dxil_spirv_shader_stage)shader_stage, entry_point,
1347ec681f3Smrg                     &conf, &obj)) {
1357ec681f3Smrg      FILE *file = fopen(output_file, "wb");
1367ec681f3Smrg      if (!file) {
1377ec681f3Smrg         fprintf(stderr, "Failed to open %s, %s\n", output_file,
1387ec681f3Smrg                 strerror(errno));
1397ec681f3Smrg         spirv_to_dxil_free(&obj);
1407ec681f3Smrg         free(file_contents);
1417ec681f3Smrg         return 1;
1427ec681f3Smrg      }
1437ec681f3Smrg
1447ec681f3Smrg      fwrite(obj.binary.buffer, sizeof(char), obj.binary.size, file);
1457ec681f3Smrg      fclose(file);
1467ec681f3Smrg      spirv_to_dxil_free(&obj);
1477ec681f3Smrg   } else {
1487ec681f3Smrg      fprintf(stderr, "Compilation failed\n");
1497ec681f3Smrg      return 1;
1507ec681f3Smrg   }
1517ec681f3Smrg
1527ec681f3Smrg   free(file_contents);
1537ec681f3Smrg
1547ec681f3Smrg   return 0;
1557ec681f3Smrg}
156