blob: 481189c785f142f6847344f34bff124671ef12c8 [file] [log] [blame]
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001/*
Hans-Kristian Arntzenf9818f02020-01-16 15:24:37 +01002 * Copyright 2015-2020 Arm Limited
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Hans-Kristian Arntzen147e53a2016-04-04 09:36:04 +020017#include "spirv_cpp.hpp"
grovesNL94cd7772018-03-01 23:47:08 -070018#include "spirv_cross_util.hpp"
Bill Hollings77f58122017-08-11 14:54:58 -040019#include "spirv_glsl.hpp"
Robert Konrad216a6812017-01-25 17:30:52 +010020#include "spirv_hlsl.hpp"
Hans-Kristian Arntzen24df8f02017-02-04 10:26:26 +010021#include "spirv_msl.hpp"
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +020022#include "spirv_parser.hpp"
Brad Davis709d3c62018-06-03 11:16:37 -070023#include "spirv_reflect.hpp"
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020024#include <algorithm>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010025#include <cstdio>
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020026#include <cstring>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010027#include <functional>
28#include <limits>
29#include <memory>
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020030#include <stdexcept>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010031#include <unordered_map>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010032#include <unordered_set>
33
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +020034#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
35#include "gitversion.h"
36#endif
37
Hans-Kristian Arntzence3fe292017-01-12 10:57:44 +010038#ifdef _MSC_VER
Hans-Kristian Arntzen27f4f752017-01-13 16:32:54 +010039#pragma warning(disable : 4996)
Hans-Kristian Arntzence3fe292017-01-12 10:57:44 +010040#endif
41
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010042using namespace spv;
Hans-Kristian Arntzen9b92e682019-03-29 10:29:44 +010043using namespace SPIRV_CROSS_NAMESPACE;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010044using namespace std;
45
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010046#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +020047static inline void THROW(const char *str)
48{
49 fprintf(stderr, "SPIRV-Cross will abort: %s\n", str);
50 fflush(stderr);
51 abort();
52}
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010053#else
Hans-Kristian Arntzenc92b8392017-02-16 11:06:57 +010054#define THROW(x) throw runtime_error(x)
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010055#endif
56
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010057struct CLIParser;
58struct CLICallbacks
59{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020060 void add(const char *cli, const function<void(CLIParser &)> &func)
61 {
62 callbacks[cli] = func;
63 }
64 unordered_map<string, function<void(CLIParser &)>> callbacks;
65 function<void()> error_handler;
66 function<void(const char *)> default_handler;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010067};
68
69struct CLIParser
70{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020071 CLIParser(CLICallbacks cbs_, int argc_, char *argv_[])
72 : cbs(move(cbs_))
73 , argc(argc_)
74 , argv(argv_)
75 {
76 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010077
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020078 bool parse()
79 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010080#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020081 try
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010082#endif
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020083 {
84 while (argc && !ended_state)
85 {
86 const char *next = *argv++;
87 argc--;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010088
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020089 if (*next != '-' && cbs.default_handler)
90 {
91 cbs.default_handler(next);
92 }
93 else
94 {
95 auto itr = cbs.callbacks.find(next);
96 if (itr == ::end(cbs.callbacks))
97 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010098 THROW("Invalid argument");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020099 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100100
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200101 itr->second(*this);
102 }
103 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100104
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200105 return true;
106 }
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100107#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200108 catch (...)
109 {
110 if (cbs.error_handler)
111 {
112 cbs.error_handler();
113 }
114 return false;
115 }
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100116#endif
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200117 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100118
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200119 void end()
120 {
121 ended_state = true;
122 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100123
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200124 uint32_t next_uint()
125 {
126 if (!argc)
127 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100128 THROW("Tried to parse uint, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200129 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100130
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200131 uint64_t val = stoul(*argv);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200132 if (val > numeric_limits<uint32_t>::max())
133 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100134 THROW("next_uint() out of range");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200135 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100136
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200137 argc--;
138 argv++;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100139
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200140 return uint32_t(val);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200141 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100142
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200143 double next_double()
144 {
145 if (!argc)
146 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100147 THROW("Tried to parse double, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200148 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100149
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200150 double val = stod(*argv);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100151
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200152 argc--;
153 argv++;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100154
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200155 return val;
156 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100157
Brad Davis709d3c62018-06-03 11:16:37 -0700158 // Return a string only if it's not prefixed with `--`, otherwise return the default value
Brad Davis76204002018-06-20 10:25:38 -0700159 const char *next_value_string(const char *default_value)
Brad Davis709d3c62018-06-03 11:16:37 -0700160 {
161 if (!argc)
162 {
Brad Davis76204002018-06-20 10:25:38 -0700163 return default_value;
Brad Davis709d3c62018-06-03 11:16:37 -0700164 }
165
166 if (0 == strncmp("--", *argv, 2))
167 {
Brad Davis76204002018-06-20 10:25:38 -0700168 return default_value;
Brad Davis709d3c62018-06-03 11:16:37 -0700169 }
170
171 return next_string();
172 }
173
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200174 const char *next_string()
175 {
176 if (!argc)
177 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100178 THROW("Tried to parse string, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200179 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100180
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200181 const char *ret = *argv;
182 argc--;
183 argv++;
184 return ret;
185 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100186
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200187 CLICallbacks cbs;
188 int argc;
189 char **argv;
190 bool ended_state = false;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100191};
192
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200193static vector<uint32_t> read_spirv_file(const char *path)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100194{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200195 FILE *file = fopen(path, "rb");
196 if (!file)
197 {
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +0200198 fprintf(stderr, "Failed to open SPIR-V file: %s\n", path);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200199 return {};
200 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100201
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200202 fseek(file, 0, SEEK_END);
203 long len = ftell(file) / sizeof(uint32_t);
204 rewind(file);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100205
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200206 vector<uint32_t> spirv(len);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200207 if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
208 spirv.clear();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100209
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200210 fclose(file);
211 return spirv;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100212}
213
214static bool write_string_to_file(const char *path, const char *string)
215{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200216 FILE *file = fopen(path, "w");
217 if (!file)
218 {
hesiodba381582017-05-30 17:17:51 +0300219 fprintf(stderr, "Failed to write file: %s\n", path);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200220 return false;
221 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100222
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200223 fprintf(file, "%s", string);
224 fclose(file);
225 return true;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100226}
227
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200228static void print_resources(const Compiler &compiler, const char *tag, const SmallVector<Resource> &resources)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100229{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200230 fprintf(stderr, "%s\n", tag);
231 fprintf(stderr, "=============\n\n");
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200232 bool print_ssbo = !strcmp(tag, "ssbos");
233
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200234 for (auto &res : resources)
235 {
236 auto &type = compiler.get_type(res.type_id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100237
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200238 if (print_ssbo && compiler.buffer_is_hlsl_counter_buffer(res.id))
239 continue;
240
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200241 // If we don't have a name, use the fallback for the type instead of the variable
242 // for SSBOs and UBOs since those are the only meaningful names to use externally.
243 // Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
244 bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100245 bool is_block = compiler.get_decoration_bitset(type.self).get(DecorationBlock) ||
246 compiler.get_decoration_bitset(type.self).get(DecorationBufferBlock);
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100247 bool is_sized_block = is_block && (compiler.get_storage_class(res.id) == StorageClassUniform ||
248 compiler.get_storage_class(res.id) == StorageClassUniformConstant);
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200249 ID fallback_id = !is_push_constant && is_block ? ID(res.base_type_id) : ID(res.id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100250
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100251 uint32_t block_size = 0;
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200252 uint32_t runtime_array_stride = 0;
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100253 if (is_sized_block)
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200254 {
255 auto &base_type = compiler.get_type(res.base_type_id);
256 block_size = uint32_t(compiler.get_declared_struct_size(base_type));
257 runtime_array_stride = uint32_t(compiler.get_declared_struct_size_runtime_array(base_type, 1) -
258 compiler.get_declared_struct_size_runtime_array(base_type, 0));
259 }
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100260
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200261 Bitset mask;
262 if (print_ssbo)
263 mask = compiler.get_buffer_block_flags(res.id);
264 else
265 mask = compiler.get_decoration_bitset(res.id);
266
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200267 string array;
268 for (auto arr : type.array)
269 array = join("[", arr ? convert_to_string(arr) : "", "]") + array;
270
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200271 fprintf(stderr, " ID %03u : %s%s", uint32_t(res.id),
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200272 !res.name.empty() ? res.name.c_str() : compiler.get_fallback_name(fallback_id).c_str(), array.c_str());
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100273
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100274 if (mask.get(DecorationLocation))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200275 fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100276 if (mask.get(DecorationDescriptorSet))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200277 fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100278 if (mask.get(DecorationBinding))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200279 fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100280 if (mask.get(DecorationInputAttachmentIndex))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200281 fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100282 if (mask.get(DecorationNonReadable))
Hans-Kristian Arntzen97f7ab82017-01-05 18:16:33 +0100283 fprintf(stderr, " writeonly");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100284 if (mask.get(DecorationNonWritable))
Hans-Kristian Arntzen97f7ab82017-01-05 18:16:33 +0100285 fprintf(stderr, " readonly");
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100286 if (is_sized_block)
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200287 {
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100288 fprintf(stderr, " (BlockSize : %u bytes)", block_size);
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200289 if (runtime_array_stride)
290 fprintf(stderr, " (Unsized array stride: %u bytes)", runtime_array_stride);
291 }
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200292
293 uint32_t counter_id = 0;
294 if (print_ssbo && compiler.buffer_get_hlsl_counter_buffer(res.id, counter_id))
295 fprintf(stderr, " (HLSL counter buffer ID: %u)", counter_id);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200296 fprintf(stderr, "\n");
297 }
298 fprintf(stderr, "=============\n\n");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100299}
300
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200301static const char *execution_model_to_str(spv::ExecutionModel model)
302{
303 switch (model)
304 {
305 case spv::ExecutionModelVertex:
306 return "vertex";
307 case spv::ExecutionModelTessellationControl:
308 return "tessellation control";
309 case ExecutionModelTessellationEvaluation:
310 return "tessellation evaluation";
311 case ExecutionModelGeometry:
312 return "geometry";
313 case ExecutionModelFragment:
314 return "fragment";
315 case ExecutionModelGLCompute:
316 return "compute";
Hans-Kristian Arntzen88ce9582019-03-27 10:21:30 +0100317 case ExecutionModelRayGenerationNV:
318 return "raygenNV";
319 case ExecutionModelIntersectionNV:
320 return "intersectionNV";
321 case ExecutionModelCallableNV:
322 return "callableNV";
323 case ExecutionModelAnyHitNV:
324 return "anyhitNV";
325 case ExecutionModelClosestHitNV:
326 return "closesthitNV";
327 case ExecutionModelMissNV:
328 return "missNV";
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200329 default:
330 return "???";
331 }
332}
333
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100334static void print_resources(const Compiler &compiler, const ShaderResources &res)
335{
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100336 auto &modes = compiler.get_execution_mode_bitset();
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200337
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200338 fprintf(stderr, "Entry points:\n");
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100339 auto entry_points = compiler.get_entry_points_and_stages();
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200340 for (auto &e : entry_points)
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100341 fprintf(stderr, " %s (%s)\n", e.name.c_str(), execution_model_to_str(e.execution_model));
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200342 fprintf(stderr, "\n");
343
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200344 fprintf(stderr, "Execution modes:\n");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100345 modes.for_each_bit([&](uint32_t i) {
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200346 auto mode = static_cast<ExecutionMode>(i);
347 uint32_t arg0 = compiler.get_execution_mode_argument(mode, 0);
348 uint32_t arg1 = compiler.get_execution_mode_argument(mode, 1);
349 uint32_t arg2 = compiler.get_execution_mode_argument(mode, 2);
350
351 switch (static_cast<ExecutionMode>(i))
352 {
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200353 case ExecutionModeInvocations:
354 fprintf(stderr, " Invocations: %u\n", arg0);
355 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200356
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200357 case ExecutionModeLocalSize:
358 fprintf(stderr, " LocalSize: (%u, %u, %u)\n", arg0, arg1, arg2);
359 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200360
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200361 case ExecutionModeOutputVertices:
362 fprintf(stderr, " OutputVertices: %u\n", arg0);
363 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200364
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200365#define CHECK_MODE(m) \
366 case ExecutionMode##m: \
367 fprintf(stderr, " %s\n", #m); \
368 break
369 CHECK_MODE(SpacingEqual);
370 CHECK_MODE(SpacingFractionalEven);
371 CHECK_MODE(SpacingFractionalOdd);
372 CHECK_MODE(VertexOrderCw);
373 CHECK_MODE(VertexOrderCcw);
374 CHECK_MODE(PixelCenterInteger);
375 CHECK_MODE(OriginUpperLeft);
376 CHECK_MODE(OriginLowerLeft);
377 CHECK_MODE(EarlyFragmentTests);
378 CHECK_MODE(PointMode);
379 CHECK_MODE(Xfb);
380 CHECK_MODE(DepthReplacing);
381 CHECK_MODE(DepthGreater);
382 CHECK_MODE(DepthLess);
383 CHECK_MODE(DepthUnchanged);
384 CHECK_MODE(LocalSizeHint);
385 CHECK_MODE(InputPoints);
386 CHECK_MODE(InputLines);
387 CHECK_MODE(InputLinesAdjacency);
388 CHECK_MODE(Triangles);
389 CHECK_MODE(InputTrianglesAdjacency);
390 CHECK_MODE(Quads);
391 CHECK_MODE(Isolines);
392 CHECK_MODE(OutputPoints);
393 CHECK_MODE(OutputLineStrip);
394 CHECK_MODE(OutputTriangleStrip);
395 CHECK_MODE(VecTypeHint);
396 CHECK_MODE(ContractionOff);
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200397
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200398 default:
399 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200400 }
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100401 });
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200402 fprintf(stderr, "\n");
403
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200404 print_resources(compiler, "subpass inputs", res.subpass_inputs);
405 print_resources(compiler, "inputs", res.stage_inputs);
406 print_resources(compiler, "outputs", res.stage_outputs);
407 print_resources(compiler, "textures", res.sampled_images);
Hans-Kristian Arntzen378fbe82016-09-11 13:47:06 +0200408 print_resources(compiler, "separate images", res.separate_images);
Hans-Kristian Arntzene9202082016-09-10 13:05:35 +0200409 print_resources(compiler, "separate samplers", res.separate_samplers);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200410 print_resources(compiler, "images", res.storage_images);
411 print_resources(compiler, "ssbos", res.storage_buffers);
412 print_resources(compiler, "ubos", res.uniform_buffers);
413 print_resources(compiler, "push", res.push_constant_buffers);
414 print_resources(compiler, "counters", res.atomic_counters);
Hans-Kristian Arntzen88ce9582019-03-27 10:21:30 +0100415 print_resources(compiler, "acceleration structures", res.acceleration_structures);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100416}
417
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200418static void print_push_constant_resources(const Compiler &compiler, const SmallVector<Resource> &res)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100419{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200420 for (auto &block : res)
421 {
422 auto ranges = compiler.get_active_buffer_ranges(block.id);
423 fprintf(stderr, "Active members in buffer: %s\n",
424 !block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str());
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100425
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200426 fprintf(stderr, "==================\n\n");
427 for (auto &range : ranges)
428 {
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200429 const auto &name = compiler.get_member_name(block.base_type_id, range.index);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100430
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200431 fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n", range.index,
432 !name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(),
433 unsigned(range.offset), unsigned(range.range));
434 }
435 fprintf(stderr, "==================\n\n");
436 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100437}
438
Hans-Kristian Arntzen6bd545b2016-09-17 15:16:07 +0200439static void print_spec_constants(const Compiler &compiler)
440{
441 auto spec_constants = compiler.get_specialization_constants();
442 fprintf(stderr, "Specialization constants\n");
443 fprintf(stderr, "==================\n\n");
444 for (auto &c : spec_constants)
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200445 fprintf(stderr, "ID: %u, Spec ID: %u\n", uint32_t(c.id), c.constant_id);
Hans-Kristian Arntzen6bd545b2016-09-17 15:16:07 +0200446 fprintf(stderr, "==================\n\n");
447}
448
Hans-Kristian Arntzen8d7a9092017-08-15 15:27:53 +0200449static void print_capabilities_and_extensions(const Compiler &compiler)
450{
451 fprintf(stderr, "Capabilities\n");
452 fprintf(stderr, "============\n");
453 for (auto &capability : compiler.get_declared_capabilities())
454 fprintf(stderr, "Capability: %u\n", static_cast<unsigned>(capability));
455 fprintf(stderr, "============\n\n");
456
457 fprintf(stderr, "Extensions\n");
458 fprintf(stderr, "============\n");
459 for (auto &ext : compiler.get_declared_extensions())
460 fprintf(stderr, "Extension: %s\n", ext.c_str());
461 fprintf(stderr, "============\n\n");
462}
463
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100464struct PLSArg
465{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200466 PlsFormat format;
467 string name;
468};
469
470struct Remap
471{
472 string src_name;
473 string dst_name;
474 unsigned components;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100475};
476
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +0200477struct VariableTypeRemap
478{
479 string variable_name;
480 string new_variable_type;
481};
482
Hans-Kristian Arntzend89d0e02017-07-24 09:29:20 +0200483struct InterfaceVariableRename
484{
485 StorageClass storageClass;
486 uint32_t location;
487 string variable_name;
Jason Chan3281e822017-06-25 15:16:09 +0200488};
489
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100490struct CLIArguments
491{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200492 const char *input = nullptr;
493 const char *output = nullptr;
494 const char *cpp_interface_name = nullptr;
495 uint32_t version = 0;
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +0100496 uint32_t shader_model = 0;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500497 uint32_t msl_version = 0;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200498 bool es = false;
499 bool set_version = false;
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +0100500 bool set_shader_model = false;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500501 bool set_msl_version = false;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200502 bool set_es = false;
503 bool dump_resources = false;
504 bool force_temporary = false;
505 bool flatten_ubo = false;
506 bool fixup = false;
Hans-Kristian Arntzenbdfa97a2017-08-03 13:02:59 +0200507 bool yflip = false;
Hans-Kristian Arntzen36650c82017-05-22 15:30:43 +0200508 bool sso = false;
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +0200509 bool support_nonzero_baseinstance = true;
Chip Davisc51e5b72019-01-08 16:33:32 -0600510 bool msl_capture_output_to_buffer = false;
Chip Davis25833212018-09-19 20:36:33 -0500511 bool msl_swizzle_texture_samples = false;
Chip Davis3a9af962018-09-26 20:06:05 -0500512 bool msl_ios = false;
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +0100513 bool msl_pad_fragment_output = false;
Chip Davis41d94242019-02-05 23:47:50 -0600514 bool msl_domain_lower_left = false;
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100515 bool msl_argument_buffers = false;
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +0200516 bool msl_texture_buffer_native = false;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400517 bool msl_framebuffer_fetch = false;
Lukas Hermannsffbd8012019-10-09 11:22:25 -0400518 bool msl_invariant_float_math = false;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400519 bool msl_emulate_cube_array = false;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500520 bool msl_multiview = false;
Chip Davis6a585542019-07-12 21:50:50 -0500521 bool msl_view_index_from_device_index = false;
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500522 bool msl_dispatch_base = false;
Akio Gaule1280df62019-11-27 01:02:46 -0800523 bool msl_decoration_binding = false;
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +0100524 bool msl_force_active_argument_buffer_resources = false;
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +0100525 bool msl_force_native_arrays = false;
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +0100526 bool glsl_emit_push_constant_as_ubo = false;
Laszlo Agocs7bc31492019-05-11 16:30:33 +0200527 bool glsl_emit_ubo_as_plain_uniforms = false;
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +0200528 bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +0200529 bool emit_line_directives = false;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200530 SmallVector<uint32_t> msl_discrete_descriptor_sets;
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +0200531 SmallVector<uint32_t> msl_device_argument_buffers;
Chip Daviscb359342019-09-05 23:14:12 -0500532 SmallVector<pair<uint32_t, uint32_t>> msl_dynamic_buffers;
Chip Davisfedbc352019-12-16 22:58:16 -0600533 SmallVector<pair<uint32_t, uint32_t>> msl_inline_uniform_blocks;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200534 SmallVector<PLSArg> pls_in;
535 SmallVector<PLSArg> pls_out;
536 SmallVector<Remap> remaps;
537 SmallVector<string> extensions;
538 SmallVector<VariableTypeRemap> variable_type_remaps;
539 SmallVector<InterfaceVariableRename> interface_variable_renames;
540 SmallVector<HLSLVertexAttributeRemap> hlsl_attr_remap;
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200541 string entry;
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100542 string entry_stage;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100543
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100544 struct Rename
545 {
546 string old_name;
547 string new_name;
548 ExecutionModel execution_model;
549 };
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200550 SmallVector<Rename> entry_point_rename;
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +0100551
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200552 uint32_t iterations = 1;
553 bool cpp = false;
Brad Davis709d3c62018-06-03 11:16:37 -0700554 string reflect;
Bill Hollings5ad73f32017-03-19 21:06:21 -0400555 bool msl = false;
Robert Konrad216a6812017-01-25 17:30:52 +0100556 bool hlsl = false;
Hans-Kristian Arntzen17d88ca2017-05-04 10:10:30 +0200557 bool hlsl_compat = false;
Hans-Kristian Arntzena2a44d92019-01-11 10:32:14 +0100558 bool hlsl_support_nonzero_base = false;
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +0100559 bool hlsl_force_storage_buffer_as_uav = false;
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100560 HLSLBindingFlags hlsl_binding_flags = 0;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200561 bool vulkan_semantics = false;
Hans-Kristian Arntzen470ae7a2017-05-22 17:40:00 +0200562 bool flatten_multidimensional_arrays = false;
Hans-Kristian Arntzen6599a412017-09-08 09:56:06 +0200563 bool use_420pack_extension = true;
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +0200564 bool remove_unused = false;
Hans-Kristian Arntzenba15dae2018-05-23 20:34:26 +0100565 bool combined_samplers_inherit_bindings = false;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100566};
567
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200568static void print_version()
569{
570#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
571 fprintf(stderr, "%s\n", SPIRV_CROSS_GIT_REVISION);
572#else
573 fprintf(stderr, "Git revision unknown. Build with CMake to create timestamp and revision info.\n");
574#endif
575}
576
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100577static void print_help()
578{
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200579 print_version();
580
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200581 fprintf(stderr, "Usage: spirv-cross\n"
582 "\t[--output <output path>]\n"
583 "\t[SPIR-V file]\n"
584 "\t[--es]\n"
585 "\t[--no-es]\n"
586 "\t[--version <GLSL version>]\n"
587 "\t[--dump-resources]\n"
588 "\t[--help]\n"
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200589 "\t[--revision]\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200590 "\t[--force-temporary]\n"
Hans-Kristian Arntzen3f2de0d2020-03-02 11:55:57 +0100591 "\t[--vulkan-semantics] or [-V]\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200592 "\t[--flatten-ubo]\n"
593 "\t[--fixup-clipspace]\n"
594 "\t[--flip-vert-y]\n"
595 "\t[--iterations iter]\n"
596 "\t[--cpp]\n"
597 "\t[--cpp-interface-name <name>]\n"
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +0100598 "\t[--glsl-emit-push-constant-as-ubo]\n"
Laszlo Agocs7bc31492019-05-11 16:30:33 +0200599 "\t[--glsl-emit-ubo-as-plain-uniforms]\n"
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +0200600 "\t[--vulkan-glsl-disable-ext-samplerless-texture-functions]\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200601 "\t[--msl]\n"
602 "\t[--msl-version <MMmmpp>]\n"
Chip Davisc51e5b72019-01-08 16:33:32 -0600603 "\t[--msl-capture-output]\n"
Chip Davis3a9af962018-09-26 20:06:05 -0500604 "\t[--msl-swizzle-texture-samples]\n"
605 "\t[--msl-ios]\n"
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +0100606 "\t[--msl-pad-fragment-output]\n"
Chip Davis41d94242019-02-05 23:47:50 -0600607 "\t[--msl-domain-lower-left]\n"
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100608 "\t[--msl-argument-buffers]\n"
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +0200609 "\t[--msl-texture-buffer-native]\n"
Hans-Kristian Arntzen8ad95842019-10-24 10:56:36 +0200610 "\t[--msl-framebuffer-fetch]\n"
611 "\t[--msl-emulate-cube-array]\n"
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +0100612 "\t[--msl-discrete-descriptor-set <index>]\n"
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +0200613 "\t[--msl-device-argument-buffer <index>]\n"
Chip Davis7eecf5a2019-05-31 12:06:20 -0500614 "\t[--msl-multiview]\n"
Chip Davis6a585542019-07-12 21:50:50 -0500615 "\t[--msl-view-index-from-device-index]\n"
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500616 "\t[--msl-dispatch-base]\n"
Chip Daviscb359342019-09-05 23:14:12 -0500617 "\t[--msl-dynamic-buffer <set index> <binding>]\n"
Chip Davisfedbc352019-12-16 22:58:16 -0600618 "\t[--msl-inline-uniform-block <set index> <binding>]\n"
Akio Gaule1280df62019-11-27 01:02:46 -0800619 "\t[--msl-decoration-binding]\n"
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +0100620 "\t[--msl-force-active-argument-buffer-resources]\n"
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +0100621 "\t[--msl-force-native-arrays]\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200622 "\t[--hlsl]\n"
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +0200623 "\t[--reflect]\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200624 "\t[--shader-model]\n"
625 "\t[--hlsl-enable-compat]\n"
Hans-Kristian Arntzena2a44d92019-01-11 10:32:14 +0100626 "\t[--hlsl-support-nonzero-basevertex-baseinstance]\n"
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100627 "\t[--hlsl-auto-binding (push, cbv, srv, uav, sampler, all)]\n"
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +0100628 "\t[--hlsl-force-storage-buffer-as-uav]\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200629 "\t[--separate-shader-objects]\n"
630 "\t[--pls-in format input-name]\n"
631 "\t[--pls-out format output-name]\n"
632 "\t[--remap source_name target_name components]\n"
633 "\t[--extension ext]\n"
634 "\t[--entry name]\n"
635 "\t[--stage <stage (vert, frag, geom, tesc, tese comp)>]\n"
636 "\t[--remove-unused-variables]\n"
637 "\t[--flatten-multidimensional-arrays]\n"
638 "\t[--no-420pack-extension]\n"
639 "\t[--remap-variable-type <variable_name> <new_variable_type>]\n"
640 "\t[--rename-interface-variable <in|out> <location> <new_variable_name>]\n"
641 "\t[--set-hlsl-vertex-input-semantic <location> <semantic>]\n"
642 "\t[--rename-entry-point <old> <new> <stage>]\n"
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +0200643 "\t[--combined-samplers-inherit-bindings]\n"
644 "\t[--no-support-nonzero-baseinstance]\n"
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +0200645 "\t[--emit-line-directives]\n"
Hans-Kristian Arntzend89d0e02017-07-24 09:29:20 +0200646 "\n");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100647}
648
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200649static bool remap_generic(Compiler &compiler, const SmallVector<Resource> &resources, const Remap &remap)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100650{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200651 auto itr =
652 find_if(begin(resources), end(resources), [&remap](const Resource &res) { return res.name == remap.src_name; });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100653
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200654 if (itr != end(resources))
655 {
656 compiler.set_remapped_variable_state(itr->id, true);
657 compiler.set_name(itr->id, remap.dst_name);
658 compiler.set_subpass_input_remapped_components(itr->id, remap.components);
659 return true;
660 }
661 else
662 return false;
663}
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100664
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200665static vector<PlsRemap> remap_pls(const SmallVector<PLSArg> &pls_variables, const SmallVector<Resource> &resources,
666 const SmallVector<Resource> *secondary_resources)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200667{
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200668 vector<PlsRemap> ret;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100669
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200670 for (auto &pls : pls_variables)
671 {
672 bool found = false;
673 for (auto &res : resources)
674 {
675 if (res.name == pls.name)
676 {
677 ret.push_back({ res.id, pls.format });
678 found = true;
679 break;
680 }
681 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100682
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200683 if (!found && secondary_resources)
684 {
685 for (auto &res : *secondary_resources)
686 {
687 if (res.name == pls.name)
688 {
689 ret.push_back({ res.id, pls.format });
690 found = true;
691 break;
692 }
693 }
694 }
695
696 if (!found)
697 fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n", pls.name.c_str());
698 }
699
700 return ret;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100701}
702
703static PlsFormat pls_format(const char *str)
704{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200705 if (!strcmp(str, "r11f_g11f_b10f"))
706 return PlsR11FG11FB10F;
707 else if (!strcmp(str, "r32f"))
708 return PlsR32F;
709 else if (!strcmp(str, "rg16f"))
710 return PlsRG16F;
711 else if (!strcmp(str, "rg16"))
712 return PlsRG16;
713 else if (!strcmp(str, "rgb10_a2"))
714 return PlsRGB10A2;
715 else if (!strcmp(str, "rgba8"))
716 return PlsRGBA8;
717 else if (!strcmp(str, "rgba8i"))
718 return PlsRGBA8I;
719 else if (!strcmp(str, "rgba8ui"))
720 return PlsRGBA8UI;
721 else if (!strcmp(str, "rg16i"))
722 return PlsRG16I;
723 else if (!strcmp(str, "rgb10_a2ui"))
724 return PlsRGB10A2UI;
725 else if (!strcmp(str, "rg16ui"))
726 return PlsRG16UI;
727 else if (!strcmp(str, "r32ui"))
728 return PlsR32UI;
729 else
730 return PlsNone;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100731}
732
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100733static ExecutionModel stage_to_execution_model(const std::string &stage)
734{
735 if (stage == "vert")
736 return ExecutionModelVertex;
737 else if (stage == "frag")
738 return ExecutionModelFragment;
739 else if (stage == "comp")
740 return ExecutionModelGLCompute;
741 else if (stage == "tesc")
742 return ExecutionModelTessellationControl;
743 else if (stage == "tese")
744 return ExecutionModelTessellationEvaluation;
745 else if (stage == "geom")
746 return ExecutionModelGeometry;
747 else
748 SPIRV_CROSS_THROW("Invalid stage.");
749}
750
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100751static HLSLBindingFlags hlsl_resource_type_to_flag(const std::string &arg)
752{
753 if (arg == "push")
754 return HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT;
755 else if (arg == "cbv")
756 return HLSL_BINDING_AUTO_CBV_BIT;
757 else if (arg == "srv")
758 return HLSL_BINDING_AUTO_SRV_BIT;
759 else if (arg == "uav")
760 return HLSL_BINDING_AUTO_UAV_BIT;
761 else if (arg == "sampler")
762 return HLSL_BINDING_AUTO_SAMPLER_BIT;
763 else if (arg == "all")
764 return HLSL_BINDING_AUTO_ALL;
765 else
766 {
767 fprintf(stderr, "Invalid resource type for --hlsl-auto-binding: %s\n", arg.c_str());
768 return 0;
769 }
770}
771
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200772static string compile_iteration(const CLIArguments &args, std::vector<uint32_t> spirv_file)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200773{
774 Parser spirv_parser(move(spirv_file));
775 spirv_parser.parse();
776
777 unique_ptr<CompilerGLSL> compiler;
778 bool combined_image_samplers = false;
779 bool build_dummy_sampler = false;
780
781 if (args.cpp)
782 {
783 compiler.reset(new CompilerCPP(move(spirv_parser.get_parsed_ir())));
784 if (args.cpp_interface_name)
785 static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name);
786 }
787 else if (args.msl)
788 {
789 compiler.reset(new CompilerMSL(move(spirv_parser.get_parsed_ir())));
790
791 auto *msl_comp = static_cast<CompilerMSL *>(compiler.get());
792 auto msl_opts = msl_comp->get_msl_options();
793 if (args.set_msl_version)
794 msl_opts.msl_version = args.msl_version;
795 msl_opts.capture_output_to_buffer = args.msl_capture_output_to_buffer;
796 msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
Lukas Hermannsffbd8012019-10-09 11:22:25 -0400797 msl_opts.invariant_float_math = args.msl_invariant_float_math;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200798 if (args.msl_ios)
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400799 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200800 msl_opts.platform = CompilerMSL::Options::iOS;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400801 msl_opts.ios_use_framebuffer_fetch_subpasses = args.msl_framebuffer_fetch;
802 msl_opts.emulate_cube_array = args.msl_emulate_cube_array;
803 }
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200804 msl_opts.pad_fragment_output_components = args.msl_pad_fragment_output;
805 msl_opts.tess_domain_origin_lower_left = args.msl_domain_lower_left;
806 msl_opts.argument_buffers = args.msl_argument_buffers;
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +0200807 msl_opts.texture_buffer_native = args.msl_texture_buffer_native;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500808 msl_opts.multiview = args.msl_multiview;
Chip Davis6a585542019-07-12 21:50:50 -0500809 msl_opts.view_index_from_device_index = args.msl_view_index_from_device_index;
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500810 msl_opts.dispatch_base = args.msl_dispatch_base;
Akio Gaule1280df62019-11-27 01:02:46 -0800811 msl_opts.enable_decoration_binding = args.msl_decoration_binding;
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +0100812 msl_opts.force_active_argument_buffer_resources = args.msl_force_active_argument_buffer_resources;
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +0100813 msl_opts.force_native_arrays = args.msl_force_native_arrays;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200814 msl_comp->set_msl_options(msl_opts);
815 for (auto &v : args.msl_discrete_descriptor_sets)
816 msl_comp->add_discrete_descriptor_set(v);
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +0200817 for (auto &v : args.msl_device_argument_buffers)
818 msl_comp->set_argument_buffer_device_address_space(v, true);
Chip Daviscb359342019-09-05 23:14:12 -0500819 uint32_t i = 0;
820 for (auto &v : args.msl_dynamic_buffers)
821 msl_comp->add_dynamic_buffer(v.first, v.second, i++);
Chip Davisfedbc352019-12-16 22:58:16 -0600822 for (auto &v : args.msl_inline_uniform_blocks)
823 msl_comp->add_inline_uniform_block(v.first, v.second);
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200824 }
825 else if (args.hlsl)
826 compiler.reset(new CompilerHLSL(move(spirv_parser.get_parsed_ir())));
827 else
828 {
829 combined_image_samplers = !args.vulkan_semantics;
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +0200830 if (!args.vulkan_semantics || args.vulkan_glsl_disable_ext_samplerless_texture_functions)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200831 build_dummy_sampler = true;
832 compiler.reset(new CompilerGLSL(move(spirv_parser.get_parsed_ir())));
833 }
834
835 if (!args.variable_type_remaps.empty())
836 {
837 auto remap_cb = [&](const SPIRType &, const string &name, string &out) -> void {
838 for (const VariableTypeRemap &remap : args.variable_type_remaps)
839 if (name == remap.variable_name)
840 out = remap.new_variable_type;
841 };
842
843 compiler->set_variable_type_remap_callback(move(remap_cb));
844 }
845
846 for (auto &rename : args.entry_point_rename)
847 compiler->rename_entry_point(rename.old_name, rename.new_name, rename.execution_model);
848
849 auto entry_points = compiler->get_entry_points_and_stages();
850 auto entry_point = args.entry;
851 ExecutionModel model = ExecutionModelMax;
852
853 if (!args.entry_stage.empty())
854 {
855 model = stage_to_execution_model(args.entry_stage);
856 if (entry_point.empty())
857 {
858 // Just use the first entry point with this stage.
859 for (auto &e : entry_points)
860 {
861 if (e.execution_model == model)
862 {
863 entry_point = e.name;
864 break;
865 }
866 }
867
868 if (entry_point.empty())
869 {
870 fprintf(stderr, "Could not find an entry point with stage: %s\n", args.entry_stage.c_str());
871 exit(EXIT_FAILURE);
872 }
873 }
874 else
875 {
876 // Make sure both stage and name exists.
877 bool exists = false;
878 for (auto &e : entry_points)
879 {
880 if (e.execution_model == model && e.name == entry_point)
881 {
882 exists = true;
883 break;
884 }
885 }
886
887 if (!exists)
888 {
889 fprintf(stderr, "Could not find an entry point %s with stage: %s\n", entry_point.c_str(),
890 args.entry_stage.c_str());
891 exit(EXIT_FAILURE);
892 }
893 }
894 }
895 else if (!entry_point.empty())
896 {
897 // Make sure there is just one entry point with this name, or the stage
898 // is ambiguous.
899 uint32_t stage_count = 0;
900 for (auto &e : entry_points)
901 {
902 if (e.name == entry_point)
903 {
904 stage_count++;
905 model = e.execution_model;
906 }
907 }
908
909 if (stage_count == 0)
910 {
911 fprintf(stderr, "There is no entry point with name: %s\n", entry_point.c_str());
912 exit(EXIT_FAILURE);
913 }
914 else if (stage_count > 1)
915 {
916 fprintf(stderr, "There is more than one entry point with name: %s. Use --stage.\n", entry_point.c_str());
917 exit(EXIT_FAILURE);
918 }
919 }
920
921 if (!entry_point.empty())
922 compiler->set_entry_point(entry_point, model);
923
924 if (!args.set_version && !compiler->get_common_options().version)
925 {
926 fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
927 print_help();
928 exit(EXIT_FAILURE);
929 }
930
931 CompilerGLSL::Options opts = compiler->get_common_options();
932 if (args.set_version)
933 opts.version = args.version;
934 if (args.set_es)
935 opts.es = args.es;
936 opts.force_temporary = args.force_temporary;
937 opts.separate_shader_objects = args.sso;
938 opts.flatten_multidimensional_arrays = args.flatten_multidimensional_arrays;
939 opts.enable_420pack_extension = args.use_420pack_extension;
940 opts.vulkan_semantics = args.vulkan_semantics;
941 opts.vertex.fixup_clipspace = args.fixup;
942 opts.vertex.flip_vert_y = args.yflip;
943 opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
944 opts.emit_push_constant_as_uniform_buffer = args.glsl_emit_push_constant_as_ubo;
Laszlo Agocs7bc31492019-05-11 16:30:33 +0200945 opts.emit_uniform_buffer_as_plain_uniforms = args.glsl_emit_ubo_as_plain_uniforms;
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +0200946 opts.emit_line_directives = args.emit_line_directives;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200947 compiler->set_common_options(opts);
948
949 // Set HLSL specific options.
950 if (args.hlsl)
951 {
952 auto *hlsl = static_cast<CompilerHLSL *>(compiler.get());
953 auto hlsl_opts = hlsl->get_hlsl_options();
954 if (args.set_shader_model)
955 {
956 if (args.shader_model < 30)
957 {
958 fprintf(stderr, "Shader model earlier than 30 (3.0) not supported.\n");
959 exit(EXIT_FAILURE);
960 }
961
962 hlsl_opts.shader_model = args.shader_model;
963 }
964
965 if (args.hlsl_compat)
966 {
967 // Enable all compat options.
968 hlsl_opts.point_size_compat = true;
969 hlsl_opts.point_coord_compat = true;
970 }
971
972 if (hlsl_opts.shader_model <= 30)
973 {
974 combined_image_samplers = true;
975 build_dummy_sampler = true;
976 }
977
978 hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +0100979 hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200980 hlsl->set_hlsl_options(hlsl_opts);
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100981 hlsl->set_resource_binding_flags(args.hlsl_binding_flags);
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200982 }
983
984 if (build_dummy_sampler)
985 {
986 uint32_t sampler = compiler->build_dummy_sampler_for_combined_images();
987 if (sampler != 0)
988 {
989 // Set some defaults to make validation happy.
990 compiler->set_decoration(sampler, DecorationDescriptorSet, 0);
991 compiler->set_decoration(sampler, DecorationBinding, 0);
992 }
993 }
994
995 ShaderResources res;
996 if (args.remove_unused)
997 {
998 auto active = compiler->get_active_interface_variables();
999 res = compiler->get_shader_resources(active);
1000 compiler->set_enabled_interface_variables(move(active));
1001 }
1002 else
1003 res = compiler->get_shader_resources();
1004
1005 if (args.flatten_ubo)
1006 {
1007 for (auto &ubo : res.uniform_buffers)
1008 compiler->flatten_buffer_block(ubo.id);
1009 for (auto &ubo : res.push_constant_buffers)
1010 compiler->flatten_buffer_block(ubo.id);
1011 }
1012
1013 auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs);
1014 auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr);
1015 compiler->remap_pixel_local_storage(move(pls_inputs), move(pls_outputs));
1016
1017 for (auto &ext : args.extensions)
1018 compiler->require_extension(ext);
1019
1020 for (auto &remap : args.remaps)
1021 {
1022 if (remap_generic(*compiler, res.stage_inputs, remap))
1023 continue;
1024 if (remap_generic(*compiler, res.stage_outputs, remap))
1025 continue;
1026 if (remap_generic(*compiler, res.subpass_inputs, remap))
1027 continue;
1028 }
1029
1030 for (auto &rename : args.interface_variable_renames)
1031 {
1032 if (rename.storageClass == StorageClassInput)
1033 spirv_cross_util::rename_interface_variable(*compiler, res.stage_inputs, rename.location,
1034 rename.variable_name);
1035 else if (rename.storageClass == StorageClassOutput)
1036 spirv_cross_util::rename_interface_variable(*compiler, res.stage_outputs, rename.location,
1037 rename.variable_name);
1038 else
1039 {
1040 fprintf(stderr, "error at --rename-interface-variable <in|out> ...\n");
1041 exit(EXIT_FAILURE);
1042 }
1043 }
1044
1045 if (args.dump_resources)
1046 {
1047 print_resources(*compiler, res);
1048 print_push_constant_resources(*compiler, res.push_constant_buffers);
1049 print_spec_constants(*compiler);
1050 print_capabilities_and_extensions(*compiler);
1051 }
1052
1053 if (combined_image_samplers)
1054 {
1055 compiler->build_combined_image_samplers();
1056 if (args.combined_samplers_inherit_bindings)
1057 spirv_cross_util::inherit_combined_sampler_bindings(*compiler);
1058
1059 // Give the remapped combined samplers new names.
1060 for (auto &remap : compiler->get_combined_image_samplers())
1061 {
1062 compiler->set_name(remap.combined_id, join("SPIRV_Cross_Combined", compiler->get_name(remap.image_id),
1063 compiler->get_name(remap.sampler_id)));
1064 }
1065 }
1066
1067 if (args.hlsl)
1068 {
1069 auto *hlsl_compiler = static_cast<CompilerHLSL *>(compiler.get());
1070 uint32_t new_builtin = hlsl_compiler->remap_num_workgroups_builtin();
1071 if (new_builtin)
1072 {
1073 hlsl_compiler->set_decoration(new_builtin, DecorationDescriptorSet, 0);
1074 hlsl_compiler->set_decoration(new_builtin, DecorationBinding, 0);
1075 }
1076 }
1077
1078 if (args.hlsl)
1079 {
1080 for (auto &remap : args.hlsl_attr_remap)
1081 static_cast<CompilerHLSL *>(compiler.get())->add_vertex_attribute_remap(remap);
1082 }
1083
1084 return compiler->compile();
1085}
1086
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +02001087static int main_inner(int argc, char *argv[])
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001088{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001089 CLIArguments args;
1090 CLICallbacks cbs;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001091
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001092 cbs.add("--help", [](CLIParser &parser) {
1093 print_help();
1094 parser.end();
1095 });
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +02001096 cbs.add("--revision", [](CLIParser &parser) {
1097 print_version();
1098 parser.end();
1099 });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001100 cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); });
1101 cbs.add("--es", [&args](CLIParser &) {
1102 args.es = true;
1103 args.set_es = true;
1104 });
1105 cbs.add("--no-es", [&args](CLIParser &) {
1106 args.es = false;
1107 args.set_es = true;
1108 });
1109 cbs.add("--version", [&args](CLIParser &parser) {
1110 args.version = parser.next_uint();
1111 args.set_version = true;
1112 });
1113 cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; });
1114 cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; });
1115 cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; });
1116 cbs.add("--fixup-clipspace", [&args](CLIParser &) { args.fixup = true; });
Hans-Kristian Arntzenbdfa97a2017-08-03 13:02:59 +02001117 cbs.add("--flip-vert-y", [&args](CLIParser &) { args.yflip = true; });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001118 cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
1119 cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
Brad Davis0ad0f942018-06-21 07:43:52 -07001120 cbs.add("--reflect", [&args](CLIParser &parser) { args.reflect = parser.next_value_string("json"); });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001121 cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
Bill Hollings5ad73f32017-03-19 21:06:21 -04001122 cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +01001123 cbs.add("--glsl-emit-push-constant-as-ubo", [&args](CLIParser &) { args.glsl_emit_push_constant_as_ubo = true; });
Laszlo Agocs7bc31492019-05-11 16:30:33 +02001124 cbs.add("--glsl-emit-ubo-as-plain-uniforms", [&args](CLIParser &) { args.glsl_emit_ubo_as_plain_uniforms = true; });
Hans-Kristian Arntzenb97e9b02019-08-01 09:51:44 +02001125 cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions",
1126 [&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
Bill Hollings5ad73f32017-03-19 21:06:21 -04001127 cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
Robert Konrad216a6812017-01-25 17:30:52 +01001128 cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
Hans-Kristian Arntzen17d88ca2017-05-04 10:10:30 +02001129 cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
Hans-Kristian Arntzen6e1c3cc2019-01-11 12:56:00 +01001130 cbs.add("--hlsl-support-nonzero-basevertex-baseinstance",
1131 [&args](CLIParser &) { args.hlsl_support_nonzero_base = true; });
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +01001132 cbs.add("--hlsl-auto-binding", [&args](CLIParser &parser) {
1133 args.hlsl_binding_flags |= hlsl_resource_type_to_flag(parser.next_string());
1134 });
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +01001135 cbs.add("--hlsl-force-storage-buffer-as-uav", [&args](CLIParser &) {
1136 args.hlsl_force_storage_buffer_as_uav = true;
1137 });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001138 cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
Hans-Kristian Arntzen3f2de0d2020-03-02 11:55:57 +01001139 cbs.add("-V", [&args](CLIParser &) { args.vulkan_semantics = true; });
Hans-Kristian Arntzen470ae7a2017-05-22 17:40:00 +02001140 cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
Hans-Kristian Arntzen6599a412017-09-08 09:56:06 +02001141 cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
Chip Davisc51e5b72019-01-08 16:33:32 -06001142 cbs.add("--msl-capture-output", [&args](CLIParser &) { args.msl_capture_output_to_buffer = true; });
Chip Davis25833212018-09-19 20:36:33 -05001143 cbs.add("--msl-swizzle-texture-samples", [&args](CLIParser &) { args.msl_swizzle_texture_samples = true; });
Chip Davis3a9af962018-09-26 20:06:05 -05001144 cbs.add("--msl-ios", [&args](CLIParser &) { args.msl_ios = true; });
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +01001145 cbs.add("--msl-pad-fragment-output", [&args](CLIParser &) { args.msl_pad_fragment_output = true; });
Chip Davis41d94242019-02-05 23:47:50 -06001146 cbs.add("--msl-domain-lower-left", [&args](CLIParser &) { args.msl_domain_lower_left = true; });
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +01001147 cbs.add("--msl-argument-buffers", [&args](CLIParser &) { args.msl_argument_buffers = true; });
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +01001148 cbs.add("--msl-discrete-descriptor-set",
1149 [&args](CLIParser &parser) { args.msl_discrete_descriptor_sets.push_back(parser.next_uint()); });
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +02001150 cbs.add("--msl-device-argument-buffer",
1151 [&args](CLIParser &parser) { args.msl_device_argument_buffers.push_back(parser.next_uint()); });
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +02001152 cbs.add("--msl-texture-buffer-native", [&args](CLIParser &) { args.msl_texture_buffer_native = true; });
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001153 cbs.add("--msl-framebuffer-fetch", [&args](CLIParser &) { args.msl_framebuffer_fetch = true; });
Lukas Hermannsffbd8012019-10-09 11:22:25 -04001154 cbs.add("--msl-invariant-float-math", [&args](CLIParser &) { args.msl_invariant_float_math = true; });
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001155 cbs.add("--msl-emulate-cube-array", [&args](CLIParser &) { args.msl_emulate_cube_array = true; });
Chip Davis7eecf5a2019-05-31 12:06:20 -05001156 cbs.add("--msl-multiview", [&args](CLIParser &) { args.msl_multiview = true; });
Chip Davis6a585542019-07-12 21:50:50 -05001157 cbs.add("--msl-view-index-from-device-index",
1158 [&args](CLIParser &) { args.msl_view_index_from_device_index = true; });
Chip Davisfb5ee4c2019-07-22 13:08:04 -05001159 cbs.add("--msl-dispatch-base", [&args](CLIParser &) { args.msl_dispatch_base = true; });
Chip Daviscb359342019-09-05 23:14:12 -05001160 cbs.add("--msl-dynamic-buffer", [&args](CLIParser &parser) {
1161 args.msl_argument_buffers = true;
Hans-Kristian Arntzenafa54802019-09-06 10:17:31 +02001162 // Make sure next_uint() is called in-order.
Hans-Kristian Arntzen1935f1a2019-09-06 10:11:18 +02001163 uint32_t desc_set = parser.next_uint();
1164 uint32_t binding = parser.next_uint();
1165 args.msl_dynamic_buffers.push_back(make_pair(desc_set, binding));
Chip Daviscb359342019-09-05 23:14:12 -05001166 });
Akio Gaule1280df62019-11-27 01:02:46 -08001167 cbs.add("--msl-decoration-binding", [&args](CLIParser &) { args.msl_decoration_binding = true; });
Hans-Kristian Arntzen7a411252020-01-16 15:20:59 +01001168 cbs.add("--msl-force-active-argument-buffer-resources",
1169 [&args](CLIParser &) { args.msl_force_active_argument_buffer_resources = true; });
Chip Davisfedbc352019-12-16 22:58:16 -06001170 cbs.add("--msl-inline-uniform-block", [&args](CLIParser &parser) {
1171 args.msl_argument_buffers = true;
1172 // Make sure next_uint() is called in-order.
1173 uint32_t desc_set = parser.next_uint();
1174 uint32_t binding = parser.next_uint();
1175 args.msl_inline_uniform_blocks.push_back(make_pair(desc_set, binding));
1176 });
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +01001177 cbs.add("--msl-force-native-arrays", [&args](CLIParser &) {
1178 args.msl_force_native_arrays = true;
1179 });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001180 cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +01001181 cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
1182 auto old_name = parser.next_string();
1183 auto new_name = parser.next_string();
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001184 auto model = stage_to_execution_model(parser.next_string());
1185 args.entry_point_rename.push_back({ old_name, new_name, move(model) });
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +01001186 });
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +02001187 cbs.add("--entry", [&args](CLIParser &parser) { args.entry = parser.next_string(); });
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001188 cbs.add("--stage", [&args](CLIParser &parser) { args.entry_stage = parser.next_string(); });
Hans-Kristian Arntzen36650c82017-05-22 15:30:43 +02001189 cbs.add("--separate-shader-objects", [&args](CLIParser &) { args.sso = true; });
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001190 cbs.add("--set-hlsl-vertex-input-semantic", [&args](CLIParser &parser) {
1191 HLSLVertexAttributeRemap remap;
1192 remap.location = parser.next_uint();
1193 remap.semantic = parser.next_string();
1194 args.hlsl_attr_remap.push_back(move(remap));
1195 });
1196
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001197 cbs.add("--remap", [&args](CLIParser &parser) {
Hans-Kristian Arntzenf4861422017-11-13 09:52:35 +01001198 string src = parser.next_string();
1199 string dst = parser.next_string();
1200 uint32_t components = parser.next_uint();
1201 args.remaps.push_back({ move(src), move(dst), components });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001202 });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001203
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +02001204 cbs.add("--remap-variable-type", [&args](CLIParser &parser) {
1205 string var_name = parser.next_string();
1206 string new_type = parser.next_string();
1207 args.variable_type_remaps.push_back({ move(var_name), move(new_type) });
1208 });
1209
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001210 cbs.add("--rename-interface-variable", [&args](CLIParser &parser) {
Jason Chan3281e822017-06-25 15:16:09 +02001211 StorageClass cls = StorageClassMax;
1212 string clsStr = parser.next_string();
1213 if (clsStr == "in")
1214 cls = StorageClassInput;
1215 else if (clsStr == "out")
1216 cls = StorageClassOutput;
1217
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001218 uint32_t loc = parser.next_uint();
1219 string var_name = parser.next_string();
Jason Chan3281e822017-06-25 15:16:09 +02001220 args.interface_variable_renames.push_back({ cls, loc, move(var_name) });
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001221 });
1222
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001223 cbs.add("--pls-in", [&args](CLIParser &parser) {
1224 auto fmt = pls_format(parser.next_string());
1225 auto name = parser.next_string();
1226 args.pls_in.push_back({ move(fmt), move(name) });
1227 });
1228 cbs.add("--pls-out", [&args](CLIParser &parser) {
1229 auto fmt = pls_format(parser.next_string());
1230 auto name = parser.next_string();
1231 args.pls_out.push_back({ move(fmt), move(name) });
1232 });
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +01001233 cbs.add("--shader-model", [&args](CLIParser &parser) {
1234 args.shader_model = parser.next_uint();
1235 args.set_shader_model = true;
1236 });
Bill Hollingsbac657d2017-11-07 15:38:13 -05001237 cbs.add("--msl-version", [&args](CLIParser &parser) {
1238 args.msl_version = parser.next_uint();
1239 args.set_msl_version = true;
1240 });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001241
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +02001242 cbs.add("--remove-unused-variables", [&args](CLIParser &) { args.remove_unused = true; });
Hans-Kristian Arntzena1b39642018-05-25 10:14:13 +02001243 cbs.add("--combined-samplers-inherit-bindings",
1244 [&args](CLIParser &) { args.combined_samplers_inherit_bindings = true; });
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +02001245
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +02001246 cbs.add("--no-support-nonzero-baseinstance", [&](CLIParser &) { args.support_nonzero_baseinstance = false; });
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +02001247 cbs.add("--emit-line-directives", [&args](CLIParser &) { args.emit_line_directives = true; });
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +02001248
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001249 cbs.default_handler = [&args](const char *value) { args.input = value; };
1250 cbs.error_handler = [] { print_help(); };
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001251
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001252 CLIParser parser{ move(cbs), argc - 1, argv + 1 };
1253 if (!parser.parse())
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001254 return EXIT_FAILURE;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001255 else if (parser.ended_state)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001256 return EXIT_SUCCESS;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001257
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001258 if (!args.input)
1259 {
1260 fprintf(stderr, "Didn't specify input file.\n");
1261 print_help();
1262 return EXIT_FAILURE;
1263 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001264
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001265 auto spirv_file = read_spirv_file(args.input);
1266 if (spirv_file.empty())
1267 return EXIT_FAILURE;
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001268
Brad Davis6c88b002018-06-18 09:30:16 -07001269 // Special case reflection because it has little to do with the path followed by code-outputting compilers
1270 if (!args.reflect.empty())
1271 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001272 Parser spirv_parser(move(spirv_file));
1273 spirv_parser.parse();
1274
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001275 CompilerReflection compiler(move(spirv_parser.get_parsed_ir()));
Brad Davis6c88b002018-06-18 09:30:16 -07001276 compiler.set_format(args.reflect);
1277 auto json = compiler.compile();
1278 if (args.output)
1279 write_string_to_file(args.output, json.c_str());
1280 else
1281 printf("%s", json.c_str());
1282 return EXIT_SUCCESS;
1283 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001284
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001285 string compiled_output;
Hans-Kristian Arntzenbcb55602016-09-10 13:56:36 +02001286
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001287 if (args.iterations == 1)
1288 compiled_output = compile_iteration(args, move(spirv_file));
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001289 else
Hans-Kristian Arntzenbcb55602016-09-10 13:56:36 +02001290 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001291 for (unsigned i = 0; i < args.iterations; i++)
1292 compiled_output = compile_iteration(args, spirv_file);
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001293 }
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001294
1295 if (args.output)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001296 write_string_to_file(args.output, compiled_output.c_str());
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001297 else
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001298 printf("%s", compiled_output.c_str());
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +02001299
1300 return EXIT_SUCCESS;
1301}
1302
1303int main(int argc, char *argv[])
1304{
1305#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
1306 return main_inner(argc, argv);
1307#else
1308 // Make sure we catch the exception or it just disappears into the aether on Windows.
1309 try
1310 {
1311 return main_inner(argc, argv);
1312 }
1313 catch (const std::exception &e)
1314 {
1315 fprintf(stderr, "SPIRV-Cross threw an exception: %s\n", e.what());
1316 return EXIT_FAILURE;
1317 }
1318#endif
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001319}