Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015-2016 ARM Limited |
| 3 | * |
| 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 Arntzen | 147e53a | 2016-04-04 09:36:04 +0200 | [diff] [blame] | 17 | #include "spirv_cpp.hpp" |
Bill Hollings | 5f2d666 | 2016-04-11 11:31:03 -0400 | [diff] [blame] | 18 | #include "spirv_msl.hpp" |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 19 | #include <algorithm> |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 20 | #include <cstdio> |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 21 | #include <cstring> |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 22 | #include <functional> |
| 23 | #include <limits> |
| 24 | #include <memory> |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 25 | #include <stdexcept> |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 26 | #include <unordered_map> |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 27 | #include <unordered_set> |
| 28 | |
| 29 | using namespace spv; |
Hans-Kristian Arntzen | 147e53a | 2016-04-04 09:36:04 +0200 | [diff] [blame] | 30 | using namespace spirv_cross; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 31 | using namespace std; |
| 32 | |
| 33 | struct CLIParser; |
| 34 | struct CLICallbacks |
| 35 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 36 | void add(const char *cli, const function<void(CLIParser &)> &func) |
| 37 | { |
| 38 | callbacks[cli] = func; |
| 39 | } |
| 40 | unordered_map<string, function<void(CLIParser &)>> callbacks; |
| 41 | function<void()> error_handler; |
| 42 | function<void(const char *)> default_handler; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | struct CLIParser |
| 46 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 47 | CLIParser(CLICallbacks cbs_, int argc_, char *argv_[]) |
| 48 | : cbs(move(cbs_)) |
| 49 | , argc(argc_) |
| 50 | , argv(argv_) |
| 51 | { |
| 52 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 53 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 54 | bool parse() |
| 55 | { |
| 56 | try |
| 57 | { |
| 58 | while (argc && !ended_state) |
| 59 | { |
| 60 | const char *next = *argv++; |
| 61 | argc--; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 62 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 63 | if (*next != '-' && cbs.default_handler) |
| 64 | { |
| 65 | cbs.default_handler(next); |
| 66 | } |
| 67 | else |
| 68 | { |
| 69 | auto itr = cbs.callbacks.find(next); |
| 70 | if (itr == ::end(cbs.callbacks)) |
| 71 | { |
| 72 | throw logic_error("Invalid argument.\n"); |
| 73 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 74 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 75 | itr->second(*this); |
| 76 | } |
| 77 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 78 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 79 | return true; |
| 80 | } |
| 81 | catch (...) |
| 82 | { |
| 83 | if (cbs.error_handler) |
| 84 | { |
| 85 | cbs.error_handler(); |
| 86 | } |
| 87 | return false; |
| 88 | } |
| 89 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 90 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 91 | void end() |
| 92 | { |
| 93 | ended_state = true; |
| 94 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 95 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 96 | uint32_t next_uint() |
| 97 | { |
| 98 | if (!argc) |
| 99 | { |
| 100 | throw logic_error("Tried to parse uint, but nothing left in arguments.\n"); |
| 101 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 102 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 103 | uint32_t val = stoul(*argv); |
| 104 | if (val > numeric_limits<uint32_t>::max()) |
| 105 | { |
| 106 | throw out_of_range("next_uint() out of range.\n"); |
| 107 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 108 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 109 | argc--; |
| 110 | argv++; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 111 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 112 | return val; |
| 113 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 114 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 115 | double next_double() |
| 116 | { |
| 117 | if (!argc) |
| 118 | { |
| 119 | throw logic_error("Tried to parse double, but nothing left in arguments.\n"); |
| 120 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 121 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 122 | double val = stod(*argv); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 123 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 124 | argc--; |
| 125 | argv++; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 126 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 127 | return val; |
| 128 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 129 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 130 | const char *next_string() |
| 131 | { |
| 132 | if (!argc) |
| 133 | { |
| 134 | throw logic_error("Tried to parse string, but nothing left in arguments.\n"); |
| 135 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 136 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 137 | const char *ret = *argv; |
| 138 | argc--; |
| 139 | argv++; |
| 140 | return ret; |
| 141 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 142 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 143 | CLICallbacks cbs; |
| 144 | int argc; |
| 145 | char **argv; |
| 146 | bool ended_state = false; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 147 | }; |
| 148 | |
| 149 | static vector<uint32_t> read_spirv_file(const char *path) |
| 150 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 151 | FILE *file = fopen(path, "rb"); |
| 152 | if (!file) |
| 153 | { |
| 154 | fprintf(stderr, "Failed to open SPIRV file: %s\n", path); |
| 155 | return {}; |
| 156 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 157 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 158 | fseek(file, 0, SEEK_END); |
| 159 | long len = ftell(file) / sizeof(uint32_t); |
| 160 | rewind(file); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 161 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 162 | vector<uint32_t> spirv(len); |
| 163 | if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len)) |
| 164 | spirv.clear(); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 165 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 166 | fclose(file); |
| 167 | return spirv; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | static bool write_string_to_file(const char *path, const char *string) |
| 171 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 172 | FILE *file = fopen(path, "w"); |
| 173 | if (!file) |
| 174 | { |
| 175 | fprintf(file, "Failed to write file: %s\n", path); |
| 176 | return false; |
| 177 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 178 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 179 | fprintf(file, "%s", string); |
| 180 | fclose(file); |
| 181 | return true; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | static void print_resources(const Compiler &compiler, const char *tag, const vector<Resource> &resources) |
| 185 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 186 | fprintf(stderr, "%s\n", tag); |
| 187 | fprintf(stderr, "=============\n\n"); |
| 188 | for (auto &res : resources) |
| 189 | { |
| 190 | auto &type = compiler.get_type(res.type_id); |
| 191 | auto mask = compiler.get_decoration_mask(res.id); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 192 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 193 | // If we don't have a name, use the fallback for the type instead of the variable |
| 194 | // for SSBOs and UBOs since those are the only meaningful names to use externally. |
| 195 | // Push constant blocks are still accessed by name and not block name, even though they are technically Blocks. |
| 196 | bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant; |
| 197 | bool is_block = (compiler.get_decoration_mask(type.self) & |
| 198 | ((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) != 0; |
Hans-Kristian Arntzen | 5c24d99 | 2016-07-12 21:20:18 +0200 | [diff] [blame] | 199 | uint32_t fallback_id = !is_push_constant && is_block ? res.base_type_id : res.id; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 200 | |
Hans-Kristian Arntzen | 5c24d99 | 2016-07-12 21:20:18 +0200 | [diff] [blame] | 201 | string array; |
| 202 | for (auto arr : type.array) |
| 203 | array = join("[", arr ? convert_to_string(arr) : "", "]") + array; |
| 204 | |
| 205 | fprintf(stderr, " ID %03u : %s%s", res.id, |
| 206 | !res.name.empty() ? res.name.c_str() : compiler.get_fallback_name(fallback_id).c_str(), array.c_str()); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 207 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 208 | if (mask & (1ull << DecorationLocation)) |
| 209 | fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation)); |
| 210 | if (mask & (1ull << DecorationDescriptorSet)) |
| 211 | fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet)); |
| 212 | if (mask & (1ull << DecorationBinding)) |
| 213 | fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding)); |
| 214 | if (mask & (1ull << DecorationInputAttachmentIndex)) |
| 215 | fprintf(stderr, " (Attachment : %u)", compiler.get_decoration(res.id, DecorationInputAttachmentIndex)); |
| 216 | fprintf(stderr, "\n"); |
| 217 | } |
| 218 | fprintf(stderr, "=============\n\n"); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 219 | } |
| 220 | |
Hans-Kristian Arntzen | 042475e | 2016-07-28 11:16:02 +0200 | [diff] [blame] | 221 | static const char *execution_model_to_str(spv::ExecutionModel model) |
| 222 | { |
| 223 | switch (model) |
| 224 | { |
| 225 | case spv::ExecutionModelVertex: |
| 226 | return "vertex"; |
| 227 | case spv::ExecutionModelTessellationControl: |
| 228 | return "tessellation control"; |
| 229 | case ExecutionModelTessellationEvaluation: |
| 230 | return "tessellation evaluation"; |
| 231 | case ExecutionModelGeometry: |
| 232 | return "geometry"; |
| 233 | case ExecutionModelFragment: |
| 234 | return "fragment"; |
| 235 | case ExecutionModelGLCompute: |
| 236 | return "compute"; |
| 237 | default: |
| 238 | return "???"; |
| 239 | } |
| 240 | } |
| 241 | |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 242 | static void print_resources(const Compiler &compiler, const ShaderResources &res) |
| 243 | { |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 244 | uint64_t modes = compiler.get_execution_mode_mask(); |
| 245 | |
Hans-Kristian Arntzen | 042475e | 2016-07-28 11:16:02 +0200 | [diff] [blame] | 246 | fprintf(stderr, "Entry points:\n"); |
| 247 | auto entry_points = compiler.get_entry_points(); |
| 248 | for (auto &e : entry_points) |
| 249 | fprintf(stderr, " %s (%s)\n", e.c_str(), execution_model_to_str(compiler.get_entry_point(e).model)); |
| 250 | fprintf(stderr, "\n"); |
| 251 | |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 252 | fprintf(stderr, "Execution modes:\n"); |
| 253 | for (unsigned i = 0; i < 64; i++) |
| 254 | { |
| 255 | if (!(modes & (1ull << i))) |
| 256 | continue; |
| 257 | |
| 258 | auto mode = static_cast<ExecutionMode>(i); |
| 259 | uint32_t arg0 = compiler.get_execution_mode_argument(mode, 0); |
| 260 | uint32_t arg1 = compiler.get_execution_mode_argument(mode, 1); |
| 261 | uint32_t arg2 = compiler.get_execution_mode_argument(mode, 2); |
| 262 | |
| 263 | switch (static_cast<ExecutionMode>(i)) |
| 264 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 265 | case ExecutionModeInvocations: |
| 266 | fprintf(stderr, " Invocations: %u\n", arg0); |
| 267 | break; |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 268 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 269 | case ExecutionModeLocalSize: |
| 270 | fprintf(stderr, " LocalSize: (%u, %u, %u)\n", arg0, arg1, arg2); |
| 271 | break; |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 272 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 273 | case ExecutionModeOutputVertices: |
| 274 | fprintf(stderr, " OutputVertices: %u\n", arg0); |
| 275 | break; |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 276 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 277 | #define CHECK_MODE(m) \ |
| 278 | case ExecutionMode##m: \ |
| 279 | fprintf(stderr, " %s\n", #m); \ |
| 280 | break |
| 281 | CHECK_MODE(SpacingEqual); |
| 282 | CHECK_MODE(SpacingFractionalEven); |
| 283 | CHECK_MODE(SpacingFractionalOdd); |
| 284 | CHECK_MODE(VertexOrderCw); |
| 285 | CHECK_MODE(VertexOrderCcw); |
| 286 | CHECK_MODE(PixelCenterInteger); |
| 287 | CHECK_MODE(OriginUpperLeft); |
| 288 | CHECK_MODE(OriginLowerLeft); |
| 289 | CHECK_MODE(EarlyFragmentTests); |
| 290 | CHECK_MODE(PointMode); |
| 291 | CHECK_MODE(Xfb); |
| 292 | CHECK_MODE(DepthReplacing); |
| 293 | CHECK_MODE(DepthGreater); |
| 294 | CHECK_MODE(DepthLess); |
| 295 | CHECK_MODE(DepthUnchanged); |
| 296 | CHECK_MODE(LocalSizeHint); |
| 297 | CHECK_MODE(InputPoints); |
| 298 | CHECK_MODE(InputLines); |
| 299 | CHECK_MODE(InputLinesAdjacency); |
| 300 | CHECK_MODE(Triangles); |
| 301 | CHECK_MODE(InputTrianglesAdjacency); |
| 302 | CHECK_MODE(Quads); |
| 303 | CHECK_MODE(Isolines); |
| 304 | CHECK_MODE(OutputPoints); |
| 305 | CHECK_MODE(OutputLineStrip); |
| 306 | CHECK_MODE(OutputTriangleStrip); |
| 307 | CHECK_MODE(VecTypeHint); |
| 308 | CHECK_MODE(ContractionOff); |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 309 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 310 | default: |
| 311 | break; |
Hans-Kristian Arntzen | 3c285a1 | 2016-07-04 13:30:05 +0200 | [diff] [blame] | 312 | } |
| 313 | } |
| 314 | fprintf(stderr, "\n"); |
| 315 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 316 | print_resources(compiler, "subpass inputs", res.subpass_inputs); |
| 317 | print_resources(compiler, "inputs", res.stage_inputs); |
| 318 | print_resources(compiler, "outputs", res.stage_outputs); |
| 319 | print_resources(compiler, "textures", res.sampled_images); |
Hans-Kristian Arntzen | e920208 | 2016-09-10 13:05:35 +0200 | [diff] [blame] | 320 | print_resources(compiler, "separate textures", res.separate_images); |
| 321 | print_resources(compiler, "separate samplers", res.separate_samplers); |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 322 | print_resources(compiler, "images", res.storage_images); |
| 323 | print_resources(compiler, "ssbos", res.storage_buffers); |
| 324 | print_resources(compiler, "ubos", res.uniform_buffers); |
| 325 | print_resources(compiler, "push", res.push_constant_buffers); |
| 326 | print_resources(compiler, "counters", res.atomic_counters); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 327 | } |
| 328 | |
| 329 | static void print_push_constant_resources(const Compiler &compiler, const vector<Resource> &res) |
| 330 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 331 | for (auto &block : res) |
| 332 | { |
| 333 | auto ranges = compiler.get_active_buffer_ranges(block.id); |
| 334 | fprintf(stderr, "Active members in buffer: %s\n", |
| 335 | !block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str()); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 336 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 337 | fprintf(stderr, "==================\n\n"); |
| 338 | for (auto &range : ranges) |
| 339 | { |
Hans-Kristian Arntzen | 5c24d99 | 2016-07-12 21:20:18 +0200 | [diff] [blame] | 340 | const auto &name = compiler.get_member_name(block.base_type_id, range.index); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 341 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 342 | fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n", range.index, |
| 343 | !name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(), |
| 344 | unsigned(range.offset), unsigned(range.range)); |
| 345 | } |
| 346 | fprintf(stderr, "==================\n\n"); |
| 347 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 348 | } |
| 349 | |
| 350 | struct PLSArg |
| 351 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 352 | PlsFormat format; |
| 353 | string name; |
| 354 | }; |
| 355 | |
| 356 | struct Remap |
| 357 | { |
| 358 | string src_name; |
| 359 | string dst_name; |
| 360 | unsigned components; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 361 | }; |
| 362 | |
| 363 | struct CLIArguments |
| 364 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 365 | const char *input = nullptr; |
| 366 | const char *output = nullptr; |
| 367 | const char *cpp_interface_name = nullptr; |
| 368 | uint32_t version = 0; |
| 369 | bool es = false; |
| 370 | bool set_version = false; |
| 371 | bool set_es = false; |
| 372 | bool dump_resources = false; |
| 373 | bool force_temporary = false; |
| 374 | bool flatten_ubo = false; |
| 375 | bool fixup = false; |
| 376 | vector<PLSArg> pls_in; |
| 377 | vector<PLSArg> pls_out; |
| 378 | vector<Remap> remaps; |
| 379 | vector<string> extensions; |
Hans-Kristian Arntzen | 042475e | 2016-07-28 11:16:02 +0200 | [diff] [blame] | 380 | string entry; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 381 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 382 | uint32_t iterations = 1; |
| 383 | bool cpp = false; |
| 384 | bool metal = false; |
| 385 | bool vulkan_semantics = false; |
Hans-Kristian Arntzen | f61a5d1 | 2016-08-26 12:58:50 +0200 | [diff] [blame] | 386 | bool remove_unused = false; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 387 | }; |
| 388 | |
| 389 | static void print_help() |
| 390 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 391 | fprintf(stderr, "Usage: spirv-cross [--output <output path>] [SPIR-V file] [--es] [--no-es] [--version <GLSL " |
| 392 | "version>] [--dump-resources] [--help] [--force-temporary] [--cpp] [--cpp-interface-name <name>] " |
| 393 | "[--metal] [--vulkan-semantics] [--flatten-ubo] [--fixup-clipspace] [--iterations iter] [--pls-in " |
| 394 | "format input-name] [--pls-out format output-name] [--remap source_name target_name components] " |
Hans-Kristian Arntzen | f61a5d1 | 2016-08-26 12:58:50 +0200 | [diff] [blame] | 395 | "[--extension ext] [--entry name] [--remove-unused-variables]\n"); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 396 | } |
| 397 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 398 | static bool remap_generic(Compiler &compiler, const vector<Resource> &resources, const Remap &remap) |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 399 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 400 | auto itr = |
| 401 | find_if(begin(resources), end(resources), [&remap](const Resource &res) { return res.name == remap.src_name; }); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 402 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 403 | if (itr != end(resources)) |
| 404 | { |
| 405 | compiler.set_remapped_variable_state(itr->id, true); |
| 406 | compiler.set_name(itr->id, remap.dst_name); |
| 407 | compiler.set_subpass_input_remapped_components(itr->id, remap.components); |
| 408 | return true; |
| 409 | } |
| 410 | else |
| 411 | return false; |
| 412 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 413 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 414 | static vector<PlsRemap> remap_pls(const vector<PLSArg> &pls_variables, const vector<Resource> &resources, |
| 415 | const vector<Resource> *secondary_resources) |
| 416 | { |
| 417 | vector<PlsRemap> ret; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 418 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 419 | for (auto &pls : pls_variables) |
| 420 | { |
| 421 | bool found = false; |
| 422 | for (auto &res : resources) |
| 423 | { |
| 424 | if (res.name == pls.name) |
| 425 | { |
| 426 | ret.push_back({ res.id, pls.format }); |
| 427 | found = true; |
| 428 | break; |
| 429 | } |
| 430 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 431 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 432 | if (!found && secondary_resources) |
| 433 | { |
| 434 | for (auto &res : *secondary_resources) |
| 435 | { |
| 436 | if (res.name == pls.name) |
| 437 | { |
| 438 | ret.push_back({ res.id, pls.format }); |
| 439 | found = true; |
| 440 | break; |
| 441 | } |
| 442 | } |
| 443 | } |
| 444 | |
| 445 | if (!found) |
| 446 | fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n", pls.name.c_str()); |
| 447 | } |
| 448 | |
| 449 | return ret; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 450 | } |
| 451 | |
| 452 | static PlsFormat pls_format(const char *str) |
| 453 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 454 | if (!strcmp(str, "r11f_g11f_b10f")) |
| 455 | return PlsR11FG11FB10F; |
| 456 | else if (!strcmp(str, "r32f")) |
| 457 | return PlsR32F; |
| 458 | else if (!strcmp(str, "rg16f")) |
| 459 | return PlsRG16F; |
| 460 | else if (!strcmp(str, "rg16")) |
| 461 | return PlsRG16; |
| 462 | else if (!strcmp(str, "rgb10_a2")) |
| 463 | return PlsRGB10A2; |
| 464 | else if (!strcmp(str, "rgba8")) |
| 465 | return PlsRGBA8; |
| 466 | else if (!strcmp(str, "rgba8i")) |
| 467 | return PlsRGBA8I; |
| 468 | else if (!strcmp(str, "rgba8ui")) |
| 469 | return PlsRGBA8UI; |
| 470 | else if (!strcmp(str, "rg16i")) |
| 471 | return PlsRG16I; |
| 472 | else if (!strcmp(str, "rgb10_a2ui")) |
| 473 | return PlsRGB10A2UI; |
| 474 | else if (!strcmp(str, "rg16ui")) |
| 475 | return PlsRG16UI; |
| 476 | else if (!strcmp(str, "r32ui")) |
| 477 | return PlsR32UI; |
| 478 | else |
| 479 | return PlsNone; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 480 | } |
| 481 | |
| 482 | int main(int argc, char *argv[]) |
| 483 | { |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 484 | CLIArguments args; |
| 485 | CLICallbacks cbs; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 486 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 487 | cbs.add("--help", [](CLIParser &parser) { |
| 488 | print_help(); |
| 489 | parser.end(); |
| 490 | }); |
| 491 | cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); }); |
| 492 | cbs.add("--es", [&args](CLIParser &) { |
| 493 | args.es = true; |
| 494 | args.set_es = true; |
| 495 | }); |
| 496 | cbs.add("--no-es", [&args](CLIParser &) { |
| 497 | args.es = false; |
| 498 | args.set_es = true; |
| 499 | }); |
| 500 | cbs.add("--version", [&args](CLIParser &parser) { |
| 501 | args.version = parser.next_uint(); |
| 502 | args.set_version = true; |
| 503 | }); |
| 504 | cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; }); |
| 505 | cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; }); |
| 506 | cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; }); |
| 507 | cbs.add("--fixup-clipspace", [&args](CLIParser &) { args.fixup = true; }); |
| 508 | cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); }); |
| 509 | cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; }); |
| 510 | cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); }); |
| 511 | cbs.add("--metal", [&args](CLIParser &) { args.metal = true; }); |
| 512 | cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; }); |
| 513 | cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); }); |
Hans-Kristian Arntzen | 042475e | 2016-07-28 11:16:02 +0200 | [diff] [blame] | 514 | cbs.add("--entry", [&args](CLIParser &parser) { args.entry = parser.next_string(); }); |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 515 | cbs.add("--remap", [&args](CLIParser &parser) { |
| 516 | string src = parser.next_string(); |
| 517 | string dst = parser.next_string(); |
| 518 | uint32_t components = parser.next_uint(); |
| 519 | args.remaps.push_back({ move(src), move(dst), components }); |
| 520 | }); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 521 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 522 | cbs.add("--pls-in", [&args](CLIParser &parser) { |
| 523 | auto fmt = pls_format(parser.next_string()); |
| 524 | auto name = parser.next_string(); |
| 525 | args.pls_in.push_back({ move(fmt), move(name) }); |
| 526 | }); |
| 527 | cbs.add("--pls-out", [&args](CLIParser &parser) { |
| 528 | auto fmt = pls_format(parser.next_string()); |
| 529 | auto name = parser.next_string(); |
| 530 | args.pls_out.push_back({ move(fmt), move(name) }); |
| 531 | }); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 532 | |
Hans-Kristian Arntzen | f61a5d1 | 2016-08-26 12:58:50 +0200 | [diff] [blame] | 533 | cbs.add("--remove-unused-variables", [&args](CLIParser &) { args.remove_unused = true; }); |
| 534 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 535 | cbs.default_handler = [&args](const char *value) { args.input = value; }; |
| 536 | cbs.error_handler = [] { print_help(); }; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 537 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 538 | CLIParser parser{ move(cbs), argc - 1, argv + 1 }; |
| 539 | if (!parser.parse()) |
| 540 | { |
| 541 | return EXIT_FAILURE; |
| 542 | } |
| 543 | else if (parser.ended_state) |
| 544 | { |
| 545 | return EXIT_SUCCESS; |
| 546 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 547 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 548 | if (!args.input) |
| 549 | { |
| 550 | fprintf(stderr, "Didn't specify input file.\n"); |
| 551 | print_help(); |
| 552 | return EXIT_FAILURE; |
| 553 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 554 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 555 | unique_ptr<CompilerGLSL> compiler; |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 556 | |
Hans-Kristian Arntzen | bcb5560 | 2016-09-10 13:56:36 +0200 | [diff] [blame] | 557 | bool combined_image_samplers = false; |
| 558 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 559 | if (args.cpp) |
| 560 | { |
| 561 | compiler = unique_ptr<CompilerGLSL>(new CompilerCPP(read_spirv_file(args.input))); |
| 562 | if (args.cpp_interface_name) |
| 563 | static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name); |
| 564 | } |
| 565 | else if (args.metal) |
| 566 | compiler = unique_ptr<CompilerMSL>(new CompilerMSL(read_spirv_file(args.input))); |
| 567 | else |
Hans-Kristian Arntzen | bcb5560 | 2016-09-10 13:56:36 +0200 | [diff] [blame] | 568 | { |
| 569 | combined_image_samplers = !args.vulkan_semantics; |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 570 | compiler = unique_ptr<CompilerGLSL>(new CompilerGLSL(read_spirv_file(args.input))); |
Hans-Kristian Arntzen | bcb5560 | 2016-09-10 13:56:36 +0200 | [diff] [blame] | 571 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 572 | |
Hans-Kristian Arntzen | 042475e | 2016-07-28 11:16:02 +0200 | [diff] [blame] | 573 | if (!args.entry.empty()) |
| 574 | compiler->set_entry_point(args.entry); |
| 575 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 576 | if (!args.set_version && !compiler->get_options().version) |
| 577 | { |
| 578 | fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n"); |
| 579 | print_help(); |
| 580 | return EXIT_FAILURE; |
| 581 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 582 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 583 | CompilerGLSL::Options opts = compiler->get_options(); |
| 584 | if (args.set_version) |
| 585 | opts.version = args.version; |
| 586 | if (args.set_es) |
| 587 | opts.es = args.es; |
| 588 | opts.force_temporary = args.force_temporary; |
| 589 | opts.vulkan_semantics = args.vulkan_semantics; |
| 590 | opts.vertex.fixup_clipspace = args.fixup; |
| 591 | compiler->set_options(opts); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 592 | |
Hans-Kristian Arntzen | f61a5d1 | 2016-08-26 12:58:50 +0200 | [diff] [blame] | 593 | ShaderResources res; |
| 594 | if (args.remove_unused) |
| 595 | { |
| 596 | auto active = compiler->get_active_interface_variables(); |
| 597 | res = compiler->get_shader_resources(active); |
| 598 | compiler->set_enabled_interface_variables(move(active)); |
| 599 | } |
| 600 | else |
| 601 | res = compiler->get_shader_resources(); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 602 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 603 | if (args.flatten_ubo) |
| 604 | for (auto &ubo : res.uniform_buffers) |
| 605 | compiler->flatten_interface_block(ubo.id); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 606 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 607 | auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs); |
| 608 | auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr); |
| 609 | compiler->remap_pixel_local_storage(move(pls_inputs), move(pls_outputs)); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 610 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 611 | for (auto &ext : args.extensions) |
| 612 | compiler->require_extension(ext); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 613 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 614 | for (auto &remap : args.remaps) |
| 615 | { |
| 616 | if (remap_generic(*compiler, res.stage_inputs, remap)) |
| 617 | continue; |
| 618 | if (remap_generic(*compiler, res.stage_outputs, remap)) |
| 619 | continue; |
| 620 | if (remap_generic(*compiler, res.subpass_inputs, remap)) |
| 621 | continue; |
| 622 | } |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 623 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 624 | if (args.dump_resources) |
| 625 | { |
| 626 | print_resources(*compiler, res); |
| 627 | print_push_constant_resources(*compiler, res.push_constant_buffers); |
| 628 | } |
| 629 | |
Hans-Kristian Arntzen | bcb5560 | 2016-09-10 13:56:36 +0200 | [diff] [blame] | 630 | if (combined_image_samplers) |
| 631 | { |
| 632 | compiler->build_combined_image_samplers(); |
| 633 | // Give the remapped combined samplers new names. |
| 634 | for (auto &remap : compiler->get_combined_image_samplers()) |
| 635 | { |
Hans-Kristian Arntzen | 1b5ca8d | 2016-09-10 16:20:19 +0200 | [diff] [blame] | 636 | compiler->set_name(remap.combined_id, join("_Combined", compiler->get_name(remap.image_id), |
Hans-Kristian Arntzen | bcb5560 | 2016-09-10 13:56:36 +0200 | [diff] [blame] | 637 | compiler->get_name(remap.sampler_id))); |
| 638 | } |
| 639 | } |
| 640 | |
Hans-Kristian Arntzen | 078eec5 | 2016-07-06 11:04:06 +0200 | [diff] [blame] | 641 | string glsl; |
| 642 | for (uint32_t i = 0; i < args.iterations; i++) |
| 643 | glsl = compiler->compile(); |
| 644 | |
| 645 | if (args.output) |
| 646 | write_string_to_file(args.output, glsl.c_str()); |
| 647 | else |
| 648 | printf("%s", glsl.c_str()); |
Hans-Kristian Arntzen | 75471fb | 2016-03-02 18:09:16 +0100 | [diff] [blame] | 649 | } |