spirv_common.hpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807
  1. /*
  2. * Copyright 2015-2021 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. /*
  17. * At your option, you may choose to accept this material under either:
  18. * 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
  19. * 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
  20. * SPDX-License-Identifier: Apache-2.0 OR MIT.
  21. */
  22. #ifndef SPIRV_CROSS_COMMON_HPP
  23. #define SPIRV_CROSS_COMMON_HPP
  24. #include "Khronos/spirv/spirv.hpp"
  25. #include "spirv_cross_containers.hpp"
  26. #include "spirv_cross_error_handling.hpp"
  27. #include <functional>
  28. // A bit crude, but allows projects which embed SPIRV-Cross statically to
  29. // effectively hide all the symbols from other projects.
  30. // There is a case where we have:
  31. // - Project A links against SPIRV-Cross statically.
  32. // - Project A links against Project B statically.
  33. // - Project B links against SPIRV-Cross statically (might be a different version).
  34. // This leads to a conflict with extremely bizarre results.
  35. // By overriding the namespace in one of the project builds, we can work around this.
  36. // If SPIRV-Cross is embedded in dynamic libraries,
  37. // prefer using -fvisibility=hidden on GCC/Clang instead.
  38. #ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE
  39. #define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE
  40. #else
  41. #define SPIRV_CROSS_NAMESPACE spirv_cross
  42. #endif
  43. namespace SPIRV_CROSS_NAMESPACE
  44. {
  45. namespace inner
  46. {
  47. template <typename T>
  48. void join_helper(StringStream<> &stream, T &&t)
  49. {
  50. stream << std::forward<T>(t);
  51. }
  52. template <typename T, typename... Ts>
  53. void join_helper(StringStream<> &stream, T &&t, Ts &&... ts)
  54. {
  55. stream << std::forward<T>(t);
  56. join_helper(stream, std::forward<Ts>(ts)...);
  57. }
  58. } // namespace inner
  59. class Bitset
  60. {
  61. public:
  62. Bitset() = default;
  63. explicit inline Bitset(uint64_t lower_)
  64. : lower(lower_)
  65. {
  66. }
  67. inline bool get(uint32_t bit) const
  68. {
  69. if (bit < 64)
  70. return (lower & (1ull << bit)) != 0;
  71. else
  72. return higher.count(bit) != 0;
  73. }
  74. inline void set(uint32_t bit)
  75. {
  76. if (bit < 64)
  77. lower |= 1ull << bit;
  78. else
  79. higher.insert(bit);
  80. }
  81. inline void clear(uint32_t bit)
  82. {
  83. if (bit < 64)
  84. lower &= ~(1ull << bit);
  85. else
  86. higher.erase(bit);
  87. }
  88. inline uint64_t get_lower() const
  89. {
  90. return lower;
  91. }
  92. inline void reset()
  93. {
  94. lower = 0;
  95. higher.clear();
  96. }
  97. inline void merge_and(const Bitset &other)
  98. {
  99. lower &= other.lower;
  100. std::unordered_set<uint32_t> tmp_set;
  101. for (auto &v : higher)
  102. if (other.higher.count(v) != 0)
  103. tmp_set.insert(v);
  104. higher = std::move(tmp_set);
  105. }
  106. inline void merge_or(const Bitset &other)
  107. {
  108. lower |= other.lower;
  109. for (auto &v : other.higher)
  110. higher.insert(v);
  111. }
  112. inline bool operator==(const Bitset &other) const
  113. {
  114. if (lower != other.lower)
  115. return false;
  116. if (higher.size() != other.higher.size())
  117. return false;
  118. for (auto &v : higher)
  119. if (other.higher.count(v) == 0)
  120. return false;
  121. return true;
  122. }
  123. inline bool operator!=(const Bitset &other) const
  124. {
  125. return !(*this == other);
  126. }
  127. template <typename Op>
  128. void for_each_bit(const Op &op) const
  129. {
  130. // TODO: Add ctz-based iteration.
  131. for (uint32_t i = 0; i < 64; i++)
  132. {
  133. if (lower & (1ull << i))
  134. op(i);
  135. }
  136. if (higher.empty())
  137. return;
  138. // Need to enforce an order here for reproducible results,
  139. // but hitting this path should happen extremely rarely, so having this slow path is fine.
  140. SmallVector<uint32_t> bits;
  141. bits.reserve(higher.size());
  142. for (auto &v : higher)
  143. bits.push_back(v);
  144. std::sort(std::begin(bits), std::end(bits));
  145. for (auto &v : bits)
  146. op(v);
  147. }
  148. inline bool empty() const
  149. {
  150. return lower == 0 && higher.empty();
  151. }
  152. private:
  153. // The most common bits to set are all lower than 64,
  154. // so optimize for this case. Bits spilling outside 64 go into a slower data structure.
  155. // In almost all cases, higher data structure will not be used.
  156. uint64_t lower = 0;
  157. std::unordered_set<uint32_t> higher;
  158. };
  159. // Helper template to avoid lots of nasty string temporary munging.
  160. template <typename... Ts>
  161. std::string join(Ts &&... ts)
  162. {
  163. StringStream<> stream;
  164. inner::join_helper(stream, std::forward<Ts>(ts)...);
  165. return stream.str();
  166. }
  167. inline std::string merge(const SmallVector<std::string> &list, const char *between = ", ")
  168. {
  169. StringStream<> stream;
  170. for (auto &elem : list)
  171. {
  172. stream << elem;
  173. if (&elem != &list.back())
  174. stream << between;
  175. }
  176. return stream.str();
  177. }
  178. // Make sure we don't accidentally call this with float or doubles with SFINAE.
  179. // Have to use the radix-aware overload.
  180. template <typename T, typename std::enable_if<!std::is_floating_point<T>::value, int>::type = 0>
  181. inline std::string convert_to_string(const T &t)
  182. {
  183. return std::to_string(t);
  184. }
  185. // Allow implementations to set a convenient standard precision
  186. #ifndef SPIRV_CROSS_FLT_FMT
  187. #define SPIRV_CROSS_FLT_FMT "%.32g"
  188. #endif
  189. // Disable sprintf and strcat warnings.
  190. // We cannot rely on snprintf and family existing because, ..., MSVC.
  191. #if defined(__clang__) || defined(__GNUC__)
  192. #pragma GCC diagnostic push
  193. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  194. #elif defined(_MSC_VER)
  195. #pragma warning(push)
  196. #pragma warning(disable : 4996)
  197. #endif
  198. static inline void fixup_radix_point(char *str, char radix_point)
  199. {
  200. // Setting locales is a very risky business in multi-threaded program,
  201. // so just fixup locales instead. We only need to care about the radix point.
  202. if (radix_point != '.')
  203. {
  204. while (*str != '\0')
  205. {
  206. if (*str == radix_point)
  207. *str = '.';
  208. str++;
  209. }
  210. }
  211. }
  212. inline std::string convert_to_string(float t, char locale_radix_point)
  213. {
  214. // std::to_string for floating point values is broken.
  215. // Fallback to something more sane.
  216. char buf[64];
  217. sprintf(buf, SPIRV_CROSS_FLT_FMT, t);
  218. fixup_radix_point(buf, locale_radix_point);
  219. // Ensure that the literal is float.
  220. if (!strchr(buf, '.') && !strchr(buf, 'e'))
  221. strcat(buf, ".0");
  222. return buf;
  223. }
  224. inline std::string convert_to_string(double t, char locale_radix_point)
  225. {
  226. // std::to_string for floating point values is broken.
  227. // Fallback to something more sane.
  228. char buf[64];
  229. sprintf(buf, SPIRV_CROSS_FLT_FMT, t);
  230. fixup_radix_point(buf, locale_radix_point);
  231. // Ensure that the literal is float.
  232. if (!strchr(buf, '.') && !strchr(buf, 'e'))
  233. strcat(buf, ".0");
  234. return buf;
  235. }
  236. template <typename T>
  237. struct ValueSaver
  238. {
  239. explicit ValueSaver(T &current_)
  240. : current(current_)
  241. , saved(current_)
  242. {
  243. }
  244. void release()
  245. {
  246. current = saved;
  247. }
  248. ~ValueSaver()
  249. {
  250. release();
  251. }
  252. T &current;
  253. T saved;
  254. };
  255. #if defined(__clang__) || defined(__GNUC__)
  256. #pragma GCC diagnostic pop
  257. #elif defined(_MSC_VER)
  258. #pragma warning(pop)
  259. #endif
  260. struct Instruction
  261. {
  262. uint16_t op = 0;
  263. uint16_t count = 0;
  264. uint32_t offset = 0;
  265. uint32_t length = 0;
  266. };
  267. enum Types
  268. {
  269. TypeNone,
  270. TypeType,
  271. TypeVariable,
  272. TypeConstant,
  273. TypeFunction,
  274. TypeFunctionPrototype,
  275. TypeBlock,
  276. TypeExtension,
  277. TypeExpression,
  278. TypeConstantOp,
  279. TypeCombinedImageSampler,
  280. TypeAccessChain,
  281. TypeUndef,
  282. TypeString,
  283. TypeCount
  284. };
  285. template <Types type>
  286. class TypedID;
  287. template <>
  288. class TypedID<TypeNone>
  289. {
  290. public:
  291. TypedID() = default;
  292. TypedID(uint32_t id_)
  293. : id(id_)
  294. {
  295. }
  296. template <Types U>
  297. TypedID(const TypedID<U> &other)
  298. {
  299. *this = other;
  300. }
  301. template <Types U>
  302. TypedID &operator=(const TypedID<U> &other)
  303. {
  304. id = uint32_t(other);
  305. return *this;
  306. }
  307. // Implicit conversion to u32 is desired here.
  308. // As long as we block implicit conversion between TypedID<A> and TypedID<B> we're good.
  309. operator uint32_t() const
  310. {
  311. return id;
  312. }
  313. template <Types U>
  314. operator TypedID<U>() const
  315. {
  316. return TypedID<U>(*this);
  317. }
  318. private:
  319. uint32_t id = 0;
  320. };
  321. template <Types type>
  322. class TypedID
  323. {
  324. public:
  325. TypedID() = default;
  326. TypedID(uint32_t id_)
  327. : id(id_)
  328. {
  329. }
  330. explicit TypedID(const TypedID<TypeNone> &other)
  331. : id(uint32_t(other))
  332. {
  333. }
  334. operator uint32_t() const
  335. {
  336. return id;
  337. }
  338. private:
  339. uint32_t id = 0;
  340. };
  341. using VariableID = TypedID<TypeVariable>;
  342. using TypeID = TypedID<TypeType>;
  343. using ConstantID = TypedID<TypeConstant>;
  344. using FunctionID = TypedID<TypeFunction>;
  345. using BlockID = TypedID<TypeBlock>;
  346. using ID = TypedID<TypeNone>;
  347. // Helper for Variant interface.
  348. struct IVariant
  349. {
  350. virtual ~IVariant() = default;
  351. virtual IVariant *clone(ObjectPoolBase *pool) = 0;
  352. ID self = 0;
  353. };
  354. #define SPIRV_CROSS_DECLARE_CLONE(T) \
  355. IVariant *clone(ObjectPoolBase *pool) override \
  356. { \
  357. return static_cast<ObjectPool<T> *>(pool)->allocate(*this); \
  358. }
  359. struct SPIRUndef : IVariant
  360. {
  361. enum
  362. {
  363. type = TypeUndef
  364. };
  365. explicit SPIRUndef(TypeID basetype_)
  366. : basetype(basetype_)
  367. {
  368. }
  369. TypeID basetype;
  370. SPIRV_CROSS_DECLARE_CLONE(SPIRUndef)
  371. };
  372. struct SPIRString : IVariant
  373. {
  374. enum
  375. {
  376. type = TypeString
  377. };
  378. explicit SPIRString(std::string str_)
  379. : str(std::move(str_))
  380. {
  381. }
  382. std::string str;
  383. SPIRV_CROSS_DECLARE_CLONE(SPIRString)
  384. };
  385. // This type is only used by backends which need to access the combined image and sampler IDs separately after
  386. // the OpSampledImage opcode.
  387. struct SPIRCombinedImageSampler : IVariant
  388. {
  389. enum
  390. {
  391. type = TypeCombinedImageSampler
  392. };
  393. SPIRCombinedImageSampler(TypeID type_, VariableID image_, VariableID sampler_)
  394. : combined_type(type_)
  395. , image(image_)
  396. , sampler(sampler_)
  397. {
  398. }
  399. TypeID combined_type;
  400. VariableID image;
  401. VariableID sampler;
  402. SPIRV_CROSS_DECLARE_CLONE(SPIRCombinedImageSampler)
  403. };
  404. struct SPIRConstantOp : IVariant
  405. {
  406. enum
  407. {
  408. type = TypeConstantOp
  409. };
  410. SPIRConstantOp(TypeID result_type, spv::Op op, const uint32_t *args, uint32_t length)
  411. : opcode(op)
  412. , basetype(result_type)
  413. {
  414. arguments.reserve(length);
  415. for (uint32_t i = 0; i < length; i++)
  416. arguments.push_back(args[i]);
  417. }
  418. spv::Op opcode;
  419. SmallVector<uint32_t> arguments;
  420. TypeID basetype;
  421. SPIRV_CROSS_DECLARE_CLONE(SPIRConstantOp)
  422. };
  423. struct SPIRType : IVariant
  424. {
  425. enum
  426. {
  427. type = TypeType
  428. };
  429. enum BaseType
  430. {
  431. Unknown,
  432. Void,
  433. Boolean,
  434. SByte,
  435. UByte,
  436. Short,
  437. UShort,
  438. Int,
  439. UInt,
  440. Int64,
  441. UInt64,
  442. AtomicCounter,
  443. Half,
  444. Float,
  445. Double,
  446. Struct,
  447. Image,
  448. SampledImage,
  449. Sampler,
  450. AccelerationStructure,
  451. RayQuery,
  452. // Keep internal types at the end.
  453. ControlPointArray,
  454. Interpolant,
  455. Char
  456. };
  457. // Scalar/vector/matrix support.
  458. BaseType basetype = Unknown;
  459. uint32_t width = 0;
  460. uint32_t vecsize = 1;
  461. uint32_t columns = 1;
  462. // Arrays, support array of arrays by having a vector of array sizes.
  463. SmallVector<uint32_t> array;
  464. // Array elements can be either specialization constants or specialization ops.
  465. // This array determines how to interpret the array size.
  466. // If an element is true, the element is a literal,
  467. // otherwise, it's an expression, which must be resolved on demand.
  468. // The actual size is not really known until runtime.
  469. SmallVector<bool> array_size_literal;
  470. // Pointers
  471. // Keep track of how many pointer layers we have.
  472. uint32_t pointer_depth = 0;
  473. bool pointer = false;
  474. bool forward_pointer = false;
  475. spv::StorageClass storage = spv::StorageClassGeneric;
  476. SmallVector<TypeID> member_types;
  477. // If member order has been rewritten to handle certain scenarios with Offset,
  478. // allow codegen to rewrite the index.
  479. SmallVector<uint32_t> member_type_index_redirection;
  480. struct ImageType
  481. {
  482. TypeID type;
  483. spv::Dim dim;
  484. bool depth;
  485. bool arrayed;
  486. bool ms;
  487. uint32_t sampled;
  488. spv::ImageFormat format;
  489. spv::AccessQualifier access;
  490. } image;
  491. // Structs can be declared multiple times if they are used as part of interface blocks.
  492. // We want to detect this so that we only emit the struct definition once.
  493. // Since we cannot rely on OpName to be equal, we need to figure out aliases.
  494. TypeID type_alias = 0;
  495. // Denotes the type which this type is based on.
  496. // Allows the backend to traverse how a complex type is built up during access chains.
  497. TypeID parent_type = 0;
  498. // Used in backends to avoid emitting members with conflicting names.
  499. std::unordered_set<std::string> member_name_cache;
  500. SPIRV_CROSS_DECLARE_CLONE(SPIRType)
  501. };
  502. struct SPIRExtension : IVariant
  503. {
  504. enum
  505. {
  506. type = TypeExtension
  507. };
  508. enum Extension
  509. {
  510. Unsupported,
  511. GLSL,
  512. SPV_debug_info,
  513. SPV_AMD_shader_ballot,
  514. SPV_AMD_shader_explicit_vertex_parameter,
  515. SPV_AMD_shader_trinary_minmax,
  516. SPV_AMD_gcn_shader
  517. };
  518. explicit SPIRExtension(Extension ext_)
  519. : ext(ext_)
  520. {
  521. }
  522. Extension ext;
  523. SPIRV_CROSS_DECLARE_CLONE(SPIRExtension)
  524. };
  525. // SPIREntryPoint is not a variant since its IDs are used to decorate OpFunction,
  526. // so in order to avoid conflicts, we can't stick them in the ids array.
  527. struct SPIREntryPoint
  528. {
  529. SPIREntryPoint(FunctionID self_, spv::ExecutionModel execution_model, const std::string &entry_name)
  530. : self(self_)
  531. , name(entry_name)
  532. , orig_name(entry_name)
  533. , model(execution_model)
  534. {
  535. }
  536. SPIREntryPoint() = default;
  537. FunctionID self = 0;
  538. std::string name;
  539. std::string orig_name;
  540. SmallVector<VariableID> interface_variables;
  541. Bitset flags;
  542. struct WorkgroupSize
  543. {
  544. uint32_t x = 0, y = 0, z = 0;
  545. uint32_t constant = 0; // Workgroup size can be expressed as a constant/spec-constant instead.
  546. } workgroup_size;
  547. uint32_t invocations = 0;
  548. uint32_t output_vertices = 0;
  549. spv::ExecutionModel model = spv::ExecutionModelMax;
  550. bool geometry_passthrough = false;
  551. };
  552. struct SPIRExpression : IVariant
  553. {
  554. enum
  555. {
  556. type = TypeExpression
  557. };
  558. // Only created by the backend target to avoid creating tons of temporaries.
  559. SPIRExpression(std::string expr, TypeID expression_type_, bool immutable_)
  560. : expression(move(expr))
  561. , expression_type(expression_type_)
  562. , immutable(immutable_)
  563. {
  564. }
  565. // If non-zero, prepend expression with to_expression(base_expression).
  566. // Used in amortizing multiple calls to to_expression()
  567. // where in certain cases that would quickly force a temporary when not needed.
  568. ID base_expression = 0;
  569. std::string expression;
  570. TypeID expression_type = 0;
  571. // If this expression is a forwarded load,
  572. // allow us to reference the original variable.
  573. ID loaded_from = 0;
  574. // If this expression will never change, we can avoid lots of temporaries
  575. // in high level source.
  576. // An expression being immutable can be speculative,
  577. // it is assumed that this is true almost always.
  578. bool immutable = false;
  579. // Before use, this expression must be transposed.
  580. // This is needed for targets which don't support row_major layouts.
  581. bool need_transpose = false;
  582. // Whether or not this is an access chain expression.
  583. bool access_chain = false;
  584. // A list of expressions which this expression depends on.
  585. SmallVector<ID> expression_dependencies;
  586. // By reading this expression, we implicitly read these expressions as well.
  587. // Used by access chain Store and Load since we read multiple expressions in this case.
  588. SmallVector<ID> implied_read_expressions;
  589. // The expression was emitted at a certain scope. Lets us track when an expression read means multiple reads.
  590. uint32_t emitted_loop_level = 0;
  591. SPIRV_CROSS_DECLARE_CLONE(SPIRExpression)
  592. };
  593. struct SPIRFunctionPrototype : IVariant
  594. {
  595. enum
  596. {
  597. type = TypeFunctionPrototype
  598. };
  599. explicit SPIRFunctionPrototype(TypeID return_type_)
  600. : return_type(return_type_)
  601. {
  602. }
  603. TypeID return_type;
  604. SmallVector<uint32_t> parameter_types;
  605. SPIRV_CROSS_DECLARE_CLONE(SPIRFunctionPrototype)
  606. };
  607. struct SPIRBlock : IVariant
  608. {
  609. enum
  610. {
  611. type = TypeBlock
  612. };
  613. enum Terminator
  614. {
  615. Unknown,
  616. Direct, // Emit next block directly without a particular condition.
  617. Select, // Block ends with an if/else block.
  618. MultiSelect, // Block ends with switch statement.
  619. Return, // Block ends with return.
  620. Unreachable, // Noop
  621. Kill, // Discard
  622. IgnoreIntersection, // Ray Tracing
  623. TerminateRay // Ray Tracing
  624. };
  625. enum Merge
  626. {
  627. MergeNone,
  628. MergeLoop,
  629. MergeSelection
  630. };
  631. enum Hints
  632. {
  633. HintNone,
  634. HintUnroll,
  635. HintDontUnroll,
  636. HintFlatten,
  637. HintDontFlatten
  638. };
  639. enum Method
  640. {
  641. MergeToSelectForLoop,
  642. MergeToDirectForLoop,
  643. MergeToSelectContinueForLoop
  644. };
  645. enum ContinueBlockType
  646. {
  647. ContinueNone,
  648. // Continue block is branchless and has at least one instruction.
  649. ForLoop,
  650. // Noop continue block.
  651. WhileLoop,
  652. // Continue block is conditional.
  653. DoWhileLoop,
  654. // Highly unlikely that anything will use this,
  655. // since it is really awkward/impossible to express in GLSL.
  656. ComplexLoop
  657. };
  658. enum : uint32_t
  659. {
  660. NoDominator = 0xffffffffu
  661. };
  662. Terminator terminator = Unknown;
  663. Merge merge = MergeNone;
  664. Hints hint = HintNone;
  665. BlockID next_block = 0;
  666. BlockID merge_block = 0;
  667. BlockID continue_block = 0;
  668. ID return_value = 0; // If 0, return nothing (void).
  669. ID condition = 0;
  670. BlockID true_block = 0;
  671. BlockID false_block = 0;
  672. BlockID default_block = 0;
  673. SmallVector<Instruction> ops;
  674. struct Phi
  675. {
  676. ID local_variable; // flush local variable ...
  677. BlockID parent; // If we're in from_block and want to branch into this block ...
  678. VariableID function_variable; // to this function-global "phi" variable first.
  679. };
  680. // Before entering this block flush out local variables to magical "phi" variables.
  681. SmallVector<Phi> phi_variables;
  682. // Declare these temporaries before beginning the block.
  683. // Used for handling complex continue blocks which have side effects.
  684. SmallVector<std::pair<TypeID, ID>> declare_temporary;
  685. // Declare these temporaries, but only conditionally if this block turns out to be
  686. // a complex loop header.
  687. SmallVector<std::pair<TypeID, ID>> potential_declare_temporary;
  688. struct Case
  689. {
  690. uint32_t value;
  691. BlockID block;
  692. };
  693. SmallVector<Case> cases;
  694. // If we have tried to optimize code for this block but failed,
  695. // keep track of this.
  696. bool disable_block_optimization = false;
  697. // If the continue block is complex, fallback to "dumb" for loops.
  698. bool complex_continue = false;
  699. // Do we need a ladder variable to defer breaking out of a loop construct after a switch block?
  700. bool need_ladder_break = false;
  701. // If marked, we have explicitly handled Phi from this block, so skip any flushes related to that on a branch.
  702. // Used to handle an edge case with switch and case-label fallthrough where fall-through writes to Phi.
  703. BlockID ignore_phi_from_block = 0;
  704. // The dominating block which this block might be within.
  705. // Used in continue; blocks to determine if we really need to write continue.
  706. BlockID loop_dominator = 0;
  707. // All access to these variables are dominated by this block,
  708. // so before branching anywhere we need to make sure that we declare these variables.
  709. SmallVector<VariableID> dominated_variables;
  710. // These are variables which should be declared in a for loop header, if we
  711. // fail to use a classic for-loop,
  712. // we remove these variables, and fall back to regular variables outside the loop.
  713. SmallVector<VariableID> loop_variables;
  714. // Some expressions are control-flow dependent, i.e. any instruction which relies on derivatives or
  715. // sub-group-like operations.
  716. // Make sure that we only use these expressions in the original block.
  717. SmallVector<ID> invalidate_expressions;
  718. SPIRV_CROSS_DECLARE_CLONE(SPIRBlock)
  719. };
  720. struct SPIRFunction : IVariant
  721. {
  722. enum
  723. {
  724. type = TypeFunction
  725. };
  726. SPIRFunction(TypeID return_type_, TypeID function_type_)
  727. : return_type(return_type_)
  728. , function_type(function_type_)
  729. {
  730. }
  731. struct Parameter
  732. {
  733. TypeID type;
  734. ID id;
  735. uint32_t read_count;
  736. uint32_t write_count;
  737. // Set to true if this parameter aliases a global variable,
  738. // used mostly in Metal where global variables
  739. // have to be passed down to functions as regular arguments.
  740. // However, for this kind of variable, we should not care about
  741. // read and write counts as access to the function arguments
  742. // is not local to the function in question.
  743. bool alias_global_variable;
  744. };
  745. // When calling a function, and we're remapping separate image samplers,
  746. // resolve these arguments into combined image samplers and pass them
  747. // as additional arguments in this order.
  748. // It gets more complicated as functions can pull in their own globals
  749. // and combine them with parameters,
  750. // so we need to distinguish if something is local parameter index
  751. // or a global ID.
  752. struct CombinedImageSamplerParameter
  753. {
  754. VariableID id;
  755. VariableID image_id;
  756. VariableID sampler_id;
  757. bool global_image;
  758. bool global_sampler;
  759. bool depth;
  760. };
  761. TypeID return_type;
  762. TypeID function_type;
  763. SmallVector<Parameter> arguments;
  764. // Can be used by backends to add magic arguments.
  765. // Currently used by combined image/sampler implementation.
  766. SmallVector<Parameter> shadow_arguments;
  767. SmallVector<VariableID> local_variables;
  768. BlockID entry_block = 0;
  769. SmallVector<BlockID> blocks;
  770. SmallVector<CombinedImageSamplerParameter> combined_parameters;
  771. struct EntryLine
  772. {
  773. uint32_t file_id = 0;
  774. uint32_t line_literal = 0;
  775. };
  776. EntryLine entry_line;
  777. void add_local_variable(VariableID id)
  778. {
  779. local_variables.push_back(id);
  780. }
  781. void add_parameter(TypeID parameter_type, ID id, bool alias_global_variable = false)
  782. {
  783. // Arguments are read-only until proven otherwise.
  784. arguments.push_back({ parameter_type, id, 0u, 0u, alias_global_variable });
  785. }
  786. // Hooks to be run when the function returns.
  787. // Mostly used for lowering internal data structures onto flattened structures.
  788. // Need to defer this, because they might rely on things which change during compilation.
  789. // Intentionally not a small vector, this one is rare, and std::function can be large.
  790. Vector<std::function<void()>> fixup_hooks_out;
  791. // Hooks to be run when the function begins.
  792. // Mostly used for populating internal data structures from flattened structures.
  793. // Need to defer this, because they might rely on things which change during compilation.
  794. // Intentionally not a small vector, this one is rare, and std::function can be large.
  795. Vector<std::function<void()>> fixup_hooks_in;
  796. // On function entry, make sure to copy a constant array into thread addr space to work around
  797. // the case where we are passing a constant array by value to a function on backends which do not
  798. // consider arrays value types.
  799. SmallVector<ID> constant_arrays_needed_on_stack;
  800. bool active = false;
  801. bool flush_undeclared = true;
  802. bool do_combined_parameters = true;
  803. SPIRV_CROSS_DECLARE_CLONE(SPIRFunction)
  804. };
  805. struct SPIRAccessChain : IVariant
  806. {
  807. enum
  808. {
  809. type = TypeAccessChain
  810. };
  811. SPIRAccessChain(TypeID basetype_, spv::StorageClass storage_, std::string base_, std::string dynamic_index_,
  812. int32_t static_index_)
  813. : basetype(basetype_)
  814. , storage(storage_)
  815. , base(std::move(base_))
  816. , dynamic_index(std::move(dynamic_index_))
  817. , static_index(static_index_)
  818. {
  819. }
  820. // The access chain represents an offset into a buffer.
  821. // Some backends need more complicated handling of access chains to be able to use buffers, like HLSL
  822. // which has no usable buffer type ala GLSL SSBOs.
  823. // StructuredBuffer is too limited, so our only option is to deal with ByteAddressBuffer which works with raw addresses.
  824. TypeID basetype;
  825. spv::StorageClass storage;
  826. std::string base;
  827. std::string dynamic_index;
  828. int32_t static_index;
  829. VariableID loaded_from = 0;
  830. uint32_t matrix_stride = 0;
  831. uint32_t array_stride = 0;
  832. bool row_major_matrix = false;
  833. bool immutable = false;
  834. // By reading this expression, we implicitly read these expressions as well.
  835. // Used by access chain Store and Load since we read multiple expressions in this case.
  836. SmallVector<ID> implied_read_expressions;
  837. SPIRV_CROSS_DECLARE_CLONE(SPIRAccessChain)
  838. };
  839. struct SPIRVariable : IVariant
  840. {
  841. enum
  842. {
  843. type = TypeVariable
  844. };
  845. SPIRVariable() = default;
  846. SPIRVariable(TypeID basetype_, spv::StorageClass storage_, ID initializer_ = 0, VariableID basevariable_ = 0)
  847. : basetype(basetype_)
  848. , storage(storage_)
  849. , initializer(initializer_)
  850. , basevariable(basevariable_)
  851. {
  852. }
  853. TypeID basetype = 0;
  854. spv::StorageClass storage = spv::StorageClassGeneric;
  855. uint32_t decoration = 0;
  856. ID initializer = 0;
  857. VariableID basevariable = 0;
  858. SmallVector<uint32_t> dereference_chain;
  859. bool compat_builtin = false;
  860. // If a variable is shadowed, we only statically assign to it
  861. // and never actually emit a statement for it.
  862. // When we read the variable as an expression, just forward
  863. // shadowed_id as the expression.
  864. bool statically_assigned = false;
  865. ID static_expression = 0;
  866. // Temporaries which can remain forwarded as long as this variable is not modified.
  867. SmallVector<ID> dependees;
  868. bool forwardable = true;
  869. bool deferred_declaration = false;
  870. bool phi_variable = false;
  871. // Used to deal with Phi variable flushes. See flush_phi().
  872. bool allocate_temporary_copy = false;
  873. bool remapped_variable = false;
  874. uint32_t remapped_components = 0;
  875. // The block which dominates all access to this variable.
  876. BlockID dominator = 0;
  877. // If true, this variable is a loop variable, when accessing the variable
  878. // outside a loop,
  879. // we should statically forward it.
  880. bool loop_variable = false;
  881. // Set to true while we're inside the for loop.
  882. bool loop_variable_enable = false;
  883. SPIRFunction::Parameter *parameter = nullptr;
  884. SPIRV_CROSS_DECLARE_CLONE(SPIRVariable)
  885. };
  886. struct SPIRConstant : IVariant
  887. {
  888. enum
  889. {
  890. type = TypeConstant
  891. };
  892. union Constant
  893. {
  894. uint32_t u32;
  895. int32_t i32;
  896. float f32;
  897. uint64_t u64;
  898. int64_t i64;
  899. double f64;
  900. };
  901. struct ConstantVector
  902. {
  903. Constant r[4];
  904. // If != 0, this element is a specialization constant, and we should keep track of it as such.
  905. ID id[4];
  906. uint32_t vecsize = 1;
  907. ConstantVector()
  908. {
  909. memset(r, 0, sizeof(r));
  910. }
  911. };
  912. struct ConstantMatrix
  913. {
  914. ConstantVector c[4];
  915. // If != 0, this column is a specialization constant, and we should keep track of it as such.
  916. ID id[4];
  917. uint32_t columns = 1;
  918. };
  919. static inline float f16_to_f32(uint16_t u16_value)
  920. {
  921. // Based on the GLM implementation.
  922. int s = (u16_value >> 15) & 0x1;
  923. int e = (u16_value >> 10) & 0x1f;
  924. int m = (u16_value >> 0) & 0x3ff;
  925. union
  926. {
  927. float f32;
  928. uint32_t u32;
  929. } u;
  930. if (e == 0)
  931. {
  932. if (m == 0)
  933. {
  934. u.u32 = uint32_t(s) << 31;
  935. return u.f32;
  936. }
  937. else
  938. {
  939. while ((m & 0x400) == 0)
  940. {
  941. m <<= 1;
  942. e--;
  943. }
  944. e++;
  945. m &= ~0x400;
  946. }
  947. }
  948. else if (e == 31)
  949. {
  950. if (m == 0)
  951. {
  952. u.u32 = (uint32_t(s) << 31) | 0x7f800000u;
  953. return u.f32;
  954. }
  955. else
  956. {
  957. u.u32 = (uint32_t(s) << 31) | 0x7f800000u | (m << 13);
  958. return u.f32;
  959. }
  960. }
  961. e += 127 - 15;
  962. m <<= 13;
  963. u.u32 = (uint32_t(s) << 31) | (e << 23) | m;
  964. return u.f32;
  965. }
  966. inline uint32_t specialization_constant_id(uint32_t col, uint32_t row) const
  967. {
  968. return m.c[col].id[row];
  969. }
  970. inline uint32_t specialization_constant_id(uint32_t col) const
  971. {
  972. return m.id[col];
  973. }
  974. inline uint32_t scalar(uint32_t col = 0, uint32_t row = 0) const
  975. {
  976. return m.c[col].r[row].u32;
  977. }
  978. inline int16_t scalar_i16(uint32_t col = 0, uint32_t row = 0) const
  979. {
  980. return int16_t(m.c[col].r[row].u32 & 0xffffu);
  981. }
  982. inline uint16_t scalar_u16(uint32_t col = 0, uint32_t row = 0) const
  983. {
  984. return uint16_t(m.c[col].r[row].u32 & 0xffffu);
  985. }
  986. inline int8_t scalar_i8(uint32_t col = 0, uint32_t row = 0) const
  987. {
  988. return int8_t(m.c[col].r[row].u32 & 0xffu);
  989. }
  990. inline uint8_t scalar_u8(uint32_t col = 0, uint32_t row = 0) const
  991. {
  992. return uint8_t(m.c[col].r[row].u32 & 0xffu);
  993. }
  994. inline float scalar_f16(uint32_t col = 0, uint32_t row = 0) const
  995. {
  996. return f16_to_f32(scalar_u16(col, row));
  997. }
  998. inline float scalar_f32(uint32_t col = 0, uint32_t row = 0) const
  999. {
  1000. return m.c[col].r[row].f32;
  1001. }
  1002. inline int32_t scalar_i32(uint32_t col = 0, uint32_t row = 0) const
  1003. {
  1004. return m.c[col].r[row].i32;
  1005. }
  1006. inline double scalar_f64(uint32_t col = 0, uint32_t row = 0) const
  1007. {
  1008. return m.c[col].r[row].f64;
  1009. }
  1010. inline int64_t scalar_i64(uint32_t col = 0, uint32_t row = 0) const
  1011. {
  1012. return m.c[col].r[row].i64;
  1013. }
  1014. inline uint64_t scalar_u64(uint32_t col = 0, uint32_t row = 0) const
  1015. {
  1016. return m.c[col].r[row].u64;
  1017. }
  1018. inline const ConstantVector &vector() const
  1019. {
  1020. return m.c[0];
  1021. }
  1022. inline uint32_t vector_size() const
  1023. {
  1024. return m.c[0].vecsize;
  1025. }
  1026. inline uint32_t columns() const
  1027. {
  1028. return m.columns;
  1029. }
  1030. inline void make_null(const SPIRType &constant_type_)
  1031. {
  1032. m = {};
  1033. m.columns = constant_type_.columns;
  1034. for (auto &c : m.c)
  1035. c.vecsize = constant_type_.vecsize;
  1036. }
  1037. inline bool constant_is_null() const
  1038. {
  1039. if (specialization)
  1040. return false;
  1041. if (!subconstants.empty())
  1042. return false;
  1043. for (uint32_t col = 0; col < columns(); col++)
  1044. for (uint32_t row = 0; row < vector_size(); row++)
  1045. if (scalar_u64(col, row) != 0)
  1046. return false;
  1047. return true;
  1048. }
  1049. explicit SPIRConstant(uint32_t constant_type_)
  1050. : constant_type(constant_type_)
  1051. {
  1052. }
  1053. SPIRConstant() = default;
  1054. SPIRConstant(TypeID constant_type_, const uint32_t *elements, uint32_t num_elements, bool specialized)
  1055. : constant_type(constant_type_)
  1056. , specialization(specialized)
  1057. {
  1058. subconstants.reserve(num_elements);
  1059. for (uint32_t i = 0; i < num_elements; i++)
  1060. subconstants.push_back(elements[i]);
  1061. specialization = specialized;
  1062. }
  1063. // Construct scalar (32-bit).
  1064. SPIRConstant(TypeID constant_type_, uint32_t v0, bool specialized)
  1065. : constant_type(constant_type_)
  1066. , specialization(specialized)
  1067. {
  1068. m.c[0].r[0].u32 = v0;
  1069. m.c[0].vecsize = 1;
  1070. m.columns = 1;
  1071. }
  1072. // Construct scalar (64-bit).
  1073. SPIRConstant(TypeID constant_type_, uint64_t v0, bool specialized)
  1074. : constant_type(constant_type_)
  1075. , specialization(specialized)
  1076. {
  1077. m.c[0].r[0].u64 = v0;
  1078. m.c[0].vecsize = 1;
  1079. m.columns = 1;
  1080. }
  1081. // Construct vectors and matrices.
  1082. SPIRConstant(TypeID constant_type_, const SPIRConstant *const *vector_elements, uint32_t num_elements,
  1083. bool specialized)
  1084. : constant_type(constant_type_)
  1085. , specialization(specialized)
  1086. {
  1087. bool matrix = vector_elements[0]->m.c[0].vecsize > 1;
  1088. if (matrix)
  1089. {
  1090. m.columns = num_elements;
  1091. for (uint32_t i = 0; i < num_elements; i++)
  1092. {
  1093. m.c[i] = vector_elements[i]->m.c[0];
  1094. if (vector_elements[i]->specialization)
  1095. m.id[i] = vector_elements[i]->self;
  1096. }
  1097. }
  1098. else
  1099. {
  1100. m.c[0].vecsize = num_elements;
  1101. m.columns = 1;
  1102. for (uint32_t i = 0; i < num_elements; i++)
  1103. {
  1104. m.c[0].r[i] = vector_elements[i]->m.c[0].r[0];
  1105. if (vector_elements[i]->specialization)
  1106. m.c[0].id[i] = vector_elements[i]->self;
  1107. }
  1108. }
  1109. }
  1110. TypeID constant_type = 0;
  1111. ConstantMatrix m;
  1112. // If this constant is a specialization constant (i.e. created with OpSpecConstant*).
  1113. bool specialization = false;
  1114. // If this constant is used as an array length which creates specialization restrictions on some backends.
  1115. bool is_used_as_array_length = false;
  1116. // If true, this is a LUT, and should always be declared in the outer scope.
  1117. bool is_used_as_lut = false;
  1118. // For composites which are constant arrays, etc.
  1119. SmallVector<ConstantID> subconstants;
  1120. // Non-Vulkan GLSL, HLSL and sometimes MSL emits defines for each specialization constant,
  1121. // and uses them to initialize the constant. This allows the user
  1122. // to still be able to specialize the value by supplying corresponding
  1123. // preprocessor directives before compiling the shader.
  1124. std::string specialization_constant_macro_name;
  1125. SPIRV_CROSS_DECLARE_CLONE(SPIRConstant)
  1126. };
  1127. // Variants have a very specific allocation scheme.
  1128. struct ObjectPoolGroup
  1129. {
  1130. std::unique_ptr<ObjectPoolBase> pools[TypeCount];
  1131. };
  1132. class Variant
  1133. {
  1134. public:
  1135. explicit Variant(ObjectPoolGroup *group_)
  1136. : group(group_)
  1137. {
  1138. }
  1139. ~Variant()
  1140. {
  1141. if (holder)
  1142. group->pools[type]->free_opaque(holder);
  1143. }
  1144. // Marking custom move constructor as noexcept is important.
  1145. Variant(Variant &&other) SPIRV_CROSS_NOEXCEPT
  1146. {
  1147. *this = std::move(other);
  1148. }
  1149. // We cannot copy from other variant without our own pool group.
  1150. // Have to explicitly copy.
  1151. Variant(const Variant &variant) = delete;
  1152. // Marking custom move constructor as noexcept is important.
  1153. Variant &operator=(Variant &&other) SPIRV_CROSS_NOEXCEPT
  1154. {
  1155. if (this != &other)
  1156. {
  1157. if (holder)
  1158. group->pools[type]->free_opaque(holder);
  1159. holder = other.holder;
  1160. group = other.group;
  1161. type = other.type;
  1162. allow_type_rewrite = other.allow_type_rewrite;
  1163. other.holder = nullptr;
  1164. other.type = TypeNone;
  1165. }
  1166. return *this;
  1167. }
  1168. // This copy/clone should only be called in the Compiler constructor.
  1169. // If this is called inside ::compile(), we invalidate any references we took higher in the stack.
  1170. // This should never happen.
  1171. Variant &operator=(const Variant &other)
  1172. {
  1173. //#define SPIRV_CROSS_COPY_CONSTRUCTOR_SANITIZE
  1174. #ifdef SPIRV_CROSS_COPY_CONSTRUCTOR_SANITIZE
  1175. abort();
  1176. #endif
  1177. if (this != &other)
  1178. {
  1179. if (holder)
  1180. group->pools[type]->free_opaque(holder);
  1181. if (other.holder)
  1182. holder = other.holder->clone(group->pools[other.type].get());
  1183. else
  1184. holder = nullptr;
  1185. type = other.type;
  1186. allow_type_rewrite = other.allow_type_rewrite;
  1187. }
  1188. return *this;
  1189. }
  1190. void set(IVariant *val, Types new_type)
  1191. {
  1192. if (holder)
  1193. group->pools[type]->free_opaque(holder);
  1194. holder = nullptr;
  1195. if (!allow_type_rewrite && type != TypeNone && type != new_type)
  1196. {
  1197. if (val)
  1198. group->pools[new_type]->free_opaque(val);
  1199. SPIRV_CROSS_THROW("Overwriting a variant with new type.");
  1200. }
  1201. holder = val;
  1202. type = new_type;
  1203. allow_type_rewrite = false;
  1204. }
  1205. template <typename T, typename... Ts>
  1206. T *allocate_and_set(Types new_type, Ts &&... ts)
  1207. {
  1208. T *val = static_cast<ObjectPool<T> &>(*group->pools[new_type]).allocate(std::forward<Ts>(ts)...);
  1209. set(val, new_type);
  1210. return val;
  1211. }
  1212. template <typename T>
  1213. T &get()
  1214. {
  1215. if (!holder)
  1216. SPIRV_CROSS_THROW("nullptr");
  1217. if (static_cast<Types>(T::type) != type)
  1218. SPIRV_CROSS_THROW("Bad cast");
  1219. return *static_cast<T *>(holder);
  1220. }
  1221. template <typename T>
  1222. const T &get() const
  1223. {
  1224. if (!holder)
  1225. SPIRV_CROSS_THROW("nullptr");
  1226. if (static_cast<Types>(T::type) != type)
  1227. SPIRV_CROSS_THROW("Bad cast");
  1228. return *static_cast<const T *>(holder);
  1229. }
  1230. Types get_type() const
  1231. {
  1232. return type;
  1233. }
  1234. ID get_id() const
  1235. {
  1236. return holder ? holder->self : ID(0);
  1237. }
  1238. bool empty() const
  1239. {
  1240. return !holder;
  1241. }
  1242. void reset()
  1243. {
  1244. if (holder)
  1245. group->pools[type]->free_opaque(holder);
  1246. holder = nullptr;
  1247. type = TypeNone;
  1248. }
  1249. void set_allow_type_rewrite()
  1250. {
  1251. allow_type_rewrite = true;
  1252. }
  1253. private:
  1254. ObjectPoolGroup *group = nullptr;
  1255. IVariant *holder = nullptr;
  1256. Types type = TypeNone;
  1257. bool allow_type_rewrite = false;
  1258. };
  1259. template <typename T>
  1260. T &variant_get(Variant &var)
  1261. {
  1262. return var.get<T>();
  1263. }
  1264. template <typename T>
  1265. const T &variant_get(const Variant &var)
  1266. {
  1267. return var.get<T>();
  1268. }
  1269. template <typename T, typename... P>
  1270. T &variant_set(Variant &var, P &&... args)
  1271. {
  1272. auto *ptr = var.allocate_and_set<T>(static_cast<Types>(T::type), std::forward<P>(args)...);
  1273. return *ptr;
  1274. }
  1275. struct AccessChainMeta
  1276. {
  1277. uint32_t storage_physical_type = 0;
  1278. bool need_transpose = false;
  1279. bool storage_is_packed = false;
  1280. bool storage_is_invariant = false;
  1281. bool flattened_struct = false;
  1282. };
  1283. enum ExtendedDecorations
  1284. {
  1285. // Marks if a buffer block is re-packed, i.e. member declaration might be subject to PhysicalTypeID remapping and padding.
  1286. SPIRVCrossDecorationBufferBlockRepacked = 0,
  1287. // A type in a buffer block might be declared with a different physical type than the logical type.
  1288. // If this is not set, PhysicalTypeID == the SPIR-V type as declared.
  1289. SPIRVCrossDecorationPhysicalTypeID,
  1290. // Marks if the physical type is to be declared with tight packing rules, i.e. packed_floatN on MSL and friends.
  1291. // If this is set, PhysicalTypeID might also be set. It can be set to same as logical type if all we're doing
  1292. // is converting float3 to packed_float3 for example.
  1293. // If this is marked on a struct, it means the struct itself must use only Packed types for all its members.
  1294. SPIRVCrossDecorationPhysicalTypePacked,
  1295. // The padding in bytes before declaring this struct member.
  1296. // If used on a struct type, marks the target size of a struct.
  1297. SPIRVCrossDecorationPaddingTarget,
  1298. SPIRVCrossDecorationInterfaceMemberIndex,
  1299. SPIRVCrossDecorationInterfaceOrigID,
  1300. SPIRVCrossDecorationResourceIndexPrimary,
  1301. // Used for decorations like resource indices for samplers when part of combined image samplers.
  1302. // A variable might need to hold two resource indices in this case.
  1303. SPIRVCrossDecorationResourceIndexSecondary,
  1304. // Used for resource indices for multiplanar images when part of combined image samplers.
  1305. SPIRVCrossDecorationResourceIndexTertiary,
  1306. SPIRVCrossDecorationResourceIndexQuaternary,
  1307. // Marks a buffer block for using explicit offsets (GLSL/HLSL).
  1308. SPIRVCrossDecorationExplicitOffset,
  1309. // Apply to a variable in the Input storage class; marks it as holding the base group passed to vkCmdDispatchBase(),
  1310. // or the base vertex and instance indices passed to vkCmdDrawIndexed().
  1311. // In MSL, this is used to adjust the WorkgroupId and GlobalInvocationId variables in compute shaders,
  1312. // and to hold the BaseVertex and BaseInstance variables in vertex shaders.
  1313. SPIRVCrossDecorationBuiltInDispatchBase,
  1314. // Apply to a variable that is a function parameter; marks it as being a "dynamic"
  1315. // combined image-sampler. In MSL, this is used when a function parameter might hold
  1316. // either a regular combined image-sampler or one that has an attached sampler
  1317. // Y'CbCr conversion.
  1318. SPIRVCrossDecorationDynamicImageSampler,
  1319. // Apply to a variable in the Input storage class; marks it as holding the size of the stage
  1320. // input grid.
  1321. // In MSL, this is used to hold the vertex and instance counts in a tessellation pipeline
  1322. // vertex shader.
  1323. SPIRVCrossDecorationBuiltInStageInputSize,
  1324. // Apply to any access chain of a tessellation I/O variable; stores the type of the sub-object
  1325. // that was chained to, as recorded in the input variable itself. This is used in case the pointer
  1326. // is itself used as the base of an access chain, to calculate the original type of the sub-object
  1327. // chained to, in case a swizzle needs to be applied. This should not happen normally with valid
  1328. // SPIR-V, but the MSL backend can change the type of input variables, necessitating the
  1329. // addition of swizzles to keep the generated code compiling.
  1330. SPIRVCrossDecorationTessIOOriginalInputTypeID,
  1331. // Apply to any access chain of an interface variable used with pull-model interpolation, where the variable is a
  1332. // vector but the resulting pointer is a scalar; stores the component index that is to be accessed by the chain.
  1333. // This is used when emitting calls to interpolation functions on the chain in MSL: in this case, the component
  1334. // must be applied to the result, since pull-model interpolants in MSL cannot be swizzled directly, but the
  1335. // results of interpolation can.
  1336. SPIRVCrossDecorationInterpolantComponentExpr,
  1337. SPIRVCrossDecorationCount
  1338. };
  1339. struct Meta
  1340. {
  1341. struct Decoration
  1342. {
  1343. std::string alias;
  1344. std::string qualified_alias;
  1345. std::string hlsl_semantic;
  1346. Bitset decoration_flags;
  1347. spv::BuiltIn builtin_type = spv::BuiltInMax;
  1348. uint32_t location = 0;
  1349. uint32_t component = 0;
  1350. uint32_t set = 0;
  1351. uint32_t binding = 0;
  1352. uint32_t offset = 0;
  1353. uint32_t xfb_buffer = 0;
  1354. uint32_t xfb_stride = 0;
  1355. uint32_t stream = 0;
  1356. uint32_t array_stride = 0;
  1357. uint32_t matrix_stride = 0;
  1358. uint32_t input_attachment = 0;
  1359. uint32_t spec_id = 0;
  1360. uint32_t index = 0;
  1361. spv::FPRoundingMode fp_rounding_mode = spv::FPRoundingModeMax;
  1362. bool builtin = false;
  1363. struct Extended
  1364. {
  1365. Extended()
  1366. {
  1367. // MSVC 2013 workaround to init like this.
  1368. for (auto &v : values)
  1369. v = 0;
  1370. }
  1371. Bitset flags;
  1372. uint32_t values[SPIRVCrossDecorationCount];
  1373. } extended;
  1374. };
  1375. Decoration decoration;
  1376. // Intentionally not a SmallVector. Decoration is large and somewhat rare.
  1377. Vector<Decoration> members;
  1378. std::unordered_map<uint32_t, uint32_t> decoration_word_offset;
  1379. // For SPV_GOOGLE_hlsl_functionality1.
  1380. bool hlsl_is_magic_counter_buffer = false;
  1381. // ID for the sibling counter buffer.
  1382. uint32_t hlsl_magic_counter_buffer = 0;
  1383. };
  1384. // A user callback that remaps the type of any variable.
  1385. // var_name is the declared name of the variable.
  1386. // name_of_type is the textual name of the type which will be used in the code unless written to by the callback.
  1387. using VariableTypeRemapCallback =
  1388. std::function<void(const SPIRType &type, const std::string &var_name, std::string &name_of_type)>;
  1389. class Hasher
  1390. {
  1391. public:
  1392. inline void u32(uint32_t value)
  1393. {
  1394. h = (h * 0x100000001b3ull) ^ value;
  1395. }
  1396. inline uint64_t get() const
  1397. {
  1398. return h;
  1399. }
  1400. private:
  1401. uint64_t h = 0xcbf29ce484222325ull;
  1402. };
  1403. static inline bool type_is_floating_point(const SPIRType &type)
  1404. {
  1405. return type.basetype == SPIRType::Half || type.basetype == SPIRType::Float || type.basetype == SPIRType::Double;
  1406. }
  1407. static inline bool type_is_integral(const SPIRType &type)
  1408. {
  1409. return type.basetype == SPIRType::SByte || type.basetype == SPIRType::UByte || type.basetype == SPIRType::Short ||
  1410. type.basetype == SPIRType::UShort || type.basetype == SPIRType::Int || type.basetype == SPIRType::UInt ||
  1411. type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64;
  1412. }
  1413. static inline SPIRType::BaseType to_signed_basetype(uint32_t width)
  1414. {
  1415. switch (width)
  1416. {
  1417. case 8:
  1418. return SPIRType::SByte;
  1419. case 16:
  1420. return SPIRType::Short;
  1421. case 32:
  1422. return SPIRType::Int;
  1423. case 64:
  1424. return SPIRType::Int64;
  1425. default:
  1426. SPIRV_CROSS_THROW("Invalid bit width.");
  1427. }
  1428. }
  1429. static inline SPIRType::BaseType to_unsigned_basetype(uint32_t width)
  1430. {
  1431. switch (width)
  1432. {
  1433. case 8:
  1434. return SPIRType::UByte;
  1435. case 16:
  1436. return SPIRType::UShort;
  1437. case 32:
  1438. return SPIRType::UInt;
  1439. case 64:
  1440. return SPIRType::UInt64;
  1441. default:
  1442. SPIRV_CROSS_THROW("Invalid bit width.");
  1443. }
  1444. }
  1445. // Returns true if an arithmetic operation does not change behavior depending on signedness.
  1446. static inline bool opcode_is_sign_invariant(spv::Op opcode)
  1447. {
  1448. switch (opcode)
  1449. {
  1450. case spv::OpIEqual:
  1451. case spv::OpINotEqual:
  1452. case spv::OpISub:
  1453. case spv::OpIAdd:
  1454. case spv::OpIMul:
  1455. case spv::OpShiftLeftLogical:
  1456. case spv::OpBitwiseOr:
  1457. case spv::OpBitwiseXor:
  1458. case spv::OpBitwiseAnd:
  1459. return true;
  1460. default:
  1461. return false;
  1462. }
  1463. }
  1464. struct SetBindingPair
  1465. {
  1466. uint32_t desc_set;
  1467. uint32_t binding;
  1468. inline bool operator==(const SetBindingPair &other) const
  1469. {
  1470. return desc_set == other.desc_set && binding == other.binding;
  1471. }
  1472. inline bool operator<(const SetBindingPair &other) const
  1473. {
  1474. return desc_set < other.desc_set || (desc_set == other.desc_set && binding < other.binding);
  1475. }
  1476. };
  1477. struct StageSetBinding
  1478. {
  1479. spv::ExecutionModel model;
  1480. uint32_t desc_set;
  1481. uint32_t binding;
  1482. inline bool operator==(const StageSetBinding &other) const
  1483. {
  1484. return model == other.model && desc_set == other.desc_set && binding == other.binding;
  1485. }
  1486. };
  1487. struct InternalHasher
  1488. {
  1489. inline size_t operator()(const SetBindingPair &value) const
  1490. {
  1491. // Quality of hash doesn't really matter here.
  1492. auto hash_set = std::hash<uint32_t>()(value.desc_set);
  1493. auto hash_binding = std::hash<uint32_t>()(value.binding);
  1494. return (hash_set * 0x10001b31) ^ hash_binding;
  1495. }
  1496. inline size_t operator()(const StageSetBinding &value) const
  1497. {
  1498. // Quality of hash doesn't really matter here.
  1499. auto hash_model = std::hash<uint32_t>()(value.model);
  1500. auto hash_set = std::hash<uint32_t>()(value.desc_set);
  1501. auto tmp_hash = (hash_model * 0x10001b31) ^ hash_set;
  1502. return (tmp_hash * 0x10001b31) ^ value.binding;
  1503. }
  1504. };
  1505. // Special constant used in a {MSL,HLSL}ResourceBinding desc_set
  1506. // element to indicate the bindings for the push constants.
  1507. static const uint32_t ResourceBindingPushConstantDescriptorSet = ~(0u);
  1508. // Special constant used in a {MSL,HLSL}ResourceBinding binding
  1509. // element to indicate the bindings for the push constants.
  1510. static const uint32_t ResourceBindingPushConstantBinding = 0;
  1511. } // namespace SPIRV_CROSS_NAMESPACE
  1512. namespace std
  1513. {
  1514. template <SPIRV_CROSS_NAMESPACE::Types type>
  1515. struct hash<SPIRV_CROSS_NAMESPACE::TypedID<type>>
  1516. {
  1517. size_t operator()(const SPIRV_CROSS_NAMESPACE::TypedID<type> &value) const
  1518. {
  1519. return std::hash<uint32_t>()(value);
  1520. }
  1521. };
  1522. } // namespace std
  1523. #endif