shaderc_metal.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. /*
  2. * Copyright 2011-2020 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. #define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
  19. #include <spirv_msl.hpp>
  20. #include <spirv_reflect.hpp>
  21. #include <spirv-tools/optimizer.hpp>
  22. BX_PRAGMA_DIAGNOSTIC_POP()
  23. namespace bgfx
  24. {
  25. struct TinyStlAllocator
  26. {
  27. static void* static_allocate(size_t _bytes);
  28. static void static_deallocate(void* _ptr, size_t /*_bytes*/);
  29. };
  30. } // namespace bgfx
  31. #define TINYSTL_ALLOCATOR bgfx::TinyStlAllocator
  32. #include <tinystl/allocator.h>
  33. #include <tinystl/string.h>
  34. #include <tinystl/unordered_map.h>
  35. #include <tinystl/vector.h>
  36. namespace stl = tinystl;
  37. #include "../../src/shader_spirv.h"
  38. namespace bgfx { namespace metal
  39. {
  40. const TBuiltInResource resourceLimits =
  41. {
  42. 32, // MaxLights
  43. 6, // MaxClipPlanes
  44. 32, // MaxTextureUnits
  45. 32, // MaxTextureCoords
  46. 64, // MaxVertexAttribs
  47. 4096, // MaxVertexUniformComponents
  48. 64, // MaxVaryingFloats
  49. 32, // MaxVertexTextureImageUnits
  50. 80, // MaxCombinedTextureImageUnits
  51. 32, // MaxTextureImageUnits
  52. 4096, // MaxFragmentUniformComponents
  53. 32, // MaxDrawBuffers
  54. 128, // MaxVertexUniformVectors
  55. 8, // MaxVaryingVectors
  56. 16, // MaxFragmentUniformVectors
  57. 16, // MaxVertexOutputVectors
  58. 15, // MaxFragmentInputVectors
  59. -8, // MinProgramTexelOffset
  60. 7, // MaxProgramTexelOffset
  61. 8, // MaxClipDistances
  62. 65535, // MaxComputeWorkGroupCountX
  63. 65535, // MaxComputeWorkGroupCountY
  64. 65535, // MaxComputeWorkGroupCountZ
  65. 1024, // MaxComputeWorkGroupSizeX
  66. 1024, // MaxComputeWorkGroupSizeY
  67. 64, // MaxComputeWorkGroupSizeZ
  68. 1024, // MaxComputeUniformComponents
  69. 16, // MaxComputeTextureImageUnits
  70. 8, // MaxComputeImageUniforms
  71. 8, // MaxComputeAtomicCounters
  72. 1, // MaxComputeAtomicCounterBuffers
  73. 60, // MaxVaryingComponents
  74. 64, // MaxVertexOutputComponents
  75. 64, // MaxGeometryInputComponents
  76. 128, // MaxGeometryOutputComponents
  77. 128, // MaxFragmentInputComponents
  78. 8, // MaxImageUnits
  79. 8, // MaxCombinedImageUnitsAndFragmentOutputs
  80. 8, // MaxCombinedShaderOutputResources
  81. 0, // MaxImageSamples
  82. 0, // MaxVertexImageUniforms
  83. 0, // MaxTessControlImageUniforms
  84. 0, // MaxTessEvaluationImageUniforms
  85. 0, // MaxGeometryImageUniforms
  86. 8, // MaxFragmentImageUniforms
  87. 8, // MaxCombinedImageUniforms
  88. 16, // MaxGeometryTextureImageUnits
  89. 256, // MaxGeometryOutputVertices
  90. 1024, // MaxGeometryTotalOutputComponents
  91. 1024, // MaxGeometryUniformComponents
  92. 64, // MaxGeometryVaryingComponents
  93. 128, // MaxTessControlInputComponents
  94. 128, // MaxTessControlOutputComponents
  95. 16, // MaxTessControlTextureImageUnits
  96. 1024, // MaxTessControlUniformComponents
  97. 4096, // MaxTessControlTotalOutputComponents
  98. 128, // MaxTessEvaluationInputComponents
  99. 128, // MaxTessEvaluationOutputComponents
  100. 16, // MaxTessEvaluationTextureImageUnits
  101. 1024, // MaxTessEvaluationUniformComponents
  102. 120, // MaxTessPatchComponents
  103. 32, // MaxPatchVertices
  104. 64, // MaxTessGenLevel
  105. 16, // MaxViewports
  106. 0, // MaxVertexAtomicCounters
  107. 0, // MaxTessControlAtomicCounters
  108. 0, // MaxTessEvaluationAtomicCounters
  109. 0, // MaxGeometryAtomicCounters
  110. 8, // MaxFragmentAtomicCounters
  111. 8, // MaxCombinedAtomicCounters
  112. 1, // MaxAtomicCounterBindings
  113. 0, // MaxVertexAtomicCounterBuffers
  114. 0, // MaxTessControlAtomicCounterBuffers
  115. 0, // MaxTessEvaluationAtomicCounterBuffers
  116. 0, // MaxGeometryAtomicCounterBuffers
  117. 1, // MaxFragmentAtomicCounterBuffers
  118. 1, // MaxCombinedAtomicCounterBuffers
  119. 16384, // MaxAtomicCounterBufferSize
  120. 4, // MaxTransformFeedbackBuffers
  121. 64, // MaxTransformFeedbackInterleavedComponents
  122. 8, // MaxCullDistances
  123. 8, // MaxCombinedClipAndCullDistances
  124. 4, // MaxSamples
  125. 0, // maxMeshOutputVerticesNV
  126. 0, // maxMeshOutputPrimitivesNV
  127. 0, // maxMeshWorkGroupSizeX_NV
  128. 0, // maxMeshWorkGroupSizeY_NV
  129. 0, // maxMeshWorkGroupSizeZ_NV
  130. 0, // maxTaskWorkGroupSizeX_NV
  131. 0, // maxTaskWorkGroupSizeY_NV
  132. 0, // maxTaskWorkGroupSizeZ_NV
  133. 0, // maxMeshViewCountNV
  134. 0, // maxDualSourceDrawBuffersEXT
  135. { // limits
  136. true, // nonInductiveForLoops
  137. true, // whileLoops
  138. true, // doWhileLoops
  139. true, // generalUniformIndexing
  140. true, // generalAttributeMatrixVectorIndexing
  141. true, // generalVaryingIndexing
  142. true, // generalSamplerIndexing
  143. true, // generalVariableIndexing
  144. true, // generalConstantMatrixVectorIndexing
  145. },
  146. };
  147. bool printAsm(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
  148. {
  149. BX_UNUSED(_userData);
  150. char temp[512];
  151. toString(temp, sizeof(temp), _instruction);
  152. BX_TRACE("%5d: %s", _offset, temp);
  153. return true;
  154. }
  155. struct SpvReflection
  156. {
  157. struct TypeId
  158. {
  159. enum Enum
  160. {
  161. Void,
  162. Bool,
  163. Int32,
  164. Int64,
  165. Uint32,
  166. Uint64,
  167. Float,
  168. Double,
  169. Vector,
  170. Matrix,
  171. Count
  172. };
  173. TypeId()
  174. : baseType(Enum::Count)
  175. , type(Enum::Count)
  176. , numComponents(0)
  177. {
  178. }
  179. Enum baseType;
  180. Enum type;
  181. uint32_t numComponents;
  182. stl::string toString()
  183. {
  184. stl::string result;
  185. switch (type)
  186. {
  187. case Float:
  188. result.append("float");
  189. break;
  190. case Vector:
  191. bx::stringPrintf(result, "vec%d"
  192. , numComponents
  193. );
  194. break;
  195. case Matrix:
  196. bx::stringPrintf(result, "mat%d"
  197. , numComponents
  198. );
  199. default:
  200. break;
  201. }
  202. return result;
  203. }
  204. };
  205. struct Id
  206. {
  207. struct Variable
  208. {
  209. Variable()
  210. : decoration(SpvDecoration::Count)
  211. , builtin(SpvBuiltin::Count)
  212. , storageClass(SpvStorageClass::Count)
  213. , location(UINT32_MAX)
  214. , offset(UINT32_MAX)
  215. , type(UINT32_MAX)
  216. {
  217. }
  218. stl::string name;
  219. SpvDecoration::Enum decoration;
  220. SpvBuiltin::Enum builtin;
  221. SpvStorageClass::Enum storageClass;
  222. uint32_t location;
  223. uint32_t offset;
  224. uint32_t type;
  225. };
  226. typedef stl::vector<Variable> MemberArray;
  227. Variable var;
  228. MemberArray members;
  229. };
  230. typedef stl::unordered_map<uint32_t, TypeId> TypeIdMap;
  231. typedef stl::unordered_map<uint32_t, Id> IdMap;
  232. TypeIdMap typeIdMap;
  233. IdMap idMap;
  234. stl::string getTypeName(uint32_t _typeId)
  235. {
  236. return getTypeId(_typeId).toString();
  237. }
  238. Id& getId(uint32_t _id)
  239. {
  240. IdMap::iterator it = idMap.find(_id);
  241. if (it == idMap.end() )
  242. {
  243. Id id;
  244. stl::pair<IdMap::iterator, bool> result = idMap.insert(stl::make_pair(_id, id) );
  245. it = result.first;
  246. }
  247. return it->second;
  248. }
  249. Id::Variable& get(uint32_t _id, uint32_t _idx)
  250. {
  251. Id& id = getId(_id);
  252. id.members.resize(bx::uint32_max(_idx+1, uint32_t(id.members.size() ) ) );
  253. return id.members[_idx];
  254. }
  255. TypeId& getTypeId(uint32_t _id)
  256. {
  257. TypeIdMap::iterator it = typeIdMap.find(_id);
  258. if (it == typeIdMap.end() )
  259. {
  260. TypeId id;
  261. stl::pair<TypeIdMap::iterator, bool> result = typeIdMap.insert(stl::make_pair(_id, id) );
  262. it = result.first;
  263. }
  264. return it->second;
  265. }
  266. void update(uint32_t _id, const stl::string& _name)
  267. {
  268. getId(_id).var.name = _name;
  269. }
  270. BX_NO_INLINE void update(Id::Variable& _variable, SpvDecoration::Enum _decoration, uint32_t _literal)
  271. {
  272. _variable.decoration = _decoration;
  273. switch (_decoration)
  274. {
  275. case SpvDecoration::Location:
  276. _variable.location = _literal;
  277. break;
  278. case SpvDecoration::Offset:
  279. _variable.offset = _literal;
  280. break;
  281. case SpvDecoration::BuiltIn:
  282. _variable.builtin = SpvBuiltin::Enum(_literal);
  283. break;
  284. default:
  285. break;
  286. }
  287. }
  288. BX_NO_INLINE void update(Id::Variable& _variable, uint32_t _type, SpvStorageClass::Enum _storageClass)
  289. {
  290. _variable.type = _type;
  291. _variable.storageClass = _storageClass;
  292. }
  293. void update(uint32_t _id, SpvDecoration::Enum _decoration, uint32_t _literal)
  294. {
  295. update(getId(_id).var, _decoration, _literal);
  296. }
  297. void update(uint32_t _id, uint32_t _type, SpvStorageClass::Enum _storageClass)
  298. {
  299. update(getId(_id).var, _type, _storageClass);
  300. }
  301. void update(uint32_t _id, uint32_t _idx, const stl::string& _name)
  302. {
  303. Id::Variable& var = get(_id, _idx);
  304. var.name = _name;
  305. }
  306. BX_NO_INLINE void update(uint32_t _id, uint32_t _idx, SpvDecoration::Enum _decoration, uint32_t _literal)
  307. {
  308. update(get(_id, _idx), _decoration, _literal);
  309. }
  310. void update(uint32_t _id, TypeId::Enum _type)
  311. {
  312. TypeId& type = getTypeId(_id);
  313. type.type = _type;
  314. }
  315. void update(uint32_t _id, TypeId::Enum _type, uint32_t _baseTypeId, uint32_t _numComonents)
  316. {
  317. TypeId& type = getTypeId(_id);
  318. type.type = _type;
  319. type.baseType = getTypeId(_baseTypeId).type;
  320. type.numComponents = _numComonents;
  321. }
  322. };
  323. bool spvParse(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
  324. {
  325. BX_UNUSED(_offset);
  326. SpvReflection* spv = (SpvReflection*)_userData;
  327. switch (_instruction.opcode)
  328. {
  329. case SpvOpcode::Name:
  330. spv->update(_instruction.result
  331. , _instruction.operand[0].literalString
  332. );
  333. break;
  334. case SpvOpcode::Decorate:
  335. spv->update(_instruction.operand[0].data
  336. , SpvDecoration::Enum(_instruction.operand[1].data)
  337. , _instruction.operand[2].data
  338. );
  339. break;
  340. case SpvOpcode::MemberName:
  341. spv->update(_instruction.result
  342. , _instruction.operand[0].data
  343. , _instruction.operand[1].literalString
  344. );
  345. break;
  346. case SpvOpcode::MemberDecorate:
  347. spv->update(_instruction.operand[0].data
  348. , _instruction.operand[1].data
  349. , SpvDecoration::Enum(_instruction.operand[2].data)
  350. , _instruction.operand[3].data
  351. );
  352. break;
  353. case SpvOpcode::Variable:
  354. spv->update(_instruction.result
  355. , _instruction.type
  356. , SpvStorageClass::Enum(_instruction.operand[0].data)
  357. );
  358. break;
  359. case SpvOpcode::TypeVoid:
  360. spv->update(_instruction.result, SpvReflection::TypeId::Void);
  361. break;
  362. case SpvOpcode::TypeBool:
  363. spv->update(_instruction.result, SpvReflection::TypeId::Bool);
  364. break;
  365. case SpvOpcode::TypeInt:
  366. spv->update(_instruction.result
  367. , 32 == _instruction.operand[0].data
  368. ? 0 == _instruction.operand[1].data
  369. ? SpvReflection::TypeId::Uint32
  370. : SpvReflection::TypeId::Int32
  371. : 0 == _instruction.operand[1].data
  372. ? SpvReflection::TypeId::Uint64
  373. : SpvReflection::TypeId::Int64
  374. );
  375. break;
  376. case SpvOpcode::TypeFloat:
  377. spv->update(_instruction.result
  378. , 32 == _instruction.operand[0].data
  379. ? SpvReflection::TypeId::Float
  380. : SpvReflection::TypeId::Double
  381. );
  382. break;
  383. case SpvOpcode::TypeVector:
  384. spv->update(_instruction.result
  385. , SpvReflection::TypeId::Vector
  386. , _instruction.operand[0].data
  387. , _instruction.operand[1].data
  388. );
  389. break;
  390. case SpvOpcode::TypeMatrix:
  391. spv->update(_instruction.result
  392. , SpvReflection::TypeId::Matrix
  393. , _instruction.operand[0].data
  394. , _instruction.operand[1].data
  395. );
  396. break;
  397. case SpvOpcode::TypeImage:
  398. case SpvOpcode::TypeSampler:
  399. case SpvOpcode::TypeSampledImage:
  400. break;
  401. case SpvOpcode::TypeStruct:
  402. for (uint32_t ii = 0, num = _instruction.numOperands; ii < num; ++ii)
  403. {
  404. SpvReflection::Id::Variable& var = spv->get(_instruction.result, ii);
  405. var.type = _instruction.operand[ii].data;
  406. }
  407. break;
  408. default:
  409. break;
  410. }
  411. return true;
  412. }
  413. #define DBG(...) // bx::debugPrintf(__VA_ARGS__)
  414. void disassemble(bx::WriterI* _writer, bx::ReaderSeekerI* _reader, bx::Error* _err)
  415. {
  416. BX_UNUSED(_writer);
  417. uint32_t magic;
  418. bx::peek(_reader, magic);
  419. SpvReflection spvx;
  420. if (magic == SPV_CHUNK_HEADER)
  421. {
  422. SpirV spirv;
  423. read(_reader, spirv, _err);
  424. parse(spirv.shader, spvParse, &spvx, _err);
  425. for (SpvReflection::IdMap::const_iterator it = spvx.idMap.begin(), itEnd = spvx.idMap.end(); it != itEnd; ++it)
  426. {
  427. const SpvReflection::Id& id = it->second;
  428. uint32_t num = uint32_t(id.members.size() );
  429. if (0 < num
  430. && 0 != bx::strCmp(id.var.name.c_str(), "gl_PerVertex") )
  431. {
  432. DBG("%3d: %s %d %s\n"
  433. , it->first
  434. , id.var.name.c_str()
  435. , id.var.location
  436. , getName(id.var.storageClass)
  437. );
  438. DBG("{\n");
  439. for (uint32_t ii = 0; ii < num; ++ii)
  440. {
  441. const SpvReflection::Id::Variable& var = id.members[ii];
  442. DBG("\t\t%s %s %d %s\n"
  443. , spvx.getTypeName(var.type).c_str()
  444. , var.name.c_str()
  445. , var.offset
  446. , getName(var.storageClass)
  447. );
  448. BX_UNUSED(var);
  449. }
  450. DBG("}\n");
  451. }
  452. }
  453. }
  454. }
  455. static EShLanguage getLang(char _p)
  456. {
  457. switch (_p)
  458. {
  459. case 'c': return EShLangCompute;
  460. case 'f': return EShLangFragment;
  461. case 'v': return EShLangVertex;
  462. default: return EShLangCount;
  463. }
  464. }
  465. static const char* s_attribName[] =
  466. {
  467. "a_position",
  468. "a_normal",
  469. "a_tangent",
  470. "a_bitangent",
  471. "a_color0",
  472. "a_color1",
  473. "a_color2",
  474. "a_color3",
  475. "a_indices",
  476. "a_weight",
  477. "a_texcoord0",
  478. "a_texcoord1",
  479. "a_texcoord2",
  480. "a_texcoord3",
  481. "a_texcoord4",
  482. "a_texcoord5",
  483. "a_texcoord6",
  484. "a_texcoord7",
  485. };
  486. BX_STATIC_ASSERT(bgfx::Attrib::Count == BX_COUNTOF(s_attribName) );
  487. bgfx::Attrib::Enum toAttribEnum(const bx::StringView& _name)
  488. {
  489. for (uint8_t ii = 0; ii < Attrib::Count; ++ii)
  490. {
  491. if (0 == bx::strCmp(s_attribName[ii], _name) )
  492. {
  493. return bgfx::Attrib::Enum(ii);
  494. }
  495. }
  496. return bgfx::Attrib::Count;
  497. }
  498. static const char* s_samplerTypes[] =
  499. {
  500. "BgfxSampler2D",
  501. "BgfxISampler2D",
  502. "BgfxUSampler2D",
  503. "BgfxSampler2DArray",
  504. "BgfxSampler2DShadow",
  505. "BgfxSampler2DArrayShadow",
  506. "BgfxSampler3D",
  507. "BgfxISampler3D",
  508. "BgfxUSampler3D",
  509. "BgfxSamplerCube",
  510. "BgfxSamplerCubeShadow",
  511. "BgfxSampler2DMS",
  512. };
  513. static uint16_t writeUniformArray(bx::WriterI* _writer, const UniformArray& uniforms, bool isFragmentShader)
  514. {
  515. uint16_t size = 0;
  516. uint16_t count = static_cast<uint16_t>(uniforms.size() );
  517. bx::write(_writer, count);
  518. uint32_t fragmentBit = isFragmentShader ? kUniformFragmentBit : 0;
  519. for (uint16_t ii = 0; ii < count; ++ii)
  520. {
  521. const Uniform& un = uniforms[ii];
  522. size += un.regCount*16;
  523. uint8_t nameSize = (uint8_t)un.name.size();
  524. bx::write(_writer, nameSize);
  525. bx::write(_writer, un.name.c_str(), nameSize);
  526. bx::write(_writer, uint8_t(un.type | fragmentBit) );
  527. bx::write(_writer, un.num);
  528. bx::write(_writer, un.regIndex);
  529. bx::write(_writer, un.regCount);
  530. bx::write(_writer, un.texComponent);
  531. bx::write(_writer, un.texDimension);
  532. BX_TRACE("%s, %s, %d, %d, %d"
  533. , un.name.c_str()
  534. , getUniformTypeName(un.type)
  535. , un.num
  536. , un.regIndex
  537. , un.regCount
  538. );
  539. }
  540. return size;
  541. }
  542. static bool compile(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _writer, bool _firstPass)
  543. {
  544. BX_UNUSED(_version);
  545. glslang::InitializeProcess();
  546. glslang::TProgram* program = new glslang::TProgram;
  547. EShLanguage stage = getLang(_options.shaderType);
  548. if (EShLangCount == stage)
  549. {
  550. bx::printf("Error: Unknown shader type '%c'.\n", _options.shaderType);
  551. return false;
  552. }
  553. glslang::TShader* shader = new glslang::TShader(stage);
  554. EShMessages messages = EShMessages(0
  555. | EShMsgDefault
  556. | EShMsgReadHlsl
  557. | EShMsgVulkanRules
  558. | EShMsgSpvRules
  559. );
  560. shader->setEntryPoint("main");
  561. shader->setAutoMapBindings(true);
  562. const int textureBindingOffset = 16;
  563. shader->setShiftBinding(glslang::EResTexture, textureBindingOffset);
  564. shader->setShiftBinding(glslang::EResSampler, textureBindingOffset);
  565. shader->setShiftBinding(glslang::EResImage, textureBindingOffset);
  566. const char* shaderStrings[] = { _code.c_str() };
  567. shader->setStrings(
  568. shaderStrings
  569. , BX_COUNTOF(shaderStrings)
  570. );
  571. bool compiled = shader->parse(&resourceLimits
  572. , 110
  573. , false
  574. , messages
  575. );
  576. bool linked = false;
  577. bool validated = true;
  578. if (!compiled)
  579. {
  580. const char* log = shader->getInfoLog();
  581. if (NULL != log)
  582. {
  583. int32_t source = 0;
  584. int32_t line = 0;
  585. int32_t column = 0;
  586. int32_t start = 0;
  587. int32_t end = INT32_MAX;
  588. bx::StringView err = bx::strFind(log, "ERROR:");
  589. bool found = false;
  590. if (!err.isEmpty() )
  591. {
  592. found = 2 == sscanf(err.getPtr(), "ERROR: %u:%u: '", &source, &line);
  593. if (found)
  594. {
  595. ++line;
  596. }
  597. }
  598. if (found)
  599. {
  600. start = bx::uint32_imax(1, line-10);
  601. end = start + 20;
  602. }
  603. printCode(_code.c_str(), line, start, end, column);
  604. bx::printf("%s\n", log);
  605. }
  606. }
  607. else
  608. {
  609. program->addShader(shader);
  610. linked = true
  611. && program->link(messages)
  612. && program->mapIO()
  613. ;
  614. if (!linked)
  615. {
  616. const char* log = program->getInfoLog();
  617. if (NULL != log)
  618. {
  619. bx::printf("%s\n", log);
  620. }
  621. }
  622. else
  623. {
  624. program->buildReflection();
  625. if (_firstPass)
  626. {
  627. // first time through, we just find unused uniforms and get rid of them
  628. std::string output;
  629. bx::Error err;
  630. bx::LineReader reader(_code.c_str() );
  631. while (!reader.isDone() )
  632. {
  633. bx::StringView strLine = reader.next();
  634. bx::StringView str = strFind(strLine, "uniform ");
  635. if (!str.isEmpty() )
  636. {
  637. bool found = false;
  638. for (uint32_t ii = 0; ii < BX_COUNTOF(s_samplerTypes); ++ii)
  639. {
  640. if (!bx::findIdentifierMatch(strLine, s_samplerTypes[ii]).isEmpty() )
  641. {
  642. found = true;
  643. break;
  644. }
  645. }
  646. if (!found)
  647. {
  648. for (int32_t ii = 0, num = program->getNumLiveUniformVariables(); ii < num; ++ii)
  649. {
  650. // matching lines like: uniform u_name;
  651. // we want to replace "uniform" with "static" so that it's no longer
  652. // included in the uniform blob that the application must upload
  653. // we can't just remove them, because unused functions might still reference
  654. // them and cause a compile error when they're gone
  655. if (!bx::findIdentifierMatch(strLine, program->getUniformName(ii) ).isEmpty() )
  656. {
  657. found = true;
  658. break;
  659. }
  660. }
  661. }
  662. if (!found)
  663. {
  664. output.append(strLine.getPtr(), str.getPtr() );
  665. output += "static ";
  666. output.append(str.getTerm(), strLine.getTerm() );
  667. output += "\n";
  668. }
  669. else
  670. {
  671. output.append(strLine.getPtr(), strLine.getTerm() );
  672. output += "\n";
  673. }
  674. }
  675. else
  676. {
  677. output.append(strLine.getPtr(), strLine.getTerm() );
  678. output += "\n";
  679. }
  680. }
  681. // recompile with the unused uniforms converted to statics
  682. return compile(_options, _version, output.c_str(), _writer, false);
  683. }
  684. UniformArray uniforms;
  685. {
  686. uint16_t count = (uint16_t)program->getNumLiveUniformVariables();
  687. for (uint16_t ii = 0; ii < count; ++ii)
  688. {
  689. Uniform un;
  690. un.name = program->getUniformName(ii);
  691. un.num = uint8_t(program->getUniformArraySize(ii) );
  692. const uint32_t offset = program->getUniformBufferOffset(ii);
  693. un.regIndex = uint16_t(offset);
  694. un.regCount = un.num;
  695. switch (program->getUniformType(ii) )
  696. {
  697. case 0x1404: // GL_INT:
  698. un.type = UniformType::Sampler;
  699. break;
  700. case 0x8B52: // GL_FLOAT_VEC4:
  701. un.type = UniformType::Vec4;
  702. break;
  703. case 0x8B5B: // GL_FLOAT_MAT3:
  704. un.type = UniformType::Mat3;
  705. un.regCount *= 3;
  706. break;
  707. case 0x8B5C: // GL_FLOAT_MAT4:
  708. un.type = UniformType::Mat4;
  709. un.regCount *= 4;
  710. break;
  711. default:
  712. un.type = UniformType::End;
  713. break;
  714. }
  715. uniforms.push_back(un);
  716. }
  717. }
  718. if (g_verbose)
  719. {
  720. program->dumpReflection();
  721. }
  722. BX_UNUSED(spv::MemorySemanticsAllMemory);
  723. glslang::TIntermediate* intermediate = program->getIntermediate(stage);
  724. std::vector<uint32_t> spirv;
  725. glslang::SpvOptions options;
  726. options.disableOptimizer = false;
  727. glslang::GlslangToSpv(*intermediate, spirv, &options);
  728. spvtools::Optimizer opt(SPV_ENV_VULKAN_1_0);
  729. auto print_msg_to_stderr = [](
  730. spv_message_level_t
  731. , const char*
  732. , const spv_position_t&
  733. , const char* m
  734. )
  735. {
  736. bx::printf("Error: %s\n", m);
  737. };
  738. opt.SetMessageConsumer(print_msg_to_stderr);
  739. opt.RegisterLegalizationPasses();
  740. spvtools::ValidatorOptions validatorOptions;
  741. validatorOptions.SetBeforeHlslLegalization(true);
  742. if (!opt.Run(
  743. spirv.data()
  744. , spirv.size()
  745. , &spirv
  746. , validatorOptions
  747. , false
  748. ) )
  749. {
  750. compiled = false;
  751. }
  752. else
  753. {
  754. bx::Error err;
  755. bx::WriterI* writer = bx::getDebugOut();
  756. bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) );
  757. disassemble(writer, &reader, &err);
  758. spirv_cross::CompilerReflection refl(spirv);
  759. spirv_cross::ShaderResources resourcesrefl = refl.get_shader_resources();
  760. // Loop through the separate_images, and extract the uniform names:
  761. for (auto &resource : resourcesrefl.separate_images)
  762. {
  763. std::string name = refl.get_name(resource.id);
  764. if (name.size() > 7 && 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
  765. {
  766. auto uniform_name = name.substr(0, name.length() - 7);
  767. Uniform un;
  768. un.name = uniform_name;
  769. un.type = UniformType::Sampler;
  770. un.num = 0; // needed?
  771. un.regIndex = 0; // needed?
  772. un.regCount = 0; // needed?
  773. uniforms.push_back(un);
  774. }
  775. }
  776. uint16_t size = writeUniformArray( _writer, uniforms, _options.shaderType == 'f');
  777. if (_version == BX_MAKEFOURCC('M', 'T', 'L', 0) )
  778. {
  779. if (g_verbose)
  780. {
  781. glslang::SpirvToolsDisassemble(std::cout, spirv);
  782. }
  783. spirv_cross::CompilerMSL msl(std::move(spirv) );
  784. auto executionModel = msl.get_execution_model();
  785. spirv_cross::MSLResourceBinding newBinding;
  786. newBinding.stage = executionModel;
  787. spirv_cross::ShaderResources resources = msl.get_shader_resources();
  788. spirv_cross::SmallVector<spirv_cross::EntryPoint> entryPoints = msl.get_entry_points_and_stages();
  789. if (!entryPoints.empty() )
  790. msl.rename_entry_point(entryPoints[0].name, "xlatMtlMain", entryPoints[0].execution_model);
  791. for (auto &resource : resources.uniform_buffers)
  792. {
  793. unsigned set = msl.get_decoration( resource.id, spv::DecorationDescriptorSet );
  794. unsigned binding = msl.get_decoration( resource.id, spv::DecorationBinding );
  795. newBinding.desc_set = set;
  796. newBinding.binding = binding;
  797. newBinding.msl_buffer = 0;
  798. msl.add_msl_resource_binding( newBinding );
  799. msl.set_name(resource.id, "_mtl_u");
  800. }
  801. for (auto &resource : resources.storage_buffers)
  802. {
  803. unsigned set = msl.get_decoration( resource.id, spv::DecorationDescriptorSet );
  804. unsigned binding = msl.get_decoration( resource.id, spv::DecorationBinding );
  805. newBinding.desc_set = set;
  806. newBinding.binding = binding;
  807. newBinding.msl_buffer = binding + 1;
  808. msl.add_msl_resource_binding( newBinding );
  809. }
  810. for (auto &resource : resources.separate_samplers)
  811. {
  812. unsigned set = msl.get_decoration( resource.id, spv::DecorationDescriptorSet );
  813. unsigned binding = msl.get_decoration( resource.id, spv::DecorationBinding );
  814. newBinding.desc_set = set;
  815. newBinding.binding = binding;
  816. newBinding.msl_texture = binding - textureBindingOffset;
  817. newBinding.msl_sampler = binding - textureBindingOffset;
  818. msl.add_msl_resource_binding( newBinding );
  819. }
  820. for (auto &resource : resources.separate_images)
  821. {
  822. std::string name = msl.get_name(resource.id);
  823. if (name.size() > 7 && 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
  824. {
  825. msl.set_name(resource.id, name.substr(0, name.length() - 7) );
  826. }
  827. unsigned set = msl.get_decoration( resource.id, spv::DecorationDescriptorSet );
  828. unsigned binding = msl.get_decoration( resource.id, spv::DecorationBinding );
  829. newBinding.desc_set = set;
  830. newBinding.binding = binding;
  831. newBinding.msl_texture = binding - textureBindingOffset;
  832. newBinding.msl_sampler = binding - textureBindingOffset;
  833. msl.add_msl_resource_binding( newBinding );
  834. }
  835. for (auto &resource : resources.storage_images)
  836. {
  837. std::string name = msl.get_name(resource.id);
  838. if (name.size() > 7 && 0 == bx::strCmp(name.c_str() + name.length() - 7, "Texture") )
  839. {
  840. msl.set_name(resource.id, name.substr(0, name.length() - 7) );
  841. }
  842. unsigned set = msl.get_decoration( resource.id, spv::DecorationDescriptorSet );
  843. unsigned binding = msl.get_decoration( resource.id, spv::DecorationBinding );
  844. newBinding.desc_set = set;
  845. newBinding.binding = binding;
  846. newBinding.msl_texture = binding - textureBindingOffset;
  847. newBinding.msl_sampler = binding - textureBindingOffset;
  848. msl.add_msl_resource_binding( newBinding );
  849. }
  850. std::string source = msl.compile();
  851. if ('c' == _options.shaderType)
  852. {
  853. for (int i = 0; i < 3; ++i)
  854. {
  855. uint16_t dim = (uint16_t)msl.get_execution_mode_argument(spv::ExecutionMode::ExecutionModeLocalSize, i);
  856. bx::write(_writer, dim);
  857. }
  858. }
  859. uint32_t shaderSize = (uint32_t)source.size();
  860. bx::write(_writer, shaderSize);
  861. bx::write(_writer, source.c_str(), shaderSize);
  862. uint8_t nul = 0;
  863. bx::write(_writer, nul);
  864. }
  865. else
  866. {
  867. uint32_t shaderSize = (uint32_t)spirv.size() * sizeof(uint32_t);
  868. bx::write(_writer, shaderSize);
  869. bx::write(_writer, spirv.data(), shaderSize);
  870. uint8_t nul = 0;
  871. bx::write(_writer, nul);
  872. }
  873. //
  874. const uint8_t numAttr = (uint8_t)program->getNumLiveAttributes();
  875. bx::write(_writer, numAttr);
  876. for (uint8_t ii = 0; ii < numAttr; ++ii)
  877. {
  878. bgfx::Attrib::Enum attr = toAttribEnum(program->getAttributeName(ii) );
  879. if (bgfx::Attrib::Count != attr)
  880. {
  881. bx::write(_writer, bgfx::attribToId(attr) );
  882. }
  883. else
  884. {
  885. bx::write(_writer, uint16_t(UINT16_MAX) );
  886. }
  887. }
  888. bx::write(_writer, size);
  889. }
  890. }
  891. }
  892. delete program;
  893. delete shader;
  894. glslang::FinalizeProcess();
  895. return compiled && linked && validated;
  896. }
  897. } // namespace metal
  898. bool compileMetalShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  899. {
  900. return metal::compile(_options, _version, _code, _writer, true);
  901. }
  902. } // namespace bgfx