Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 1 | /* |
Hans-Kristian Arntzen | 4704482 | 2021-01-14 16:07:49 +0100 | [diff] [blame] | 2 | * Copyright 2018-2021 Bradley Austin Davis |
Jon Leech | f2a6554 | 2021-05-08 01:47:48 -0700 | [diff] [blame] | 3 | * SPDX-License-Identifier: Apache-2.0 OR MIT |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
| 17 | |
Hans-Kristian Arntzen | cf1e9e0 | 2020-11-25 15:22:08 +0100 | [diff] [blame] | 18 | /* |
| 19 | * At your option, you may choose to accept this material under either: |
| 20 | * 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or |
| 21 | * 2. The MIT License, found at <http://opensource.org/licenses/MIT>. |
Hans-Kristian Arntzen | cf1e9e0 | 2020-11-25 15:22:08 +0100 | [diff] [blame] | 22 | */ |
| 23 | |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 24 | #include "spirv_reflect.hpp" |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 25 | #include "spirv_glsl.hpp" |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 26 | #include <iomanip> |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 27 | |
| 28 | using namespace spv; |
Hans-Kristian Arntzen | 9b92e68 | 2019-03-29 10:29:44 +0100 | [diff] [blame] | 29 | using namespace SPIRV_CROSS_NAMESPACE; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 30 | using namespace std; |
| 31 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 32 | namespace simple_json |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 33 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 34 | enum class Type |
| 35 | { |
| 36 | Object, |
| 37 | Array, |
| 38 | }; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 39 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 40 | using State = std::pair<Type, bool>; |
| 41 | using Stack = std::stack<State>; |
| 42 | |
| 43 | class Stream |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 44 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 45 | Stack stack; |
Hans-Kristian Arntzen | a489ba7 | 2019-04-02 11:19:03 +0200 | [diff] [blame] | 46 | StringStream<> buffer; |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 47 | uint32_t indent{ 0 }; |
Hans-Kristian Arntzen | a489ba7 | 2019-04-02 11:19:03 +0200 | [diff] [blame] | 48 | char current_locale_radix_character = '.'; |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 49 | |
| 50 | public: |
Hans-Kristian Arntzen | a489ba7 | 2019-04-02 11:19:03 +0200 | [diff] [blame] | 51 | void set_current_locale_radix_character(char c) |
| 52 | { |
| 53 | current_locale_radix_character = c; |
| 54 | } |
| 55 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 56 | void begin_json_object(); |
| 57 | void end_json_object(); |
| 58 | void emit_json_key(const std::string &key); |
| 59 | void emit_json_key_value(const std::string &key, const std::string &value); |
| 60 | void emit_json_key_value(const std::string &key, bool value); |
| 61 | void emit_json_key_value(const std::string &key, uint32_t value); |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 62 | void emit_json_key_value(const std::string &key, int32_t value); |
| 63 | void emit_json_key_value(const std::string &key, float value); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 64 | void emit_json_key_object(const std::string &key); |
| 65 | void emit_json_key_array(const std::string &key); |
| 66 | |
| 67 | void begin_json_array(); |
| 68 | void end_json_array(); |
| 69 | void emit_json_array_value(const std::string &value); |
| 70 | void emit_json_array_value(uint32_t value); |
Hans-Kristian Arntzen | 43e89bd | 2019-10-04 10:37:47 +0200 | [diff] [blame] | 71 | void emit_json_array_value(bool value); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 72 | |
| 73 | std::string str() const |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 74 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 75 | return buffer.str(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 76 | } |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 77 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 78 | private: |
| 79 | inline void statement_indent() |
| 80 | { |
| 81 | for (uint32_t i = 0; i < indent; i++) |
| 82 | buffer << " "; |
| 83 | } |
| 84 | |
| 85 | template <typename T> |
| 86 | inline void statement_inner(T &&t) |
| 87 | { |
| 88 | buffer << std::forward<T>(t); |
| 89 | } |
| 90 | |
| 91 | template <typename T, typename... Ts> |
| 92 | inline void statement_inner(T &&t, Ts &&... ts) |
| 93 | { |
| 94 | buffer << std::forward<T>(t); |
| 95 | statement_inner(std::forward<Ts>(ts)...); |
| 96 | } |
| 97 | |
| 98 | template <typename... Ts> |
| 99 | inline void statement(Ts &&... ts) |
| 100 | { |
| 101 | statement_indent(); |
| 102 | statement_inner(std::forward<Ts>(ts)...); |
| 103 | buffer << '\n'; |
| 104 | } |
| 105 | |
| 106 | template <typename... Ts> |
| 107 | void statement_no_return(Ts &&... ts) |
| 108 | { |
| 109 | statement_indent(); |
| 110 | statement_inner(std::forward<Ts>(ts)...); |
| 111 | } |
| 112 | }; |
| 113 | } // namespace simple_json |
| 114 | |
| 115 | using namespace simple_json; |
| 116 | |
| 117 | // Hackery to emit JSON without using nlohmann/json C++ library (which requires a |
| 118 | // higher level of compiler compliance than is required by SPIRV-Cross |
| 119 | void Stream::begin_json_array() |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 120 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 121 | if (!stack.empty() && stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 122 | { |
| 123 | statement_inner(",\n"); |
| 124 | } |
| 125 | statement("["); |
| 126 | ++indent; |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 127 | stack.emplace(Type::Array, false); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 128 | } |
| 129 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 130 | void Stream::end_json_array() |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 131 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 132 | if (stack.empty() || stack.top().first != Type::Array) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 133 | SPIRV_CROSS_THROW("Invalid JSON state"); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 134 | if (stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 135 | { |
| 136 | statement_inner("\n"); |
| 137 | } |
| 138 | --indent; |
| 139 | statement_no_return("]"); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 140 | stack.pop(); |
| 141 | if (!stack.empty()) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 142 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 143 | stack.top().second = true; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 144 | } |
| 145 | } |
| 146 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 147 | void Stream::emit_json_array_value(const std::string &value) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 148 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 149 | if (stack.empty() || stack.top().first != Type::Array) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 150 | SPIRV_CROSS_THROW("Invalid JSON state"); |
| 151 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 152 | if (stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 153 | statement_inner(",\n"); |
| 154 | |
| 155 | statement_no_return("\"", value, "\""); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 156 | stack.top().second = true; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 157 | } |
| 158 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 159 | void Stream::emit_json_array_value(uint32_t value) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 160 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 161 | if (stack.empty() || stack.top().first != Type::Array) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 162 | SPIRV_CROSS_THROW("Invalid JSON state"); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 163 | if (stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 164 | statement_inner(",\n"); |
| 165 | statement_no_return(std::to_string(value)); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 166 | stack.top().second = true; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 167 | } |
| 168 | |
Hans-Kristian Arntzen | 43e89bd | 2019-10-04 10:37:47 +0200 | [diff] [blame] | 169 | void Stream::emit_json_array_value(bool value) |
| 170 | { |
| 171 | if (stack.empty() || stack.top().first != Type::Array) |
| 172 | SPIRV_CROSS_THROW("Invalid JSON state"); |
| 173 | if (stack.top().second) |
| 174 | statement_inner(",\n"); |
| 175 | statement_no_return(value ? "true" : "false"); |
| 176 | stack.top().second = true; |
| 177 | } |
| 178 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 179 | void Stream::begin_json_object() |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 180 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 181 | if (!stack.empty() && stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 182 | { |
| 183 | statement_inner(",\n"); |
| 184 | } |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 185 | statement("{"); |
| 186 | ++indent; |
| 187 | stack.emplace(Type::Object, false); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 188 | } |
| 189 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 190 | void Stream::end_json_object() |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 191 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 192 | if (stack.empty() || stack.top().first != Type::Object) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 193 | SPIRV_CROSS_THROW("Invalid JSON state"); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 194 | if (stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 195 | { |
| 196 | statement_inner("\n"); |
| 197 | } |
| 198 | --indent; |
| 199 | statement_no_return("}"); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 200 | stack.pop(); |
| 201 | if (!stack.empty()) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 202 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 203 | stack.top().second = true; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 204 | } |
| 205 | } |
| 206 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 207 | void Stream::emit_json_key(const std::string &key) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 208 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 209 | if (stack.empty() || stack.top().first != Type::Object) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 210 | SPIRV_CROSS_THROW("Invalid JSON state"); |
| 211 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 212 | if (stack.top().second) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 213 | statement_inner(",\n"); |
| 214 | statement_no_return("\"", key, "\" : "); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 215 | stack.top().second = true; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 216 | } |
| 217 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 218 | void Stream::emit_json_key_value(const std::string &key, const std::string &value) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 219 | { |
| 220 | emit_json_key(key); |
| 221 | statement_inner("\"", value, "\""); |
| 222 | } |
| 223 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 224 | void Stream::emit_json_key_value(const std::string &key, uint32_t value) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 225 | { |
| 226 | emit_json_key(key); |
| 227 | statement_inner(value); |
| 228 | } |
| 229 | |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 230 | void Stream::emit_json_key_value(const std::string &key, int32_t value) |
| 231 | { |
| 232 | emit_json_key(key); |
| 233 | statement_inner(value); |
| 234 | } |
| 235 | |
| 236 | void Stream::emit_json_key_value(const std::string &key, float value) |
| 237 | { |
| 238 | emit_json_key(key); |
Hans-Kristian Arntzen | a489ba7 | 2019-04-02 11:19:03 +0200 | [diff] [blame] | 239 | statement_inner(convert_to_string(value, current_locale_radix_character)); |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 240 | } |
| 241 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 242 | void Stream::emit_json_key_value(const std::string &key, bool value) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 243 | { |
| 244 | emit_json_key(key); |
| 245 | statement_inner(value ? "true" : "false"); |
| 246 | } |
| 247 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 248 | void Stream::emit_json_key_object(const std::string &key) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 249 | { |
| 250 | emit_json_key(key); |
| 251 | statement_inner("{\n"); |
| 252 | ++indent; |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 253 | stack.emplace(Type::Object, false); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 254 | } |
| 255 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 256 | void Stream::emit_json_key_array(const std::string &key) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 257 | { |
| 258 | emit_json_key(key); |
| 259 | statement_inner("[\n"); |
| 260 | ++indent; |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 261 | stack.emplace(Type::Array, false); |
| 262 | } |
| 263 | |
| 264 | void CompilerReflection::set_format(const std::string &format) |
| 265 | { |
| 266 | if (format != "json") |
| 267 | { |
| 268 | SPIRV_CROSS_THROW("Unsupported format"); |
| 269 | } |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | string CompilerReflection::compile() |
| 273 | { |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 274 | json_stream = std::make_shared<simple_json::Stream>(); |
Hans-Kristian Arntzen | a489ba7 | 2019-04-02 11:19:03 +0200 | [diff] [blame] | 275 | json_stream->set_current_locale_radix_character(current_locale_radix_character); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 276 | json_stream->begin_json_object(); |
Hans-Kristian Arntzen | 9649264 | 2019-05-23 14:54:04 +0200 | [diff] [blame] | 277 | reorder_type_alias(); |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 278 | emit_entry_points(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 279 | emit_types(); |
| 280 | emit_resources(); |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 281 | emit_specialization_constants(); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 282 | json_stream->end_json_object(); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 283 | return json_stream->str(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 284 | } |
| 285 | |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 286 | static bool naturally_emit_type(const SPIRType &type) |
| 287 | { |
| 288 | return type.basetype == SPIRType::Struct && !type.pointer && type.array.empty(); |
| 289 | } |
| 290 | |
| 291 | bool CompilerReflection::type_is_reference(const SPIRType &type) const |
| 292 | { |
| 293 | // Physical pointers and arrays of physical pointers need to refer to the pointee's type. |
| 294 | return type_is_top_level_physical_pointer(type) || |
| 295 | (!type.array.empty() && type_is_top_level_physical_pointer(get<SPIRType>(type.parent_type))); |
| 296 | } |
| 297 | |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 298 | void CompilerReflection::emit_types() |
| 299 | { |
| 300 | bool emitted_open_tag = false; |
Hans-Kristian Arntzen | b82cede | 2019-01-10 14:42:17 +0100 | [diff] [blame] | 301 | |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 302 | SmallVector<uint32_t> physical_pointee_types; |
| 303 | |
| 304 | // If we have physical pointers or arrays of physical pointers, it's also helpful to emit the pointee type |
| 305 | // and chain the type hierarchy. For POD, arrays can emit the entire type in-place. |
| 306 | ir.for_each_typed_id<SPIRType>([&](uint32_t self, SPIRType &type) { |
| 307 | if (naturally_emit_type(type)) |
| 308 | { |
| 309 | emit_type(self, emitted_open_tag); |
| 310 | } |
| 311 | else if (type_is_reference(type)) |
| 312 | { |
| 313 | if (!naturally_emit_type(this->get<SPIRType>(type.parent_type)) && |
Hans-Kristian Arntzen | d573a95 | 2020-07-01 11:42:58 +0200 | [diff] [blame] | 314 | find(physical_pointee_types.begin(), physical_pointee_types.end(), type.parent_type) == |
| 315 | physical_pointee_types.end()) |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 316 | { |
| 317 | physical_pointee_types.push_back(type.parent_type); |
| 318 | } |
| 319 | } |
Hans-Kristian Arntzen | b82cede | 2019-01-10 14:42:17 +0100 | [diff] [blame] | 320 | }); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 321 | |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 322 | for (uint32_t pointee_type : physical_pointee_types) |
| 323 | emit_type(pointee_type, emitted_open_tag); |
| 324 | |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 325 | if (emitted_open_tag) |
| 326 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 327 | json_stream->end_json_object(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 328 | } |
| 329 | } |
| 330 | |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 331 | void CompilerReflection::emit_type(uint32_t type_id, bool &emitted_open_tag) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 332 | { |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 333 | auto &type = get<SPIRType>(type_id); |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 334 | auto name = type_to_glsl(type); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 335 | |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 336 | if (!emitted_open_tag) |
| 337 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 338 | json_stream->emit_json_key_object("types"); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 339 | emitted_open_tag = true; |
| 340 | } |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 341 | json_stream->emit_json_key_object("_" + std::to_string(type_id)); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 342 | json_stream->emit_json_key_value("name", name); |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 343 | |
| 344 | if (type_is_top_level_physical_pointer(type)) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 345 | { |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 346 | json_stream->emit_json_key_value("type", "_" + std::to_string(type.parent_type)); |
| 347 | json_stream->emit_json_key_value("physical_pointer", true); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 348 | } |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 349 | else if (!type.array.empty()) |
| 350 | { |
| 351 | emit_type_array(type); |
| 352 | json_stream->emit_json_key_value("type", "_" + std::to_string(type.parent_type)); |
| 353 | json_stream->emit_json_key_value("array_stride", get_decoration(type_id, DecorationArrayStride)); |
| 354 | } |
| 355 | else |
| 356 | { |
| 357 | json_stream->emit_json_key_array("members"); |
| 358 | // FIXME ideally we'd like to emit the size of a structure as a |
| 359 | // convenience to people parsing the reflected JSON. The problem |
| 360 | // is that there's no implicit size for a type. It's final size |
| 361 | // will be determined by the top level declaration in which it's |
| 362 | // included. So there might be one size for the struct if it's |
| 363 | // included in a std140 uniform block and another if it's included |
| 364 | // in a std430 uniform block. |
| 365 | // The solution is to include *all* potential sizes as a map of |
| 366 | // layout type name to integer, but that will probably require |
| 367 | // some additional logic being written in this class, or in the |
| 368 | // parent CompilerGLSL class. |
| 369 | auto size = type.member_types.size(); |
| 370 | for (uint32_t i = 0; i < size; ++i) |
| 371 | { |
| 372 | emit_type_member(type, i); |
| 373 | } |
| 374 | json_stream->end_json_array(); |
| 375 | } |
| 376 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 377 | json_stream->end_json_object(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 378 | } |
| 379 | |
| 380 | void CompilerReflection::emit_type_member(const SPIRType &type, uint32_t index) |
| 381 | { |
| 382 | auto &membertype = get<SPIRType>(type.member_types[index]); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 383 | json_stream->begin_json_object(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 384 | auto name = to_member_name(type, index); |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 385 | // FIXME we'd like to emit the offset of each member, but such offsets are |
| 386 | // context dependent. See the comment above regarding structure sizes |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 387 | json_stream->emit_json_key_value("name", name); |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 388 | |
| 389 | if (type_is_reference(membertype)) |
| 390 | { |
| 391 | json_stream->emit_json_key_value("type", "_" + std::to_string(membertype.parent_type)); |
| 392 | } |
| 393 | else if (membertype.basetype == SPIRType::Struct) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 394 | { |
Brad Davis | 9ad4324 | 2018-06-21 09:24:22 -0700 | [diff] [blame] | 395 | json_stream->emit_json_key_value("type", "_" + std::to_string(membertype.self)); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 396 | } |
| 397 | else |
| 398 | { |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 399 | json_stream->emit_json_key_value("type", type_to_glsl(membertype)); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 400 | } |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 401 | emit_type_member_qualifiers(type, index); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 402 | json_stream->end_json_object(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 403 | } |
| 404 | |
| 405 | void CompilerReflection::emit_type_array(const SPIRType &type) |
| 406 | { |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 407 | if (!type_is_top_level_physical_pointer(type) && !type.array.empty()) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 408 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 409 | json_stream->emit_json_key_array("array"); |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 410 | // Note that we emit the zeros here as a means of identifying |
| 411 | // unbounded arrays. This is necessary as otherwise there would |
| 412 | // be no way of differentiating between float[4] and float[4][] |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 413 | for (const auto &value : type.array) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 414 | json_stream->emit_json_array_value(value); |
| 415 | json_stream->end_json_array(); |
Hans-Kristian Arntzen | 18e24c3 | 2020-01-15 16:46:38 +0100 | [diff] [blame] | 416 | |
| 417 | json_stream->emit_json_key_array("array_size_is_literal"); |
| 418 | for (const auto &value : type.array_size_literal) |
| 419 | json_stream->emit_json_array_value(value); |
| 420 | json_stream->end_json_array(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 421 | } |
| 422 | } |
| 423 | |
| 424 | void CompilerReflection::emit_type_member_qualifiers(const SPIRType &type, uint32_t index) |
| 425 | { |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 426 | auto &membertype = get<SPIRType>(type.member_types[index]); |
| 427 | emit_type_array(membertype); |
Hans-Kristian Arntzen | 5bcf02f | 2018-10-05 11:30:57 +0200 | [diff] [blame] | 428 | auto &memb = ir.meta[type.self].members; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 429 | if (index < memb.size()) |
| 430 | { |
| 431 | auto &dec = memb[index]; |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 432 | if (dec.decoration_flags.get(DecorationLocation)) |
| 433 | json_stream->emit_json_key_value("location", dec.location); |
| 434 | if (dec.decoration_flags.get(DecorationOffset)) |
| 435 | json_stream->emit_json_key_value("offset", dec.offset); |
Hans-Kristian Arntzen | 762c87a | 2020-01-15 17:01:35 +0100 | [diff] [blame] | 436 | |
| 437 | // Array stride is a property of the array type, not the struct. |
| 438 | if (has_decoration(type.member_types[index], DecorationArrayStride)) |
Hans-Kristian Arntzen | 7a41125 | 2020-01-16 15:20:59 +0100 | [diff] [blame] | 439 | json_stream->emit_json_key_value("array_stride", |
| 440 | get_decoration(type.member_types[index], DecorationArrayStride)); |
Hans-Kristian Arntzen | 762c87a | 2020-01-15 17:01:35 +0100 | [diff] [blame] | 441 | |
| 442 | if (dec.decoration_flags.get(DecorationMatrixStride)) |
| 443 | json_stream->emit_json_key_value("matrix_stride", dec.matrix_stride); |
| 444 | if (dec.decoration_flags.get(DecorationRowMajor)) |
| 445 | json_stream->emit_json_key_value("row_major", true); |
Hans-Kristian Arntzen | 58dad82 | 2020-05-25 11:05:42 +0200 | [diff] [blame] | 446 | |
| 447 | if (type_is_top_level_physical_pointer(membertype)) |
| 448 | json_stream->emit_json_key_value("physical_pointer", true); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 449 | } |
| 450 | } |
| 451 | |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 452 | string CompilerReflection::execution_model_to_str(spv::ExecutionModel model) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 453 | { |
| 454 | switch (model) |
| 455 | { |
Patrick Mours | 524bd43 | 2019-03-26 14:46:51 +0100 | [diff] [blame] | 456 | case ExecutionModelVertex: |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 457 | return "vert"; |
Patrick Mours | 524bd43 | 2019-03-26 14:46:51 +0100 | [diff] [blame] | 458 | case ExecutionModelTessellationControl: |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 459 | return "tesc"; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 460 | case ExecutionModelTessellationEvaluation: |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 461 | return "tese"; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 462 | case ExecutionModelGeometry: |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 463 | return "geom"; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 464 | case ExecutionModelFragment: |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 465 | return "frag"; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 466 | case ExecutionModelGLCompute: |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 467 | return "comp"; |
Patrick Mours | 524bd43 | 2019-03-26 14:46:51 +0100 | [diff] [blame] | 468 | case ExecutionModelRayGenerationNV: |
| 469 | return "rgen"; |
| 470 | case ExecutionModelIntersectionNV: |
| 471 | return "rint"; |
| 472 | case ExecutionModelAnyHitNV: |
| 473 | return "rahit"; |
| 474 | case ExecutionModelClosestHitNV: |
| 475 | return "rchit"; |
| 476 | case ExecutionModelMissNV: |
| 477 | return "rmiss"; |
| 478 | case ExecutionModelCallableNV: |
| 479 | return "rcall"; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 480 | default: |
| 481 | return "???"; |
| 482 | } |
| 483 | } |
| 484 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 485 | // FIXME include things like the local_size dimensions, geometry output vertex count, etc |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 486 | void CompilerReflection::emit_entry_points() |
| 487 | { |
Hans-Kristian Arntzen | 040204d | 2018-06-22 09:41:43 +0200 | [diff] [blame] | 488 | auto entries = get_entry_points_and_stages(); |
| 489 | if (!entries.empty()) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 490 | { |
Hans-Kristian Arntzen | d2cc43e | 2019-02-19 17:00:49 +0100 | [diff] [blame] | 491 | // Needed to make output deterministic. |
| 492 | sort(begin(entries), end(entries), [](const EntryPoint &a, const EntryPoint &b) -> bool { |
| 493 | if (a.execution_model < b.execution_model) |
| 494 | return true; |
| 495 | else if (a.execution_model > b.execution_model) |
| 496 | return false; |
| 497 | else |
| 498 | return a.name < b.name; |
| 499 | }); |
| 500 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 501 | json_stream->emit_json_key_array("entryPoints"); |
Hans-Kristian Arntzen | 040204d | 2018-06-22 09:41:43 +0200 | [diff] [blame] | 502 | for (auto &e : entries) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 503 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 504 | json_stream->begin_json_object(); |
| 505 | json_stream->emit_json_key_value("name", e.name); |
| 506 | json_stream->emit_json_key_value("mode", execution_model_to_str(e.execution_model)); |
Hans-Kristian Arntzen | 43e89bd | 2019-10-04 10:37:47 +0200 | [diff] [blame] | 507 | if (e.execution_model == ExecutionModelGLCompute) |
Frank Richter | 227a004 | 2019-10-03 16:36:17 +0200 | [diff] [blame] | 508 | { |
| 509 | const auto &spv_entry = get_entry_point(e.name, e.execution_model); |
Hans-Kristian Arntzen | 43e89bd | 2019-10-04 10:37:47 +0200 | [diff] [blame] | 510 | |
| 511 | SpecializationConstant spec_x, spec_y, spec_z; |
| 512 | get_work_group_size_specialization_constants(spec_x, spec_y, spec_z); |
| 513 | |
Frank Richter | 227a004 | 2019-10-03 16:36:17 +0200 | [diff] [blame] | 514 | json_stream->emit_json_key_array("workgroup_size"); |
Hans-Kristian Arntzen | 2d20b1a | 2019-10-07 10:29:04 +0200 | [diff] [blame] | 515 | json_stream->emit_json_array_value(spec_x.id != ID(0) ? spec_x.constant_id : |
| 516 | spv_entry.workgroup_size.x); |
| 517 | json_stream->emit_json_array_value(spec_y.id != ID(0) ? spec_y.constant_id : |
| 518 | spv_entry.workgroup_size.y); |
| 519 | json_stream->emit_json_array_value(spec_z.id != ID(0) ? spec_z.constant_id : |
| 520 | spv_entry.workgroup_size.z); |
Hans-Kristian Arntzen | 43e89bd | 2019-10-04 10:37:47 +0200 | [diff] [blame] | 521 | json_stream->end_json_array(); |
| 522 | |
| 523 | json_stream->emit_json_key_array("workgroup_size_is_spec_constant_id"); |
| 524 | json_stream->emit_json_array_value(spec_x.id != ID(0)); |
| 525 | json_stream->emit_json_array_value(spec_y.id != ID(0)); |
| 526 | json_stream->emit_json_array_value(spec_z.id != ID(0)); |
Frank Richter | 227a004 | 2019-10-03 16:36:17 +0200 | [diff] [blame] | 527 | json_stream->end_json_array(); |
| 528 | } |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 529 | json_stream->end_json_object(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 530 | } |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 531 | json_stream->end_json_array(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 532 | } |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 533 | } |
| 534 | |
| 535 | void CompilerReflection::emit_resources() |
| 536 | { |
| 537 | auto res = get_shader_resources(); |
| 538 | emit_resources("subpass_inputs", res.subpass_inputs); |
| 539 | emit_resources("inputs", res.stage_inputs); |
| 540 | emit_resources("outputs", res.stage_outputs); |
| 541 | emit_resources("textures", res.sampled_images); |
| 542 | emit_resources("separate_images", res.separate_images); |
| 543 | emit_resources("separate_samplers", res.separate_samplers); |
| 544 | emit_resources("images", res.storage_images); |
| 545 | emit_resources("ssbos", res.storage_buffers); |
| 546 | emit_resources("ubos", res.uniform_buffers); |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 547 | emit_resources("push_constants", res.push_constant_buffers); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 548 | emit_resources("counters", res.atomic_counters); |
Patrick Mours | b2a6675 | 2019-03-26 15:02:00 +0100 | [diff] [blame] | 549 | emit_resources("acceleration_structures", res.acceleration_structures); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 550 | } |
| 551 | |
Hans-Kristian Arntzen | a489ba7 | 2019-04-02 11:19:03 +0200 | [diff] [blame] | 552 | void CompilerReflection::emit_resources(const char *tag, const SmallVector<Resource> &resources) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 553 | { |
| 554 | if (resources.empty()) |
| 555 | { |
| 556 | return; |
| 557 | } |
| 558 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 559 | json_stream->emit_json_key_array(tag); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 560 | for (auto &res : resources) |
| 561 | { |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 562 | auto &type = get_type(res.type_id); |
Hans-Kristian Arntzen | 5bcf02f | 2018-10-05 11:30:57 +0200 | [diff] [blame] | 563 | auto typeflags = ir.meta[type.self].decoration.decoration_flags; |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 564 | auto &mask = get_decoration_bitset(res.id); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 565 | |
| 566 | // If we don't have a name, use the fallback for the type instead of the variable |
| 567 | // for SSBOs and UBOs since those are the only meaningful names to use externally. |
| 568 | // Push constant blocks are still accessed by name and not block name, even though they are technically Blocks. |
| 569 | bool is_push_constant = get_storage_class(res.id) == StorageClassPushConstant; |
| 570 | bool is_block = get_decoration_bitset(type.self).get(DecorationBlock) || |
| 571 | get_decoration_bitset(type.self).get(DecorationBufferBlock); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 572 | |
Hans-Kristian Arntzen | 333980a | 2019-09-05 12:43:40 +0200 | [diff] [blame] | 573 | ID fallback_id = !is_push_constant && is_block ? ID(res.base_type_id) : ID(res.id); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 574 | |
| 575 | json_stream->begin_json_object(); |
| 576 | |
| 577 | if (type.basetype == SPIRType::Struct) |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 578 | { |
Brad Davis | 9ad4324 | 2018-06-21 09:24:22 -0700 | [diff] [blame] | 579 | json_stream->emit_json_key_value("type", "_" + std::to_string(res.base_type_id)); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 580 | } |
| 581 | else |
| 582 | { |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 583 | json_stream->emit_json_key_value("type", type_to_glsl(type)); |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 584 | } |
| 585 | |
| 586 | json_stream->emit_json_key_value("name", !res.name.empty() ? res.name : get_fallback_name(fallback_id)); |
| 587 | { |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 588 | bool ssbo_block = type.storage == StorageClassStorageBuffer || |
| 589 | (type.storage == StorageClassUniform && typeflags.get(DecorationBufferBlock)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 590 | if (ssbo_block) |
| 591 | { |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 592 | auto buffer_flags = get_buffer_block_flags(res.id); |
| 593 | if (buffer_flags.get(DecorationNonReadable)) |
| 594 | json_stream->emit_json_key_value("writeonly", true); |
| 595 | if (buffer_flags.get(DecorationNonWritable)) |
| 596 | json_stream->emit_json_key_value("readonly", true); |
| 597 | if (buffer_flags.get(DecorationRestrict)) |
| 598 | json_stream->emit_json_key_value("restrict", true); |
| 599 | if (buffer_flags.get(DecorationCoherent)) |
| 600 | json_stream->emit_json_key_value("coherent", true); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 601 | } |
| 602 | } |
| 603 | |
| 604 | emit_type_array(type); |
| 605 | |
| 606 | { |
| 607 | bool is_sized_block = is_block && (get_storage_class(res.id) == StorageClassUniform || |
Hans-Kristian Arntzen | 4e7777c | 2019-01-30 13:31:17 +0100 | [diff] [blame] | 608 | get_storage_class(res.id) == StorageClassUniformConstant || |
| 609 | get_storage_class(res.id) == StorageClassStorageBuffer); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 610 | if (is_sized_block) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 611 | { |
| 612 | uint32_t block_size = uint32_t(get_declared_struct_size(get_type(res.base_type_id))); |
| 613 | json_stream->emit_json_key_value("block_size", block_size); |
| 614 | } |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 615 | } |
| 616 | |
| 617 | if (type.storage == StorageClassPushConstant) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 618 | json_stream->emit_json_key_value("push_constant", true); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 619 | if (mask.get(DecorationLocation)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 620 | json_stream->emit_json_key_value("location", get_decoration(res.id, DecorationLocation)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 621 | if (mask.get(DecorationRowMajor)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 622 | json_stream->emit_json_key_value("row_major", true); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 623 | if (mask.get(DecorationColMajor)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 624 | json_stream->emit_json_key_value("column_major", true); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 625 | if (mask.get(DecorationIndex)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 626 | json_stream->emit_json_key_value("index", get_decoration(res.id, DecorationIndex)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 627 | if (type.storage != StorageClassPushConstant && mask.get(DecorationDescriptorSet)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 628 | json_stream->emit_json_key_value("set", get_decoration(res.id, DecorationDescriptorSet)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 629 | if (mask.get(DecorationBinding)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 630 | json_stream->emit_json_key_value("binding", get_decoration(res.id, DecorationBinding)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 631 | if (mask.get(DecorationInputAttachmentIndex)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 632 | json_stream->emit_json_key_value("input_attachment_index", |
| 633 | get_decoration(res.id, DecorationInputAttachmentIndex)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 634 | if (mask.get(DecorationOffset)) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 635 | json_stream->emit_json_key_value("offset", get_decoration(res.id, DecorationOffset)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 636 | |
| 637 | // For images, the type itself adds a layout qualifer. |
| 638 | // Only emit the format for storage images. |
| 639 | if (type.basetype == SPIRType::Image && type.image.sampled == 2) |
| 640 | { |
Brad Davis | 7620400 | 2018-06-20 10:25:38 -0700 | [diff] [blame] | 641 | const char *fmt = format_to_glsl(type.image.format); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 642 | if (fmt != nullptr) |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 643 | json_stream->emit_json_key_value("format", std::string(fmt)); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 644 | } |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 645 | json_stream->end_json_object(); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 646 | } |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 647 | json_stream->end_json_array(); |
| 648 | } |
| 649 | |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 650 | void CompilerReflection::emit_specialization_constants() |
| 651 | { |
| 652 | auto specialization_constants = get_specialization_constants(); |
| 653 | if (specialization_constants.empty()) |
| 654 | return; |
| 655 | |
| 656 | json_stream->emit_json_key_array("specialization_constants"); |
Corentin Wallez | bcd7153 | 2020-09-04 10:04:25 +0200 | [diff] [blame] | 657 | for (const auto &spec_const : specialization_constants) |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 658 | { |
| 659 | auto &c = get<SPIRConstant>(spec_const.id); |
| 660 | auto type = get<SPIRType>(c.constant_type); |
| 661 | json_stream->begin_json_object(); |
Panagiotis Christopoulos Charitos | b3109b8 | 2020-04-18 22:00:36 +0200 | [diff] [blame] | 662 | json_stream->emit_json_key_value("name", get_name(spec_const.id)); |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 663 | json_stream->emit_json_key_value("id", spec_const.constant_id); |
| 664 | json_stream->emit_json_key_value("type", type_to_glsl(type)); |
Hans-Kristian Arntzen | 18e24c3 | 2020-01-15 16:46:38 +0100 | [diff] [blame] | 665 | json_stream->emit_json_key_value("variable_id", spec_const.id); |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 666 | switch (type.basetype) |
| 667 | { |
| 668 | case SPIRType::UInt: |
| 669 | json_stream->emit_json_key_value("default_value", c.scalar()); |
| 670 | break; |
| 671 | |
| 672 | case SPIRType::Int: |
| 673 | json_stream->emit_json_key_value("default_value", c.scalar_i32()); |
| 674 | break; |
| 675 | |
| 676 | case SPIRType::Float: |
| 677 | json_stream->emit_json_key_value("default_value", c.scalar_f32()); |
| 678 | break; |
| 679 | |
| 680 | case SPIRType::Boolean: |
| 681 | json_stream->emit_json_key_value("default_value", c.scalar() != 0); |
| 682 | break; |
Hans-Kristian Arntzen | 040204d | 2018-06-22 09:41:43 +0200 | [diff] [blame] | 683 | |
| 684 | default: |
| 685 | break; |
Brad Davis | 8d84a54 | 2018-06-20 11:47:31 -0700 | [diff] [blame] | 686 | } |
| 687 | json_stream->end_json_object(); |
| 688 | } |
| 689 | json_stream->end_json_array(); |
| 690 | } |
| 691 | |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 692 | string CompilerReflection::to_member_name(const SPIRType &type, uint32_t index) const |
| 693 | { |
Hans-Kristian Arntzen | b629878 | 2019-01-10 14:04:01 +0100 | [diff] [blame] | 694 | auto *type_meta = ir.find_meta(type.self); |
| 695 | |
| 696 | if (type_meta) |
| 697 | { |
| 698 | auto &memb = type_meta->members; |
| 699 | if (index < memb.size() && !memb[index].alias.empty()) |
| 700 | return memb[index].alias; |
| 701 | else |
| 702 | return join("_m", index); |
| 703 | } |
Brad Davis | 6c88b00 | 2018-06-18 09:30:16 -0700 | [diff] [blame] | 704 | else |
| 705 | return join("_m", index); |
Brad Davis | 709d3c6 | 2018-06-03 11:16:37 -0700 | [diff] [blame] | 706 | } |