blob: e83284a03b7cae724185d2f7b500dbf20bfdcf18 [file] [log] [blame]
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001/*
Hans-Kristian Arntzen47044822021-01-14 16:07:49 +01002 * Copyright 2015-2021 Arm Limited
Jon Leechf2a65542021-05-08 01:47:48 -07003 * SPDX-License-Identifier: Apache-2.0 OR MIT
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Hans-Kristian Arntzencf1e9e02020-11-25 15:22:08 +010018/*
19 * At your option, you may choose to accept this material under either:
20 * 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
21 * 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
Hans-Kristian Arntzencf1e9e02020-11-25 15:22:08 +010022 */
23
Hans-Kristian Arntzen147e53a2016-04-04 09:36:04 +020024#include "spirv_cpp.hpp"
grovesNL94cd7772018-03-01 23:47:08 -070025#include "spirv_cross_util.hpp"
Bill Hollings77f58122017-08-11 14:54:58 -040026#include "spirv_glsl.hpp"
Robert Konrad216a6812017-01-25 17:30:52 +010027#include "spirv_hlsl.hpp"
Hans-Kristian Arntzen24df8f02017-02-04 10:26:26 +010028#include "spirv_msl.hpp"
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +020029#include "spirv_parser.hpp"
Brad Davis709d3c62018-06-03 11:16:37 -070030#include "spirv_reflect.hpp"
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020031#include <algorithm>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010032#include <cstdio>
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020033#include <cstring>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010034#include <functional>
35#include <limits>
36#include <memory>
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020037#include <stdexcept>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010038#include <unordered_map>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010039#include <unordered_set>
40
Hans-Kristian Arntzen02b7f9c2021-01-06 11:06:41 +010041#ifdef _WIN32
42#include <io.h>
43#include <fcntl.h>
44#endif
45
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +020046#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
47#include "gitversion.h"
48#endif
49
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010050using namespace spv;
Hans-Kristian Arntzen9b92e682019-03-29 10:29:44 +010051using namespace SPIRV_CROSS_NAMESPACE;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010052using namespace std;
53
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010054#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +020055static inline void THROW(const char *str)
56{
57 fprintf(stderr, "SPIRV-Cross will abort: %s\n", str);
58 fflush(stderr);
59 abort();
60}
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010061#else
Hans-Kristian Arntzenc92b8392017-02-16 11:06:57 +010062#define THROW(x) throw runtime_error(x)
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010063#endif
64
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010065struct CLIParser;
66struct CLICallbacks
67{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020068 void add(const char *cli, const function<void(CLIParser &)> &func)
69 {
70 callbacks[cli] = func;
71 }
72 unordered_map<string, function<void(CLIParser &)>> callbacks;
73 function<void()> error_handler;
74 function<void(const char *)> default_handler;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010075};
76
77struct CLIParser
78{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020079 CLIParser(CLICallbacks cbs_, int argc_, char *argv_[])
Daniel Thornburgh44c33332022-03-02 23:02:38 +000080 : cbs(std::move(cbs_))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020081 , argc(argc_)
82 , argv(argv_)
83 {
84 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010085
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020086 bool parse()
87 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010088#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020089 try
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010090#endif
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020091 {
92 while (argc && !ended_state)
93 {
94 const char *next = *argv++;
95 argc--;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010096
Hans-Kristian Arntzence18d1b2021-01-08 10:47:46 +010097 if (*next != '-' && cbs.default_handler)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020098 {
99 cbs.default_handler(next);
100 }
101 else
102 {
103 auto itr = cbs.callbacks.find(next);
104 if (itr == ::end(cbs.callbacks))
105 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100106 THROW("Invalid argument");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200107 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100108
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200109 itr->second(*this);
110 }
111 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100112
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200113 return true;
114 }
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100115#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200116 catch (...)
117 {
118 if (cbs.error_handler)
119 {
120 cbs.error_handler();
121 }
122 return false;
123 }
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100124#endif
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200125 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100126
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200127 void end()
128 {
129 ended_state = true;
130 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100131
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200132 uint32_t next_uint()
133 {
134 if (!argc)
135 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100136 THROW("Tried to parse uint, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200137 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100138
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200139 uint64_t val = stoul(*argv);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200140 if (val > numeric_limits<uint32_t>::max())
141 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100142 THROW("next_uint() out of range");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200143 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100144
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200145 argc--;
146 argv++;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100147
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200148 return uint32_t(val);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200149 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100150
Chip Davisb29f83c2020-04-10 01:13:33 -0500151 uint32_t next_hex_uint()
152 {
153 if (!argc)
154 {
155 THROW("Tried to parse uint, but nothing left in arguments");
156 }
157
158 uint64_t val = stoul(*argv, nullptr, 16);
159 if (val > numeric_limits<uint32_t>::max())
160 {
161 THROW("next_uint() out of range");
162 }
163
164 argc--;
165 argv++;
166
167 return uint32_t(val);
168 }
169
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200170 double next_double()
171 {
172 if (!argc)
173 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100174 THROW("Tried to parse double, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200175 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100176
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200177 double val = stod(*argv);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100178
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200179 argc--;
180 argv++;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100181
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200182 return val;
183 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100184
Brad Davis709d3c62018-06-03 11:16:37 -0700185 // Return a string only if it's not prefixed with `--`, otherwise return the default value
Brad Davis76204002018-06-20 10:25:38 -0700186 const char *next_value_string(const char *default_value)
Brad Davis709d3c62018-06-03 11:16:37 -0700187 {
188 if (!argc)
189 {
Brad Davis76204002018-06-20 10:25:38 -0700190 return default_value;
Brad Davis709d3c62018-06-03 11:16:37 -0700191 }
192
193 if (0 == strncmp("--", *argv, 2))
194 {
Brad Davis76204002018-06-20 10:25:38 -0700195 return default_value;
Brad Davis709d3c62018-06-03 11:16:37 -0700196 }
197
198 return next_string();
199 }
200
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200201 const char *next_string()
202 {
203 if (!argc)
204 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100205 THROW("Tried to parse string, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200206 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100207
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200208 const char *ret = *argv;
209 argc--;
210 argv++;
211 return ret;
212 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100213
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200214 CLICallbacks cbs;
215 int argc;
216 char **argv;
217 bool ended_state = false;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100218};
219
Hanno4560ee22020-04-09 17:30:20 +0200220#if defined(__clang__) || defined(__GNUC__)
221#pragma GCC diagnostic push
222#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
223#elif defined(_MSC_VER)
224#pragma warning(push)
225#pragma warning(disable : 4996)
226#endif
227
Hans-Kristian Arntzen02b7f9c2021-01-06 11:06:41 +0100228static vector<uint32_t> read_spirv_file_stdin()
229{
230#ifdef _WIN32
231 setmode(fileno(stdin), O_BINARY);
232#endif
233
234 vector<uint32_t> buffer;
235 uint32_t tmp[256];
236 size_t ret;
237
238 while ((ret = fread(tmp, sizeof(uint32_t), 256, stdin)))
239 buffer.insert(buffer.end(), tmp, tmp + ret);
240
241 return buffer;
242}
243
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200244static vector<uint32_t> read_spirv_file(const char *path)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100245{
Hans-Kristian Arntzen02b7f9c2021-01-06 11:06:41 +0100246 if (path[0] == '-' && path[1] == '\0')
247 return read_spirv_file_stdin();
248
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200249 FILE *file = fopen(path, "rb");
250 if (!file)
251 {
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +0200252 fprintf(stderr, "Failed to open SPIR-V file: %s\n", path);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200253 return {};
254 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100255
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200256 fseek(file, 0, SEEK_END);
257 long len = ftell(file) / sizeof(uint32_t);
258 rewind(file);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100259
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200260 vector<uint32_t> spirv(len);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200261 if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
262 spirv.clear();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100263
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200264 fclose(file);
265 return spirv;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100266}
267
268static bool write_string_to_file(const char *path, const char *string)
269{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200270 FILE *file = fopen(path, "w");
271 if (!file)
272 {
hesiodba381582017-05-30 17:17:51 +0300273 fprintf(stderr, "Failed to write file: %s\n", path);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200274 return false;
275 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100276
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200277 fprintf(file, "%s", string);
278 fclose(file);
279 return true;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100280}
281
Hanno4560ee22020-04-09 17:30:20 +0200282#if defined(__clang__) || defined(__GNUC__)
283#pragma GCC diagnostic pop
284#elif defined(_MSC_VER)
285#pragma warning(pop)
286#endif
287
Hans-Kristian Arntzenb4a380a2021-04-16 13:32:37 +0200288static void print_resources(const Compiler &compiler, spv::StorageClass storage,
289 const SmallVector<BuiltInResource> &resources)
290{
291 fprintf(stderr, "%s\n", storage == StorageClassInput ? "builtin inputs" : "builtin outputs");
292 fprintf(stderr, "=============\n\n");
293 for (auto &res : resources)
294 {
295 bool active = compiler.has_active_builtin(res.builtin, storage);
296 const char *basetype = "?";
297 auto &type = compiler.get_type(res.value_type_id);
298 switch (type.basetype)
299 {
300 case SPIRType::Float: basetype = "float"; break;
301 case SPIRType::Int: basetype = "int"; break;
302 case SPIRType::UInt: basetype = "uint"; break;
303 default: break;
304 }
305
306 uint32_t array_size = 0;
307 bool array_size_literal = false;
308 if (!type.array.empty())
309 {
310 array_size = type.array.front();
311 array_size_literal = type.array_size_literal.front();
312 }
313
314 string type_str = basetype;
315 if (type.vecsize > 1)
316 type_str += std::to_string(type.vecsize);
317
318 if (array_size)
319 {
320 if (array_size_literal)
321 type_str += join("[", array_size, "]");
322 else
323 type_str += join("[", array_size, " (spec constant ID)]");
324 }
325
326 string builtin_str;
327 switch (res.builtin)
328 {
329 case spv::BuiltInPosition: builtin_str = "Position"; break;
330 case spv::BuiltInPointSize: builtin_str = "PointSize"; break;
331 case spv::BuiltInCullDistance: builtin_str = "CullDistance"; break;
332 case spv::BuiltInClipDistance: builtin_str = "ClipDistance"; break;
333 case spv::BuiltInTessLevelInner: builtin_str = "TessLevelInner"; break;
334 case spv::BuiltInTessLevelOuter: builtin_str = "TessLevelOuter"; break;
335 default: builtin_str = string("builtin #") + to_string(res.builtin);
336 }
337
338 fprintf(stderr, "Builtin %s (%s) (active: %s).\n", builtin_str.c_str(), type_str.c_str(), active ? "yes" : "no");
339 }
340 fprintf(stderr, "=============\n\n");
341}
342
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200343static void print_resources(const Compiler &compiler, const char *tag, const SmallVector<Resource> &resources)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100344{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200345 fprintf(stderr, "%s\n", tag);
346 fprintf(stderr, "=============\n\n");
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200347 bool print_ssbo = !strcmp(tag, "ssbos");
348
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200349 for (auto &res : resources)
350 {
351 auto &type = compiler.get_type(res.type_id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100352
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200353 if (print_ssbo && compiler.buffer_is_hlsl_counter_buffer(res.id))
354 continue;
355
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200356 // If we don't have a name, use the fallback for the type instead of the variable
357 // for SSBOs and UBOs since those are the only meaningful names to use externally.
358 // Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
359 bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100360 bool is_block = compiler.get_decoration_bitset(type.self).get(DecorationBlock) ||
361 compiler.get_decoration_bitset(type.self).get(DecorationBufferBlock);
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100362 bool is_sized_block = is_block && (compiler.get_storage_class(res.id) == StorageClassUniform ||
363 compiler.get_storage_class(res.id) == StorageClassUniformConstant);
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200364 ID fallback_id = !is_push_constant && is_block ? ID(res.base_type_id) : ID(res.id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100365
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100366 uint32_t block_size = 0;
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200367 uint32_t runtime_array_stride = 0;
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100368 if (is_sized_block)
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200369 {
370 auto &base_type = compiler.get_type(res.base_type_id);
371 block_size = uint32_t(compiler.get_declared_struct_size(base_type));
372 runtime_array_stride = uint32_t(compiler.get_declared_struct_size_runtime_array(base_type, 1) -
373 compiler.get_declared_struct_size_runtime_array(base_type, 0));
374 }
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100375
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200376 Bitset mask;
377 if (print_ssbo)
378 mask = compiler.get_buffer_block_flags(res.id);
379 else
380 mask = compiler.get_decoration_bitset(res.id);
381
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200382 string array;
383 for (auto arr : type.array)
384 array = join("[", arr ? convert_to_string(arr) : "", "]") + array;
385
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200386 fprintf(stderr, " ID %03u : %s%s", uint32_t(res.id),
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200387 !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 +0100388
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100389 if (mask.get(DecorationLocation))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200390 fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100391 if (mask.get(DecorationDescriptorSet))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200392 fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100393 if (mask.get(DecorationBinding))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200394 fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
Hans-Kristian Arntzen941ccee2020-04-03 12:26:42 +0200395 if (static_cast<const CompilerGLSL &>(compiler).variable_is_depth_or_compare(res.id))
396 fprintf(stderr, " (comparison)");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100397 if (mask.get(DecorationInputAttachmentIndex))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200398 fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100399 if (mask.get(DecorationNonReadable))
Hans-Kristian Arntzen97f7ab82017-01-05 18:16:33 +0100400 fprintf(stderr, " writeonly");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100401 if (mask.get(DecorationNonWritable))
Hans-Kristian Arntzen97f7ab82017-01-05 18:16:33 +0100402 fprintf(stderr, " readonly");
Stefan Lienhard05c9a142022-04-21 15:18:56 +0200403 if (mask.get(DecorationRestrict))
404 fprintf(stderr, " restrict");
405 if (mask.get(DecorationCoherent))
406 fprintf(stderr, " coherent");
407 if (mask.get(DecorationVolatile))
408 fprintf(stderr, " volatile");
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100409 if (is_sized_block)
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200410 {
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100411 fprintf(stderr, " (BlockSize : %u bytes)", block_size);
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200412 if (runtime_array_stride)
413 fprintf(stderr, " (Unsized array stride: %u bytes)", runtime_array_stride);
414 }
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200415
416 uint32_t counter_id = 0;
417 if (print_ssbo && compiler.buffer_get_hlsl_counter_buffer(res.id, counter_id))
418 fprintf(stderr, " (HLSL counter buffer ID: %u)", counter_id);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200419 fprintf(stderr, "\n");
420 }
421 fprintf(stderr, "=============\n\n");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100422}
423
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200424static const char *execution_model_to_str(spv::ExecutionModel model)
425{
426 switch (model)
427 {
428 case spv::ExecutionModelVertex:
429 return "vertex";
430 case spv::ExecutionModelTessellationControl:
431 return "tessellation control";
432 case ExecutionModelTessellationEvaluation:
433 return "tessellation evaluation";
434 case ExecutionModelGeometry:
435 return "geometry";
436 case ExecutionModelFragment:
437 return "fragment";
438 case ExecutionModelGLCompute:
439 return "compute";
Hans-Kristian Arntzen88ce9582019-03-27 10:21:30 +0100440 case ExecutionModelRayGenerationNV:
441 return "raygenNV";
442 case ExecutionModelIntersectionNV:
443 return "intersectionNV";
444 case ExecutionModelCallableNV:
445 return "callableNV";
446 case ExecutionModelAnyHitNV:
447 return "anyhitNV";
448 case ExecutionModelClosestHitNV:
449 return "closesthitNV";
450 case ExecutionModelMissNV:
451 return "missNV";
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200452 default:
453 return "???";
454 }
455}
456
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100457static void print_resources(const Compiler &compiler, const ShaderResources &res)
458{
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100459 auto &modes = compiler.get_execution_mode_bitset();
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200460
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200461 fprintf(stderr, "Entry points:\n");
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100462 auto entry_points = compiler.get_entry_points_and_stages();
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200463 for (auto &e : entry_points)
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100464 fprintf(stderr, " %s (%s)\n", e.name.c_str(), execution_model_to_str(e.execution_model));
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200465 fprintf(stderr, "\n");
466
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200467 fprintf(stderr, "Execution modes:\n");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100468 modes.for_each_bit([&](uint32_t i) {
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200469 auto mode = static_cast<ExecutionMode>(i);
470 uint32_t arg0 = compiler.get_execution_mode_argument(mode, 0);
471 uint32_t arg1 = compiler.get_execution_mode_argument(mode, 1);
472 uint32_t arg2 = compiler.get_execution_mode_argument(mode, 2);
473
474 switch (static_cast<ExecutionMode>(i))
475 {
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200476 case ExecutionModeInvocations:
477 fprintf(stderr, " Invocations: %u\n", arg0);
478 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200479
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200480 case ExecutionModeLocalSize:
481 fprintf(stderr, " LocalSize: (%u, %u, %u)\n", arg0, arg1, arg2);
482 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200483
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200484 case ExecutionModeOutputVertices:
485 fprintf(stderr, " OutputVertices: %u\n", arg0);
486 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200487
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200488#define CHECK_MODE(m) \
489 case ExecutionMode##m: \
490 fprintf(stderr, " %s\n", #m); \
491 break
492 CHECK_MODE(SpacingEqual);
493 CHECK_MODE(SpacingFractionalEven);
494 CHECK_MODE(SpacingFractionalOdd);
495 CHECK_MODE(VertexOrderCw);
496 CHECK_MODE(VertexOrderCcw);
497 CHECK_MODE(PixelCenterInteger);
498 CHECK_MODE(OriginUpperLeft);
499 CHECK_MODE(OriginLowerLeft);
500 CHECK_MODE(EarlyFragmentTests);
501 CHECK_MODE(PointMode);
502 CHECK_MODE(Xfb);
503 CHECK_MODE(DepthReplacing);
504 CHECK_MODE(DepthGreater);
505 CHECK_MODE(DepthLess);
506 CHECK_MODE(DepthUnchanged);
507 CHECK_MODE(LocalSizeHint);
508 CHECK_MODE(InputPoints);
509 CHECK_MODE(InputLines);
510 CHECK_MODE(InputLinesAdjacency);
511 CHECK_MODE(Triangles);
512 CHECK_MODE(InputTrianglesAdjacency);
513 CHECK_MODE(Quads);
514 CHECK_MODE(Isolines);
515 CHECK_MODE(OutputPoints);
516 CHECK_MODE(OutputLineStrip);
517 CHECK_MODE(OutputTriangleStrip);
518 CHECK_MODE(VecTypeHint);
519 CHECK_MODE(ContractionOff);
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200520
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200521 default:
522 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200523 }
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100524 });
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200525 fprintf(stderr, "\n");
526
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200527 print_resources(compiler, "subpass inputs", res.subpass_inputs);
528 print_resources(compiler, "inputs", res.stage_inputs);
529 print_resources(compiler, "outputs", res.stage_outputs);
530 print_resources(compiler, "textures", res.sampled_images);
Hans-Kristian Arntzen378fbe82016-09-11 13:47:06 +0200531 print_resources(compiler, "separate images", res.separate_images);
Hans-Kristian Arntzene9202082016-09-10 13:05:35 +0200532 print_resources(compiler, "separate samplers", res.separate_samplers);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200533 print_resources(compiler, "images", res.storage_images);
534 print_resources(compiler, "ssbos", res.storage_buffers);
535 print_resources(compiler, "ubos", res.uniform_buffers);
536 print_resources(compiler, "push", res.push_constant_buffers);
537 print_resources(compiler, "counters", res.atomic_counters);
Hans-Kristian Arntzen88ce9582019-03-27 10:21:30 +0100538 print_resources(compiler, "acceleration structures", res.acceleration_structures);
Hans-Kristian Arntzenb4a380a2021-04-16 13:32:37 +0200539 print_resources(compiler, spv::StorageClassInput, res.builtin_inputs);
540 print_resources(compiler, spv::StorageClassOutput, res.builtin_outputs);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100541}
542
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200543static void print_push_constant_resources(const Compiler &compiler, const SmallVector<Resource> &res)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100544{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200545 for (auto &block : res)
546 {
547 auto ranges = compiler.get_active_buffer_ranges(block.id);
548 fprintf(stderr, "Active members in buffer: %s\n",
549 !block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str());
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100550
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200551 fprintf(stderr, "==================\n\n");
552 for (auto &range : ranges)
553 {
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200554 const auto &name = compiler.get_member_name(block.base_type_id, range.index);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100555
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200556 fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n", range.index,
557 !name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(),
558 unsigned(range.offset), unsigned(range.range));
559 }
560 fprintf(stderr, "==================\n\n");
561 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100562}
563
Hans-Kristian Arntzen6bd545b2016-09-17 15:16:07 +0200564static void print_spec_constants(const Compiler &compiler)
565{
566 auto spec_constants = compiler.get_specialization_constants();
567 fprintf(stderr, "Specialization constants\n");
568 fprintf(stderr, "==================\n\n");
569 for (auto &c : spec_constants)
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200570 fprintf(stderr, "ID: %u, Spec ID: %u\n", uint32_t(c.id), c.constant_id);
Hans-Kristian Arntzen6bd545b2016-09-17 15:16:07 +0200571 fprintf(stderr, "==================\n\n");
572}
573
Hans-Kristian Arntzen8d7a9092017-08-15 15:27:53 +0200574static void print_capabilities_and_extensions(const Compiler &compiler)
575{
576 fprintf(stderr, "Capabilities\n");
577 fprintf(stderr, "============\n");
578 for (auto &capability : compiler.get_declared_capabilities())
579 fprintf(stderr, "Capability: %u\n", static_cast<unsigned>(capability));
580 fprintf(stderr, "============\n\n");
581
582 fprintf(stderr, "Extensions\n");
583 fprintf(stderr, "============\n");
584 for (auto &ext : compiler.get_declared_extensions())
585 fprintf(stderr, "Extension: %s\n", ext.c_str());
586 fprintf(stderr, "============\n\n");
587}
588
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100589struct PLSArg
590{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200591 PlsFormat format;
592 string name;
593};
594
595struct Remap
596{
597 string src_name;
598 string dst_name;
599 unsigned components;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100600};
601
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +0200602struct VariableTypeRemap
603{
604 string variable_name;
605 string new_variable_type;
606};
607
Hans-Kristian Arntzend89d0e02017-07-24 09:29:20 +0200608struct InterfaceVariableRename
609{
610 StorageClass storageClass;
611 uint32_t location;
612 string variable_name;
Jason Chan3281e822017-06-25 15:16:09 +0200613};
614
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100615struct CLIArguments
616{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200617 const char *input = nullptr;
618 const char *output = nullptr;
619 const char *cpp_interface_name = nullptr;
620 uint32_t version = 0;
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +0100621 uint32_t shader_model = 0;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500622 uint32_t msl_version = 0;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200623 bool es = false;
624 bool set_version = false;
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +0100625 bool set_shader_model = false;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500626 bool set_msl_version = false;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200627 bool set_es = false;
628 bool dump_resources = false;
629 bool force_temporary = false;
630 bool flatten_ubo = false;
631 bool fixup = false;
Hans-Kristian Arntzenbdfa97a2017-08-03 13:02:59 +0200632 bool yflip = false;
Hans-Kristian Arntzen36650c82017-05-22 15:30:43 +0200633 bool sso = false;
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +0200634 bool support_nonzero_baseinstance = true;
Chip Davisc51e5b72019-01-08 16:33:32 -0600635 bool msl_capture_output_to_buffer = false;
Chip Davis25833212018-09-19 20:36:33 -0500636 bool msl_swizzle_texture_samples = false;
Chip Davis3a9af962018-09-26 20:06:05 -0500637 bool msl_ios = false;
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +0100638 bool msl_pad_fragment_output = false;
Chip Davis41d94242019-02-05 23:47:50 -0600639 bool msl_domain_lower_left = false;
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100640 bool msl_argument_buffers = false;
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +0200641 bool msl_texture_buffer_native = false;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400642 bool msl_framebuffer_fetch = false;
Lukas Hermannsffbd8012019-10-09 11:22:25 -0400643 bool msl_invariant_float_math = false;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400644 bool msl_emulate_cube_array = false;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500645 bool msl_multiview = false;
Chip Daviscab73352020-08-23 16:44:41 -0500646 bool msl_multiview_layered_rendering = true;
Chip Davis6a585542019-07-12 21:50:50 -0500647 bool msl_view_index_from_device_index = false;
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500648 bool msl_dispatch_base = false;
Akio Gaule1280df62019-11-27 01:02:46 -0800649 bool msl_decoration_binding = false;
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +0100650 bool msl_force_active_argument_buffer_resources = false;
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +0100651 bool msl_force_native_arrays = false;
Chip Davisb29f83c2020-04-10 01:13:33 -0500652 bool msl_enable_frag_depth_builtin = true;
653 bool msl_enable_frag_stencil_ref_builtin = true;
654 uint32_t msl_enable_frag_output_mask = 0xffffffff;
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +0200655 bool msl_enable_clip_distance_user_varying = true;
Chip Davis688c5fc2020-02-20 21:38:28 -0600656 bool msl_multi_patch_workgroup = false;
657 bool msl_vertex_for_tessellation = false;
Tomek Ponitka18f23c42020-07-22 18:37:17 +0200658 uint32_t msl_additional_fixed_sample_mask = 0xffffffff;
Chip Davis4cf840e2020-08-27 19:24:20 -0500659 bool msl_arrayed_subpass_input = false;
Chip Davis21d38f72020-10-13 13:20:49 -0500660 uint32_t msl_r32ui_linear_texture_alignment = 4;
661 uint32_t msl_r32ui_alignment_constant_id = 65535;
Chip Davis5845e002020-10-14 20:48:52 -0500662 bool msl_texture_1d_as_2d = false;
Chip Davis68908352020-11-18 23:16:46 -0600663 bool msl_ios_use_simdgroup_functions = false;
664 bool msl_emulate_subgroups = false;
665 uint32_t msl_fixed_subgroup_size = 0;
Chip Davisfd738e32020-11-20 15:41:46 -0600666 bool msl_force_sample_rate_shading = false;
Hans-Kristian Arntzenc87cb542021-05-21 16:47:41 +0200667 const char *msl_combined_sampler_suffix = nullptr;
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +0100668 bool glsl_emit_push_constant_as_ubo = false;
Laszlo Agocs7bc31492019-05-11 16:30:33 +0200669 bool glsl_emit_ubo_as_plain_uniforms = false;
Hans-Kristian Arntzen57c93d42020-07-28 15:15:24 +0200670 bool glsl_force_flattened_io_blocks = false;
Hans-Kristian Arntzend75666b2021-06-28 12:55:37 +0200671 uint32_t glsl_ovr_multiview_view_count = 0;
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +0100672 SmallVector<pair<uint32_t, uint32_t>> glsl_ext_framebuffer_fetch;
Hans-Kristian Arntzen26a49862021-05-21 14:21:13 +0200673 bool glsl_ext_framebuffer_fetch_noncoherent = false;
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +0200674 bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +0200675 bool emit_line_directives = false;
Hans-Kristian Arntzen95cd20f2020-03-04 16:41:00 +0100676 bool enable_storage_image_qualifier_deduction = true;
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +0100677 bool force_zero_initialized_variables = false;
Hans-Kristian Arntzen31be74a2022-03-03 11:04:45 +0100678 bool relax_nan_checks = false;
Hans-Kristian Arntzenc716a9a2022-02-16 12:12:27 +0100679 uint32_t force_recompile_max_debug_iterations = 3;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200680 SmallVector<uint32_t> msl_discrete_descriptor_sets;
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +0200681 SmallVector<uint32_t> msl_device_argument_buffers;
Chip Daviscb359342019-09-05 23:14:12 -0500682 SmallVector<pair<uint32_t, uint32_t>> msl_dynamic_buffers;
Chip Davisfedbc352019-12-16 22:58:16 -0600683 SmallVector<pair<uint32_t, uint32_t>> msl_inline_uniform_blocks;
Chip Davis064eaeb2022-08-13 16:55:34 -0700684 SmallVector<MSLShaderInterfaceVariable> msl_shader_inputs;
685 SmallVector<MSLShaderInterfaceVariable> msl_shader_outputs;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200686 SmallVector<PLSArg> pls_in;
687 SmallVector<PLSArg> pls_out;
688 SmallVector<Remap> remaps;
689 SmallVector<string> extensions;
690 SmallVector<VariableTypeRemap> variable_type_remaps;
691 SmallVector<InterfaceVariableRename> interface_variable_renames;
692 SmallVector<HLSLVertexAttributeRemap> hlsl_attr_remap;
Hans-Kristian Arntzen9c1cadd2021-03-26 15:58:41 +0100693 SmallVector<std::pair<uint32_t, uint32_t>> masked_stage_outputs;
694 SmallVector<BuiltIn> masked_stage_builtins;
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200695 string entry;
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100696 string entry_stage;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100697
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100698 struct Rename
699 {
700 string old_name;
701 string new_name;
702 ExecutionModel execution_model;
703 };
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200704 SmallVector<Rename> entry_point_rename;
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +0100705
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200706 uint32_t iterations = 1;
707 bool cpp = false;
Brad Davis709d3c62018-06-03 11:16:37 -0700708 string reflect;
Bill Hollings5ad73f32017-03-19 21:06:21 -0400709 bool msl = false;
Robert Konrad216a6812017-01-25 17:30:52 +0100710 bool hlsl = false;
Hans-Kristian Arntzen17d88ca2017-05-04 10:10:30 +0200711 bool hlsl_compat = false;
Hans-Kristian Arntzena2a44d92019-01-11 10:32:14 +0100712 bool hlsl_support_nonzero_base = false;
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +0100713 bool hlsl_force_storage_buffer_as_uav = false;
Hans-Kristian Arntzen28bf9052020-04-03 11:21:41 +0200714 bool hlsl_nonwritable_uav_texture_as_srv = false;
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +0200715 bool hlsl_enable_16bit_types = false;
Hans-Kristian Arntzenb3344172020-11-03 11:18:32 +0100716 bool hlsl_flatten_matrix_vertex_input_semantics = false;
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100717 HLSLBindingFlags hlsl_binding_flags = 0;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200718 bool vulkan_semantics = false;
Hans-Kristian Arntzen470ae7a2017-05-22 17:40:00 +0200719 bool flatten_multidimensional_arrays = false;
Hans-Kristian Arntzen6599a412017-09-08 09:56:06 +0200720 bool use_420pack_extension = true;
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +0200721 bool remove_unused = false;
Hans-Kristian Arntzenba15dae2018-05-23 20:34:26 +0100722 bool combined_samplers_inherit_bindings = false;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100723};
724
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200725static void print_version()
726{
727#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
728 fprintf(stderr, "%s\n", SPIRV_CROSS_GIT_REVISION);
729#else
730 fprintf(stderr, "Git revision unknown. Build with CMake to create timestamp and revision info.\n");
731#endif
732}
733
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200734static void print_help_backend()
735{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200736 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200737 fprintf(stderr, "\nSelect backend:\n"
738 "\tBy default, OpenGL-style GLSL is the target, with #version and GLSL/ESSL information inherited from the SPIR-V module if present.\n"
739 "\t[--vulkan-semantics] or [-V]:\n\t\tEmit Vulkan GLSL instead of plain GLSL. Makes use of Vulkan-only features to match SPIR-V.\n"
740 "\t[--msl]:\n\t\tEmit Metal Shading Language (MSL).\n"
741 "\t[--hlsl]:\n\t\tEmit HLSL.\n"
742 "\t[--reflect]:\n\t\tEmit JSON reflection.\n"
743 "\t[--cpp]:\n\t\tDEPRECATED. Emits C++ code.\n"
744 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200745 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200746}
747
748static void print_help_glsl()
749{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200750 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200751 fprintf(stderr, "\nGLSL options:\n"
752 "\t[--es]:\n\t\tForce ESSL.\n"
753 "\t[--no-es]:\n\t\tForce desktop GLSL.\n"
754 "\t[--version <GLSL version>]:\n\t\tE.g. --version 450 will emit '#version 450' in shader.\n"
755 "\t\tCode generation will depend on the version used.\n"
756 "\t[--flatten-ubo]:\n\t\tEmit UBOs as plain uniform arrays which are suitable for use with glUniform4*v().\n"
757 "\t\tThis can be an optimization on GL implementations where this is faster or works around buggy driver implementations.\n"
758 "\t\tE.g.: uniform MyUBO { vec4 a; float b, c, d, e; }; will be emitted as uniform vec4 MyUBO[2];\n"
759 "\t\tCaveat: You cannot mix and match floating-point and integer in the same UBO with this option.\n"
760 "\t\tLegacy GLSL/ESSL (where this flattening makes sense) does not support bit-casting, which would have been the obvious workaround.\n"
761 "\t[--extension ext]:\n\t\tAdd #extension string of your choosing to GLSL output.\n"
762 "\t\tUseful if you use variable name remapping to something that requires an extension unknown to SPIRV-Cross.\n"
763 "\t[--remove-unused-variables]:\n\t\tDo not emit interface variables which are not statically accessed by the shader.\n"
764 "\t[--separate-shader-objects]:\n\t\tRedeclare gl_PerVertex blocks to be suitable for desktop GL separate shader objects.\n"
765 "\t[--glsl-emit-push-constant-as-ubo]:\n\t\tInstead of a plain uniform of struct for push constants, emit a UBO block instead.\n"
766 "\t[--glsl-emit-ubo-as-plain-uniforms]:\n\t\tInstead of emitting UBOs, emit them as plain uniform structs.\n"
767 "\t[--glsl-remap-ext-framebuffer-fetch input-attachment color-location]:\n\t\tRemaps an input attachment to use GL_EXT_shader_framebuffer_fetch.\n"
768 "\t\tgl_LastFragData[location] is read from. The attachment to read from must be declared as an output in the shader.\n"
Hans-Kristian Arntzen26a49862021-05-21 14:21:13 +0200769 "\t[--glsl-ext-framebuffer-fetch-noncoherent]:\n\t\tUses noncoherent qualifier for framebuffer fetch.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200770 "\t[--vulkan-glsl-disable-ext-samplerless-texture-functions]:\n\t\tDo not allow use of GL_EXT_samperless_texture_functions, even in Vulkan GLSL.\n"
771 "\t\tUse of texelFetch and similar might have to create dummy samplers to work around it.\n"
772 "\t[--combined-samplers-inherit-bindings]:\n\t\tInherit binding information from the textures when building combined image samplers from separate textures and samplers.\n"
773 "\t[--no-support-nonzero-baseinstance]:\n\t\tWhen using gl_InstanceIndex with desktop GL,\n"
774 "\t\tassume that base instance is always 0, and do not attempt to fix up gl_InstanceID to match Vulkan semantics.\n"
775 "\t[--pls-in format input-name]:\n\t\tRemaps a subpass input with name into a GL_EXT_pixel_local_storage input.\n"
776 "\t\tEntry in PLS block is ordered where first --pls-in marks the first entry. Can be called multiple times.\n"
777 "\t\tFormats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui.\n"
778 "\t\tRequires ESSL.\n"
779 "\t[--pls-out format output-name]:\n\t\tRemaps a color output with name into a GL_EXT_pixel_local_storage output.\n"
780 "\t\tEntry in PLS block is ordered where first --pls-output marks the first entry. Can be called multiple times.\n"
781 "\t\tFormats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui.\n"
782 "\t\tRequires ESSL.\n"
783 "\t[--remap source_name target_name components]:\n\t\tRemaps a variable to a different name with N components.\n"
784 "\t\tMain use case is to remap a subpass input to gl_LastFragDepthARM.\n"
785 "\t\tE.g.:\n"
786 "\t\tuniform subpassInput uDepth;\n"
787 "\t\t--remap uDepth gl_LastFragDepthARM 1 --extension GL_ARM_shader_framebuffer_fetch_depth_stencil\n"
788 "\t[--no-420pack-extension]:\n\t\tDo not make use of GL_ARB_shading_language_420pack in older GL targets to support layout(binding).\n"
789 "\t[--remap-variable-type <variable_name> <new_variable_type>]:\n\t\tRemaps a variable type based on name.\n"
790 "\t\tPrimary use case is supporting external samplers in ESSL for video rendering on Android where you could remap a texture to a YUV one.\n"
Hans-Kristian Arntzen57c93d42020-07-28 15:15:24 +0200791 "\t[--glsl-force-flattened-io-blocks]:\n\t\tAlways flatten I/O blocks and structs.\n"
Hans-Kristian Arntzend75666b2021-06-28 12:55:37 +0200792 "\t[--glsl-ovr-multiview-view-count count]:\n\t\tIn GL_OVR_multiview2, specify layout(num_views).\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200793 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200794 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200795}
796
797static void print_help_hlsl()
798{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200799 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200800 fprintf(stderr, "\nHLSL options:\n"
801 "\t[--shader-model]:\n\t\tEnables a specific shader model, e.g. --shader-model 50 for SM 5.0.\n"
Shintaro Sakaharaed4ded02022-02-16 21:53:24 +0900802 "\t[--flatten-ubo]:\n\t\tEmit UBOs as plain uniform arrays.\n"
803 "\t\tE.g.: uniform MyUBO { vec4 a; float b, c, d, e; }; will be emitted as uniform float4 MyUBO[2];\n"
804 "\t\tCaveat: You cannot mix and match floating-point and integer in the same UBO with this option.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200805 "\t[--hlsl-enable-compat]:\n\t\tAllow point size and point coord to be used, even if they won't work as expected.\n"
806 "\t\tPointSize is ignored, and PointCoord returns (0.5, 0.5).\n"
807 "\t[--hlsl-support-nonzero-basevertex-baseinstance]:\n\t\tSupport base vertex and base instance by emitting a special cbuffer declared as:\n"
808 "\t\tcbuffer SPIRV_Cross_VertexInfo { int SPIRV_Cross_BaseVertex; int SPIRV_Cross_BaseInstance; };\n"
809 "\t[--hlsl-auto-binding (push, cbv, srv, uav, sampler, all)]\n"
810 "\t\tDo not emit any : register(#) bindings for specific resource types, and rely on HLSL compiler to assign something.\n"
811 "\t[--hlsl-force-storage-buffer-as-uav]:\n\t\tAlways emit SSBOs as UAVs, even when marked as read-only.\n"
812 "\t\tNormally, SSBOs marked with NonWritable will be emitted as SRVs.\n"
813 "\t[--hlsl-nonwritable-uav-texture-as-srv]:\n\t\tEmit NonWritable storage images as SRV textures instead of UAV.\n"
814 "\t\tUsing this option messes with the type system. SPIRV-Cross cannot guarantee that this will work.\n"
815 "\t\tOne major problem area with this feature is function arguments, where we won't know if we're seeing a UAV or SRV.\n"
816 "\t\tShader must ensure that read/write state is consistent at all call sites.\n"
817 "\t[--set-hlsl-vertex-input-semantic <location> <semantic>]:\n\t\tEmits a specific vertex input semantic for a given location.\n"
818 "\t\tOtherwise, TEXCOORD# is used as semantics, where # is location.\n"
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +0200819 "\t[--hlsl-enable-16bit-types]:\n\t\tEnables native use of half/int16_t/uint16_t and ByteAddressBuffer interaction with these types. Requires SM 6.2.\n"
Hans-Kristian Arntzenb3344172020-11-03 11:18:32 +0100820 "\t[--hlsl-flatten-matrix-vertex-input-semantics]:\n\t\tEmits matrix vertex inputs with input semantics as if they were independent vectors, e.g. TEXCOORD{2,3,4} rather than matrix form TEXCOORD2_{0,1,2}.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200821 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200822 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200823}
824
825static void print_help_msl()
826{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200827 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200828 fprintf(stderr, "\nMSL options:\n"
829 "\t[--msl-version <MMmmpp>]:\n\t\tUses a specific MSL version, e.g. --msl-version 20100 for MSL 2.1.\n"
830 "\t[--msl-capture-output]:\n\t\tWrites geometry varyings to a buffer instead of as stage-outputs.\n"
831 "\t[--msl-swizzle-texture-samples]:\n\t\tWorks around lack of support for VkImageView component swizzles.\n"
832 "\t\tThis has a massive impact on performance and bloat. Do not use this unless you are absolutely forced to.\n"
833 "\t\tTo use this feature, the API side must pass down swizzle buffers.\n"
834 "\t\tShould only be used by translation layers as a last resort.\n"
835 "\t\tRecent Metal versions do not require this workaround.\n"
836 "\t[--msl-ios]:\n\t\tTarget iOS Metal instead of macOS Metal.\n"
837 "\t[--msl-pad-fragment-output]:\n\t\tAlways emit color outputs as 4-component variables.\n"
838 "\t\tIn Metal, the fragment shader must emit at least as many components as the render target format.\n"
839 "\t[--msl-domain-lower-left]:\n\t\tUse a lower-left tessellation domain.\n"
840 "\t[--msl-argument-buffers]:\n\t\tEmit Indirect Argument buffers instead of plain bindings.\n"
841 "\t\tRequires MSL 2.0 to be enabled.\n"
842 "\t[--msl-texture-buffer-native]:\n\t\tEnable native support for texel buffers. Otherwise, it is emulated as a normal texture.\n"
843 "\t[--msl-framebuffer-fetch]:\n\t\tImplement subpass inputs with frame buffer fetch.\n"
844 "\t\tEmits [[color(N)]] inputs in fragment stage.\n"
Chip Davisc20d5942020-10-27 21:42:33 -0500845 "\t\tRequires an Apple GPU.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200846 "\t[--msl-emulate-cube-array]:\n\t\tEmulate cube arrays with 2D array and manual math.\n"
847 "\t[--msl-discrete-descriptor-set <index>]:\n\t\tWhen using argument buffers, forces a specific descriptor set to be implemented without argument buffers.\n"
848 "\t\tUseful for implementing push descriptors in emulation layers.\n"
849 "\t\tCan be used multiple times for each descriptor set in question.\n"
850 "\t[--msl-device-argument-buffer <descriptor set index>]:\n\t\tUse device address space to hold indirect argument buffers instead of constant.\n"
851 "\t\tComes up when trying to support argument buffers which are larger than 64 KiB.\n"
852 "\t[--msl-multiview]:\n\t\tEnable SPV_KHR_multiview emulation.\n"
Chip Daviscab73352020-08-23 16:44:41 -0500853 "\t[--msl-multiview-no-layered-rendering]:\n\t\tDon't set [[render_target_array_index]] in multiview shaders.\n"
854 "\t\tUseful for devices which don't support layered rendering. Only effective when --msl-multiview is enabled.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200855 "\t[--msl-view-index-from-device-index]:\n\t\tTreat the view index as the device index instead.\n"
856 "\t\tFor multi-GPU rendering.\n"
857 "\t[--msl-dispatch-base]:\n\t\tAdd support for vkCmdDispatchBase() or similar APIs.\n"
858 "\t\tOffsets the workgroup ID based on a buffer.\n"
859 "\t[--msl-dynamic-buffer <set index> <binding>]:\n\t\tMarks a buffer as having dynamic offset.\n"
860 "\t\tThe offset is applied in the shader with pointer arithmetic.\n"
861 "\t\tUseful for argument buffers where it is non-trivial to apply dynamic offset otherwise.\n"
862 "\t[--msl-inline-uniform-block <set index> <binding>]:\n\t\tIn argument buffers, mark an UBO as being an inline uniform block which is embedded into the argument buffer itself.\n"
863 "\t[--msl-decoration-binding]:\n\t\tUse SPIR-V bindings directly as MSL bindings.\n"
864 "\t\tThis does not work in the general case as there is no descriptor set support, and combined image samplers are split up.\n"
865 "\t\tHowever, if the shader author knows of binding limitations, this option will avoid the need for reflection on Metal side.\n"
866 "\t[--msl-force-active-argument-buffer-resources]:\n\t\tAlways emit resources which are part of argument buffers.\n"
867 "\t\tThis makes sure that similar shaders with same resource declarations can share the argument buffer as declaring an argument buffer implies an ABI.\n"
868 "\t[--msl-force-native-arrays]:\n\t\tRather than implementing array types as a templated value type ala std::array<T>, use plain, native arrays.\n"
869 "\t\tThis will lead to worse code-gen, but can work around driver bugs on certain driver revisions of certain Intel-based Macbooks where template arrays break.\n"
870 "\t[--msl-disable-frag-depth-builtin]:\n\t\tDisables FragDepth output. Useful if pipeline does not enable depth, as pipeline creation might otherwise fail.\n"
871 "\t[--msl-disable-frag-stencil-ref-builtin]:\n\t\tDisable FragStencilRef output. Useful if pipeline does not enable stencil output, as pipeline creation might otherwise fail.\n"
872 "\t[--msl-enable-frag-output-mask <mask>]:\n\t\tOnly selectively enable fragment outputs. Useful if pipeline does not enable fragment output for certain locations, as pipeline creation might otherwise fail.\n"
873 "\t[--msl-no-clip-distance-user-varying]:\n\t\tDo not emit user varyings to emulate gl_ClipDistance in fragment shaders.\n"
Chip Davis5281d992020-06-13 23:03:30 -0500874 "\t[--msl-shader-input <index> <format> <size>]:\n\t\tSpecify the format of the shader input at <index>.\n"
Chip Davis688c5fc2020-02-20 21:38:28 -0600875 "\t\t<format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, "
Chip Davis5281d992020-06-13 23:03:30 -0500876 "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader.\n"
Chip Davis688c5fc2020-02-20 21:38:28 -0600877 "\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n"
Chip Davis064eaeb2022-08-13 16:55:34 -0700878 "\t[--msl-shader-output <index> <format> <size>]:\n\t\tSpecify the format of the shader output at <index>.\n"
879 "\t\t<format> can be 'any32', 'any16', 'u16', 'u8', or 'other', to indicate a 32-bit opaque value, 16-bit opaque value, 16-bit unsigned integer, 8-bit unsigned integer, "
880 "or other-typed variable. <size> is the vector length of the variable, which must be greater than or equal to that declared in the shader.\n"
881 "\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n"
Chip Davis688c5fc2020-02-20 21:38:28 -0600882 "\t[--msl-multi-patch-workgroup]:\n\t\tUse the new style of tessellation control processing, where multiple patches are processed per workgroup.\n"
883 "\t\tThis should increase throughput by ensuring all the GPU's SIMD lanes are occupied, but it is not compatible with the old style.\n"
884 "\t\tIn addition, this style also passes input variables in buffers directly instead of using vertex attribute processing.\n"
885 "\t\tIn a future version of SPIRV-Cross, this will become the default.\n"
886 "\t[--msl-vertex-for-tessellation]:\n\t\tWhen handling a vertex shader, marks it as one that will be used with a new-style tessellation control shader.\n"
Tomek Ponitka18f23c42020-07-22 18:37:17 +0200887 "\t\tThe vertex shader is output to MSL as a compute kernel which outputs vertices to the buffer in the order they are received, rather than in index order as with --msl-capture-output normally.\n"
888 "\t[--msl-additional-fixed-sample-mask <mask>]:\n"
Chip Davis4cf840e2020-08-27 19:24:20 -0500889 "\t\tSet an additional fixed sample mask. If the shader outputs a sample mask, then the final sample mask will be a bitwise AND of the two.\n"
890 "\t[--msl-arrayed-subpass-input]:\n\t\tAssume that images of dimension SubpassData have multiple layers. Layered input attachments are accessed relative to BuiltInLayer.\n"
Chip Davis21d38f72020-10-13 13:20:49 -0500891 "\t\tThis option has no effect if multiview is also enabled.\n"
892 "\t[--msl-r32ui-linear-texture-align <alignment>]:\n\t\tThe required alignment of linear textures of format MTLPixelFormatR32Uint.\n"
893 "\t\tThis is used to align the row stride for atomic accesses to such images.\n"
894 "\t[--msl-r32ui-linear-texture-align-constant-id <id>]:\n\t\tThe function constant ID to use for the linear texture alignment.\n"
Chip Davis5845e002020-10-14 20:48:52 -0500895 "\t\tOn MSL 1.2 or later, you can override the alignment by setting this function constant.\n"
896 "\t[--msl-texture-1d-as-2d]:\n\t\tEmit Image variables of dimension Dim1D as texture2d.\n"
Chip Davis68908352020-11-18 23:16:46 -0600897 "\t\tIn Metal, 1D textures do not support all features that 2D textures do. Use this option if your code relies on these features.\n"
898 "\t[--msl-ios-use-simdgroup-functions]:\n\t\tUse simd_*() functions for subgroup ops instead of quad_*().\n"
899 "\t\tRecent Apple GPUs support SIMD-groups larger than a quad. Use this option to take advantage of this support.\n"
900 "\t[--msl-emulate-subgroups]:\n\t\tAssume subgroups of size 1.\n"
901 "\t\tIntended for Vulkan Portability implementations where Metal support for SIMD-groups is insufficient for true subgroups.\n"
902 "\t[--msl-fixed-subgroup-size <size>]:\n\t\tAssign a constant <size> to the SubgroupSize builtin.\n"
903 "\t\tIntended for Vulkan Portability implementations where VK_EXT_subgroup_size_control is not supported or disabled.\n"
Chip Davisfd738e32020-11-20 15:41:46 -0600904 "\t\tIf 0, assume variable subgroup size as actually exposed by Metal.\n"
905 "\t[--msl-force-sample-rate-shading]:\n\t\tForce fragment shaders to run per sample.\n"
Hans-Kristian Arntzenc87cb542021-05-21 16:47:41 +0200906 "\t\tThis adds a [[sample_id]] parameter if none is already present.\n"
907 "\t[--msl-combined-sampler-suffix <suffix>]:\n\t\tUses a custom suffix for combined samplers.\n");
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200908 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200909}
910
911static void print_help_common()
912{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200913 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200914 fprintf(stderr, "\nCommon options:\n"
915 "\t[--entry name]:\n\t\tUse a specific entry point. By default, the first entry point in the module is used.\n"
Sergii Penner1bba4d52022-06-20 09:26:34 -0600916 "\t[--stage <stage (vert, frag, geom, tesc, tese, comp)>]:\n\t\tForces use of a certain shader stage.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200917 "\t\tCan disambiguate the entry point if more than one entry point exists with same name, but different stage.\n"
918 "\t[--emit-line-directives]:\n\t\tIf SPIR-V has OpLine directives, aim to emit those accurately in output code as well.\n"
919 "\t[--rename-entry-point <old> <new> <stage>]:\n\t\tRenames an entry point from what is declared in SPIR-V to code output.\n"
920 "\t\tMostly relevant for HLSL or MSL.\n"
921 "\t[--rename-interface-variable <in|out> <location> <new_variable_name>]:\n\t\tRename an interface variable based on location decoration.\n"
922 "\t[--force-zero-initialized-variables]:\n\t\tForces temporary variables to be initialized to zero.\n"
923 "\t\tCan be useful in environments where compilers do not allow potentially uninitialized variables.\n"
924 "\t\tThis usually comes up with Phi temporaries.\n"
925 "\t[--fixup-clipspace]:\n\t\tFixup Z clip-space at the end of a vertex shader. The behavior is backend-dependent.\n"
926 "\t\tGLSL: Rewrites [0, w] Z range (D3D/Metal/Vulkan) to GL-style [-w, w].\n"
927 "\t\tHLSL/MSL: Rewrites [-w, w] Z range (GL) to D3D/Metal/Vulkan-style [0, w].\n"
928 "\t[--flip-vert-y]:\n\t\tInverts gl_Position.y (or equivalent) at the end of a vertex shader. This is equivalent to using negative viewport height.\n"
Hans-Kristian Arntzen9c1cadd2021-03-26 15:58:41 +0100929 "\t[--mask-stage-output-location <location> <component>]:\n"
930 "\t\tIf a stage output variable with matching location and component is active, optimize away the variable if applicable.\n"
Hans-Kristian Arntzenee85bb32021-04-14 10:51:51 +0200931 "\t[--mask-stage-output-builtin <Position|PointSize|ClipDistance|CullDistance>]:\n"
Hans-Kristian Arntzen9c1cadd2021-03-26 15:58:41 +0100932 "\t\tIf a stage output variable with matching builtin is active, "
933 "optimize away the variable if it can affect cross-stage linking correctness.\n"
Hans-Kristian Arntzen31be74a2022-03-03 11:04:45 +0100934 "\t[--relax-nan-checks]:\n\t\tRelax NaN checks for N{Clamp,Min,Max} and ordered vs. unordered compare instructions.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200935 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200936 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200937}
938
939static void print_help_obscure()
940{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200941 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200942 fprintf(stderr, "\nObscure options:\n"
943 "\tThese options are not meant to be used on a regular basis. They have some occasional uses in the test suite.\n"
944
945 "\t[--force-temporary]:\n\t\tAggressively emit temporary expressions instead of forwarding expressions. Very rarely used and under-tested.\n"
946 "\t[--revision]:\n\t\tPrints build timestamp and Git commit information (updated when cmake is configured).\n"
947 "\t[--iterations iter]:\n\t\tRecompiles the same shader over and over, benchmarking related.\n"
948 "\t[--disable-storage-image-qualifier-deduction]:\n\t\tIf storage images are received without any nonwritable or nonreadable information,\n"""
949 "\t\tdo not attempt to analyze usage, and always emit read/write state.\n"
950 "\t[--flatten-multidimensional-arrays]:\n\t\tDo not support multi-dimensional arrays and flatten them to one dimension.\n"
951 "\t[--cpp-interface-name <name>]:\n\t\tEmit a specific class name in C++ codegen.\n"
Hans-Kristian Arntzenc716a9a2022-02-16 12:12:27 +0100952 "\t[--force-recompile-max-debug-iterations <count>]:\n\t\tAllow compilation loop to run for N loops.\n"
953 "\t\tCan be used to triage workarounds, but should not be used as a crutch, since it masks an implementation bug.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200954 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200955 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200956}
957
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100958static void print_help()
959{
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200960 print_version();
961
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200962 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200963 fprintf(stderr, "Usage: spirv-cross <...>\n"
964 "\nBasic:\n"
Hans-Kristian Arntzen02b7f9c2021-01-06 11:06:41 +0100965 "\t[SPIR-V file] (- is stdin)\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200966 "\t[--output <output path>]: If not provided, prints output to stdout.\n"
967 "\t[--dump-resources]:\n\t\tPrints a basic reflection of the SPIR-V module along with other output.\n"
968 "\t[--help]:\n\t\tPrints this help message.\n"
969 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200970 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200971
972 print_help_backend();
973 print_help_common();
974 print_help_glsl();
975 print_help_msl();
976 print_help_hlsl();
977 print_help_obscure();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100978}
979
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200980static bool remap_generic(Compiler &compiler, const SmallVector<Resource> &resources, const Remap &remap)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100981{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200982 auto itr =
983 find_if(begin(resources), end(resources), [&remap](const Resource &res) { return res.name == remap.src_name; });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100984
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200985 if (itr != end(resources))
986 {
987 compiler.set_remapped_variable_state(itr->id, true);
988 compiler.set_name(itr->id, remap.dst_name);
989 compiler.set_subpass_input_remapped_components(itr->id, remap.components);
990 return true;
991 }
992 else
993 return false;
994}
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100995
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200996static vector<PlsRemap> remap_pls(const SmallVector<PLSArg> &pls_variables, const SmallVector<Resource> &resources,
997 const SmallVector<Resource> *secondary_resources)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200998{
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200999 vector<PlsRemap> ret;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001000
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001001 for (auto &pls : pls_variables)
1002 {
1003 bool found = false;
1004 for (auto &res : resources)
1005 {
1006 if (res.name == pls.name)
1007 {
1008 ret.push_back({ res.id, pls.format });
1009 found = true;
1010 break;
1011 }
1012 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001013
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001014 if (!found && secondary_resources)
1015 {
1016 for (auto &res : *secondary_resources)
1017 {
1018 if (res.name == pls.name)
1019 {
1020 ret.push_back({ res.id, pls.format });
1021 found = true;
1022 break;
1023 }
1024 }
1025 }
1026
1027 if (!found)
1028 fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n", pls.name.c_str());
1029 }
1030
1031 return ret;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001032}
1033
1034static PlsFormat pls_format(const char *str)
1035{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001036 if (!strcmp(str, "r11f_g11f_b10f"))
1037 return PlsR11FG11FB10F;
1038 else if (!strcmp(str, "r32f"))
1039 return PlsR32F;
1040 else if (!strcmp(str, "rg16f"))
1041 return PlsRG16F;
1042 else if (!strcmp(str, "rg16"))
1043 return PlsRG16;
1044 else if (!strcmp(str, "rgb10_a2"))
1045 return PlsRGB10A2;
1046 else if (!strcmp(str, "rgba8"))
1047 return PlsRGBA8;
1048 else if (!strcmp(str, "rgba8i"))
1049 return PlsRGBA8I;
1050 else if (!strcmp(str, "rgba8ui"))
1051 return PlsRGBA8UI;
1052 else if (!strcmp(str, "rg16i"))
1053 return PlsRG16I;
1054 else if (!strcmp(str, "rgb10_a2ui"))
1055 return PlsRGB10A2UI;
1056 else if (!strcmp(str, "rg16ui"))
1057 return PlsRG16UI;
1058 else if (!strcmp(str, "r32ui"))
1059 return PlsR32UI;
1060 else
1061 return PlsNone;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001062}
1063
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001064static ExecutionModel stage_to_execution_model(const std::string &stage)
1065{
1066 if (stage == "vert")
1067 return ExecutionModelVertex;
1068 else if (stage == "frag")
1069 return ExecutionModelFragment;
1070 else if (stage == "comp")
1071 return ExecutionModelGLCompute;
1072 else if (stage == "tesc")
1073 return ExecutionModelTessellationControl;
1074 else if (stage == "tese")
1075 return ExecutionModelTessellationEvaluation;
1076 else if (stage == "geom")
1077 return ExecutionModelGeometry;
Hans-Kristian Arntzen0b303aa2022-05-10 17:14:54 +02001078 else if (stage == "rgen")
1079 return ExecutionModelRayGenerationKHR;
1080 else if (stage == "rint")
1081 return ExecutionModelIntersectionKHR;
1082 else if (stage == "rahit")
1083 return ExecutionModelAnyHitKHR;
1084 else if (stage == "rchit")
1085 return ExecutionModelClosestHitKHR;
1086 else if (stage == "rmiss")
1087 return ExecutionModelMissKHR;
1088 else if (stage == "rcall")
1089 return ExecutionModelCallableKHR;
Hans-Kristian Arntzen4c345162022-09-05 12:31:22 +02001090 else if (stage == "mesh")
1091 return spv::ExecutionModelMeshEXT;
1092 else if (stage == "task")
1093 return spv::ExecutionModelTaskEXT;
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001094 else
1095 SPIRV_CROSS_THROW("Invalid stage.");
1096}
1097
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +01001098static HLSLBindingFlags hlsl_resource_type_to_flag(const std::string &arg)
1099{
1100 if (arg == "push")
1101 return HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT;
1102 else if (arg == "cbv")
1103 return HLSL_BINDING_AUTO_CBV_BIT;
1104 else if (arg == "srv")
1105 return HLSL_BINDING_AUTO_SRV_BIT;
1106 else if (arg == "uav")
1107 return HLSL_BINDING_AUTO_UAV_BIT;
1108 else if (arg == "sampler")
1109 return HLSL_BINDING_AUTO_SAMPLER_BIT;
1110 else if (arg == "all")
1111 return HLSL_BINDING_AUTO_ALL;
1112 else
1113 {
1114 fprintf(stderr, "Invalid resource type for --hlsl-auto-binding: %s\n", arg.c_str());
1115 return 0;
1116 }
1117}
1118
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +02001119static string compile_iteration(const CLIArguments &args, std::vector<uint32_t> spirv_file)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001120{
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001121 Parser spirv_parser(std::move(spirv_file));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001122 spirv_parser.parse();
1123
1124 unique_ptr<CompilerGLSL> compiler;
1125 bool combined_image_samplers = false;
1126 bool build_dummy_sampler = false;
1127
1128 if (args.cpp)
1129 {
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001130 compiler.reset(new CompilerCPP(std::move(spirv_parser.get_parsed_ir())));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001131 if (args.cpp_interface_name)
1132 static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name);
1133 }
1134 else if (args.msl)
1135 {
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001136 compiler.reset(new CompilerMSL(std::move(spirv_parser.get_parsed_ir())));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001137
1138 auto *msl_comp = static_cast<CompilerMSL *>(compiler.get());
1139 auto msl_opts = msl_comp->get_msl_options();
1140 if (args.set_msl_version)
1141 msl_opts.msl_version = args.msl_version;
1142 msl_opts.capture_output_to_buffer = args.msl_capture_output_to_buffer;
1143 msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
Lukas Hermannsffbd8012019-10-09 11:22:25 -04001144 msl_opts.invariant_float_math = args.msl_invariant_float_math;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001145 if (args.msl_ios)
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001146 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001147 msl_opts.platform = CompilerMSL::Options::iOS;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001148 msl_opts.emulate_cube_array = args.msl_emulate_cube_array;
1149 }
Chip Davisc20d5942020-10-27 21:42:33 -05001150 msl_opts.use_framebuffer_fetch_subpasses = args.msl_framebuffer_fetch;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001151 msl_opts.pad_fragment_output_components = args.msl_pad_fragment_output;
1152 msl_opts.tess_domain_origin_lower_left = args.msl_domain_lower_left;
1153 msl_opts.argument_buffers = args.msl_argument_buffers;
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +02001154 msl_opts.texture_buffer_native = args.msl_texture_buffer_native;
Chip Davis7eecf5a2019-05-31 12:06:20 -05001155 msl_opts.multiview = args.msl_multiview;
Chip Daviscab73352020-08-23 16:44:41 -05001156 msl_opts.multiview_layered_rendering = args.msl_multiview_layered_rendering;
Chip Davis6a585542019-07-12 21:50:50 -05001157 msl_opts.view_index_from_device_index = args.msl_view_index_from_device_index;
Chip Davisfb5ee4c2019-07-22 13:08:04 -05001158 msl_opts.dispatch_base = args.msl_dispatch_base;
Akio Gaule1280df62019-11-27 01:02:46 -08001159 msl_opts.enable_decoration_binding = args.msl_decoration_binding;
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +01001160 msl_opts.force_active_argument_buffer_resources = args.msl_force_active_argument_buffer_resources;
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +01001161 msl_opts.force_native_arrays = args.msl_force_native_arrays;
Chip Davisb29f83c2020-04-10 01:13:33 -05001162 msl_opts.enable_frag_depth_builtin = args.msl_enable_frag_depth_builtin;
1163 msl_opts.enable_frag_stencil_ref_builtin = args.msl_enable_frag_stencil_ref_builtin;
1164 msl_opts.enable_frag_output_mask = args.msl_enable_frag_output_mask;
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +02001165 msl_opts.enable_clip_distance_user_varying = args.msl_enable_clip_distance_user_varying;
Chip Davis688c5fc2020-02-20 21:38:28 -06001166 msl_opts.multi_patch_workgroup = args.msl_multi_patch_workgroup;
1167 msl_opts.vertex_for_tessellation = args.msl_vertex_for_tessellation;
Tomek Ponitka18f23c42020-07-22 18:37:17 +02001168 msl_opts.additional_fixed_sample_mask = args.msl_additional_fixed_sample_mask;
Chip Davis4cf840e2020-08-27 19:24:20 -05001169 msl_opts.arrayed_subpass_input = args.msl_arrayed_subpass_input;
Chip Davis21d38f72020-10-13 13:20:49 -05001170 msl_opts.r32ui_linear_texture_alignment = args.msl_r32ui_linear_texture_alignment;
1171 msl_opts.r32ui_alignment_constant_id = args.msl_r32ui_alignment_constant_id;
Chip Davis5845e002020-10-14 20:48:52 -05001172 msl_opts.texture_1D_as_2D = args.msl_texture_1d_as_2d;
Chip Davis68908352020-11-18 23:16:46 -06001173 msl_opts.ios_use_simdgroup_functions = args.msl_ios_use_simdgroup_functions;
1174 msl_opts.emulate_subgroups = args.msl_emulate_subgroups;
1175 msl_opts.fixed_subgroup_size = args.msl_fixed_subgroup_size;
Chip Davisfd738e32020-11-20 15:41:46 -06001176 msl_opts.force_sample_rate_shading = args.msl_force_sample_rate_shading;
Hans-Kristian Arntzen585fc6f2021-06-03 11:27:49 +02001177 msl_opts.ios_support_base_vertex_instance = true;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001178 msl_comp->set_msl_options(msl_opts);
1179 for (auto &v : args.msl_discrete_descriptor_sets)
1180 msl_comp->add_discrete_descriptor_set(v);
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +02001181 for (auto &v : args.msl_device_argument_buffers)
1182 msl_comp->set_argument_buffer_device_address_space(v, true);
Chip Daviscb359342019-09-05 23:14:12 -05001183 uint32_t i = 0;
1184 for (auto &v : args.msl_dynamic_buffers)
1185 msl_comp->add_dynamic_buffer(v.first, v.second, i++);
Chip Davisfedbc352019-12-16 22:58:16 -06001186 for (auto &v : args.msl_inline_uniform_blocks)
1187 msl_comp->add_inline_uniform_block(v.first, v.second);
Chip Davis5281d992020-06-13 23:03:30 -05001188 for (auto &v : args.msl_shader_inputs)
1189 msl_comp->add_msl_shader_input(v);
Chip Davis064eaeb2022-08-13 16:55:34 -07001190 for (auto &v : args.msl_shader_outputs)
1191 msl_comp->add_msl_shader_output(v);
Hans-Kristian Arntzenc87cb542021-05-21 16:47:41 +02001192 if (args.msl_combined_sampler_suffix)
1193 msl_comp->set_combined_sampler_suffix(args.msl_combined_sampler_suffix);
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001194 }
1195 else if (args.hlsl)
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001196 compiler.reset(new CompilerHLSL(std::move(spirv_parser.get_parsed_ir())));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001197 else
1198 {
1199 combined_image_samplers = !args.vulkan_semantics;
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +02001200 if (!args.vulkan_semantics || args.vulkan_glsl_disable_ext_samplerless_texture_functions)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001201 build_dummy_sampler = true;
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001202 compiler.reset(new CompilerGLSL(std::move(spirv_parser.get_parsed_ir())));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001203 }
1204
1205 if (!args.variable_type_remaps.empty())
1206 {
1207 auto remap_cb = [&](const SPIRType &, const string &name, string &out) -> void {
1208 for (const VariableTypeRemap &remap : args.variable_type_remaps)
1209 if (name == remap.variable_name)
1210 out = remap.new_variable_type;
1211 };
1212
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001213 compiler->set_variable_type_remap_callback(std::move(remap_cb));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001214 }
1215
Hans-Kristian Arntzen9c1cadd2021-03-26 15:58:41 +01001216 for (auto &masked : args.masked_stage_outputs)
1217 compiler->mask_stage_output_by_location(masked.first, masked.second);
1218 for (auto &masked : args.masked_stage_builtins)
1219 compiler->mask_stage_output_by_builtin(masked);
1220
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001221 for (auto &rename : args.entry_point_rename)
1222 compiler->rename_entry_point(rename.old_name, rename.new_name, rename.execution_model);
1223
1224 auto entry_points = compiler->get_entry_points_and_stages();
1225 auto entry_point = args.entry;
1226 ExecutionModel model = ExecutionModelMax;
1227
1228 if (!args.entry_stage.empty())
1229 {
1230 model = stage_to_execution_model(args.entry_stage);
1231 if (entry_point.empty())
1232 {
1233 // Just use the first entry point with this stage.
1234 for (auto &e : entry_points)
1235 {
1236 if (e.execution_model == model)
1237 {
1238 entry_point = e.name;
1239 break;
1240 }
1241 }
1242
1243 if (entry_point.empty())
1244 {
1245 fprintf(stderr, "Could not find an entry point with stage: %s\n", args.entry_stage.c_str());
1246 exit(EXIT_FAILURE);
1247 }
1248 }
1249 else
1250 {
1251 // Make sure both stage and name exists.
1252 bool exists = false;
1253 for (auto &e : entry_points)
1254 {
1255 if (e.execution_model == model && e.name == entry_point)
1256 {
1257 exists = true;
1258 break;
1259 }
1260 }
1261
1262 if (!exists)
1263 {
1264 fprintf(stderr, "Could not find an entry point %s with stage: %s\n", entry_point.c_str(),
1265 args.entry_stage.c_str());
1266 exit(EXIT_FAILURE);
1267 }
1268 }
1269 }
1270 else if (!entry_point.empty())
1271 {
1272 // Make sure there is just one entry point with this name, or the stage
1273 // is ambiguous.
1274 uint32_t stage_count = 0;
1275 for (auto &e : entry_points)
1276 {
1277 if (e.name == entry_point)
1278 {
1279 stage_count++;
1280 model = e.execution_model;
1281 }
1282 }
1283
1284 if (stage_count == 0)
1285 {
1286 fprintf(stderr, "There is no entry point with name: %s\n", entry_point.c_str());
1287 exit(EXIT_FAILURE);
1288 }
1289 else if (stage_count > 1)
1290 {
1291 fprintf(stderr, "There is more than one entry point with name: %s. Use --stage.\n", entry_point.c_str());
1292 exit(EXIT_FAILURE);
1293 }
1294 }
1295
1296 if (!entry_point.empty())
1297 compiler->set_entry_point(entry_point, model);
1298
1299 if (!args.set_version && !compiler->get_common_options().version)
1300 {
1301 fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
1302 print_help();
1303 exit(EXIT_FAILURE);
1304 }
1305
1306 CompilerGLSL::Options opts = compiler->get_common_options();
1307 if (args.set_version)
1308 opts.version = args.version;
1309 if (args.set_es)
1310 opts.es = args.es;
1311 opts.force_temporary = args.force_temporary;
1312 opts.separate_shader_objects = args.sso;
1313 opts.flatten_multidimensional_arrays = args.flatten_multidimensional_arrays;
1314 opts.enable_420pack_extension = args.use_420pack_extension;
1315 opts.vulkan_semantics = args.vulkan_semantics;
1316 opts.vertex.fixup_clipspace = args.fixup;
1317 opts.vertex.flip_vert_y = args.yflip;
1318 opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
1319 opts.emit_push_constant_as_uniform_buffer = args.glsl_emit_push_constant_as_ubo;
Laszlo Agocs7bc31492019-05-11 16:30:33 +02001320 opts.emit_uniform_buffer_as_plain_uniforms = args.glsl_emit_ubo_as_plain_uniforms;
Hans-Kristian Arntzen57c93d42020-07-28 15:15:24 +02001321 opts.force_flattened_io_blocks = args.glsl_force_flattened_io_blocks;
Hans-Kristian Arntzend75666b2021-06-28 12:55:37 +02001322 opts.ovr_multiview_view_count = args.glsl_ovr_multiview_view_count;
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +02001323 opts.emit_line_directives = args.emit_line_directives;
Hans-Kristian Arntzen95cd20f2020-03-04 16:41:00 +01001324 opts.enable_storage_image_qualifier_deduction = args.enable_storage_image_qualifier_deduction;
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +01001325 opts.force_zero_initialized_variables = args.force_zero_initialized_variables;
Hans-Kristian Arntzen31be74a2022-03-03 11:04:45 +01001326 opts.relax_nan_checks = args.relax_nan_checks;
Hans-Kristian Arntzenc716a9a2022-02-16 12:12:27 +01001327 opts.force_recompile_max_debug_iterations = args.force_recompile_max_debug_iterations;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001328 compiler->set_common_options(opts);
1329
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +01001330 for (auto &fetch : args.glsl_ext_framebuffer_fetch)
Hans-Kristian Arntzen26a49862021-05-21 14:21:13 +02001331 compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second, !args.glsl_ext_framebuffer_fetch_noncoherent);
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +01001332
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001333 // Set HLSL specific options.
1334 if (args.hlsl)
1335 {
1336 auto *hlsl = static_cast<CompilerHLSL *>(compiler.get());
1337 auto hlsl_opts = hlsl->get_hlsl_options();
1338 if (args.set_shader_model)
1339 {
1340 if (args.shader_model < 30)
1341 {
1342 fprintf(stderr, "Shader model earlier than 30 (3.0) not supported.\n");
1343 exit(EXIT_FAILURE);
1344 }
1345
1346 hlsl_opts.shader_model = args.shader_model;
1347 }
1348
1349 if (args.hlsl_compat)
1350 {
1351 // Enable all compat options.
1352 hlsl_opts.point_size_compat = true;
1353 hlsl_opts.point_coord_compat = true;
1354 }
1355
1356 if (hlsl_opts.shader_model <= 30)
1357 {
1358 combined_image_samplers = true;
1359 build_dummy_sampler = true;
1360 }
1361
Hans-Kristian Arntzen06ca9ac2022-07-22 12:04:33 +02001362 // If we're explicitly renaming, we probably want that name to be output.
1363 if (!args.entry_point_rename.empty())
1364 hlsl_opts.use_entry_point_name = true;
1365
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001366 hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +01001367 hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav;
Hans-Kristian Arntzen28bf9052020-04-03 11:21:41 +02001368 hlsl_opts.nonwritable_uav_texture_as_srv = args.hlsl_nonwritable_uav_texture_as_srv;
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +02001369 hlsl_opts.enable_16bit_types = args.hlsl_enable_16bit_types;
Hans-Kristian Arntzenb3344172020-11-03 11:18:32 +01001370 hlsl_opts.flatten_matrix_vertex_input_semantics = args.hlsl_flatten_matrix_vertex_input_semantics;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001371 hlsl->set_hlsl_options(hlsl_opts);
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +01001372 hlsl->set_resource_binding_flags(args.hlsl_binding_flags);
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001373 }
1374
1375 if (build_dummy_sampler)
1376 {
1377 uint32_t sampler = compiler->build_dummy_sampler_for_combined_images();
1378 if (sampler != 0)
1379 {
1380 // Set some defaults to make validation happy.
1381 compiler->set_decoration(sampler, DecorationDescriptorSet, 0);
1382 compiler->set_decoration(sampler, DecorationBinding, 0);
1383 }
1384 }
1385
1386 ShaderResources res;
1387 if (args.remove_unused)
1388 {
1389 auto active = compiler->get_active_interface_variables();
1390 res = compiler->get_shader_resources(active);
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001391 compiler->set_enabled_interface_variables(std::move(active));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001392 }
1393 else
1394 res = compiler->get_shader_resources();
1395
1396 if (args.flatten_ubo)
1397 {
1398 for (auto &ubo : res.uniform_buffers)
1399 compiler->flatten_buffer_block(ubo.id);
1400 for (auto &ubo : res.push_constant_buffers)
1401 compiler->flatten_buffer_block(ubo.id);
1402 }
1403
1404 auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs);
1405 auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr);
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001406 compiler->remap_pixel_local_storage(std::move(pls_inputs), std::move(pls_outputs));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001407
1408 for (auto &ext : args.extensions)
1409 compiler->require_extension(ext);
1410
1411 for (auto &remap : args.remaps)
1412 {
1413 if (remap_generic(*compiler, res.stage_inputs, remap))
1414 continue;
1415 if (remap_generic(*compiler, res.stage_outputs, remap))
1416 continue;
1417 if (remap_generic(*compiler, res.subpass_inputs, remap))
1418 continue;
1419 }
1420
1421 for (auto &rename : args.interface_variable_renames)
1422 {
1423 if (rename.storageClass == StorageClassInput)
1424 spirv_cross_util::rename_interface_variable(*compiler, res.stage_inputs, rename.location,
1425 rename.variable_name);
1426 else if (rename.storageClass == StorageClassOutput)
1427 spirv_cross_util::rename_interface_variable(*compiler, res.stage_outputs, rename.location,
1428 rename.variable_name);
1429 else
1430 {
1431 fprintf(stderr, "error at --rename-interface-variable <in|out> ...\n");
1432 exit(EXIT_FAILURE);
1433 }
1434 }
1435
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001436 if (combined_image_samplers)
1437 {
1438 compiler->build_combined_image_samplers();
1439 if (args.combined_samplers_inherit_bindings)
1440 spirv_cross_util::inherit_combined_sampler_bindings(*compiler);
1441
1442 // Give the remapped combined samplers new names.
1443 for (auto &remap : compiler->get_combined_image_samplers())
1444 {
1445 compiler->set_name(remap.combined_id, join("SPIRV_Cross_Combined", compiler->get_name(remap.image_id),
1446 compiler->get_name(remap.sampler_id)));
1447 }
1448 }
1449
1450 if (args.hlsl)
1451 {
1452 auto *hlsl_compiler = static_cast<CompilerHLSL *>(compiler.get());
Hans-Kristian Arntzenbb041562021-09-30 14:27:05 +02001453 hlsl_compiler->remap_num_workgroups_builtin();
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001454 }
1455
1456 if (args.hlsl)
1457 {
1458 for (auto &remap : args.hlsl_attr_remap)
1459 static_cast<CompilerHLSL *>(compiler.get())->add_vertex_attribute_remap(remap);
1460 }
1461
Hans-Kristian Arntzen941ccee2020-04-03 12:26:42 +02001462 auto ret = compiler->compile();
1463
1464 if (args.dump_resources)
1465 {
Hans-Kristian Arntzenb4a380a2021-04-16 13:32:37 +02001466 compiler->update_active_builtins();
Hans-Kristian Arntzen941ccee2020-04-03 12:26:42 +02001467 print_resources(*compiler, res);
1468 print_push_constant_resources(*compiler, res.push_constant_buffers);
1469 print_spec_constants(*compiler);
1470 print_capabilities_and_extensions(*compiler);
1471 }
1472
1473 return ret;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001474}
1475
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +02001476static int main_inner(int argc, char *argv[])
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001477{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001478 CLIArguments args;
1479 CLICallbacks cbs;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001480
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001481 cbs.add("--help", [](CLIParser &parser) {
1482 print_help();
1483 parser.end();
1484 });
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +02001485 cbs.add("--revision", [](CLIParser &parser) {
1486 print_version();
1487 parser.end();
1488 });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001489 cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); });
1490 cbs.add("--es", [&args](CLIParser &) {
1491 args.es = true;
1492 args.set_es = true;
1493 });
1494 cbs.add("--no-es", [&args](CLIParser &) {
1495 args.es = false;
1496 args.set_es = true;
1497 });
1498 cbs.add("--version", [&args](CLIParser &parser) {
1499 args.version = parser.next_uint();
1500 args.set_version = true;
1501 });
1502 cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; });
1503 cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; });
1504 cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; });
1505 cbs.add("--fixup-clipspace", [&args](CLIParser &) { args.fixup = true; });
Hans-Kristian Arntzenbdfa97a2017-08-03 13:02:59 +02001506 cbs.add("--flip-vert-y", [&args](CLIParser &) { args.yflip = true; });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001507 cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
1508 cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
Brad Davis0ad0f942018-06-21 07:43:52 -07001509 cbs.add("--reflect", [&args](CLIParser &parser) { args.reflect = parser.next_value_string("json"); });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001510 cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
Bill Hollings5ad73f32017-03-19 21:06:21 -04001511 cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +01001512 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 +02001513 cbs.add("--glsl-emit-ubo-as-plain-uniforms", [&args](CLIParser &) { args.glsl_emit_ubo_as_plain_uniforms = true; });
Hans-Kristian Arntzen57c93d42020-07-28 15:15:24 +02001514 cbs.add("--glsl-force-flattened-io-blocks", [&args](CLIParser &) { args.glsl_force_flattened_io_blocks = true; });
Hans-Kristian Arntzend75666b2021-06-28 12:55:37 +02001515 cbs.add("--glsl-ovr-multiview-view-count", [&args](CLIParser &parser) { args.glsl_ovr_multiview_view_count = parser.next_uint(); });
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +01001516 cbs.add("--glsl-remap-ext-framebuffer-fetch", [&args](CLIParser &parser) {
1517 uint32_t input_index = parser.next_uint();
1518 uint32_t color_attachment = parser.next_uint();
1519 args.glsl_ext_framebuffer_fetch.push_back({ input_index, color_attachment });
1520 });
Hans-Kristian Arntzen26a49862021-05-21 14:21:13 +02001521 cbs.add("--glsl-ext-framebuffer-fetch-noncoherent", [&args](CLIParser &) {
1522 args.glsl_ext_framebuffer_fetch_noncoherent = true;
1523 });
Hans-Kristian Arntzenb97e9b02019-08-01 09:51:44 +02001524 cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions",
1525 [&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
Hans-Kristian Arntzenc2655ab2020-03-19 14:21:42 +01001526 cbs.add("--disable-storage-image-qualifier-deduction",
1527 [&args](CLIParser &) { args.enable_storage_image_qualifier_deduction = false; });
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +01001528 cbs.add("--force-zero-initialized-variables",
1529 [&args](CLIParser &) { args.force_zero_initialized_variables = true; });
Bill Hollings5ad73f32017-03-19 21:06:21 -04001530 cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
Robert Konrad216a6812017-01-25 17:30:52 +01001531 cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
Hans-Kristian Arntzen17d88ca2017-05-04 10:10:30 +02001532 cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
Hans-Kristian Arntzen6e1c3cc2019-01-11 12:56:00 +01001533 cbs.add("--hlsl-support-nonzero-basevertex-baseinstance",
1534 [&args](CLIParser &) { args.hlsl_support_nonzero_base = true; });
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +01001535 cbs.add("--hlsl-auto-binding", [&args](CLIParser &parser) {
1536 args.hlsl_binding_flags |= hlsl_resource_type_to_flag(parser.next_string());
1537 });
Hans-Kristian Arntzenc2655ab2020-03-19 14:21:42 +01001538 cbs.add("--hlsl-force-storage-buffer-as-uav",
1539 [&args](CLIParser &) { args.hlsl_force_storage_buffer_as_uav = true; });
Hans-Kristian Arntzen28bf9052020-04-03 11:21:41 +02001540 cbs.add("--hlsl-nonwritable-uav-texture-as-srv",
1541 [&args](CLIParser &) { args.hlsl_nonwritable_uav_texture_as_srv = true; });
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +02001542 cbs.add("--hlsl-enable-16bit-types", [&args](CLIParser &) { args.hlsl_enable_16bit_types = true; });
Hans-Kristian Arntzen6fc2a052020-11-08 13:59:52 +01001543 cbs.add("--hlsl-flatten-matrix-vertex-input-semantics",
1544 [&args](CLIParser &) { args.hlsl_flatten_matrix_vertex_input_semantics = true; });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001545 cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
Hans-Kristian Arntzen3f2de0d2020-03-02 11:55:57 +01001546 cbs.add("-V", [&args](CLIParser &) { args.vulkan_semantics = true; });
Hans-Kristian Arntzen470ae7a2017-05-22 17:40:00 +02001547 cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
Hans-Kristian Arntzen6599a412017-09-08 09:56:06 +02001548 cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
Chip Davisc51e5b72019-01-08 16:33:32 -06001549 cbs.add("--msl-capture-output", [&args](CLIParser &) { args.msl_capture_output_to_buffer = true; });
Chip Davis25833212018-09-19 20:36:33 -05001550 cbs.add("--msl-swizzle-texture-samples", [&args](CLIParser &) { args.msl_swizzle_texture_samples = true; });
Chip Davis3a9af962018-09-26 20:06:05 -05001551 cbs.add("--msl-ios", [&args](CLIParser &) { args.msl_ios = true; });
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +01001552 cbs.add("--msl-pad-fragment-output", [&args](CLIParser &) { args.msl_pad_fragment_output = true; });
Chip Davis41d94242019-02-05 23:47:50 -06001553 cbs.add("--msl-domain-lower-left", [&args](CLIParser &) { args.msl_domain_lower_left = true; });
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +01001554 cbs.add("--msl-argument-buffers", [&args](CLIParser &) { args.msl_argument_buffers = true; });
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +01001555 cbs.add("--msl-discrete-descriptor-set",
1556 [&args](CLIParser &parser) { args.msl_discrete_descriptor_sets.push_back(parser.next_uint()); });
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +02001557 cbs.add("--msl-device-argument-buffer",
1558 [&args](CLIParser &parser) { args.msl_device_argument_buffers.push_back(parser.next_uint()); });
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +02001559 cbs.add("--msl-texture-buffer-native", [&args](CLIParser &) { args.msl_texture_buffer_native = true; });
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001560 cbs.add("--msl-framebuffer-fetch", [&args](CLIParser &) { args.msl_framebuffer_fetch = true; });
Lukas Hermannsffbd8012019-10-09 11:22:25 -04001561 cbs.add("--msl-invariant-float-math", [&args](CLIParser &) { args.msl_invariant_float_math = true; });
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001562 cbs.add("--msl-emulate-cube-array", [&args](CLIParser &) { args.msl_emulate_cube_array = true; });
Chip Davis7eecf5a2019-05-31 12:06:20 -05001563 cbs.add("--msl-multiview", [&args](CLIParser &) { args.msl_multiview = true; });
Chip Daviscab73352020-08-23 16:44:41 -05001564 cbs.add("--msl-multiview-no-layered-rendering",
1565 [&args](CLIParser &) { args.msl_multiview_layered_rendering = false; });
Chip Davis6a585542019-07-12 21:50:50 -05001566 cbs.add("--msl-view-index-from-device-index",
1567 [&args](CLIParser &) { args.msl_view_index_from_device_index = true; });
Chip Davisfb5ee4c2019-07-22 13:08:04 -05001568 cbs.add("--msl-dispatch-base", [&args](CLIParser &) { args.msl_dispatch_base = true; });
Chip Daviscb359342019-09-05 23:14:12 -05001569 cbs.add("--msl-dynamic-buffer", [&args](CLIParser &parser) {
1570 args.msl_argument_buffers = true;
Hans-Kristian Arntzenafa54802019-09-06 10:17:31 +02001571 // Make sure next_uint() is called in-order.
Hans-Kristian Arntzen1935f1a2019-09-06 10:11:18 +02001572 uint32_t desc_set = parser.next_uint();
1573 uint32_t binding = parser.next_uint();
1574 args.msl_dynamic_buffers.push_back(make_pair(desc_set, binding));
Chip Daviscb359342019-09-05 23:14:12 -05001575 });
Akio Gaule1280df62019-11-27 01:02:46 -08001576 cbs.add("--msl-decoration-binding", [&args](CLIParser &) { args.msl_decoration_binding = true; });
Hans-Kristian Arntzen7a411252020-01-16 15:20:59 +01001577 cbs.add("--msl-force-active-argument-buffer-resources",
1578 [&args](CLIParser &) { args.msl_force_active_argument_buffer_resources = true; });
Chip Davisfedbc352019-12-16 22:58:16 -06001579 cbs.add("--msl-inline-uniform-block", [&args](CLIParser &parser) {
1580 args.msl_argument_buffers = true;
1581 // Make sure next_uint() is called in-order.
1582 uint32_t desc_set = parser.next_uint();
1583 uint32_t binding = parser.next_uint();
1584 args.msl_inline_uniform_blocks.push_back(make_pair(desc_set, binding));
1585 });
Hans-Kristian Arntzenc2655ab2020-03-19 14:21:42 +01001586 cbs.add("--msl-force-native-arrays", [&args](CLIParser &) { args.msl_force_native_arrays = true; });
Chip Davisb29f83c2020-04-10 01:13:33 -05001587 cbs.add("--msl-disable-frag-depth-builtin", [&args](CLIParser &) { args.msl_enable_frag_depth_builtin = false; });
1588 cbs.add("--msl-disable-frag-stencil-ref-builtin",
1589 [&args](CLIParser &) { args.msl_enable_frag_stencil_ref_builtin = false; });
1590 cbs.add("--msl-enable-frag-output-mask",
1591 [&args](CLIParser &parser) { args.msl_enable_frag_output_mask = parser.next_hex_uint(); });
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +02001592 cbs.add("--msl-no-clip-distance-user-varying",
1593 [&args](CLIParser &) { args.msl_enable_clip_distance_user_varying = false; });
Chip Davis5281d992020-06-13 23:03:30 -05001594 cbs.add("--msl-shader-input", [&args](CLIParser &parser) {
Chip Davis064eaeb2022-08-13 16:55:34 -07001595 MSLShaderInterfaceVariable input;
Chip Davis5281d992020-06-13 23:03:30 -05001596 // Make sure next_uint() is called in-order.
1597 input.location = parser.next_uint();
1598 const char *format = parser.next_value_string("other");
Chip Davis688c5fc2020-02-20 21:38:28 -06001599 if (strcmp(format, "any32") == 0)
Chip Davis064eaeb2022-08-13 16:55:34 -07001600 input.format = MSL_SHADER_VARIABLE_FORMAT_ANY32;
Chip Davis688c5fc2020-02-20 21:38:28 -06001601 else if (strcmp(format, "any16") == 0)
Chip Davis064eaeb2022-08-13 16:55:34 -07001602 input.format = MSL_SHADER_VARIABLE_FORMAT_ANY16;
Chip Davis688c5fc2020-02-20 21:38:28 -06001603 else if (strcmp(format, "u16") == 0)
Chip Davis064eaeb2022-08-13 16:55:34 -07001604 input.format = MSL_SHADER_VARIABLE_FORMAT_UINT16;
Chip Davis5281d992020-06-13 23:03:30 -05001605 else if (strcmp(format, "u8") == 0)
Chip Davis064eaeb2022-08-13 16:55:34 -07001606 input.format = MSL_SHADER_VARIABLE_FORMAT_UINT8;
Chip Davis5281d992020-06-13 23:03:30 -05001607 else
Chip Davis064eaeb2022-08-13 16:55:34 -07001608 input.format = MSL_SHADER_VARIABLE_FORMAT_OTHER;
Chip Davis5281d992020-06-13 23:03:30 -05001609 input.vecsize = parser.next_uint();
1610 args.msl_shader_inputs.push_back(input);
1611 });
Chip Davis064eaeb2022-08-13 16:55:34 -07001612 cbs.add("--msl-shader-output", [&args](CLIParser &parser) {
1613 MSLShaderInterfaceVariable output;
1614 // Make sure next_uint() is called in-order.
1615 output.location = parser.next_uint();
1616 const char *format = parser.next_value_string("other");
1617 if (strcmp(format, "any32") == 0)
1618 output.format = MSL_SHADER_VARIABLE_FORMAT_ANY32;
1619 else if (strcmp(format, "any16") == 0)
1620 output.format = MSL_SHADER_VARIABLE_FORMAT_ANY16;
1621 else if (strcmp(format, "u16") == 0)
1622 output.format = MSL_SHADER_VARIABLE_FORMAT_UINT16;
1623 else if (strcmp(format, "u8") == 0)
1624 output.format = MSL_SHADER_VARIABLE_FORMAT_UINT8;
1625 else
1626 output.format = MSL_SHADER_VARIABLE_FORMAT_OTHER;
1627 output.vecsize = parser.next_uint();
1628 args.msl_shader_outputs.push_back(output);
1629 });
Chip Davis688c5fc2020-02-20 21:38:28 -06001630 cbs.add("--msl-multi-patch-workgroup", [&args](CLIParser &) { args.msl_multi_patch_workgroup = true; });
1631 cbs.add("--msl-vertex-for-tessellation", [&args](CLIParser &) { args.msl_vertex_for_tessellation = true; });
Tomek Ponitka18f23c42020-07-22 18:37:17 +02001632 cbs.add("--msl-additional-fixed-sample-mask",
1633 [&args](CLIParser &parser) { args.msl_additional_fixed_sample_mask = parser.next_hex_uint(); });
Chip Davis4cf840e2020-08-27 19:24:20 -05001634 cbs.add("--msl-arrayed-subpass-input", [&args](CLIParser &) { args.msl_arrayed_subpass_input = true; });
Chip Davis21d38f72020-10-13 13:20:49 -05001635 cbs.add("--msl-r32ui-linear-texture-align",
1636 [&args](CLIParser &parser) { args.msl_r32ui_linear_texture_alignment = parser.next_uint(); });
1637 cbs.add("--msl-r32ui-linear-texture-align-constant-id",
1638 [&args](CLIParser &parser) { args.msl_r32ui_alignment_constant_id = parser.next_uint(); });
Chip Davis5845e002020-10-14 20:48:52 -05001639 cbs.add("--msl-texture-1d-as-2d", [&args](CLIParser &) { args.msl_texture_1d_as_2d = true; });
Chip Davis68908352020-11-18 23:16:46 -06001640 cbs.add("--msl-ios-use-simdgroup-functions", [&args](CLIParser &) { args.msl_ios_use_simdgroup_functions = true; });
1641 cbs.add("--msl-emulate-subgroups", [&args](CLIParser &) { args.msl_emulate_subgroups = true; });
1642 cbs.add("--msl-fixed-subgroup-size",
1643 [&args](CLIParser &parser) { args.msl_fixed_subgroup_size = parser.next_uint(); });
Chip Davisfd738e32020-11-20 15:41:46 -06001644 cbs.add("--msl-force-sample-rate-shading", [&args](CLIParser &) { args.msl_force_sample_rate_shading = true; });
Hans-Kristian Arntzenc87cb542021-05-21 16:47:41 +02001645 cbs.add("--msl-combined-sampler-suffix", [&args](CLIParser &parser) {
1646 args.msl_combined_sampler_suffix = parser.next_string();
1647 });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001648 cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +01001649 cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
1650 auto old_name = parser.next_string();
1651 auto new_name = parser.next_string();
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001652 auto model = stage_to_execution_model(parser.next_string());
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001653 args.entry_point_rename.push_back({ old_name, new_name, std::move(model) });
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +01001654 });
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +02001655 cbs.add("--entry", [&args](CLIParser &parser) { args.entry = parser.next_string(); });
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001656 cbs.add("--stage", [&args](CLIParser &parser) { args.entry_stage = parser.next_string(); });
Hans-Kristian Arntzen36650c82017-05-22 15:30:43 +02001657 cbs.add("--separate-shader-objects", [&args](CLIParser &) { args.sso = true; });
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001658 cbs.add("--set-hlsl-vertex-input-semantic", [&args](CLIParser &parser) {
1659 HLSLVertexAttributeRemap remap;
1660 remap.location = parser.next_uint();
1661 remap.semantic = parser.next_string();
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001662 args.hlsl_attr_remap.push_back(std::move(remap));
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001663 });
1664
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001665 cbs.add("--remap", [&args](CLIParser &parser) {
Hans-Kristian Arntzenf4861422017-11-13 09:52:35 +01001666 string src = parser.next_string();
1667 string dst = parser.next_string();
1668 uint32_t components = parser.next_uint();
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001669 args.remaps.push_back({ std::move(src), std::move(dst), components });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001670 });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001671
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +02001672 cbs.add("--remap-variable-type", [&args](CLIParser &parser) {
1673 string var_name = parser.next_string();
1674 string new_type = parser.next_string();
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001675 args.variable_type_remaps.push_back({ std::move(var_name), std::move(new_type) });
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +02001676 });
1677
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001678 cbs.add("--rename-interface-variable", [&args](CLIParser &parser) {
Jason Chan3281e822017-06-25 15:16:09 +02001679 StorageClass cls = StorageClassMax;
1680 string clsStr = parser.next_string();
1681 if (clsStr == "in")
1682 cls = StorageClassInput;
1683 else if (clsStr == "out")
1684 cls = StorageClassOutput;
1685
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001686 uint32_t loc = parser.next_uint();
1687 string var_name = parser.next_string();
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001688 args.interface_variable_renames.push_back({ cls, loc, std::move(var_name) });
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001689 });
1690
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001691 cbs.add("--pls-in", [&args](CLIParser &parser) {
1692 auto fmt = pls_format(parser.next_string());
1693 auto name = parser.next_string();
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001694 args.pls_in.push_back({ std::move(fmt), std::move(name) });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001695 });
1696 cbs.add("--pls-out", [&args](CLIParser &parser) {
1697 auto fmt = pls_format(parser.next_string());
1698 auto name = parser.next_string();
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001699 args.pls_out.push_back({ std::move(fmt), std::move(name) });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001700 });
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +01001701 cbs.add("--shader-model", [&args](CLIParser &parser) {
1702 args.shader_model = parser.next_uint();
1703 args.set_shader_model = true;
1704 });
Bill Hollingsbac657d2017-11-07 15:38:13 -05001705 cbs.add("--msl-version", [&args](CLIParser &parser) {
1706 args.msl_version = parser.next_uint();
1707 args.set_msl_version = true;
1708 });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001709
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +02001710 cbs.add("--remove-unused-variables", [&args](CLIParser &) { args.remove_unused = true; });
Hans-Kristian Arntzena1b39642018-05-25 10:14:13 +02001711 cbs.add("--combined-samplers-inherit-bindings",
1712 [&args](CLIParser &) { args.combined_samplers_inherit_bindings = true; });
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +02001713
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +02001714 cbs.add("--no-support-nonzero-baseinstance", [&](CLIParser &) { args.support_nonzero_baseinstance = false; });
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +02001715 cbs.add("--emit-line-directives", [&args](CLIParser &) { args.emit_line_directives = true; });
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +02001716
Hans-Kristian Arntzen9c1cadd2021-03-26 15:58:41 +01001717 cbs.add("--mask-stage-output-location", [&](CLIParser &parser) {
1718 uint32_t location = parser.next_uint();
1719 uint32_t component = parser.next_uint();
1720 args.masked_stage_outputs.push_back({ location, component });
1721 });
1722
1723 cbs.add("--mask-stage-output-builtin", [&](CLIParser &parser) {
1724 BuiltIn masked_builtin = BuiltInMax;
1725 std::string builtin = parser.next_string();
1726 if (builtin == "Position")
1727 masked_builtin = BuiltInPosition;
1728 else if (builtin == "PointSize")
1729 masked_builtin = BuiltInPointSize;
1730 else if (builtin == "CullDistance")
1731 masked_builtin = BuiltInCullDistance;
1732 else if (builtin == "ClipDistance")
1733 masked_builtin = BuiltInClipDistance;
1734 else
1735 {
1736 print_help();
1737 exit(EXIT_FAILURE);
1738 }
1739 args.masked_stage_builtins.push_back(masked_builtin);
1740 });
1741
Hans-Kristian Arntzenc716a9a2022-02-16 12:12:27 +01001742 cbs.add("--force-recompile-max-debug-iterations", [&](CLIParser &parser) {
1743 args.force_recompile_max_debug_iterations = parser.next_uint();
1744 });
1745
Hans-Kristian Arntzen31be74a2022-03-03 11:04:45 +01001746 cbs.add("--relax-nan-checks", [&](CLIParser &) { args.relax_nan_checks = true; });
1747
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001748 cbs.default_handler = [&args](const char *value) { args.input = value; };
Hans-Kristian Arntzence18d1b2021-01-08 10:47:46 +01001749 cbs.add("-", [&args](CLIParser &) { args.input = "-"; });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001750 cbs.error_handler = [] { print_help(); };
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001751
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001752 CLIParser parser{ std::move(cbs), argc - 1, argv + 1 };
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001753 if (!parser.parse())
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001754 return EXIT_FAILURE;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001755 else if (parser.ended_state)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001756 return EXIT_SUCCESS;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001757
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001758 if (!args.input)
1759 {
1760 fprintf(stderr, "Didn't specify input file.\n");
1761 print_help();
1762 return EXIT_FAILURE;
1763 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001764
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001765 auto spirv_file = read_spirv_file(args.input);
1766 if (spirv_file.empty())
1767 return EXIT_FAILURE;
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001768
Brad Davis6c88b002018-06-18 09:30:16 -07001769 // Special case reflection because it has little to do with the path followed by code-outputting compilers
1770 if (!args.reflect.empty())
1771 {
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001772 Parser spirv_parser(std::move(spirv_file));
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001773 spirv_parser.parse();
1774
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001775 CompilerReflection compiler(std::move(spirv_parser.get_parsed_ir()));
Brad Davis6c88b002018-06-18 09:30:16 -07001776 compiler.set_format(args.reflect);
1777 auto json = compiler.compile();
1778 if (args.output)
1779 write_string_to_file(args.output, json.c_str());
1780 else
1781 printf("%s", json.c_str());
1782 return EXIT_SUCCESS;
1783 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001784
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001785 string compiled_output;
Hans-Kristian Arntzenbcb55602016-09-10 13:56:36 +02001786
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001787 if (args.iterations == 1)
Daniel Thornburgh44c33332022-03-02 23:02:38 +00001788 compiled_output = compile_iteration(args, std::move(spirv_file));
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001789 else
Hans-Kristian Arntzenbcb55602016-09-10 13:56:36 +02001790 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001791 for (unsigned i = 0; i < args.iterations; i++)
1792 compiled_output = compile_iteration(args, spirv_file);
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001793 }
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001794
1795 if (args.output)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001796 write_string_to_file(args.output, compiled_output.c_str());
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001797 else
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001798 printf("%s", compiled_output.c_str());
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +02001799
1800 return EXIT_SUCCESS;
1801}
1802
1803int main(int argc, char *argv[])
1804{
1805#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
1806 return main_inner(argc, argv);
1807#else
1808 // Make sure we catch the exception or it just disappears into the aether on Windows.
1809 try
1810 {
1811 return main_inner(argc, argv);
1812 }
1813 catch (const std::exception &e)
1814 {
1815 fprintf(stderr, "SPIRV-Cross threw an exception: %s\n", e.what());
1816 return EXIT_FAILURE;
1817 }
1818#endif
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001819}