shaderc_spirv.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. /*
  2. * Copyright 2011-2021 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "shaderc.h"
  6. BX_PRAGMA_DIAGNOSTIC_PUSH()
  7. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // error C4100: 'inclusionDepth' : unreferenced formal parameter
  8. BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4265) // error C4265: 'spv::spirvbin_t': class has virtual functions, but destructor is not virtual
  9. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wattributes") // warning: attribute ignored
  10. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wdeprecated-declarations") // warning: ‘MSLVertexAttr’ is deprecated
  11. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wtype-limits") // warning: comparison of unsigned expression in ‘< 0’ is always false
  12. BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'userData' shadows a member of 'glslang::TShader::Includer::IncludeResult'
  13. #define ENABLE_OPT 1
  14. #include <ShaderLang.h>
  15. #include <ResourceLimits.h>
  16. #include <SPIRV/SPVRemapper.h>
  17. #include <SPIRV/GlslangToSpv.h>
  18. #include <webgpu/webgpu_cpp.h>
  19. #define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
  20. #include <spirv_msl.hpp>
  21. #include <spirv_reflect.hpp>
  22. #include <spirv-tools/optimizer.hpp>
  23. BX_PRAGMA_DIAGNOSTIC_POP()
  24. namespace bgfx
  25. {
  26. static bx::DefaultAllocator s_allocator;
  27. bx::AllocatorI* g_allocator = &s_allocator;
  28. struct TinyStlAllocator
  29. {
  30. static void* static_allocate(size_t _bytes);
  31. static void static_deallocate(void* _ptr, size_t /*_bytes*/);
  32. };
  33. void* TinyStlAllocator::static_allocate(size_t _bytes)
  34. {
  35. return BX_ALLOC(g_allocator, _bytes);
  36. }
  37. void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
  38. {
  39. if (NULL != _ptr)
  40. {
  41. BX_FREE(g_allocator, _ptr);
  42. }
  43. }
  44. } // namespace bgfx
  45. #define TINYSTL_ALLOCATOR bgfx::TinyStlAllocator
  46. #include <tinystl/allocator.h>
  47. #include <tinystl/string.h>
  48. #include <tinystl/unordered_map.h>
  49. #include <tinystl/vector.h>
  50. namespace stl = tinystl;
  51. #include "../../src/shader.h"
  52. #include "../../src/shader_spirv.h"
  53. #include "../../3rdparty/khronos/vulkan-local/vulkan.h"
  54. namespace bgfx { namespace spirv
  55. {
  56. const TBuiltInResource resourceLimits =
  57. {
  58. 32, // MaxLights
  59. 6, // MaxClipPlanes
  60. 32, // MaxTextureUnits
  61. 32, // MaxTextureCoords
  62. 64, // MaxVertexAttribs
  63. 4096, // MaxVertexUniformComponents
  64. 64, // MaxVaryingFloats
  65. 32, // MaxVertexTextureImageUnits
  66. 80, // MaxCombinedTextureImageUnits
  67. 32, // MaxTextureImageUnits
  68. 4096, // MaxFragmentUniformComponents
  69. 32, // MaxDrawBuffers
  70. 128, // MaxVertexUniformVectors
  71. 8, // MaxVaryingVectors
  72. 16, // MaxFragmentUniformVectors
  73. 16, // MaxVertexOutputVectors
  74. 15, // MaxFragmentInputVectors
  75. -8, // MinProgramTexelOffset
  76. 7, // MaxProgramTexelOffset
  77. 8, // MaxClipDistances
  78. 65535, // MaxComputeWorkGroupCountX
  79. 65535, // MaxComputeWorkGroupCountY
  80. 65535, // MaxComputeWorkGroupCountZ
  81. 1024, // MaxComputeWorkGroupSizeX
  82. 1024, // MaxComputeWorkGroupSizeY
  83. 64, // MaxComputeWorkGroupSizeZ
  84. 1024, // MaxComputeUniformComponents
  85. 16, // MaxComputeTextureImageUnits
  86. 8, // MaxComputeImageUniforms
  87. 8, // MaxComputeAtomicCounters
  88. 1, // MaxComputeAtomicCounterBuffers
  89. 60, // MaxVaryingComponents
  90. 64, // MaxVertexOutputComponents
  91. 64, // MaxGeometryInputComponents
  92. 128, // MaxGeometryOutputComponents
  93. 128, // MaxFragmentInputComponents
  94. 8, // MaxImageUnits
  95. 8, // MaxCombinedImageUnitsAndFragmentOutputs
  96. 8, // MaxCombinedShaderOutputResources
  97. 0, // MaxImageSamples
  98. 0, // MaxVertexImageUniforms
  99. 0, // MaxTessControlImageUniforms
  100. 0, // MaxTessEvaluationImageUniforms
  101. 0, // MaxGeometryImageUniforms
  102. 8, // MaxFragmentImageUniforms
  103. 8, // MaxCombinedImageUniforms
  104. 16, // MaxGeometryTextureImageUnits
  105. 256, // MaxGeometryOutputVertices
  106. 1024, // MaxGeometryTotalOutputComponents
  107. 1024, // MaxGeometryUniformComponents
  108. 64, // MaxGeometryVaryingComponents
  109. 128, // MaxTessControlInputComponents
  110. 128, // MaxTessControlOutputComponents
  111. 16, // MaxTessControlTextureImageUnits
  112. 1024, // MaxTessControlUniformComponents
  113. 4096, // MaxTessControlTotalOutputComponents
  114. 128, // MaxTessEvaluationInputComponents
  115. 128, // MaxTessEvaluationOutputComponents
  116. 16, // MaxTessEvaluationTextureImageUnits
  117. 1024, // MaxTessEvaluationUniformComponents
  118. 120, // MaxTessPatchComponents
  119. 32, // MaxPatchVertices
  120. 64, // MaxTessGenLevel
  121. 16, // MaxViewports
  122. 0, // MaxVertexAtomicCounters
  123. 0, // MaxTessControlAtomicCounters
  124. 0, // MaxTessEvaluationAtomicCounters
  125. 0, // MaxGeometryAtomicCounters
  126. 8, // MaxFragmentAtomicCounters
  127. 8, // MaxCombinedAtomicCounters
  128. 1, // MaxAtomicCounterBindings
  129. 0, // MaxVertexAtomicCounterBuffers
  130. 0, // MaxTessControlAtomicCounterBuffers
  131. 0, // MaxTessEvaluationAtomicCounterBuffers
  132. 0, // MaxGeometryAtomicCounterBuffers
  133. 1, // MaxFragmentAtomicCounterBuffers
  134. 1, // MaxCombinedAtomicCounterBuffers
  135. 16384, // MaxAtomicCounterBufferSize
  136. 4, // MaxTransformFeedbackBuffers
  137. 64, // MaxTransformFeedbackInterleavedComponents
  138. 8, // MaxCullDistances
  139. 8, // MaxCombinedClipAndCullDistances
  140. 4, // MaxSamples
  141. 0, // maxMeshOutputVerticesNV
  142. 0, // maxMeshOutputPrimitivesNV
  143. 0, // maxMeshWorkGroupSizeX_NV
  144. 0, // maxMeshWorkGroupSizeY_NV
  145. 0, // maxMeshWorkGroupSizeZ_NV
  146. 0, // maxTaskWorkGroupSizeX_NV
  147. 0, // maxTaskWorkGroupSizeY_NV
  148. 0, // maxTaskWorkGroupSizeZ_NV
  149. 0, // maxMeshViewCountNV
  150. 0, // maxDualSourceDrawBuffersEXT
  151. { // limits
  152. true, // nonInductiveForLoops
  153. true, // whileLoops
  154. true, // doWhileLoops
  155. true, // generalUniformIndexing
  156. true, // generalAttributeMatrixVectorIndexing
  157. true, // generalVaryingIndexing
  158. true, // generalSamplerIndexing
  159. true, // generalVariableIndexing
  160. true, // generalConstantMatrixVectorIndexing
  161. },
  162. };
  163. bool printAsm(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
  164. {
  165. BX_UNUSED(_userData);
  166. char temp[512];
  167. toString(temp, sizeof(temp), _instruction);
  168. BX_TRACE("%5d: %s", _offset, temp);
  169. return true;
  170. }
  171. bgfx::TextureComponentType::Enum SpirvCrossBaseTypeToFormatType(spirv_cross::SPIRType::BaseType spirvBaseType, bool depth)
  172. {
  173. if (depth)
  174. return bgfx::TextureComponentType::Depth;
  175. switch (spirvBaseType)
  176. {
  177. case spirv_cross::SPIRType::Float:
  178. return bgfx::TextureComponentType::Float;
  179. case spirv_cross::SPIRType::Int:
  180. return bgfx::TextureComponentType::Int;
  181. case spirv_cross::SPIRType::UInt:
  182. return bgfx::TextureComponentType::Uint;
  183. default:
  184. return bgfx::TextureComponentType::Float;
  185. }
  186. }
  187. bgfx::TextureDimension::Enum SpirvDimToTextureViewDimension(spv::Dim _dim, bool _arrayed)
  188. {
  189. switch (_dim)
  190. {
  191. case spv::Dim::Dim1D:
  192. return bgfx::TextureDimension::Dimension1D;
  193. case spv::Dim::Dim2D:
  194. return _arrayed
  195. ? bgfx::TextureDimension::Dimension2DArray
  196. : bgfx::TextureDimension::Dimension2D
  197. ;
  198. case spv::Dim::Dim3D:
  199. return bgfx::TextureDimension::Dimension3D;
  200. case spv::Dim::DimCube:
  201. return _arrayed
  202. ? bgfx::TextureDimension::DimensionCubeArray
  203. : bgfx::TextureDimension::DimensionCube
  204. ;
  205. default:
  206. BX_ASSERT(false, "Unknown texture dimension %d", _dim);
  207. return bgfx::TextureDimension::Dimension2D;
  208. }
  209. }
  210. static bgfx::TextureFormat::Enum s_textureFormats[] =
  211. {
  212. bgfx::TextureFormat::Unknown, // spv::ImageFormatUnknown = 0
  213. bgfx::TextureFormat::RGBA32F, // spv::ImageFormatRgba32f = 1
  214. bgfx::TextureFormat::RGBA16F, // spv::ImageFormatRgba16f = 2
  215. bgfx::TextureFormat::R32F, // spv::ImageFormatR32f = 3
  216. bgfx::TextureFormat::RGBA8, // spv::ImageFormatRgba8 = 4
  217. bgfx::TextureFormat::RGBA8S, // spv::ImageFormatRgba8Snorm = 5
  218. bgfx::TextureFormat::RG32F, // spv::ImageFormatRg32f = 6
  219. bgfx::TextureFormat::RG16F, // spv::ImageFormatRg16f = 7
  220. bgfx::TextureFormat::RG11B10F, // spv::ImageFormatR11fG11fB10f = 8
  221. bgfx::TextureFormat::R16F, // spv::ImageFormatR16f = 9
  222. bgfx::TextureFormat::RGBA16, // spv::ImageFormatRgba16 = 10
  223. bgfx::TextureFormat::RGB10A2, // spv::ImageFormatRgb10A2 = 11
  224. bgfx::TextureFormat::RG16, // spv::ImageFormatRg16 = 12
  225. bgfx::TextureFormat::RG8, // spv::ImageFormatRg8 = 13
  226. bgfx::TextureFormat::R16, // spv::ImageFormatR16 = 14
  227. bgfx::TextureFormat::R8, // spv::ImageFormatR8 = 15
  228. bgfx::TextureFormat::RGBA16S, // spv::ImageFormatRgba16Snorm = 16
  229. bgfx::TextureFormat::RG16S, // spv::ImageFormatRg16Snorm = 17
  230. bgfx::TextureFormat::RG8S, // spv::ImageFormatRg8Snorm = 18
  231. bgfx::TextureFormat::R16S, // spv::ImageFormatR16Snorm = 19
  232. bgfx::TextureFormat::R8S, // spv::ImageFormatR8Snorm = 20
  233. bgfx::TextureFormat::RGBA32I, // spv::ImageFormatRgba32i = 21
  234. bgfx::TextureFormat::RGBA16I, // spv::ImageFormatRgba16i = 22
  235. bgfx::TextureFormat::RGBA8I, // spv::ImageFormatRgba8i = 23
  236. bgfx::TextureFormat::R32I, // spv::ImageFormatR32i = 24
  237. bgfx::TextureFormat::RG32I, // spv::ImageFormatRg32i = 25
  238. bgfx::TextureFormat::RG16I, // spv::ImageFormatRg16i = 26
  239. bgfx::TextureFormat::RG8I, // spv::ImageFormatRg8i = 27
  240. bgfx::TextureFormat::R16I, // spv::ImageFormatR16i = 28
  241. bgfx::TextureFormat::R8I, // spv::ImageFormatR8i = 29
  242. bgfx::TextureFormat::RGBA32U, // spv::ImageFormatRgba32ui = 30
  243. bgfx::TextureFormat::RGBA16U, // spv::ImageFormatRgba16ui = 31
  244. bgfx::TextureFormat::RGBA8U, // spv::ImageFormatRgba8ui = 32
  245. bgfx::TextureFormat::R32U, // spv::ImageFormatR32ui = 33
  246. bgfx::TextureFormat::Unknown, // spv::ImageFormatRgb10a2ui = 34
  247. bgfx::TextureFormat::RG32U, // spv::ImageFormatRg32ui = 35
  248. bgfx::TextureFormat::RG16U, // spv::ImageFormatRg16ui = 36
  249. bgfx::TextureFormat::RG8U, // spv::ImageFormatRg8ui = 37
  250. bgfx::TextureFormat::R16U, // spv::ImageFormatR16ui = 38
  251. bgfx::TextureFormat::R8U, // spv::ImageFormatR8ui = 39
  252. bgfx::TextureFormat::Unknown, // spv::ImageFormatR64ui = 40
  253. bgfx::TextureFormat::Unknown, // spv::ImageFormatR64i = 41
  254. };
  255. struct SpvReflection
  256. {
  257. struct TypeId
  258. {
  259. enum Enum
  260. {
  261. Void,
  262. Bool,
  263. Int32,
  264. Int64,
  265. Uint32,
  266. Uint64,
  267. Float,
  268. Double,
  269. Vector,
  270. Matrix,
  271. Count
  272. };
  273. TypeId()
  274. : baseType(Enum::Count)
  275. , type(Enum::Count)
  276. , numComponents(0)
  277. {
  278. }
  279. Enum baseType;
  280. Enum type;
  281. uint32_t numComponents;
  282. stl::string toString()
  283. {
  284. stl::string result;
  285. switch (type)
  286. {
  287. case Float:
  288. result.append("float");
  289. break;
  290. case Vector:
  291. bx::stringPrintf(result, "vec%d"
  292. , numComponents
  293. );
  294. break;
  295. case Matrix:
  296. bx::stringPrintf(result, "mat%d"
  297. , numComponents
  298. );
  299. default:
  300. break;
  301. }
  302. return result;
  303. }
  304. };
  305. struct Id
  306. {
  307. struct Variable
  308. {
  309. Variable()
  310. : decoration(SpvDecoration::Count)
  311. , builtin(SpvBuiltin::Count)
  312. , storageClass(SpvStorageClass::Count)
  313. , location(UINT32_MAX)
  314. , offset(UINT32_MAX)
  315. , type(UINT32_MAX)
  316. {
  317. }
  318. stl::string name;
  319. SpvDecoration::Enum decoration;
  320. SpvBuiltin::Enum builtin;
  321. SpvStorageClass::Enum storageClass;
  322. uint32_t location;
  323. uint32_t offset;
  324. uint32_t type;
  325. };
  326. typedef stl::vector<Variable> MemberArray;
  327. Variable var;
  328. MemberArray members;
  329. };
  330. typedef stl::unordered_map<uint32_t, TypeId> TypeIdMap;
  331. typedef stl::unordered_map<uint32_t, Id> IdMap;
  332. TypeIdMap typeIdMap;
  333. IdMap idMap;
  334. stl::string getTypeName(uint32_t _typeId)
  335. {
  336. return getTypeId(_typeId).toString();
  337. }
  338. Id& getId(uint32_t _id)
  339. {
  340. IdMap::iterator it = idMap.find(_id);
  341. if (it == idMap.end() )
  342. {
  343. Id id;
  344. stl::pair<IdMap::iterator, bool> result = idMap.insert(stl::make_pair(_id, id) );
  345. it = result.first;
  346. }
  347. return it->second;
  348. }
  349. Id::Variable& get(uint32_t _id, uint32_t _idx)
  350. {
  351. Id& id = getId(_id);
  352. id.members.resize(bx::uint32_max(_idx+1, uint32_t(id.members.size() ) ) );
  353. return id.members[_idx];
  354. }
  355. TypeId& getTypeId(uint32_t _id)
  356. {
  357. TypeIdMap::iterator it = typeIdMap.find(_id);
  358. if (it == typeIdMap.end() )
  359. {
  360. TypeId id;
  361. stl::pair<TypeIdMap::iterator, bool> result = typeIdMap.insert(stl::make_pair(_id, id) );
  362. it = result.first;
  363. }
  364. return it->second;
  365. }
  366. void update(uint32_t _id, const stl::string& _name)
  367. {
  368. getId(_id).var.name = _name;
  369. }
  370. BX_NO_INLINE void update(Id::Variable& _variable, SpvDecoration::Enum _decoration, uint32_t _literal)
  371. {
  372. _variable.decoration = _decoration;
  373. switch (_decoration)
  374. {
  375. case SpvDecoration::Location:
  376. _variable.location = _literal;
  377. break;
  378. case SpvDecoration::Offset:
  379. _variable.offset = _literal;
  380. break;
  381. case SpvDecoration::BuiltIn:
  382. _variable.builtin = SpvBuiltin::Enum(_literal);
  383. break;
  384. default:
  385. break;
  386. }
  387. }
  388. BX_NO_INLINE void update(Id::Variable& _variable, uint32_t _type, SpvStorageClass::Enum _storageClass)
  389. {
  390. _variable.type = _type;
  391. _variable.storageClass = _storageClass;
  392. }
  393. void update(uint32_t _id, SpvDecoration::Enum _decoration, uint32_t _literal)
  394. {
  395. update(getId(_id).var, _decoration, _literal);
  396. }
  397. void update(uint32_t _id, uint32_t _type, SpvStorageClass::Enum _storageClass)
  398. {
  399. update(getId(_id).var, _type, _storageClass);
  400. }
  401. void update(uint32_t _id, uint32_t _idx, const stl::string& _name)
  402. {
  403. Id::Variable& var = get(_id, _idx);
  404. var.name = _name;
  405. }
  406. BX_NO_INLINE void update(uint32_t _id, uint32_t _idx, SpvDecoration::Enum _decoration, uint32_t _literal)
  407. {
  408. update(get(_id, _idx), _decoration, _literal);
  409. }
  410. void update(uint32_t _id, TypeId::Enum _type)
  411. {
  412. TypeId& type = getTypeId(_id);
  413. type.type = _type;
  414. }
  415. void update(uint32_t _id, TypeId::Enum _type, uint32_t _baseTypeId, uint32_t _numComonents)
  416. {
  417. TypeId& type = getTypeId(_id);
  418. type.type = _type;
  419. type.baseType = getTypeId(_baseTypeId).type;
  420. type.numComponents = _numComonents;
  421. }
  422. };
  423. bool spvParse(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
  424. {
  425. BX_UNUSED(_offset);
  426. SpvReflection* spv = (SpvReflection*)_userData;
  427. switch (_instruction.opcode)
  428. {
  429. case SpvOpcode::Name:
  430. spv->update(_instruction.result
  431. , _instruction.operand[0].literalString
  432. );
  433. break;
  434. case SpvOpcode::Decorate:
  435. spv->update(_instruction.operand[0].data
  436. , SpvDecoration::Enum(_instruction.operand[1].data)
  437. , _instruction.operand[2].data
  438. );
  439. break;
  440. case SpvOpcode::MemberName:
  441. spv->update(_instruction.result
  442. , _instruction.operand[0].data
  443. , _instruction.operand[1].literalString
  444. );
  445. break;
  446. case SpvOpcode::MemberDecorate:
  447. spv->update(_instruction.operand[0].data
  448. , _instruction.operand[1].data
  449. , SpvDecoration::Enum(_instruction.operand[2].data)
  450. , _instruction.operand[3].data
  451. );
  452. break;
  453. case SpvOpcode::Variable:
  454. spv->update(_instruction.result
  455. , _instruction.type
  456. , SpvStorageClass::Enum(_instruction.operand[0].data)
  457. );
  458. break;
  459. case SpvOpcode::TypeVoid:
  460. spv->update(_instruction.result, SpvReflection::TypeId::Void);
  461. break;
  462. case SpvOpcode::TypeBool:
  463. spv->update(_instruction.result, SpvReflection::TypeId::Bool);
  464. break;
  465. case SpvOpcode::TypeInt:
  466. spv->update(_instruction.result
  467. , 32 == _instruction.operand[0].data
  468. ? 0 == _instruction.operand[1].data
  469. ? SpvReflection::TypeId::Uint32
  470. : SpvReflection::TypeId::Int32
  471. : 0 == _instruction.operand[1].data
  472. ? SpvReflection::TypeId::Uint64
  473. : SpvReflection::TypeId::Int64
  474. );
  475. break;
  476. case SpvOpcode::TypeFloat:
  477. spv->update(_instruction.result
  478. , 32 == _instruction.operand[0].data
  479. ? SpvReflection::TypeId::Float
  480. : SpvReflection::TypeId::Double
  481. );
  482. break;
  483. case SpvOpcode::TypeVector:
  484. spv->update(_instruction.result
  485. , SpvReflection::TypeId::Vector
  486. , _instruction.operand[0].data
  487. , _instruction.operand[1].data
  488. );
  489. break;
  490. case SpvOpcode::TypeMatrix:
  491. spv->update(_instruction.result
  492. , SpvReflection::TypeId::Matrix
  493. , _instruction.operand[0].data
  494. , _instruction.operand[1].data
  495. );
  496. break;
  497. case SpvOpcode::TypeImage:
  498. case SpvOpcode::TypeSampler:
  499. case SpvOpcode::TypeSampledImage:
  500. break;
  501. case SpvOpcode::TypeStruct:
  502. for (uint32_t ii = 0, num = _instruction.numOperands; ii < num; ++ii)
  503. {
  504. SpvReflection::Id::Variable& var = spv->get(_instruction.result, ii);
  505. var.type = _instruction.operand[ii].data;
  506. }
  507. break;
  508. default:
  509. break;
  510. }
  511. return true;
  512. }
  513. #define DBG(...) // bx::debugPrintf(__VA_ARGS__)
  514. void disassemble(bx::WriterI* _writer, bx::ReaderSeekerI* _reader, bx::Error* _err)
  515. {
  516. BX_UNUSED(_writer);
  517. uint32_t magic;
  518. bx::peek(_reader, magic);
  519. SpvReflection spvx;
  520. if (magic == SPV_CHUNK_HEADER)
  521. {
  522. SpirV spirv;
  523. read(_reader, spirv, _err);
  524. parse(spirv.shader, spvParse, &spvx, _err);
  525. for (SpvReflection::IdMap::const_iterator it = spvx.idMap.begin(), itEnd = spvx.idMap.end(); it != itEnd; ++it)
  526. {
  527. const SpvReflection::Id& id = it->second;
  528. uint32_t num = uint32_t(id.members.size() );
  529. if (0 < num
  530. && 0 != bx::strCmp(id.var.name.c_str(), "gl_PerVertex") )
  531. {
  532. DBG("%3d: %s %d %s\n"
  533. , it->first
  534. , id.var.name.c_str()
  535. , id.var.location
  536. , getName(id.var.storageClass)
  537. );
  538. DBG("{\n");
  539. for (uint32_t ii = 0; ii < num; ++ii)
  540. {
  541. const SpvReflection::Id::Variable& var = id.members[ii];
  542. DBG("\t\t%s %s %d %s\n"
  543. , spvx.getTypeName(var.type).c_str()
  544. , var.name.c_str()
  545. , var.offset
  546. , getName(var.storageClass)
  547. );
  548. BX_UNUSED(var);
  549. }
  550. DBG("}\n");
  551. }
  552. }
  553. }
  554. }
  555. static EShLanguage getLang(char _p)
  556. {
  557. switch (_p)
  558. {
  559. case 'c': return EShLangCompute;
  560. case 'f': return EShLangFragment;
  561. case 'v': return EShLangVertex;
  562. default: return EShLangCount;
  563. }
  564. }
  565. static const char* s_attribName[] =
  566. {
  567. "a_position",
  568. "a_normal",
  569. "a_tangent",
  570. "a_bitangent",
  571. "a_color0",
  572. "a_color1",
  573. "a_color2",
  574. "a_color3",
  575. "a_indices",
  576. "a_weight",
  577. "a_texcoord0",
  578. "a_texcoord1",
  579. "a_texcoord2",
  580. "a_texcoord3",
  581. "a_texcoord4",
  582. "a_texcoord5",
  583. "a_texcoord6",
  584. "a_texcoord7",
  585. };
  586. BX_STATIC_ASSERT(bgfx::Attrib::Count == BX_COUNTOF(s_attribName) );
  587. bgfx::Attrib::Enum toAttribEnum(const bx::StringView& _name)
  588. {
  589. for (uint8_t ii = 0; ii < Attrib::Count; ++ii)
  590. {
  591. if (0 == bx::strCmp(s_attribName[ii], _name) )
  592. {
  593. return bgfx::Attrib::Enum(ii);
  594. }
  595. }
  596. return bgfx::Attrib::Count;
  597. }
  598. static const char* s_samplerTypes[] =
  599. {
  600. "BgfxSampler2D",
  601. "BgfxISampler2D",
  602. "BgfxUSampler2D",
  603. "BgfxSampler2DArray",
  604. "BgfxSampler2DShadow",
  605. "BgfxSampler2DArrayShadow",
  606. "BgfxSampler3D",
  607. "BgfxISampler3D",
  608. "BgfxUSampler3D",
  609. "BgfxSamplerCube",
  610. "BgfxSamplerCubeShadow",
  611. "BgfxSampler2DMS",
  612. };
  613. static uint16_t writeUniformArray(bx::WriterI* _writer, const UniformArray& uniforms, bool isFragmentShader)
  614. {
  615. uint16_t size = 0;
  616. uint16_t count = static_cast<uint16_t>(uniforms.size() );
  617. bx::write(_writer, count);
  618. uint32_t fragmentBit = isFragmentShader ? kUniformFragmentBit : 0;
  619. for (uint16_t ii = 0; ii < count; ++ii)
  620. {
  621. const Uniform& un = uniforms[ii];
  622. if ( (un.type & ~kUniformMask) > UniformType::End)
  623. {
  624. size = bx::max(size, (uint16_t)(un.regIndex + un.regCount*16) );
  625. }
  626. uint8_t nameSize = (uint8_t)un.name.size();
  627. bx::write(_writer, nameSize);
  628. bx::write(_writer, un.name.c_str(), nameSize);
  629. bx::write(_writer, uint8_t(un.type | fragmentBit) );
  630. bx::write(_writer, un.num);
  631. bx::write(_writer, un.regIndex);
  632. bx::write(_writer, un.regCount);
  633. bx::write(_writer, un.texComponent);
  634. bx::write(_writer, un.texDimension);
  635. bx::write(_writer, un.texFormat);
  636. BX_TRACE("%s, %s, %d, %d, %d"
  637. , un.name.c_str()
  638. , getUniformTypeName(un.type)
  639. , un.num
  640. , un.regIndex
  641. , un.regCount
  642. );
  643. }
  644. return size;
  645. }
  646. static spv_target_env getSpirvTargetVersion(uint32_t version)
  647. {
  648. switch (version)
  649. {
  650. case 1010:
  651. return SPV_ENV_VULKAN_1_0;
  652. case 1311:
  653. return SPV_ENV_VULKAN_1_1;
  654. case 1411:
  655. return SPV_ENV_VULKAN_1_1_SPIRV_1_4;
  656. case 1512:
  657. return SPV_ENV_VULKAN_1_2;
  658. default:
  659. BX_ASSERT(0, "Unknown SPIR-V version requested. Returning SPV_ENV_VULKAN_1_0 as default.");
  660. return SPV_ENV_VULKAN_1_0;
  661. }
  662. }
  663. static glslang::EShTargetClientVersion getGlslangTargetVulkanVersion(uint32_t version)
  664. {
  665. switch (version)
  666. {
  667. case 1010:
  668. return glslang::EShTargetVulkan_1_0;
  669. case 1311:
  670. case 1411:
  671. return glslang::EShTargetVulkan_1_1;
  672. case 1512:
  673. return glslang::EShTargetVulkan_1_2;
  674. default:
  675. BX_ASSERT(0, "Unknown SPIR-V version requested. Returning EShTargetVulkan_1_0 as default.");
  676. return glslang::EShTargetVulkan_1_0;
  677. }
  678. }
  679. static glslang::EShTargetLanguageVersion getGlslangTargetSpirvVersion(uint32_t version)
  680. {
  681. switch (version)
  682. {
  683. case 1010:
  684. return glslang::EShTargetSpv_1_0;
  685. case 1311:
  686. return glslang::EShTargetSpv_1_3;
  687. case 1411:
  688. return glslang::EShTargetSpv_1_4;
  689. case 1512:
  690. return glslang::EShTargetSpv_1_5;
  691. default:
  692. BX_ASSERT(0, "Unknown SPIR-V version requested. Returning EShTargetSpv_1_0 as default.");
  693. return glslang::EShTargetSpv_1_0;
  694. }
  695. }
  696. /// This is the value used to fill out GLSLANG's SpvVersion object.
  697. /// The required value is that which is defined by GL_KHR_vulkan_glsl, which is defined here:
  698. /// https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_vulkan_glsl.txt
  699. /// The value is 100.
  700. constexpr int s_GLSL_VULKAN_CLIENT_VERSION = 100;
  701. static bool compile(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _writer, bool _firstPass)
  702. {
  703. BX_UNUSED(_version);
  704. glslang::InitializeProcess();
  705. EShLanguage stage = getLang(_options.shaderType);
  706. if (EShLangCount == stage)
  707. {
  708. bx::printf("Error: Unknown shader type '%c'.\n", _options.shaderType);
  709. return false;
  710. }
  711. glslang::TProgram* program = new glslang::TProgram;
  712. glslang::TShader* shader = new glslang::TShader(stage);
  713. EShMessages messages = EShMessages(0
  714. | EShMsgDefault
  715. | EShMsgReadHlsl
  716. | EShMsgVulkanRules
  717. | EShMsgSpvRules
  718. );
  719. shader->setEntryPoint("main");
  720. shader->setAutoMapBindings(true);
  721. shader->setEnvInput(glslang::EShSourceHlsl, stage, glslang::EShClientVulkan, s_GLSL_VULKAN_CLIENT_VERSION);
  722. shader->setEnvClient(glslang::EShClientVulkan, getGlslangTargetVulkanVersion(_version));
  723. shader->setEnvTarget(glslang::EShTargetSpv, getGlslangTargetSpirvVersion(_version));
  724. uint32_t bindingOffset = (stage == EShLanguage::EShLangFragment ? 48 : 0);
  725. shader->setShiftBinding(glslang::EResUbo, bindingOffset);
  726. shader->setShiftBinding(glslang::EResTexture, bindingOffset + 16);
  727. shader->setShiftBinding(glslang::EResSampler, bindingOffset + 32);
  728. shader->setShiftBinding(glslang::EResSsbo, bindingOffset + 16);
  729. shader->setShiftBinding(glslang::EResImage, bindingOffset + 32);
  730. const char* shaderStrings[] = { _code.c_str() };
  731. shader->setStrings(
  732. shaderStrings
  733. , BX_COUNTOF(shaderStrings)
  734. );
  735. bool compiled = shader->parse(&resourceLimits
  736. , 110
  737. , false
  738. , messages
  739. );
  740. bool linked = false;
  741. bool validated = true;
  742. if (!compiled)
  743. {
  744. const char* log = shader->getInfoLog();
  745. if (NULL != log)
  746. {
  747. int32_t source = 0;
  748. int32_t line = 0;
  749. int32_t column = 0;
  750. int32_t start = 0;
  751. int32_t end = INT32_MAX;
  752. bx::StringView err = bx::strFind(log, "ERROR:");
  753. bool found = false;
  754. if (!err.isEmpty() )
  755. {
  756. found = 2 == sscanf(err.getPtr(), "ERROR: %u:%u: '", &source, &line);
  757. if (found)
  758. {
  759. ++line;
  760. }
  761. }
  762. if (found)
  763. {
  764. start = bx::uint32_imax(1, line-10);
  765. end = start + 20;
  766. }
  767. printCode(_code.c_str(), line, start, end, column);
  768. bx::printf("%s\n", log);
  769. }
  770. }
  771. else
  772. {
  773. program->addShader(shader);
  774. linked = true
  775. && program->link(messages)
  776. && program->mapIO()
  777. ;
  778. if (!linked)
  779. {
  780. const char* log = program->getInfoLog();
  781. if (NULL != log)
  782. {
  783. bx::printf("%s\n", log);
  784. }
  785. }
  786. else
  787. {
  788. program->buildReflection();
  789. if (_firstPass)
  790. {
  791. // first time through, we just find unused uniforms and get rid of them
  792. std::string output;
  793. struct Uniform
  794. {
  795. std::string name;
  796. std::string decl;
  797. };
  798. std::vector<Uniform> uniforms;
  799. bx::LineReader reader(_code.c_str() );
  800. while (!reader.isDone() )
  801. {
  802. bx::StringView strLine = reader.next();
  803. bool moved = false;
  804. bx::StringView str = strFind(strLine, "uniform ");
  805. if (!str.isEmpty() )
  806. {
  807. bool found = false;
  808. bool sampler = false;
  809. std::string name = "";
  810. // add to samplers
  811. for (uint32_t ii = 0; ii < BX_COUNTOF(s_samplerTypes); ++ii)
  812. {
  813. if (!bx::findIdentifierMatch(strLine, s_samplerTypes[ii]).isEmpty() )
  814. {
  815. found = true;
  816. sampler = true;
  817. break;
  818. }
  819. }
  820. if (!found)
  821. {
  822. for (int32_t ii = 0, num = program->getNumLiveUniformVariables(); ii < num; ++ii)
  823. {
  824. // matching lines like: uniform u_name;
  825. // we want to replace "uniform" with "static" so that it's no longer
  826. // included in the uniform blob that the application must upload
  827. // we can't just remove them, because unused functions might still reference
  828. // them and cause a compile error when they're gone
  829. if (!bx::findIdentifierMatch(strLine, program->getUniformName(ii) ).isEmpty() )
  830. {
  831. found = true;
  832. name = program->getUniformName(ii);
  833. break;
  834. }
  835. }
  836. }
  837. if (!found)
  838. {
  839. output.append(strLine.getPtr(), str.getPtr() );
  840. output += "static ";
  841. output.append(str.getTerm(), strLine.getTerm() );
  842. output += "\n";
  843. moved = true;
  844. }
  845. else if (!sampler)
  846. {
  847. Uniform uniform;
  848. uniform.name = name;
  849. uniform.decl = std::string(strLine.getPtr(), strLine.getTerm() );
  850. uniforms.push_back(uniform);
  851. moved = true;
  852. }
  853. }
  854. if (!moved)
  855. {
  856. output.append(strLine.getPtr(), strLine.getTerm() );
  857. output += "\n";
  858. }
  859. }
  860. std::string uniformBlock;
  861. uniformBlock += "cbuffer UniformBlock\n";
  862. uniformBlock += "{\n";
  863. for (const Uniform& uniform : uniforms)
  864. {
  865. uniformBlock += uniform.decl.substr(7 /* uniform */);
  866. uniformBlock += "\n";
  867. }
  868. uniformBlock += "};\n";
  869. output = uniformBlock + output;
  870. // recompile with the unused uniforms converted to statics
  871. delete program;
  872. delete shader;
  873. return compile(_options, _version, output.c_str(), _writer, false);
  874. }
  875. UniformArray uniforms;
  876. {
  877. uint16_t count = (uint16_t)program->getNumLiveUniformVariables();
  878. for (uint16_t ii = 0; ii < count; ++ii)
  879. {
  880. Uniform un;
  881. un.name = program->getUniformName(ii);
  882. un.num = 0;
  883. const uint32_t offset = program->getUniformBufferOffset(ii);
  884. un.regIndex = uint16_t(offset);
  885. un.regCount = uint16_t(program->getUniformArraySize(ii));
  886. switch (program->getUniformType(ii) )
  887. {
  888. case 0x1404: // GL_INT:
  889. un.type = UniformType::Sampler;
  890. break;
  891. case 0x8B52: // GL_FLOAT_VEC4:
  892. un.type = UniformType::Vec4;
  893. break;
  894. case 0x8B5B: // GL_FLOAT_MAT3:
  895. un.type = UniformType::Mat3;
  896. un.regCount *= 3;
  897. break;
  898. case 0x8B5C: // GL_FLOAT_MAT4:
  899. un.type = UniformType::Mat4;
  900. un.regCount *= 4;
  901. break;
  902. default:
  903. continue;
  904. }
  905. uniforms.push_back(un);
  906. }
  907. }
  908. if (g_verbose)
  909. {
  910. program->dumpReflection();
  911. }
  912. BX_UNUSED(spv::MemorySemanticsAllMemory);
  913. glslang::TIntermediate* intermediate = program->getIntermediate(stage);
  914. std::vector<uint32_t> spirv;
  915. glslang::SpvOptions options;
  916. options.disableOptimizer = false;
  917. glslang::GlslangToSpv(*intermediate, spirv, &options);
  918. spvtools::Optimizer opt(getSpirvTargetVersion(_version));
  919. auto print_msg_to_stderr = [](
  920. spv_message_level_t
  921. , const char*
  922. , const spv_position_t&
  923. , const char* m
  924. )
  925. {
  926. bx::printf("Error: %s\n", m);
  927. };
  928. opt.SetMessageConsumer(print_msg_to_stderr);
  929. opt.RegisterLegalizationPasses();
  930. spvtools::ValidatorOptions validatorOptions;
  931. validatorOptions.SetBeforeHlslLegalization(true);
  932. if (!opt.Run(
  933. spirv.data()
  934. , spirv.size()
  935. , &spirv
  936. , validatorOptions
  937. , false
  938. ) )
  939. {
  940. compiled = false;
  941. }
  942. else
  943. {
  944. bx::Error err;
  945. bx::WriterI* writer = bx::getDebugOut();
  946. bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) );
  947. disassemble(writer, &reader, &err);
  948. spirv_cross::CompilerReflection refl(spirv);
  949. spirv_cross::ShaderResources resourcesrefl = refl.get_shader_resources();
  950. if (g_verbose)
  951. {
  952. glslang::SpirvToolsDisassemble(std::cout, spirv, getSpirvTargetVersion(_version) );
  953. }
  954. // Loop through the separate_images, and extract the uniform names:
  955. for (auto &resource : resourcesrefl.separate_images)
  956. {
  957. std::string name = refl.get_name(resource.id);
  958. if (name.size() > 7
  959. && 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
  960. {
  961. name = name.substr(0, name.length() - 7);
  962. }
  963. uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
  964. auto imageType = refl.get_type(resource.base_type_id).image;
  965. auto componentType = refl.get_type(imageType.type).basetype;
  966. bool isCompareSampler = false;
  967. for (auto& sampler : resourcesrefl.separate_samplers)
  968. {
  969. if (binding_index + 16 == refl.get_decoration(sampler.id, spv::Decoration::DecorationBinding) )
  970. {
  971. std::string samplerName = refl.get_name(sampler.id);
  972. isCompareSampler = refl.variable_is_depth_or_compare(sampler.id) || samplerName.find("Comparison") != std::string::npos;
  973. break;
  974. }
  975. }
  976. Uniform un;
  977. un.name = name;
  978. un.type = UniformType::Enum(UniformType::Sampler
  979. | kUniformSamplerBit
  980. | (isCompareSampler ? kUniformCompareBit : 0)
  981. );
  982. un.texComponent = textureComponentTypeToId(SpirvCrossBaseTypeToFormatType(componentType, imageType.depth) );
  983. un.texDimension = textureDimensionToId(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed) );
  984. un.texFormat = uint16_t(s_textureFormats[imageType.format]);
  985. un.regIndex = binding_index;
  986. un.regCount = 0; // unused
  987. uniforms.push_back(un);
  988. }
  989. // Loop through the storage_images, and extract the uniform names:
  990. for (auto &resource : resourcesrefl.storage_images)
  991. {
  992. std::string name = refl.get_name(resource.id);
  993. uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
  994. auto imageType = refl.get_type(resource.base_type_id).image;
  995. auto componentType = refl.get_type(imageType.type).basetype;
  996. spirv_cross::Bitset flags = refl.get_decoration_bitset(resource.id);
  997. UniformType::Enum type = flags.get(spv::DecorationNonWritable)
  998. ? UniformType::Enum(kUniformReadOnlyBit | UniformType::End)
  999. : UniformType::End;
  1000. Uniform un;
  1001. un.name = name;
  1002. un.type = type;
  1003. un.texComponent = textureComponentTypeToId(SpirvCrossBaseTypeToFormatType(componentType, imageType.depth) );
  1004. un.texDimension = textureDimensionToId(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed) );
  1005. un.texFormat = uint16_t(s_textureFormats[imageType.format]);
  1006. un.regIndex = binding_index;
  1007. un.regCount = descriptorTypeToId(DescriptorType::StorageImage);
  1008. uniforms.push_back(un);
  1009. }
  1010. // Loop through the storage buffer, and extract the uniform names:
  1011. for (auto& resource : resourcesrefl.storage_buffers)
  1012. {
  1013. std::string name = refl.get_name(resource.id);
  1014. uint32_t binding_index = refl.get_decoration(resource.id, spv::Decoration::DecorationBinding);
  1015. spirv_cross::Bitset flags = refl.get_buffer_block_flags(resource.id);
  1016. UniformType::Enum type = flags.get(spv::DecorationNonWritable)
  1017. ? UniformType::Enum(kUniformReadOnlyBit | UniformType::End)
  1018. : UniformType::End;
  1019. Uniform un;
  1020. un.name = name;
  1021. un.type = type;
  1022. un.num = 0;
  1023. un.regIndex = binding_index;
  1024. un.regCount = descriptorTypeToId(DescriptorType::StorageBuffer);
  1025. uniforms.push_back(un);
  1026. }
  1027. uint16_t size = writeUniformArray( _writer, uniforms, _options.shaderType == 'f');
  1028. if (_version == BX_MAKEFOURCC('M', 'T', 'L', 0) )
  1029. {
  1030. spirv_cross::CompilerMSL msl(std::move(spirv) );
  1031. spirv_cross::ShaderResources resources = msl.get_shader_resources();
  1032. spirv_cross::SmallVector<spirv_cross::EntryPoint> entryPoints = msl.get_entry_points_and_stages();
  1033. if (!entryPoints.empty() )
  1034. {
  1035. msl.rename_entry_point(
  1036. entryPoints[0].name
  1037. , "xlatMtlMain"
  1038. , entryPoints[0].execution_model
  1039. );
  1040. }
  1041. for (auto &resource : resources.uniform_buffers)
  1042. {
  1043. msl.set_name(resource.id, "_mtl_u");
  1044. }
  1045. for (auto &resource : resources.storage_buffers)
  1046. {
  1047. unsigned binding = msl.get_decoration(resource.id, spv::DecorationBinding);
  1048. msl.set_decoration(resource.id, spv::DecorationBinding, binding + 1);
  1049. }
  1050. for (auto &resource : resources.separate_images)
  1051. {
  1052. std::string name = msl.get_name(resource.id);
  1053. if (name.size() > 7
  1054. && 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
  1055. {
  1056. msl.set_name(resource.id, name.substr(0, name.length() - 7) );
  1057. }
  1058. }
  1059. std::string source = msl.compile();
  1060. if ('c' == _options.shaderType)
  1061. {
  1062. for (int i = 0; i < 3; ++i)
  1063. {
  1064. uint16_t dim = (uint16_t)msl.get_execution_mode_argument(spv::ExecutionMode::ExecutionModeLocalSize, i);
  1065. bx::write(_writer, dim);
  1066. }
  1067. }
  1068. uint32_t shaderSize = (uint32_t)source.size();
  1069. bx::write(_writer, shaderSize);
  1070. bx::write(_writer, source.c_str(), shaderSize);
  1071. uint8_t nul = 0;
  1072. bx::write(_writer, nul);
  1073. }
  1074. else
  1075. {
  1076. uint32_t shaderSize = (uint32_t)spirv.size() * sizeof(uint32_t);
  1077. bx::write(_writer, shaderSize);
  1078. bx::write(_writer, spirv.data(), shaderSize);
  1079. uint8_t nul = 0;
  1080. bx::write(_writer, nul);
  1081. }
  1082. const uint8_t numAttr = (uint8_t)program->getNumLiveAttributes();
  1083. bx::write(_writer, numAttr);
  1084. for (uint8_t ii = 0; ii < numAttr; ++ii)
  1085. {
  1086. bgfx::Attrib::Enum attr = toAttribEnum(program->getAttributeName(ii) );
  1087. if (bgfx::Attrib::Count != attr)
  1088. {
  1089. bx::write(_writer, bgfx::attribToId(attr) );
  1090. }
  1091. else
  1092. {
  1093. bx::write(_writer, uint16_t(UINT16_MAX) );
  1094. }
  1095. }
  1096. bx::write(_writer, size);
  1097. }
  1098. }
  1099. }
  1100. delete program;
  1101. delete shader;
  1102. glslang::FinalizeProcess();
  1103. return compiled && linked && validated;
  1104. }
  1105. } // namespace spirv
  1106. bool compileSPIRVShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  1107. {
  1108. return spirv::compile(_options, _version, _code, _writer, true);
  1109. }
  1110. } // namespace bgfx