blob: f0660bea247b9649a3aa73f447c5b1d2737eab2e [file] [log] [blame]
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001/*
Hans-Kristian Arntzenf9818f02020-01-16 15:24:37 +01002 * Copyright 2015-2020 Arm Limited
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Hans-Kristian Arntzen147e53a2016-04-04 09:36:04 +020017#include "spirv_cpp.hpp"
grovesNL94cd7772018-03-01 23:47:08 -070018#include "spirv_cross_util.hpp"
Bill Hollings77f58122017-08-11 14:54:58 -040019#include "spirv_glsl.hpp"
Robert Konrad216a6812017-01-25 17:30:52 +010020#include "spirv_hlsl.hpp"
Hans-Kristian Arntzen24df8f02017-02-04 10:26:26 +010021#include "spirv_msl.hpp"
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +020022#include "spirv_parser.hpp"
Brad Davis709d3c62018-06-03 11:16:37 -070023#include "spirv_reflect.hpp"
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020024#include <algorithm>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010025#include <cstdio>
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020026#include <cstring>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010027#include <functional>
28#include <limits>
29#include <memory>
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020030#include <stdexcept>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010031#include <unordered_map>
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010032#include <unordered_set>
33
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +020034#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
35#include "gitversion.h"
36#endif
37
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010038using namespace spv;
Hans-Kristian Arntzen9b92e682019-03-29 10:29:44 +010039using namespace SPIRV_CROSS_NAMESPACE;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010040using namespace std;
41
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010042#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +020043static inline void THROW(const char *str)
44{
45 fprintf(stderr, "SPIRV-Cross will abort: %s\n", str);
46 fflush(stderr);
47 abort();
48}
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010049#else
Hans-Kristian Arntzenc92b8392017-02-16 11:06:57 +010050#define THROW(x) throw runtime_error(x)
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010051#endif
52
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010053struct CLIParser;
54struct CLICallbacks
55{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020056 void add(const char *cli, const function<void(CLIParser &)> &func)
57 {
58 callbacks[cli] = func;
59 }
60 unordered_map<string, function<void(CLIParser &)>> callbacks;
61 function<void()> error_handler;
62 function<void(const char *)> default_handler;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010063};
64
65struct CLIParser
66{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020067 CLIParser(CLICallbacks cbs_, int argc_, char *argv_[])
68 : cbs(move(cbs_))
69 , argc(argc_)
70 , argv(argv_)
71 {
72 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010073
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020074 bool parse()
75 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010076#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020077 try
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010078#endif
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020079 {
80 while (argc && !ended_state)
81 {
82 const char *next = *argv++;
83 argc--;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010084
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020085 if (*next != '-' && cbs.default_handler)
86 {
87 cbs.default_handler(next);
88 }
89 else
90 {
91 auto itr = cbs.callbacks.find(next);
92 if (itr == ::end(cbs.callbacks))
93 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +010094 THROW("Invalid argument");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020095 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +010096
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +020097 itr->second(*this);
98 }
99 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100100
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200101 return true;
102 }
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100103#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200104 catch (...)
105 {
106 if (cbs.error_handler)
107 {
108 cbs.error_handler();
109 }
110 return false;
111 }
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100112#endif
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200113 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100114
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200115 void end()
116 {
117 ended_state = true;
118 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100119
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200120 uint32_t next_uint()
121 {
122 if (!argc)
123 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100124 THROW("Tried to parse uint, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200125 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100126
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200127 uint64_t val = stoul(*argv);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200128 if (val > numeric_limits<uint32_t>::max())
129 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100130 THROW("next_uint() out of range");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200131 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100132
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200133 argc--;
134 argv++;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100135
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200136 return uint32_t(val);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200137 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100138
Chip Davisb29f83c2020-04-10 01:13:33 -0500139 uint32_t next_hex_uint()
140 {
141 if (!argc)
142 {
143 THROW("Tried to parse uint, but nothing left in arguments");
144 }
145
146 uint64_t val = stoul(*argv, nullptr, 16);
147 if (val > numeric_limits<uint32_t>::max())
148 {
149 THROW("next_uint() out of range");
150 }
151
152 argc--;
153 argv++;
154
155 return uint32_t(val);
156 }
157
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200158 double next_double()
159 {
160 if (!argc)
161 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100162 THROW("Tried to parse double, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200163 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100164
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200165 double val = stod(*argv);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100166
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200167 argc--;
168 argv++;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100169
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200170 return val;
171 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100172
Brad Davis709d3c62018-06-03 11:16:37 -0700173 // Return a string only if it's not prefixed with `--`, otherwise return the default value
Brad Davis76204002018-06-20 10:25:38 -0700174 const char *next_value_string(const char *default_value)
Brad Davis709d3c62018-06-03 11:16:37 -0700175 {
176 if (!argc)
177 {
Brad Davis76204002018-06-20 10:25:38 -0700178 return default_value;
Brad Davis709d3c62018-06-03 11:16:37 -0700179 }
180
181 if (0 == strncmp("--", *argv, 2))
182 {
Brad Davis76204002018-06-20 10:25:38 -0700183 return default_value;
Brad Davis709d3c62018-06-03 11:16:37 -0700184 }
185
186 return next_string();
187 }
188
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200189 const char *next_string()
190 {
191 if (!argc)
192 {
Panagiotis Christopoulos Charitos7f69f932016-12-15 20:46:10 +0100193 THROW("Tried to parse string, but nothing left in arguments");
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200194 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100195
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200196 const char *ret = *argv;
197 argc--;
198 argv++;
199 return ret;
200 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100201
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200202 CLICallbacks cbs;
203 int argc;
204 char **argv;
205 bool ended_state = false;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100206};
207
Hanno4560ee22020-04-09 17:30:20 +0200208#if defined(__clang__) || defined(__GNUC__)
209#pragma GCC diagnostic push
210#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
211#elif defined(_MSC_VER)
212#pragma warning(push)
213#pragma warning(disable : 4996)
214#endif
215
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200216static vector<uint32_t> read_spirv_file(const char *path)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100217{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200218 FILE *file = fopen(path, "rb");
219 if (!file)
220 {
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +0200221 fprintf(stderr, "Failed to open SPIR-V file: %s\n", path);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200222 return {};
223 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100224
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200225 fseek(file, 0, SEEK_END);
226 long len = ftell(file) / sizeof(uint32_t);
227 rewind(file);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100228
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200229 vector<uint32_t> spirv(len);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200230 if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
231 spirv.clear();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100232
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200233 fclose(file);
234 return spirv;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100235}
236
237static bool write_string_to_file(const char *path, const char *string)
238{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200239 FILE *file = fopen(path, "w");
240 if (!file)
241 {
hesiodba381582017-05-30 17:17:51 +0300242 fprintf(stderr, "Failed to write file: %s\n", path);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200243 return false;
244 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100245
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200246 fprintf(file, "%s", string);
247 fclose(file);
248 return true;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100249}
250
Hanno4560ee22020-04-09 17:30:20 +0200251#if defined(__clang__) || defined(__GNUC__)
252#pragma GCC diagnostic pop
253#elif defined(_MSC_VER)
254#pragma warning(pop)
255#endif
256
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200257static void print_resources(const Compiler &compiler, const char *tag, const SmallVector<Resource> &resources)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100258{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200259 fprintf(stderr, "%s\n", tag);
260 fprintf(stderr, "=============\n\n");
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200261 bool print_ssbo = !strcmp(tag, "ssbos");
262
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200263 for (auto &res : resources)
264 {
265 auto &type = compiler.get_type(res.type_id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100266
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200267 if (print_ssbo && compiler.buffer_is_hlsl_counter_buffer(res.id))
268 continue;
269
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200270 // If we don't have a name, use the fallback for the type instead of the variable
271 // for SSBOs and UBOs since those are the only meaningful names to use externally.
272 // Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
273 bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100274 bool is_block = compiler.get_decoration_bitset(type.self).get(DecorationBlock) ||
275 compiler.get_decoration_bitset(type.self).get(DecorationBufferBlock);
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100276 bool is_sized_block = is_block && (compiler.get_storage_class(res.id) == StorageClassUniform ||
277 compiler.get_storage_class(res.id) == StorageClassUniformConstant);
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200278 ID fallback_id = !is_push_constant && is_block ? ID(res.base_type_id) : ID(res.id);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100279
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100280 uint32_t block_size = 0;
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200281 uint32_t runtime_array_stride = 0;
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100282 if (is_sized_block)
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200283 {
284 auto &base_type = compiler.get_type(res.base_type_id);
285 block_size = uint32_t(compiler.get_declared_struct_size(base_type));
286 runtime_array_stride = uint32_t(compiler.get_declared_struct_size_runtime_array(base_type, 1) -
287 compiler.get_declared_struct_size_runtime_array(base_type, 0));
288 }
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100289
Hans-Kristian Arntzen3a9b0452018-06-03 12:00:22 +0200290 Bitset mask;
291 if (print_ssbo)
292 mask = compiler.get_buffer_block_flags(res.id);
293 else
294 mask = compiler.get_decoration_bitset(res.id);
295
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200296 string array;
297 for (auto arr : type.array)
298 array = join("[", arr ? convert_to_string(arr) : "", "]") + array;
299
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200300 fprintf(stderr, " ID %03u : %s%s", uint32_t(res.id),
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200301 !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 +0100302
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100303 if (mask.get(DecorationLocation))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200304 fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100305 if (mask.get(DecorationDescriptorSet))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200306 fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100307 if (mask.get(DecorationBinding))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200308 fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
Hans-Kristian Arntzen941ccee2020-04-03 12:26:42 +0200309 if (static_cast<const CompilerGLSL &>(compiler).variable_is_depth_or_compare(res.id))
310 fprintf(stderr, " (comparison)");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100311 if (mask.get(DecorationInputAttachmentIndex))
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200312 fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex));
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100313 if (mask.get(DecorationNonReadable))
Hans-Kristian Arntzen97f7ab82017-01-05 18:16:33 +0100314 fprintf(stderr, " writeonly");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100315 if (mask.get(DecorationNonWritable))
Hans-Kristian Arntzen97f7ab82017-01-05 18:16:33 +0100316 fprintf(stderr, " readonly");
Hans-Kristian Arntzenb9600aa2016-11-29 09:04:28 +0100317 if (is_sized_block)
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200318 {
Hans-Kristian Arntzen2d79d362016-11-28 15:01:36 +0100319 fprintf(stderr, " (BlockSize : %u bytes)", block_size);
Hans-Kristian Arntzene86018f2018-09-10 11:08:47 +0200320 if (runtime_array_stride)
321 fprintf(stderr, " (Unsized array stride: %u bytes)", runtime_array_stride);
322 }
Hans-Kristian Arntzenec45c9e2017-04-19 17:33:14 +0200323
324 uint32_t counter_id = 0;
325 if (print_ssbo && compiler.buffer_get_hlsl_counter_buffer(res.id, counter_id))
326 fprintf(stderr, " (HLSL counter buffer ID: %u)", counter_id);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200327 fprintf(stderr, "\n");
328 }
329 fprintf(stderr, "=============\n\n");
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100330}
331
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200332static const char *execution_model_to_str(spv::ExecutionModel model)
333{
334 switch (model)
335 {
336 case spv::ExecutionModelVertex:
337 return "vertex";
338 case spv::ExecutionModelTessellationControl:
339 return "tessellation control";
340 case ExecutionModelTessellationEvaluation:
341 return "tessellation evaluation";
342 case ExecutionModelGeometry:
343 return "geometry";
344 case ExecutionModelFragment:
345 return "fragment";
346 case ExecutionModelGLCompute:
347 return "compute";
Hans-Kristian Arntzen88ce9582019-03-27 10:21:30 +0100348 case ExecutionModelRayGenerationNV:
349 return "raygenNV";
350 case ExecutionModelIntersectionNV:
351 return "intersectionNV";
352 case ExecutionModelCallableNV:
353 return "callableNV";
354 case ExecutionModelAnyHitNV:
355 return "anyhitNV";
356 case ExecutionModelClosestHitNV:
357 return "closesthitNV";
358 case ExecutionModelMissNV:
359 return "missNV";
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200360 default:
361 return "???";
362 }
363}
364
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100365static void print_resources(const Compiler &compiler, const ShaderResources &res)
366{
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100367 auto &modes = compiler.get_execution_mode_bitset();
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200368
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200369 fprintf(stderr, "Entry points:\n");
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100370 auto entry_points = compiler.get_entry_points_and_stages();
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200371 for (auto &e : entry_points)
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100372 fprintf(stderr, " %s (%s)\n", e.name.c_str(), execution_model_to_str(e.execution_model));
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200373 fprintf(stderr, "\n");
374
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200375 fprintf(stderr, "Execution modes:\n");
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100376 modes.for_each_bit([&](uint32_t i) {
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200377 auto mode = static_cast<ExecutionMode>(i);
378 uint32_t arg0 = compiler.get_execution_mode_argument(mode, 0);
379 uint32_t arg1 = compiler.get_execution_mode_argument(mode, 1);
380 uint32_t arg2 = compiler.get_execution_mode_argument(mode, 2);
381
382 switch (static_cast<ExecutionMode>(i))
383 {
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200384 case ExecutionModeInvocations:
385 fprintf(stderr, " Invocations: %u\n", arg0);
386 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200387
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200388 case ExecutionModeLocalSize:
389 fprintf(stderr, " LocalSize: (%u, %u, %u)\n", arg0, arg1, arg2);
390 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200391
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200392 case ExecutionModeOutputVertices:
393 fprintf(stderr, " OutputVertices: %u\n", arg0);
394 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200395
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200396#define CHECK_MODE(m) \
397 case ExecutionMode##m: \
398 fprintf(stderr, " %s\n", #m); \
399 break
400 CHECK_MODE(SpacingEqual);
401 CHECK_MODE(SpacingFractionalEven);
402 CHECK_MODE(SpacingFractionalOdd);
403 CHECK_MODE(VertexOrderCw);
404 CHECK_MODE(VertexOrderCcw);
405 CHECK_MODE(PixelCenterInteger);
406 CHECK_MODE(OriginUpperLeft);
407 CHECK_MODE(OriginLowerLeft);
408 CHECK_MODE(EarlyFragmentTests);
409 CHECK_MODE(PointMode);
410 CHECK_MODE(Xfb);
411 CHECK_MODE(DepthReplacing);
412 CHECK_MODE(DepthGreater);
413 CHECK_MODE(DepthLess);
414 CHECK_MODE(DepthUnchanged);
415 CHECK_MODE(LocalSizeHint);
416 CHECK_MODE(InputPoints);
417 CHECK_MODE(InputLines);
418 CHECK_MODE(InputLinesAdjacency);
419 CHECK_MODE(Triangles);
420 CHECK_MODE(InputTrianglesAdjacency);
421 CHECK_MODE(Quads);
422 CHECK_MODE(Isolines);
423 CHECK_MODE(OutputPoints);
424 CHECK_MODE(OutputLineStrip);
425 CHECK_MODE(OutputTriangleStrip);
426 CHECK_MODE(VecTypeHint);
427 CHECK_MODE(ContractionOff);
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200428
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200429 default:
430 break;
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200431 }
Hans-Kristian Arntzene8e58842018-03-12 13:09:25 +0100432 });
Hans-Kristian Arntzen3c285a12016-07-04 13:30:05 +0200433 fprintf(stderr, "\n");
434
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200435 print_resources(compiler, "subpass inputs", res.subpass_inputs);
436 print_resources(compiler, "inputs", res.stage_inputs);
437 print_resources(compiler, "outputs", res.stage_outputs);
438 print_resources(compiler, "textures", res.sampled_images);
Hans-Kristian Arntzen378fbe82016-09-11 13:47:06 +0200439 print_resources(compiler, "separate images", res.separate_images);
Hans-Kristian Arntzene9202082016-09-10 13:05:35 +0200440 print_resources(compiler, "separate samplers", res.separate_samplers);
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200441 print_resources(compiler, "images", res.storage_images);
442 print_resources(compiler, "ssbos", res.storage_buffers);
443 print_resources(compiler, "ubos", res.uniform_buffers);
444 print_resources(compiler, "push", res.push_constant_buffers);
445 print_resources(compiler, "counters", res.atomic_counters);
Hans-Kristian Arntzen88ce9582019-03-27 10:21:30 +0100446 print_resources(compiler, "acceleration structures", res.acceleration_structures);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100447}
448
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200449static void print_push_constant_resources(const Compiler &compiler, const SmallVector<Resource> &res)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100450{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200451 for (auto &block : res)
452 {
453 auto ranges = compiler.get_active_buffer_ranges(block.id);
454 fprintf(stderr, "Active members in buffer: %s\n",
455 !block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str());
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100456
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200457 fprintf(stderr, "==================\n\n");
458 for (auto &range : ranges)
459 {
Hans-Kristian Arntzen5c24d992016-07-12 21:20:18 +0200460 const auto &name = compiler.get_member_name(block.base_type_id, range.index);
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100461
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200462 fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n", range.index,
463 !name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(),
464 unsigned(range.offset), unsigned(range.range));
465 }
466 fprintf(stderr, "==================\n\n");
467 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100468}
469
Hans-Kristian Arntzen6bd545b2016-09-17 15:16:07 +0200470static void print_spec_constants(const Compiler &compiler)
471{
472 auto spec_constants = compiler.get_specialization_constants();
473 fprintf(stderr, "Specialization constants\n");
474 fprintf(stderr, "==================\n\n");
475 for (auto &c : spec_constants)
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200476 fprintf(stderr, "ID: %u, Spec ID: %u\n", uint32_t(c.id), c.constant_id);
Hans-Kristian Arntzen6bd545b2016-09-17 15:16:07 +0200477 fprintf(stderr, "==================\n\n");
478}
479
Hans-Kristian Arntzen8d7a9092017-08-15 15:27:53 +0200480static void print_capabilities_and_extensions(const Compiler &compiler)
481{
482 fprintf(stderr, "Capabilities\n");
483 fprintf(stderr, "============\n");
484 for (auto &capability : compiler.get_declared_capabilities())
485 fprintf(stderr, "Capability: %u\n", static_cast<unsigned>(capability));
486 fprintf(stderr, "============\n\n");
487
488 fprintf(stderr, "Extensions\n");
489 fprintf(stderr, "============\n");
490 for (auto &ext : compiler.get_declared_extensions())
491 fprintf(stderr, "Extension: %s\n", ext.c_str());
492 fprintf(stderr, "============\n\n");
493}
494
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100495struct PLSArg
496{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200497 PlsFormat format;
498 string name;
499};
500
501struct Remap
502{
503 string src_name;
504 string dst_name;
505 unsigned components;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100506};
507
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +0200508struct VariableTypeRemap
509{
510 string variable_name;
511 string new_variable_type;
512};
513
Hans-Kristian Arntzend89d0e02017-07-24 09:29:20 +0200514struct InterfaceVariableRename
515{
516 StorageClass storageClass;
517 uint32_t location;
518 string variable_name;
Jason Chan3281e822017-06-25 15:16:09 +0200519};
520
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100521struct CLIArguments
522{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200523 const char *input = nullptr;
524 const char *output = nullptr;
525 const char *cpp_interface_name = nullptr;
526 uint32_t version = 0;
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +0100527 uint32_t shader_model = 0;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500528 uint32_t msl_version = 0;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200529 bool es = false;
530 bool set_version = false;
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +0100531 bool set_shader_model = false;
Bill Hollingsbac657d2017-11-07 15:38:13 -0500532 bool set_msl_version = false;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200533 bool set_es = false;
534 bool dump_resources = false;
535 bool force_temporary = false;
536 bool flatten_ubo = false;
537 bool fixup = false;
Hans-Kristian Arntzenbdfa97a2017-08-03 13:02:59 +0200538 bool yflip = false;
Hans-Kristian Arntzen36650c82017-05-22 15:30:43 +0200539 bool sso = false;
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +0200540 bool support_nonzero_baseinstance = true;
Chip Davisc51e5b72019-01-08 16:33:32 -0600541 bool msl_capture_output_to_buffer = false;
Chip Davis25833212018-09-19 20:36:33 -0500542 bool msl_swizzle_texture_samples = false;
Chip Davis3a9af962018-09-26 20:06:05 -0500543 bool msl_ios = false;
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +0100544 bool msl_pad_fragment_output = false;
Chip Davis41d94242019-02-05 23:47:50 -0600545 bool msl_domain_lower_left = false;
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +0100546 bool msl_argument_buffers = false;
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +0200547 bool msl_texture_buffer_native = false;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400548 bool msl_framebuffer_fetch = false;
Lukas Hermannsffbd8012019-10-09 11:22:25 -0400549 bool msl_invariant_float_math = false;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400550 bool msl_emulate_cube_array = false;
Chip Davis7eecf5a2019-05-31 12:06:20 -0500551 bool msl_multiview = false;
Chip Daviscab73352020-08-23 16:44:41 -0500552 bool msl_multiview_layered_rendering = true;
Chip Davis6a585542019-07-12 21:50:50 -0500553 bool msl_view_index_from_device_index = false;
Chip Davisfb5ee4c2019-07-22 13:08:04 -0500554 bool msl_dispatch_base = false;
Akio Gaule1280df62019-11-27 01:02:46 -0800555 bool msl_decoration_binding = false;
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +0100556 bool msl_force_active_argument_buffer_resources = false;
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +0100557 bool msl_force_native_arrays = false;
Chip Davisb29f83c2020-04-10 01:13:33 -0500558 bool msl_enable_frag_depth_builtin = true;
559 bool msl_enable_frag_stencil_ref_builtin = true;
560 uint32_t msl_enable_frag_output_mask = 0xffffffff;
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +0200561 bool msl_enable_clip_distance_user_varying = true;
Chip Davis688c5fc2020-02-20 21:38:28 -0600562 bool msl_multi_patch_workgroup = false;
563 bool msl_vertex_for_tessellation = false;
Tomek Ponitka18f23c42020-07-22 18:37:17 +0200564 uint32_t msl_additional_fixed_sample_mask = 0xffffffff;
Chip Davis4cf840e2020-08-27 19:24:20 -0500565 bool msl_arrayed_subpass_input = false;
Chip Davis21d38f72020-10-13 13:20:49 -0500566 uint32_t msl_r32ui_linear_texture_alignment = 4;
567 uint32_t msl_r32ui_alignment_constant_id = 65535;
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +0100568 bool glsl_emit_push_constant_as_ubo = false;
Laszlo Agocs7bc31492019-05-11 16:30:33 +0200569 bool glsl_emit_ubo_as_plain_uniforms = false;
Hans-Kristian Arntzen57c93d42020-07-28 15:15:24 +0200570 bool glsl_force_flattened_io_blocks = false;
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +0100571 SmallVector<pair<uint32_t, uint32_t>> glsl_ext_framebuffer_fetch;
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +0200572 bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +0200573 bool emit_line_directives = false;
Hans-Kristian Arntzen95cd20f2020-03-04 16:41:00 +0100574 bool enable_storage_image_qualifier_deduction = true;
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +0100575 bool force_zero_initialized_variables = false;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200576 SmallVector<uint32_t> msl_discrete_descriptor_sets;
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +0200577 SmallVector<uint32_t> msl_device_argument_buffers;
Chip Daviscb359342019-09-05 23:14:12 -0500578 SmallVector<pair<uint32_t, uint32_t>> msl_dynamic_buffers;
Chip Davisfedbc352019-12-16 22:58:16 -0600579 SmallVector<pair<uint32_t, uint32_t>> msl_inline_uniform_blocks;
Chip Davis5281d992020-06-13 23:03:30 -0500580 SmallVector<MSLShaderInput> msl_shader_inputs;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200581 SmallVector<PLSArg> pls_in;
582 SmallVector<PLSArg> pls_out;
583 SmallVector<Remap> remaps;
584 SmallVector<string> extensions;
585 SmallVector<VariableTypeRemap> variable_type_remaps;
586 SmallVector<InterfaceVariableRename> interface_variable_renames;
587 SmallVector<HLSLVertexAttributeRemap> hlsl_attr_remap;
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +0200588 string entry;
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100589 string entry_stage;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100590
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100591 struct Rename
592 {
593 string old_name;
594 string new_name;
595 ExecutionModel execution_model;
596 };
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200597 SmallVector<Rename> entry_point_rename;
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +0100598
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200599 uint32_t iterations = 1;
600 bool cpp = false;
Brad Davis709d3c62018-06-03 11:16:37 -0700601 string reflect;
Bill Hollings5ad73f32017-03-19 21:06:21 -0400602 bool msl = false;
Robert Konrad216a6812017-01-25 17:30:52 +0100603 bool hlsl = false;
Hans-Kristian Arntzen17d88ca2017-05-04 10:10:30 +0200604 bool hlsl_compat = false;
Hans-Kristian Arntzena2a44d92019-01-11 10:32:14 +0100605 bool hlsl_support_nonzero_base = false;
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +0100606 bool hlsl_force_storage_buffer_as_uav = false;
Hans-Kristian Arntzen28bf9052020-04-03 11:21:41 +0200607 bool hlsl_nonwritable_uav_texture_as_srv = false;
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +0200608 bool hlsl_enable_16bit_types = false;
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100609 HLSLBindingFlags hlsl_binding_flags = 0;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200610 bool vulkan_semantics = false;
Hans-Kristian Arntzen470ae7a2017-05-22 17:40:00 +0200611 bool flatten_multidimensional_arrays = false;
Hans-Kristian Arntzen6599a412017-09-08 09:56:06 +0200612 bool use_420pack_extension = true;
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +0200613 bool remove_unused = false;
Hans-Kristian Arntzenba15dae2018-05-23 20:34:26 +0100614 bool combined_samplers_inherit_bindings = false;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100615};
616
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200617static void print_version()
618{
619#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
620 fprintf(stderr, "%s\n", SPIRV_CROSS_GIT_REVISION);
621#else
622 fprintf(stderr, "Git revision unknown. Build with CMake to create timestamp and revision info.\n");
623#endif
624}
625
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200626static void print_help_backend()
627{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200628 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200629 fprintf(stderr, "\nSelect backend:\n"
630 "\tBy default, OpenGL-style GLSL is the target, with #version and GLSL/ESSL information inherited from the SPIR-V module if present.\n"
631 "\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"
632 "\t[--msl]:\n\t\tEmit Metal Shading Language (MSL).\n"
633 "\t[--hlsl]:\n\t\tEmit HLSL.\n"
634 "\t[--reflect]:\n\t\tEmit JSON reflection.\n"
635 "\t[--cpp]:\n\t\tDEPRECATED. Emits C++ code.\n"
636 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200637 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200638}
639
640static void print_help_glsl()
641{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200642 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200643 fprintf(stderr, "\nGLSL options:\n"
644 "\t[--es]:\n\t\tForce ESSL.\n"
645 "\t[--no-es]:\n\t\tForce desktop GLSL.\n"
646 "\t[--version <GLSL version>]:\n\t\tE.g. --version 450 will emit '#version 450' in shader.\n"
647 "\t\tCode generation will depend on the version used.\n"
648 "\t[--flatten-ubo]:\n\t\tEmit UBOs as plain uniform arrays which are suitable for use with glUniform4*v().\n"
649 "\t\tThis can be an optimization on GL implementations where this is faster or works around buggy driver implementations.\n"
650 "\t\tE.g.: uniform MyUBO { vec4 a; float b, c, d, e; }; will be emitted as uniform vec4 MyUBO[2];\n"
651 "\t\tCaveat: You cannot mix and match floating-point and integer in the same UBO with this option.\n"
652 "\t\tLegacy GLSL/ESSL (where this flattening makes sense) does not support bit-casting, which would have been the obvious workaround.\n"
653 "\t[--extension ext]:\n\t\tAdd #extension string of your choosing to GLSL output.\n"
654 "\t\tUseful if you use variable name remapping to something that requires an extension unknown to SPIRV-Cross.\n"
655 "\t[--remove-unused-variables]:\n\t\tDo not emit interface variables which are not statically accessed by the shader.\n"
656 "\t[--separate-shader-objects]:\n\t\tRedeclare gl_PerVertex blocks to be suitable for desktop GL separate shader objects.\n"
657 "\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"
658 "\t[--glsl-emit-ubo-as-plain-uniforms]:\n\t\tInstead of emitting UBOs, emit them as plain uniform structs.\n"
659 "\t[--glsl-remap-ext-framebuffer-fetch input-attachment color-location]:\n\t\tRemaps an input attachment to use GL_EXT_shader_framebuffer_fetch.\n"
660 "\t\tgl_LastFragData[location] is read from. The attachment to read from must be declared as an output in the shader.\n"
661 "\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"
662 "\t\tUse of texelFetch and similar might have to create dummy samplers to work around it.\n"
663 "\t[--combined-samplers-inherit-bindings]:\n\t\tInherit binding information from the textures when building combined image samplers from separate textures and samplers.\n"
664 "\t[--no-support-nonzero-baseinstance]:\n\t\tWhen using gl_InstanceIndex with desktop GL,\n"
665 "\t\tassume that base instance is always 0, and do not attempt to fix up gl_InstanceID to match Vulkan semantics.\n"
666 "\t[--pls-in format input-name]:\n\t\tRemaps a subpass input with name into a GL_EXT_pixel_local_storage input.\n"
667 "\t\tEntry in PLS block is ordered where first --pls-in marks the first entry. Can be called multiple times.\n"
668 "\t\tFormats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui.\n"
669 "\t\tRequires ESSL.\n"
670 "\t[--pls-out format output-name]:\n\t\tRemaps a color output with name into a GL_EXT_pixel_local_storage output.\n"
671 "\t\tEntry in PLS block is ordered where first --pls-output marks the first entry. Can be called multiple times.\n"
672 "\t\tFormats allowed: r11f_g11f_b10f, r32f, rg16f, rg16, rgb10_a2, rgba8, rgba8i, rgba8ui, rg16i, rgb10_a2ui, rg16ui, r32ui.\n"
673 "\t\tRequires ESSL.\n"
674 "\t[--remap source_name target_name components]:\n\t\tRemaps a variable to a different name with N components.\n"
675 "\t\tMain use case is to remap a subpass input to gl_LastFragDepthARM.\n"
676 "\t\tE.g.:\n"
677 "\t\tuniform subpassInput uDepth;\n"
678 "\t\t--remap uDepth gl_LastFragDepthARM 1 --extension GL_ARM_shader_framebuffer_fetch_depth_stencil\n"
679 "\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"
680 "\t[--remap-variable-type <variable_name> <new_variable_type>]:\n\t\tRemaps a variable type based on name.\n"
681 "\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 +0200682 "\t[--glsl-force-flattened-io-blocks]:\n\t\tAlways flatten I/O blocks and structs.\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200683 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200684 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200685}
686
687static void print_help_hlsl()
688{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200689 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200690 fprintf(stderr, "\nHLSL options:\n"
691 "\t[--shader-model]:\n\t\tEnables a specific shader model, e.g. --shader-model 50 for SM 5.0.\n"
692 "\t[--hlsl-enable-compat]:\n\t\tAllow point size and point coord to be used, even if they won't work as expected.\n"
693 "\t\tPointSize is ignored, and PointCoord returns (0.5, 0.5).\n"
694 "\t[--hlsl-support-nonzero-basevertex-baseinstance]:\n\t\tSupport base vertex and base instance by emitting a special cbuffer declared as:\n"
695 "\t\tcbuffer SPIRV_Cross_VertexInfo { int SPIRV_Cross_BaseVertex; int SPIRV_Cross_BaseInstance; };\n"
696 "\t[--hlsl-auto-binding (push, cbv, srv, uav, sampler, all)]\n"
697 "\t\tDo not emit any : register(#) bindings for specific resource types, and rely on HLSL compiler to assign something.\n"
698 "\t[--hlsl-force-storage-buffer-as-uav]:\n\t\tAlways emit SSBOs as UAVs, even when marked as read-only.\n"
699 "\t\tNormally, SSBOs marked with NonWritable will be emitted as SRVs.\n"
700 "\t[--hlsl-nonwritable-uav-texture-as-srv]:\n\t\tEmit NonWritable storage images as SRV textures instead of UAV.\n"
701 "\t\tUsing this option messes with the type system. SPIRV-Cross cannot guarantee that this will work.\n"
702 "\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"
703 "\t\tShader must ensure that read/write state is consistent at all call sites.\n"
704 "\t[--set-hlsl-vertex-input-semantic <location> <semantic>]:\n\t\tEmits a specific vertex input semantic for a given location.\n"
705 "\t\tOtherwise, TEXCOORD# is used as semantics, where # is location.\n"
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +0200706 "\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 Arntzen165392a2020-05-28 13:23:33 +0200707 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200708 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200709}
710
711static void print_help_msl()
712{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200713 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200714 fprintf(stderr, "\nMSL options:\n"
715 "\t[--msl-version <MMmmpp>]:\n\t\tUses a specific MSL version, e.g. --msl-version 20100 for MSL 2.1.\n"
716 "\t[--msl-capture-output]:\n\t\tWrites geometry varyings to a buffer instead of as stage-outputs.\n"
717 "\t[--msl-swizzle-texture-samples]:\n\t\tWorks around lack of support for VkImageView component swizzles.\n"
718 "\t\tThis has a massive impact on performance and bloat. Do not use this unless you are absolutely forced to.\n"
719 "\t\tTo use this feature, the API side must pass down swizzle buffers.\n"
720 "\t\tShould only be used by translation layers as a last resort.\n"
721 "\t\tRecent Metal versions do not require this workaround.\n"
722 "\t[--msl-ios]:\n\t\tTarget iOS Metal instead of macOS Metal.\n"
723 "\t[--msl-pad-fragment-output]:\n\t\tAlways emit color outputs as 4-component variables.\n"
724 "\t\tIn Metal, the fragment shader must emit at least as many components as the render target format.\n"
725 "\t[--msl-domain-lower-left]:\n\t\tUse a lower-left tessellation domain.\n"
726 "\t[--msl-argument-buffers]:\n\t\tEmit Indirect Argument buffers instead of plain bindings.\n"
727 "\t\tRequires MSL 2.0 to be enabled.\n"
728 "\t[--msl-texture-buffer-native]:\n\t\tEnable native support for texel buffers. Otherwise, it is emulated as a normal texture.\n"
729 "\t[--msl-framebuffer-fetch]:\n\t\tImplement subpass inputs with frame buffer fetch.\n"
730 "\t\tEmits [[color(N)]] inputs in fragment stage.\n"
731 "\t\tRequires iOS Metal.\n"
732 "\t[--msl-emulate-cube-array]:\n\t\tEmulate cube arrays with 2D array and manual math.\n"
733 "\t[--msl-discrete-descriptor-set <index>]:\n\t\tWhen using argument buffers, forces a specific descriptor set to be implemented without argument buffers.\n"
734 "\t\tUseful for implementing push descriptors in emulation layers.\n"
735 "\t\tCan be used multiple times for each descriptor set in question.\n"
736 "\t[--msl-device-argument-buffer <descriptor set index>]:\n\t\tUse device address space to hold indirect argument buffers instead of constant.\n"
737 "\t\tComes up when trying to support argument buffers which are larger than 64 KiB.\n"
738 "\t[--msl-multiview]:\n\t\tEnable SPV_KHR_multiview emulation.\n"
Chip Daviscab73352020-08-23 16:44:41 -0500739 "\t[--msl-multiview-no-layered-rendering]:\n\t\tDon't set [[render_target_array_index]] in multiview shaders.\n"
740 "\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 +0200741 "\t[--msl-view-index-from-device-index]:\n\t\tTreat the view index as the device index instead.\n"
742 "\t\tFor multi-GPU rendering.\n"
743 "\t[--msl-dispatch-base]:\n\t\tAdd support for vkCmdDispatchBase() or similar APIs.\n"
744 "\t\tOffsets the workgroup ID based on a buffer.\n"
745 "\t[--msl-dynamic-buffer <set index> <binding>]:\n\t\tMarks a buffer as having dynamic offset.\n"
746 "\t\tThe offset is applied in the shader with pointer arithmetic.\n"
747 "\t\tUseful for argument buffers where it is non-trivial to apply dynamic offset otherwise.\n"
748 "\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"
749 "\t[--msl-decoration-binding]:\n\t\tUse SPIR-V bindings directly as MSL bindings.\n"
750 "\t\tThis does not work in the general case as there is no descriptor set support, and combined image samplers are split up.\n"
751 "\t\tHowever, if the shader author knows of binding limitations, this option will avoid the need for reflection on Metal side.\n"
752 "\t[--msl-force-active-argument-buffer-resources]:\n\t\tAlways emit resources which are part of argument buffers.\n"
753 "\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"
754 "\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"
755 "\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"
756 "\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"
757 "\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"
758 "\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"
759 "\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 -0500760 "\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 -0600761 "\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 -0500762 "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 -0600763 "\t\tUseful if shader stage interfaces don't match up, as pipeline creation might otherwise fail.\n"
764 "\t[--msl-multi-patch-workgroup]:\n\t\tUse the new style of tessellation control processing, where multiple patches are processed per workgroup.\n"
765 "\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"
766 "\t\tIn addition, this style also passes input variables in buffers directly instead of using vertex attribute processing.\n"
767 "\t\tIn a future version of SPIRV-Cross, this will become the default.\n"
768 "\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 +0200769 "\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"
770 "\t[--msl-additional-fixed-sample-mask <mask>]:\n"
Chip Davis4cf840e2020-08-27 19:24:20 -0500771 "\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"
772 "\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 -0500773 "\t\tThis option has no effect if multiview is also enabled.\n"
774 "\t[--msl-r32ui-linear-texture-align <alignment>]:\n\t\tThe required alignment of linear textures of format MTLPixelFormatR32Uint.\n"
775 "\t\tThis is used to align the row stride for atomic accesses to such images.\n"
776 "\t[--msl-r32ui-linear-texture-align-constant-id <id>]:\n\t\tThe function constant ID to use for the linear texture alignment.\n"
777 "\t\tOn MSL 1.2 or later, you can override the alignment by setting this function constant.\n");
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200778 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200779}
780
781static void print_help_common()
782{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200783 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200784 fprintf(stderr, "\nCommon options:\n"
785 "\t[--entry name]:\n\t\tUse a specific entry point. By default, the first entry point in the module is used.\n"
786 "\t[--stage <stage (vert, frag, geom, tesc, tese comp)>]:\n\t\tForces use of a certain shader stage.\n"
787 "\t\tCan disambiguate the entry point if more than one entry point exists with same name, but different stage.\n"
788 "\t[--emit-line-directives]:\n\t\tIf SPIR-V has OpLine directives, aim to emit those accurately in output code as well.\n"
789 "\t[--rename-entry-point <old> <new> <stage>]:\n\t\tRenames an entry point from what is declared in SPIR-V to code output.\n"
790 "\t\tMostly relevant for HLSL or MSL.\n"
791 "\t[--rename-interface-variable <in|out> <location> <new_variable_name>]:\n\t\tRename an interface variable based on location decoration.\n"
792 "\t[--force-zero-initialized-variables]:\n\t\tForces temporary variables to be initialized to zero.\n"
793 "\t\tCan be useful in environments where compilers do not allow potentially uninitialized variables.\n"
794 "\t\tThis usually comes up with Phi temporaries.\n"
795 "\t[--fixup-clipspace]:\n\t\tFixup Z clip-space at the end of a vertex shader. The behavior is backend-dependent.\n"
796 "\t\tGLSL: Rewrites [0, w] Z range (D3D/Metal/Vulkan) to GL-style [-w, w].\n"
797 "\t\tHLSL/MSL: Rewrites [-w, w] Z range (GL) to D3D/Metal/Vulkan-style [0, w].\n"
798 "\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"
799 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200800 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200801}
802
803static void print_help_obscure()
804{
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200805 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200806 fprintf(stderr, "\nObscure options:\n"
807 "\tThese options are not meant to be used on a regular basis. They have some occasional uses in the test suite.\n"
808
809 "\t[--force-temporary]:\n\t\tAggressively emit temporary expressions instead of forwarding expressions. Very rarely used and under-tested.\n"
810 "\t[--revision]:\n\t\tPrints build timestamp and Git commit information (updated when cmake is configured).\n"
811 "\t[--iterations iter]:\n\t\tRecompiles the same shader over and over, benchmarking related.\n"
812 "\t[--disable-storage-image-qualifier-deduction]:\n\t\tIf storage images are received without any nonwritable or nonreadable information,\n"""
813 "\t\tdo not attempt to analyze usage, and always emit read/write state.\n"
814 "\t[--flatten-multidimensional-arrays]:\n\t\tDo not support multi-dimensional arrays and flatten them to one dimension.\n"
815 "\t[--cpp-interface-name <name>]:\n\t\tEmit a specific class name in C++ codegen.\n"
816 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200817 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200818}
819
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100820static void print_help()
821{
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +0200822 print_version();
823
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200824 // clang-format off
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200825 fprintf(stderr, "Usage: spirv-cross <...>\n"
826 "\nBasic:\n"
Hans-Kristian Arntzene30a9422018-04-18 16:19:55 +0200827 "\t[SPIR-V file]\n"
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200828 "\t[--output <output path>]: If not provided, prints output to stdout.\n"
829 "\t[--dump-resources]:\n\t\tPrints a basic reflection of the SPIR-V module along with other output.\n"
830 "\t[--help]:\n\t\tPrints this help message.\n"
831 );
Hans-Kristian Arntzend573a952020-07-01 11:42:58 +0200832 // clang-format on
Hans-Kristian Arntzen165392a2020-05-28 13:23:33 +0200833
834 print_help_backend();
835 print_help_common();
836 print_help_glsl();
837 print_help_msl();
838 print_help_hlsl();
839 print_help_obscure();
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100840}
841
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200842static bool remap_generic(Compiler &compiler, const SmallVector<Resource> &resources, const Remap &remap)
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100843{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200844 auto itr =
845 find_if(begin(resources), end(resources), [&remap](const Resource &res) { return res.name == remap.src_name; });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100846
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200847 if (itr != end(resources))
848 {
849 compiler.set_remapped_variable_state(itr->id, true);
850 compiler.set_name(itr->id, remap.dst_name);
851 compiler.set_subpass_input_remapped_components(itr->id, remap.components);
852 return true;
853 }
854 else
855 return false;
856}
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100857
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200858static vector<PlsRemap> remap_pls(const SmallVector<PLSArg> &pls_variables, const SmallVector<Resource> &resources,
859 const SmallVector<Resource> *secondary_resources)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200860{
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200861 vector<PlsRemap> ret;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100862
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200863 for (auto &pls : pls_variables)
864 {
865 bool found = false;
866 for (auto &res : resources)
867 {
868 if (res.name == pls.name)
869 {
870 ret.push_back({ res.id, pls.format });
871 found = true;
872 break;
873 }
874 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100875
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200876 if (!found && secondary_resources)
877 {
878 for (auto &res : *secondary_resources)
879 {
880 if (res.name == pls.name)
881 {
882 ret.push_back({ res.id, pls.format });
883 found = true;
884 break;
885 }
886 }
887 }
888
889 if (!found)
890 fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n", pls.name.c_str());
891 }
892
893 return ret;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100894}
895
896static PlsFormat pls_format(const char *str)
897{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +0200898 if (!strcmp(str, "r11f_g11f_b10f"))
899 return PlsR11FG11FB10F;
900 else if (!strcmp(str, "r32f"))
901 return PlsR32F;
902 else if (!strcmp(str, "rg16f"))
903 return PlsRG16F;
904 else if (!strcmp(str, "rg16"))
905 return PlsRG16;
906 else if (!strcmp(str, "rgb10_a2"))
907 return PlsRGB10A2;
908 else if (!strcmp(str, "rgba8"))
909 return PlsRGBA8;
910 else if (!strcmp(str, "rgba8i"))
911 return PlsRGBA8I;
912 else if (!strcmp(str, "rgba8ui"))
913 return PlsRGBA8UI;
914 else if (!strcmp(str, "rg16i"))
915 return PlsRG16I;
916 else if (!strcmp(str, "rgb10_a2ui"))
917 return PlsRGB10A2UI;
918 else if (!strcmp(str, "rg16ui"))
919 return PlsRG16UI;
920 else if (!strcmp(str, "r32ui"))
921 return PlsR32UI;
922 else
923 return PlsNone;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +0100924}
925
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +0100926static ExecutionModel stage_to_execution_model(const std::string &stage)
927{
928 if (stage == "vert")
929 return ExecutionModelVertex;
930 else if (stage == "frag")
931 return ExecutionModelFragment;
932 else if (stage == "comp")
933 return ExecutionModelGLCompute;
934 else if (stage == "tesc")
935 return ExecutionModelTessellationControl;
936 else if (stage == "tese")
937 return ExecutionModelTessellationEvaluation;
938 else if (stage == "geom")
939 return ExecutionModelGeometry;
940 else
941 SPIRV_CROSS_THROW("Invalid stage.");
942}
943
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +0100944static HLSLBindingFlags hlsl_resource_type_to_flag(const std::string &arg)
945{
946 if (arg == "push")
947 return HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT;
948 else if (arg == "cbv")
949 return HLSL_BINDING_AUTO_CBV_BIT;
950 else if (arg == "srv")
951 return HLSL_BINDING_AUTO_SRV_BIT;
952 else if (arg == "uav")
953 return HLSL_BINDING_AUTO_UAV_BIT;
954 else if (arg == "sampler")
955 return HLSL_BINDING_AUTO_SAMPLER_BIT;
956 else if (arg == "all")
957 return HLSL_BINDING_AUTO_ALL;
958 else
959 {
960 fprintf(stderr, "Invalid resource type for --hlsl-auto-binding: %s\n", arg.c_str());
961 return 0;
962 }
963}
964
Hans-Kristian Arntzen3fe57d32019-04-09 12:46:23 +0200965static string compile_iteration(const CLIArguments &args, std::vector<uint32_t> spirv_file)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200966{
967 Parser spirv_parser(move(spirv_file));
968 spirv_parser.parse();
969
970 unique_ptr<CompilerGLSL> compiler;
971 bool combined_image_samplers = false;
972 bool build_dummy_sampler = false;
973
974 if (args.cpp)
975 {
976 compiler.reset(new CompilerCPP(move(spirv_parser.get_parsed_ir())));
977 if (args.cpp_interface_name)
978 static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name);
979 }
980 else if (args.msl)
981 {
982 compiler.reset(new CompilerMSL(move(spirv_parser.get_parsed_ir())));
983
984 auto *msl_comp = static_cast<CompilerMSL *>(compiler.get());
985 auto msl_opts = msl_comp->get_msl_options();
986 if (args.set_msl_version)
987 msl_opts.msl_version = args.msl_version;
988 msl_opts.capture_output_to_buffer = args.msl_capture_output_to_buffer;
989 msl_opts.swizzle_texture_samples = args.msl_swizzle_texture_samples;
Lukas Hermannsffbd8012019-10-09 11:22:25 -0400990 msl_opts.invariant_float_math = args.msl_invariant_float_math;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200991 if (args.msl_ios)
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400992 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200993 msl_opts.platform = CompilerMSL::Options::iOS;
Lukas Hermannsf3a6d282019-09-27 15:49:54 -0400994 msl_opts.ios_use_framebuffer_fetch_subpasses = args.msl_framebuffer_fetch;
995 msl_opts.emulate_cube_array = args.msl_emulate_cube_array;
996 }
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +0200997 msl_opts.pad_fragment_output_components = args.msl_pad_fragment_output;
998 msl_opts.tess_domain_origin_lower_left = args.msl_domain_lower_left;
999 msl_opts.argument_buffers = args.msl_argument_buffers;
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +02001000 msl_opts.texture_buffer_native = args.msl_texture_buffer_native;
Chip Davis7eecf5a2019-05-31 12:06:20 -05001001 msl_opts.multiview = args.msl_multiview;
Chip Daviscab73352020-08-23 16:44:41 -05001002 msl_opts.multiview_layered_rendering = args.msl_multiview_layered_rendering;
Chip Davis6a585542019-07-12 21:50:50 -05001003 msl_opts.view_index_from_device_index = args.msl_view_index_from_device_index;
Chip Davisfb5ee4c2019-07-22 13:08:04 -05001004 msl_opts.dispatch_base = args.msl_dispatch_base;
Akio Gaule1280df62019-11-27 01:02:46 -08001005 msl_opts.enable_decoration_binding = args.msl_decoration_binding;
Hans-Kristian Arntzenc3bd1362020-01-16 11:07:30 +01001006 msl_opts.force_active_argument_buffer_resources = args.msl_force_active_argument_buffer_resources;
Hans-Kristian Arntzenc9d4f9c2020-02-24 12:47:14 +01001007 msl_opts.force_native_arrays = args.msl_force_native_arrays;
Chip Davisb29f83c2020-04-10 01:13:33 -05001008 msl_opts.enable_frag_depth_builtin = args.msl_enable_frag_depth_builtin;
1009 msl_opts.enable_frag_stencil_ref_builtin = args.msl_enable_frag_stencil_ref_builtin;
1010 msl_opts.enable_frag_output_mask = args.msl_enable_frag_output_mask;
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +02001011 msl_opts.enable_clip_distance_user_varying = args.msl_enable_clip_distance_user_varying;
Chip Davis688c5fc2020-02-20 21:38:28 -06001012 msl_opts.multi_patch_workgroup = args.msl_multi_patch_workgroup;
1013 msl_opts.vertex_for_tessellation = args.msl_vertex_for_tessellation;
Tomek Ponitka18f23c42020-07-22 18:37:17 +02001014 msl_opts.additional_fixed_sample_mask = args.msl_additional_fixed_sample_mask;
Chip Davis4cf840e2020-08-27 19:24:20 -05001015 msl_opts.arrayed_subpass_input = args.msl_arrayed_subpass_input;
Chip Davis21d38f72020-10-13 13:20:49 -05001016 msl_opts.r32ui_linear_texture_alignment = args.msl_r32ui_linear_texture_alignment;
1017 msl_opts.r32ui_alignment_constant_id = args.msl_r32ui_alignment_constant_id;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001018 msl_comp->set_msl_options(msl_opts);
1019 for (auto &v : args.msl_discrete_descriptor_sets)
1020 msl_comp->add_discrete_descriptor_set(v);
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +02001021 for (auto &v : args.msl_device_argument_buffers)
1022 msl_comp->set_argument_buffer_device_address_space(v, true);
Chip Daviscb359342019-09-05 23:14:12 -05001023 uint32_t i = 0;
1024 for (auto &v : args.msl_dynamic_buffers)
1025 msl_comp->add_dynamic_buffer(v.first, v.second, i++);
Chip Davisfedbc352019-12-16 22:58:16 -06001026 for (auto &v : args.msl_inline_uniform_blocks)
1027 msl_comp->add_inline_uniform_block(v.first, v.second);
Chip Davis5281d992020-06-13 23:03:30 -05001028 for (auto &v : args.msl_shader_inputs)
1029 msl_comp->add_msl_shader_input(v);
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001030 }
1031 else if (args.hlsl)
1032 compiler.reset(new CompilerHLSL(move(spirv_parser.get_parsed_ir())));
1033 else
1034 {
1035 combined_image_samplers = !args.vulkan_semantics;
Hans-Kristian Arntzen12ca9d12019-07-25 11:07:14 +02001036 if (!args.vulkan_semantics || args.vulkan_glsl_disable_ext_samplerless_texture_functions)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001037 build_dummy_sampler = true;
1038 compiler.reset(new CompilerGLSL(move(spirv_parser.get_parsed_ir())));
1039 }
1040
1041 if (!args.variable_type_remaps.empty())
1042 {
1043 auto remap_cb = [&](const SPIRType &, const string &name, string &out) -> void {
1044 for (const VariableTypeRemap &remap : args.variable_type_remaps)
1045 if (name == remap.variable_name)
1046 out = remap.new_variable_type;
1047 };
1048
1049 compiler->set_variable_type_remap_callback(move(remap_cb));
1050 }
1051
1052 for (auto &rename : args.entry_point_rename)
1053 compiler->rename_entry_point(rename.old_name, rename.new_name, rename.execution_model);
1054
1055 auto entry_points = compiler->get_entry_points_and_stages();
1056 auto entry_point = args.entry;
1057 ExecutionModel model = ExecutionModelMax;
1058
1059 if (!args.entry_stage.empty())
1060 {
1061 model = stage_to_execution_model(args.entry_stage);
1062 if (entry_point.empty())
1063 {
1064 // Just use the first entry point with this stage.
1065 for (auto &e : entry_points)
1066 {
1067 if (e.execution_model == model)
1068 {
1069 entry_point = e.name;
1070 break;
1071 }
1072 }
1073
1074 if (entry_point.empty())
1075 {
1076 fprintf(stderr, "Could not find an entry point with stage: %s\n", args.entry_stage.c_str());
1077 exit(EXIT_FAILURE);
1078 }
1079 }
1080 else
1081 {
1082 // Make sure both stage and name exists.
1083 bool exists = false;
1084 for (auto &e : entry_points)
1085 {
1086 if (e.execution_model == model && e.name == entry_point)
1087 {
1088 exists = true;
1089 break;
1090 }
1091 }
1092
1093 if (!exists)
1094 {
1095 fprintf(stderr, "Could not find an entry point %s with stage: %s\n", entry_point.c_str(),
1096 args.entry_stage.c_str());
1097 exit(EXIT_FAILURE);
1098 }
1099 }
1100 }
1101 else if (!entry_point.empty())
1102 {
1103 // Make sure there is just one entry point with this name, or the stage
1104 // is ambiguous.
1105 uint32_t stage_count = 0;
1106 for (auto &e : entry_points)
1107 {
1108 if (e.name == entry_point)
1109 {
1110 stage_count++;
1111 model = e.execution_model;
1112 }
1113 }
1114
1115 if (stage_count == 0)
1116 {
1117 fprintf(stderr, "There is no entry point with name: %s\n", entry_point.c_str());
1118 exit(EXIT_FAILURE);
1119 }
1120 else if (stage_count > 1)
1121 {
1122 fprintf(stderr, "There is more than one entry point with name: %s. Use --stage.\n", entry_point.c_str());
1123 exit(EXIT_FAILURE);
1124 }
1125 }
1126
1127 if (!entry_point.empty())
1128 compiler->set_entry_point(entry_point, model);
1129
1130 if (!args.set_version && !compiler->get_common_options().version)
1131 {
1132 fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
1133 print_help();
1134 exit(EXIT_FAILURE);
1135 }
1136
1137 CompilerGLSL::Options opts = compiler->get_common_options();
1138 if (args.set_version)
1139 opts.version = args.version;
1140 if (args.set_es)
1141 opts.es = args.es;
1142 opts.force_temporary = args.force_temporary;
1143 opts.separate_shader_objects = args.sso;
1144 opts.flatten_multidimensional_arrays = args.flatten_multidimensional_arrays;
1145 opts.enable_420pack_extension = args.use_420pack_extension;
1146 opts.vulkan_semantics = args.vulkan_semantics;
1147 opts.vertex.fixup_clipspace = args.fixup;
1148 opts.vertex.flip_vert_y = args.yflip;
1149 opts.vertex.support_nonzero_base_instance = args.support_nonzero_baseinstance;
1150 opts.emit_push_constant_as_uniform_buffer = args.glsl_emit_push_constant_as_ubo;
Laszlo Agocs7bc31492019-05-11 16:30:33 +02001151 opts.emit_uniform_buffer_as_plain_uniforms = args.glsl_emit_ubo_as_plain_uniforms;
Hans-Kristian Arntzen57c93d42020-07-28 15:15:24 +02001152 opts.force_flattened_io_blocks = args.glsl_force_flattened_io_blocks;
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +02001153 opts.emit_line_directives = args.emit_line_directives;
Hans-Kristian Arntzen95cd20f2020-03-04 16:41:00 +01001154 opts.enable_storage_image_qualifier_deduction = args.enable_storage_image_qualifier_deduction;
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +01001155 opts.force_zero_initialized_variables = args.force_zero_initialized_variables;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001156 compiler->set_common_options(opts);
1157
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +01001158 for (auto &fetch : args.glsl_ext_framebuffer_fetch)
1159 compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second);
1160
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001161 // Set HLSL specific options.
1162 if (args.hlsl)
1163 {
1164 auto *hlsl = static_cast<CompilerHLSL *>(compiler.get());
1165 auto hlsl_opts = hlsl->get_hlsl_options();
1166 if (args.set_shader_model)
1167 {
1168 if (args.shader_model < 30)
1169 {
1170 fprintf(stderr, "Shader model earlier than 30 (3.0) not supported.\n");
1171 exit(EXIT_FAILURE);
1172 }
1173
1174 hlsl_opts.shader_model = args.shader_model;
1175 }
1176
1177 if (args.hlsl_compat)
1178 {
1179 // Enable all compat options.
1180 hlsl_opts.point_size_compat = true;
1181 hlsl_opts.point_coord_compat = true;
1182 }
1183
1184 if (hlsl_opts.shader_model <= 30)
1185 {
1186 combined_image_samplers = true;
1187 build_dummy_sampler = true;
1188 }
1189
1190 hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
Hans-Kristian Arntzenc27e1ef2020-03-04 16:32:52 +01001191 hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav;
Hans-Kristian Arntzen28bf9052020-04-03 11:21:41 +02001192 hlsl_opts.nonwritable_uav_texture_as_srv = args.hlsl_nonwritable_uav_texture_as_srv;
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +02001193 hlsl_opts.enable_16bit_types = args.hlsl_enable_16bit_types;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001194 hlsl->set_hlsl_options(hlsl_opts);
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +01001195 hlsl->set_resource_binding_flags(args.hlsl_binding_flags);
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001196 }
1197
1198 if (build_dummy_sampler)
1199 {
1200 uint32_t sampler = compiler->build_dummy_sampler_for_combined_images();
1201 if (sampler != 0)
1202 {
1203 // Set some defaults to make validation happy.
1204 compiler->set_decoration(sampler, DecorationDescriptorSet, 0);
1205 compiler->set_decoration(sampler, DecorationBinding, 0);
1206 }
1207 }
1208
1209 ShaderResources res;
1210 if (args.remove_unused)
1211 {
1212 auto active = compiler->get_active_interface_variables();
1213 res = compiler->get_shader_resources(active);
1214 compiler->set_enabled_interface_variables(move(active));
1215 }
1216 else
1217 res = compiler->get_shader_resources();
1218
1219 if (args.flatten_ubo)
1220 {
1221 for (auto &ubo : res.uniform_buffers)
1222 compiler->flatten_buffer_block(ubo.id);
1223 for (auto &ubo : res.push_constant_buffers)
1224 compiler->flatten_buffer_block(ubo.id);
1225 }
1226
1227 auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs);
1228 auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr);
1229 compiler->remap_pixel_local_storage(move(pls_inputs), move(pls_outputs));
1230
1231 for (auto &ext : args.extensions)
1232 compiler->require_extension(ext);
1233
1234 for (auto &remap : args.remaps)
1235 {
1236 if (remap_generic(*compiler, res.stage_inputs, remap))
1237 continue;
1238 if (remap_generic(*compiler, res.stage_outputs, remap))
1239 continue;
1240 if (remap_generic(*compiler, res.subpass_inputs, remap))
1241 continue;
1242 }
1243
1244 for (auto &rename : args.interface_variable_renames)
1245 {
1246 if (rename.storageClass == StorageClassInput)
1247 spirv_cross_util::rename_interface_variable(*compiler, res.stage_inputs, rename.location,
1248 rename.variable_name);
1249 else if (rename.storageClass == StorageClassOutput)
1250 spirv_cross_util::rename_interface_variable(*compiler, res.stage_outputs, rename.location,
1251 rename.variable_name);
1252 else
1253 {
1254 fprintf(stderr, "error at --rename-interface-variable <in|out> ...\n");
1255 exit(EXIT_FAILURE);
1256 }
1257 }
1258
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001259 if (combined_image_samplers)
1260 {
1261 compiler->build_combined_image_samplers();
1262 if (args.combined_samplers_inherit_bindings)
1263 spirv_cross_util::inherit_combined_sampler_bindings(*compiler);
1264
1265 // Give the remapped combined samplers new names.
1266 for (auto &remap : compiler->get_combined_image_samplers())
1267 {
1268 compiler->set_name(remap.combined_id, join("SPIRV_Cross_Combined", compiler->get_name(remap.image_id),
1269 compiler->get_name(remap.sampler_id)));
1270 }
1271 }
1272
1273 if (args.hlsl)
1274 {
1275 auto *hlsl_compiler = static_cast<CompilerHLSL *>(compiler.get());
1276 uint32_t new_builtin = hlsl_compiler->remap_num_workgroups_builtin();
1277 if (new_builtin)
1278 {
1279 hlsl_compiler->set_decoration(new_builtin, DecorationDescriptorSet, 0);
1280 hlsl_compiler->set_decoration(new_builtin, DecorationBinding, 0);
1281 }
1282 }
1283
1284 if (args.hlsl)
1285 {
1286 for (auto &remap : args.hlsl_attr_remap)
1287 static_cast<CompilerHLSL *>(compiler.get())->add_vertex_attribute_remap(remap);
1288 }
1289
Hans-Kristian Arntzen941ccee2020-04-03 12:26:42 +02001290 auto ret = compiler->compile();
1291
1292 if (args.dump_resources)
1293 {
1294 print_resources(*compiler, res);
1295 print_push_constant_resources(*compiler, res.push_constant_buffers);
1296 print_spec_constants(*compiler);
1297 print_capabilities_and_extensions(*compiler);
1298 }
1299
1300 return ret;
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001301}
1302
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +02001303static int main_inner(int argc, char *argv[])
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001304{
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001305 CLIArguments args;
1306 CLICallbacks cbs;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001307
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001308 cbs.add("--help", [](CLIParser &parser) {
1309 print_help();
1310 parser.end();
1311 });
Hans-Kristian Arntzen0b9a8842019-05-24 15:23:29 +02001312 cbs.add("--revision", [](CLIParser &parser) {
1313 print_version();
1314 parser.end();
1315 });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001316 cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); });
1317 cbs.add("--es", [&args](CLIParser &) {
1318 args.es = true;
1319 args.set_es = true;
1320 });
1321 cbs.add("--no-es", [&args](CLIParser &) {
1322 args.es = false;
1323 args.set_es = true;
1324 });
1325 cbs.add("--version", [&args](CLIParser &parser) {
1326 args.version = parser.next_uint();
1327 args.set_version = true;
1328 });
1329 cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; });
1330 cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; });
1331 cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; });
1332 cbs.add("--fixup-clipspace", [&args](CLIParser &) { args.fixup = true; });
Hans-Kristian Arntzenbdfa97a2017-08-03 13:02:59 +02001333 cbs.add("--flip-vert-y", [&args](CLIParser &) { args.yflip = true; });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001334 cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
1335 cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
Brad Davis0ad0f942018-06-21 07:43:52 -07001336 cbs.add("--reflect", [&args](CLIParser &parser) { args.reflect = parser.next_value_string("json"); });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001337 cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
Bill Hollings5ad73f32017-03-19 21:06:21 -04001338 cbs.add("--metal", [&args](CLIParser &) { args.msl = true; }); // Legacy compatibility
Hans-Kristian Arntzen04748482019-03-19 10:58:37 +01001339 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 +02001340 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 +02001341 cbs.add("--glsl-force-flattened-io-blocks", [&args](CLIParser &) { args.glsl_force_flattened_io_blocks = true; });
Hans-Kristian Arntzen04e877d2020-03-19 14:20:37 +01001342 cbs.add("--glsl-remap-ext-framebuffer-fetch", [&args](CLIParser &parser) {
1343 uint32_t input_index = parser.next_uint();
1344 uint32_t color_attachment = parser.next_uint();
1345 args.glsl_ext_framebuffer_fetch.push_back({ input_index, color_attachment });
1346 });
Hans-Kristian Arntzenb97e9b02019-08-01 09:51:44 +02001347 cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions",
1348 [&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
Hans-Kristian Arntzenc2655ab2020-03-19 14:21:42 +01001349 cbs.add("--disable-storage-image-qualifier-deduction",
1350 [&args](CLIParser &) { args.enable_storage_image_qualifier_deduction = false; });
Hans-Kristian Arntzenb8905bb2020-03-26 11:21:23 +01001351 cbs.add("--force-zero-initialized-variables",
1352 [&args](CLIParser &) { args.force_zero_initialized_variables = true; });
Bill Hollings5ad73f32017-03-19 21:06:21 -04001353 cbs.add("--msl", [&args](CLIParser &) { args.msl = true; });
Robert Konrad216a6812017-01-25 17:30:52 +01001354 cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
Hans-Kristian Arntzen17d88ca2017-05-04 10:10:30 +02001355 cbs.add("--hlsl-enable-compat", [&args](CLIParser &) { args.hlsl_compat = true; });
Hans-Kristian Arntzen6e1c3cc2019-01-11 12:56:00 +01001356 cbs.add("--hlsl-support-nonzero-basevertex-baseinstance",
1357 [&args](CLIParser &) { args.hlsl_support_nonzero_base = true; });
Hans-Kristian Arntzene38cbb92019-11-12 10:49:01 +01001358 cbs.add("--hlsl-auto-binding", [&args](CLIParser &parser) {
1359 args.hlsl_binding_flags |= hlsl_resource_type_to_flag(parser.next_string());
1360 });
Hans-Kristian Arntzenc2655ab2020-03-19 14:21:42 +01001361 cbs.add("--hlsl-force-storage-buffer-as-uav",
1362 [&args](CLIParser &) { args.hlsl_force_storage_buffer_as_uav = true; });
Hans-Kristian Arntzen28bf9052020-04-03 11:21:41 +02001363 cbs.add("--hlsl-nonwritable-uav-texture-as-srv",
1364 [&args](CLIParser &) { args.hlsl_nonwritable_uav_texture_as_srv = true; });
Hans-Kristian Arntzen2d520062020-06-04 11:35:21 +02001365 cbs.add("--hlsl-enable-16bit-types", [&args](CLIParser &) { args.hlsl_enable_16bit_types = true; });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001366 cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
Hans-Kristian Arntzen3f2de0d2020-03-02 11:55:57 +01001367 cbs.add("-V", [&args](CLIParser &) { args.vulkan_semantics = true; });
Hans-Kristian Arntzen470ae7a2017-05-22 17:40:00 +02001368 cbs.add("--flatten-multidimensional-arrays", [&args](CLIParser &) { args.flatten_multidimensional_arrays = true; });
Hans-Kristian Arntzen6599a412017-09-08 09:56:06 +02001369 cbs.add("--no-420pack-extension", [&args](CLIParser &) { args.use_420pack_extension = false; });
Chip Davisc51e5b72019-01-08 16:33:32 -06001370 cbs.add("--msl-capture-output", [&args](CLIParser &) { args.msl_capture_output_to_buffer = true; });
Chip Davis25833212018-09-19 20:36:33 -05001371 cbs.add("--msl-swizzle-texture-samples", [&args](CLIParser &) { args.msl_swizzle_texture_samples = true; });
Chip Davis3a9af962018-09-26 20:06:05 -05001372 cbs.add("--msl-ios", [&args](CLIParser &) { args.msl_ios = true; });
Hans-Kristian Arntzenb8033d72019-01-14 14:53:47 +01001373 cbs.add("--msl-pad-fragment-output", [&args](CLIParser &) { args.msl_pad_fragment_output = true; });
Chip Davis41d94242019-02-05 23:47:50 -06001374 cbs.add("--msl-domain-lower-left", [&args](CLIParser &) { args.msl_domain_lower_left = true; });
Hans-Kristian Arntzene47a77d2019-03-14 10:29:34 +01001375 cbs.add("--msl-argument-buffers", [&args](CLIParser &) { args.msl_argument_buffers = true; });
Hans-Kristian Arntzene2aadf82019-03-15 21:53:21 +01001376 cbs.add("--msl-discrete-descriptor-set",
1377 [&args](CLIParser &parser) { args.msl_discrete_descriptor_sets.push_back(parser.next_uint()); });
Hans-Kristian Arntzen4bb673a2019-10-14 12:51:48 +02001378 cbs.add("--msl-device-argument-buffer",
1379 [&args](CLIParser &parser) { args.msl_device_argument_buffers.push_back(parser.next_uint()); });
Hans-Kristian Arntzenfc4f39b2019-04-23 12:17:21 +02001380 cbs.add("--msl-texture-buffer-native", [&args](CLIParser &) { args.msl_texture_buffer_native = true; });
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001381 cbs.add("--msl-framebuffer-fetch", [&args](CLIParser &) { args.msl_framebuffer_fetch = true; });
Lukas Hermannsffbd8012019-10-09 11:22:25 -04001382 cbs.add("--msl-invariant-float-math", [&args](CLIParser &) { args.msl_invariant_float_math = true; });
Lukas Hermannsf3a6d282019-09-27 15:49:54 -04001383 cbs.add("--msl-emulate-cube-array", [&args](CLIParser &) { args.msl_emulate_cube_array = true; });
Chip Davis7eecf5a2019-05-31 12:06:20 -05001384 cbs.add("--msl-multiview", [&args](CLIParser &) { args.msl_multiview = true; });
Chip Daviscab73352020-08-23 16:44:41 -05001385 cbs.add("--msl-multiview-no-layered-rendering",
1386 [&args](CLIParser &) { args.msl_multiview_layered_rendering = false; });
Chip Davis6a585542019-07-12 21:50:50 -05001387 cbs.add("--msl-view-index-from-device-index",
1388 [&args](CLIParser &) { args.msl_view_index_from_device_index = true; });
Chip Davisfb5ee4c2019-07-22 13:08:04 -05001389 cbs.add("--msl-dispatch-base", [&args](CLIParser &) { args.msl_dispatch_base = true; });
Chip Daviscb359342019-09-05 23:14:12 -05001390 cbs.add("--msl-dynamic-buffer", [&args](CLIParser &parser) {
1391 args.msl_argument_buffers = true;
Hans-Kristian Arntzenafa54802019-09-06 10:17:31 +02001392 // Make sure next_uint() is called in-order.
Hans-Kristian Arntzen1935f1a2019-09-06 10:11:18 +02001393 uint32_t desc_set = parser.next_uint();
1394 uint32_t binding = parser.next_uint();
1395 args.msl_dynamic_buffers.push_back(make_pair(desc_set, binding));
Chip Daviscb359342019-09-05 23:14:12 -05001396 });
Akio Gaule1280df62019-11-27 01:02:46 -08001397 cbs.add("--msl-decoration-binding", [&args](CLIParser &) { args.msl_decoration_binding = true; });
Hans-Kristian Arntzen7a411252020-01-16 15:20:59 +01001398 cbs.add("--msl-force-active-argument-buffer-resources",
1399 [&args](CLIParser &) { args.msl_force_active_argument_buffer_resources = true; });
Chip Davisfedbc352019-12-16 22:58:16 -06001400 cbs.add("--msl-inline-uniform-block", [&args](CLIParser &parser) {
1401 args.msl_argument_buffers = true;
1402 // Make sure next_uint() is called in-order.
1403 uint32_t desc_set = parser.next_uint();
1404 uint32_t binding = parser.next_uint();
1405 args.msl_inline_uniform_blocks.push_back(make_pair(desc_set, binding));
1406 });
Hans-Kristian Arntzenc2655ab2020-03-19 14:21:42 +01001407 cbs.add("--msl-force-native-arrays", [&args](CLIParser &) { args.msl_force_native_arrays = true; });
Chip Davisb29f83c2020-04-10 01:13:33 -05001408 cbs.add("--msl-disable-frag-depth-builtin", [&args](CLIParser &) { args.msl_enable_frag_depth_builtin = false; });
1409 cbs.add("--msl-disable-frag-stencil-ref-builtin",
1410 [&args](CLIParser &) { args.msl_enable_frag_stencil_ref_builtin = false; });
1411 cbs.add("--msl-enable-frag-output-mask",
1412 [&args](CLIParser &parser) { args.msl_enable_frag_output_mask = parser.next_hex_uint(); });
Hans-Kristian Arntzenebf46362020-04-20 09:48:20 +02001413 cbs.add("--msl-no-clip-distance-user-varying",
1414 [&args](CLIParser &) { args.msl_enable_clip_distance_user_varying = false; });
Chip Davis5281d992020-06-13 23:03:30 -05001415 cbs.add("--msl-shader-input", [&args](CLIParser &parser) {
1416 MSLShaderInput input;
1417 // Make sure next_uint() is called in-order.
1418 input.location = parser.next_uint();
1419 const char *format = parser.next_value_string("other");
Chip Davis688c5fc2020-02-20 21:38:28 -06001420 if (strcmp(format, "any32") == 0)
1421 input.format = MSL_SHADER_INPUT_FORMAT_ANY32;
1422 else if (strcmp(format, "any16") == 0)
1423 input.format = MSL_SHADER_INPUT_FORMAT_ANY16;
1424 else if (strcmp(format, "u16") == 0)
1425 input.format = MSL_SHADER_INPUT_FORMAT_UINT16;
Chip Davis5281d992020-06-13 23:03:30 -05001426 else if (strcmp(format, "u8") == 0)
Chip Davis688c5fc2020-02-20 21:38:28 -06001427 input.format = MSL_SHADER_INPUT_FORMAT_UINT8;
Chip Davis5281d992020-06-13 23:03:30 -05001428 else
Chip Davis688c5fc2020-02-20 21:38:28 -06001429 input.format = MSL_SHADER_INPUT_FORMAT_OTHER;
Chip Davis5281d992020-06-13 23:03:30 -05001430 input.vecsize = parser.next_uint();
1431 args.msl_shader_inputs.push_back(input);
1432 });
Chip Davis688c5fc2020-02-20 21:38:28 -06001433 cbs.add("--msl-multi-patch-workgroup", [&args](CLIParser &) { args.msl_multi_patch_workgroup = true; });
1434 cbs.add("--msl-vertex-for-tessellation", [&args](CLIParser &) { args.msl_vertex_for_tessellation = true; });
Tomek Ponitka18f23c42020-07-22 18:37:17 +02001435 cbs.add("--msl-additional-fixed-sample-mask",
1436 [&args](CLIParser &parser) { args.msl_additional_fixed_sample_mask = parser.next_hex_uint(); });
Chip Davis4cf840e2020-08-27 19:24:20 -05001437 cbs.add("--msl-arrayed-subpass-input", [&args](CLIParser &) { args.msl_arrayed_subpass_input = true; });
Chip Davis21d38f72020-10-13 13:20:49 -05001438 cbs.add("--msl-r32ui-linear-texture-align",
1439 [&args](CLIParser &parser) { args.msl_r32ui_linear_texture_alignment = parser.next_uint(); });
1440 cbs.add("--msl-r32ui-linear-texture-align-constant-id",
1441 [&args](CLIParser &parser) { args.msl_r32ui_alignment_constant_id = parser.next_uint(); });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001442 cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +01001443 cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
1444 auto old_name = parser.next_string();
1445 auto new_name = parser.next_string();
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001446 auto model = stage_to_execution_model(parser.next_string());
1447 args.entry_point_rename.push_back({ old_name, new_name, move(model) });
Hans-Kristian Arntzen4427cb92017-11-13 13:49:11 +01001448 });
Hans-Kristian Arntzen042475e2016-07-28 11:16:02 +02001449 cbs.add("--entry", [&args](CLIParser &parser) { args.entry = parser.next_string(); });
Hans-Kristian Arntzeneecbeaa2018-03-01 14:00:04 +01001450 cbs.add("--stage", [&args](CLIParser &parser) { args.entry_stage = parser.next_string(); });
Hans-Kristian Arntzen36650c82017-05-22 15:30:43 +02001451 cbs.add("--separate-shader-objects", [&args](CLIParser &) { args.sso = true; });
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001452 cbs.add("--set-hlsl-vertex-input-semantic", [&args](CLIParser &parser) {
1453 HLSLVertexAttributeRemap remap;
1454 remap.location = parser.next_uint();
1455 remap.semantic = parser.next_string();
1456 args.hlsl_attr_remap.push_back(move(remap));
1457 });
1458
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001459 cbs.add("--remap", [&args](CLIParser &parser) {
Hans-Kristian Arntzenf4861422017-11-13 09:52:35 +01001460 string src = parser.next_string();
1461 string dst = parser.next_string();
1462 uint32_t components = parser.next_uint();
1463 args.remaps.push_back({ move(src), move(dst), components });
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001464 });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001465
Panagiotis Christopoulos Charitos66e76d92016-09-20 10:17:41 +02001466 cbs.add("--remap-variable-type", [&args](CLIParser &parser) {
1467 string var_name = parser.next_string();
1468 string new_type = parser.next_string();
1469 args.variable_type_remaps.push_back({ move(var_name), move(new_type) });
1470 });
1471
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001472 cbs.add("--rename-interface-variable", [&args](CLIParser &parser) {
Jason Chan3281e822017-06-25 15:16:09 +02001473 StorageClass cls = StorageClassMax;
1474 string clsStr = parser.next_string();
1475 if (clsStr == "in")
1476 cls = StorageClassInput;
1477 else if (clsStr == "out")
1478 cls = StorageClassOutput;
1479
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001480 uint32_t loc = parser.next_uint();
1481 string var_name = parser.next_string();
Jason Chan3281e822017-06-25 15:16:09 +02001482 args.interface_variable_renames.push_back({ cls, loc, move(var_name) });
Jason Chan9f1eb5a2017-06-23 22:20:42 +02001483 });
1484
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001485 cbs.add("--pls-in", [&args](CLIParser &parser) {
1486 auto fmt = pls_format(parser.next_string());
1487 auto name = parser.next_string();
1488 args.pls_in.push_back({ move(fmt), move(name) });
1489 });
1490 cbs.add("--pls-out", [&args](CLIParser &parser) {
1491 auto fmt = pls_format(parser.next_string());
1492 auto name = parser.next_string();
1493 args.pls_out.push_back({ move(fmt), move(name) });
1494 });
Hans-Kristian Arntzen2e3c6ec2017-02-16 11:17:12 +01001495 cbs.add("--shader-model", [&args](CLIParser &parser) {
1496 args.shader_model = parser.next_uint();
1497 args.set_shader_model = true;
1498 });
Bill Hollingsbac657d2017-11-07 15:38:13 -05001499 cbs.add("--msl-version", [&args](CLIParser &parser) {
1500 args.msl_version = parser.next_uint();
1501 args.set_msl_version = true;
1502 });
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001503
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +02001504 cbs.add("--remove-unused-variables", [&args](CLIParser &) { args.remove_unused = true; });
Hans-Kristian Arntzena1b39642018-05-25 10:14:13 +02001505 cbs.add("--combined-samplers-inherit-bindings",
1506 [&args](CLIParser &) { args.combined_samplers_inherit_bindings = true; });
Hans-Kristian Arntzenf61a5d12016-08-26 12:58:50 +02001507
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +02001508 cbs.add("--no-support-nonzero-baseinstance", [&](CLIParser &) { args.support_nonzero_baseinstance = false; });
Hans-Kristian Arntzen65af09d2019-05-28 13:41:46 +02001509 cbs.add("--emit-line-directives", [&args](CLIParser &) { args.emit_line_directives = true; });
Hans-Kristian Arntzenb29629f2018-06-22 10:01:38 +02001510
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001511 cbs.default_handler = [&args](const char *value) { args.input = value; };
1512 cbs.error_handler = [] { print_help(); };
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001513
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001514 CLIParser parser{ move(cbs), argc - 1, argv + 1 };
1515 if (!parser.parse())
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001516 return EXIT_FAILURE;
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001517 else if (parser.ended_state)
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001518 return EXIT_SUCCESS;
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001519
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001520 if (!args.input)
1521 {
1522 fprintf(stderr, "Didn't specify input file.\n");
1523 print_help();
1524 return EXIT_FAILURE;
1525 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001526
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001527 auto spirv_file = read_spirv_file(args.input);
1528 if (spirv_file.empty())
1529 return EXIT_FAILURE;
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001530
Brad Davis6c88b002018-06-18 09:30:16 -07001531 // Special case reflection because it has little to do with the path followed by code-outputting compilers
1532 if (!args.reflect.empty())
1533 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001534 Parser spirv_parser(move(spirv_file));
1535 spirv_parser.parse();
1536
Hans-Kristian Arntzen5bcf02f2018-10-05 11:30:57 +02001537 CompilerReflection compiler(move(spirv_parser.get_parsed_ir()));
Brad Davis6c88b002018-06-18 09:30:16 -07001538 compiler.set_format(args.reflect);
1539 auto json = compiler.compile();
1540 if (args.output)
1541 write_string_to_file(args.output, json.c_str());
1542 else
1543 printf("%s", json.c_str());
1544 return EXIT_SUCCESS;
1545 }
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001546
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001547 string compiled_output;
Hans-Kristian Arntzenbcb55602016-09-10 13:56:36 +02001548
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001549 if (args.iterations == 1)
1550 compiled_output = compile_iteration(args, move(spirv_file));
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001551 else
Hans-Kristian Arntzenbcb55602016-09-10 13:56:36 +02001552 {
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001553 for (unsigned i = 0; i < args.iterations; i++)
1554 compiled_output = compile_iteration(args, spirv_file);
Hans-Kristian Arntzen4f88f972017-11-13 09:46:45 +01001555 }
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001556
1557 if (args.output)
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001558 write_string_to_file(args.output, compiled_output.c_str());
Hans-Kristian Arntzen078eec52016-07-06 11:04:06 +02001559 else
Hans-Kristian Arntzenc60b9a12019-04-08 11:53:13 +02001560 printf("%s", compiled_output.c_str());
Hans-Kristian Arntzend9cbc032017-09-08 09:33:34 +02001561
1562 return EXIT_SUCCESS;
1563}
1564
1565int main(int argc, char *argv[])
1566{
1567#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
1568 return main_inner(argc, argv);
1569#else
1570 // Make sure we catch the exception or it just disappears into the aether on Windows.
1571 try
1572 {
1573 return main_inner(argc, argv);
1574 }
1575 catch (const std::exception &e)
1576 {
1577 fprintf(stderr, "SPIRV-Cross threw an exception: %s\n", e.what());
1578 return EXIT_FAILURE;
1579 }
1580#endif
Hans-Kristian Arntzen75471fb2016-03-02 18:09:16 +01001581}