shaderc_spirv.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * Copyright 2011-2017 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("-Wshadow") // warning: declaration of 'userData' shadows a member of 'glslang::TShader::Includer::IncludeResult'
  10. #include <ShaderLang.h>
  11. #include <ResourceLimits.h>
  12. #include <SPIRV/SPVRemapper.h>
  13. //#include <spirv-tools/libspirv.hpp>
  14. //#include <spirv-tools/optimizer.hpp>
  15. BX_PRAGMA_DIAGNOSTIC_POP()
  16. namespace bgfx
  17. {
  18. static bx::CrtAllocator s_allocator;
  19. bx::AllocatorI* g_allocator = &s_allocator;
  20. struct TinyStlAllocator
  21. {
  22. static void* static_allocate(size_t _bytes);
  23. static void static_deallocate(void* _ptr, size_t /*_bytes*/);
  24. };
  25. void* TinyStlAllocator::static_allocate(size_t _bytes)
  26. {
  27. return BX_ALLOC(g_allocator, _bytes);
  28. }
  29. void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
  30. {
  31. if (NULL != _ptr)
  32. {
  33. BX_FREE(g_allocator, _ptr);
  34. }
  35. }
  36. } // namespace bgfx
  37. #define TINYSTL_ALLOCATOR bgfx::TinyStlAllocator
  38. #include <tinystl/allocator.h>
  39. #include <tinystl/string.h>
  40. #include <tinystl/unordered_map.h>
  41. #include <tinystl/vector.h>
  42. namespace stl = tinystl;
  43. #include "../../src/shader_spirv.h"
  44. namespace glslang
  45. {
  46. void GlslangToSpv(const glslang::TIntermediate& _intermediate, std::vector<uint32_t>& _spirv);
  47. } // namespace glslang
  48. namespace bgfx { namespace spirv
  49. {
  50. const TBuiltInResource resourceLimits =
  51. {
  52. 32, // MaxLights
  53. 6, // MaxClipPlanes
  54. 32, // MaxTextureUnits
  55. 32, // MaxTextureCoords
  56. 64, // MaxVertexAttribs
  57. 4096, // MaxVertexUniformComponents
  58. 64, // MaxVaryingFloats
  59. 32, // MaxVertexTextureImageUnits
  60. 80, // MaxCombinedTextureImageUnits
  61. 32, // MaxTextureImageUnits
  62. 4096, // MaxFragmentUniformComponents
  63. 32, // MaxDrawBuffers
  64. 128, // MaxVertexUniformVectors
  65. 8, // MaxVaryingVectors
  66. 16, // MaxFragmentUniformVectors
  67. 16, // MaxVertexOutputVectors
  68. 15, // MaxFragmentInputVectors
  69. -8, // MinProgramTexelOffset
  70. 7, // MaxProgramTexelOffset
  71. 8, // MaxClipDistances
  72. 65535, // MaxComputeWorkGroupCountX
  73. 65535, // MaxComputeWorkGroupCountY
  74. 65535, // MaxComputeWorkGroupCountZ
  75. 1024, // MaxComputeWorkGroupSizeX
  76. 1024, // MaxComputeWorkGroupSizeY
  77. 64, // MaxComputeWorkGroupSizeZ
  78. 1024, // MaxComputeUniformComponents
  79. 16, // MaxComputeTextureImageUnits
  80. 8, // MaxComputeImageUniforms
  81. 8, // MaxComputeAtomicCounters
  82. 1, // MaxComputeAtomicCounterBuffers
  83. 60, // MaxVaryingComponents
  84. 64, // MaxVertexOutputComponents
  85. 64, // MaxGeometryInputComponents
  86. 128, // MaxGeometryOutputComponents
  87. 128, // MaxFragmentInputComponents
  88. 8, // MaxImageUnits
  89. 8, // MaxCombinedImageUnitsAndFragmentOutputs
  90. 8, // MaxCombinedShaderOutputResources
  91. 0, // MaxImageSamples
  92. 0, // MaxVertexImageUniforms
  93. 0, // MaxTessControlImageUniforms
  94. 0, // MaxTessEvaluationImageUniforms
  95. 0, // MaxGeometryImageUniforms
  96. 8, // MaxFragmentImageUniforms
  97. 8, // MaxCombinedImageUniforms
  98. 16, // MaxGeometryTextureImageUnits
  99. 256, // MaxGeometryOutputVertices
  100. 1024, // MaxGeometryTotalOutputComponents
  101. 1024, // MaxGeometryUniformComponents
  102. 64, // MaxGeometryVaryingComponents
  103. 128, // MaxTessControlInputComponents
  104. 128, // MaxTessControlOutputComponents
  105. 16, // MaxTessControlTextureImageUnits
  106. 1024, // MaxTessControlUniformComponents
  107. 4096, // MaxTessControlTotalOutputComponents
  108. 128, // MaxTessEvaluationInputComponents
  109. 128, // MaxTessEvaluationOutputComponents
  110. 16, // MaxTessEvaluationTextureImageUnits
  111. 1024, // MaxTessEvaluationUniformComponents
  112. 120, // MaxTessPatchComponents
  113. 32, // MaxPatchVertices
  114. 64, // MaxTessGenLevel
  115. 16, // MaxViewports
  116. 0, // MaxVertexAtomicCounters
  117. 0, // MaxTessControlAtomicCounters
  118. 0, // MaxTessEvaluationAtomicCounters
  119. 0, // MaxGeometryAtomicCounters
  120. 8, // MaxFragmentAtomicCounters
  121. 8, // MaxCombinedAtomicCounters
  122. 1, // MaxAtomicCounterBindings
  123. 0, // MaxVertexAtomicCounterBuffers
  124. 0, // MaxTessControlAtomicCounterBuffers
  125. 0, // MaxTessEvaluationAtomicCounterBuffers
  126. 0, // MaxGeometryAtomicCounterBuffers
  127. 1, // MaxFragmentAtomicCounterBuffers
  128. 1, // MaxCombinedAtomicCounterBuffers
  129. 16384, // MaxAtomicCounterBufferSize
  130. 4, // MaxTransformFeedbackBuffers
  131. 64, // MaxTransformFeedbackInterleavedComponents
  132. 8, // MaxCullDistances
  133. 8, // MaxCombinedClipAndCullDistances
  134. 4, // MaxSamples
  135. { // limits
  136. 1, // nonInductiveForLoops
  137. 1, // whileLoops
  138. 1, // doWhileLoops
  139. 1, // generalUniformIndexing
  140. 1, // generalAttributeMatrixVectorIndexing
  141. 1, // generalVaryingIndexing
  142. 1, // generalSamplerIndexing
  143. 1, // generalVariableIndexing
  144. 1, // 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(...)
  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. struct DebugOutputWriter : public bx::WriterI
  456. {
  457. virtual int32_t write(const void* _data, int32_t _size, bx::Error*) BX_OVERRIDE
  458. {
  459. char* out = (char*)alloca(_size + 1);
  460. memcpy(out, _data, _size);
  461. out[_size] = '\0';
  462. printf("%s", out);
  463. return _size;
  464. }
  465. };
  466. static EShLanguage getLang(char _p)
  467. {
  468. switch (_p)
  469. {
  470. case 'c': return EShLangCompute;
  471. case 'f': return EShLangFragment;
  472. case 'v': return EShLangVertex;
  473. default: return EShLangCount;
  474. }
  475. }
  476. // static void printError(spv_message_level_t, const char*, const spv_position_t&, const char* _message)
  477. // {
  478. // fprintf(stderr, "%s\n", _message);
  479. // }
  480. static bool compile(bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  481. {
  482. BX_UNUSED(_cmdLine, _version, _code, _writer);
  483. const char* type = _cmdLine.findOption('\0', "type");
  484. if (NULL == type)
  485. {
  486. fprintf(stderr, "Error: Shader type must be specified.\n");
  487. return false;
  488. }
  489. glslang::InitializeProcess();
  490. glslang::TProgram* program = new glslang::TProgram;
  491. EShLanguage stage = getLang(type[0]);
  492. if (EShLangCount == stage)
  493. {
  494. fprintf(stderr, "Error: Unknown shader type %s.\n", type);
  495. return false;
  496. }
  497. glslang::TShader* shader = new glslang::TShader(stage);
  498. EShMessages messages = EShMessages(0
  499. | EShMsgDefault
  500. | EShMsgReadHlsl
  501. | EShMsgVulkanRules
  502. | EShMsgSpvRules
  503. );
  504. shader->setEntryPoint("main");
  505. const char* shaderStrings[] = { _code.c_str() };
  506. shader->setStrings(
  507. shaderStrings
  508. , BX_COUNTOF(shaderStrings)
  509. );
  510. bool compiled = shader->parse(&resourceLimits
  511. , 110
  512. , false
  513. , messages
  514. );
  515. bool linked = false;
  516. bool validated = true;
  517. bool optimized = true;
  518. if (!compiled)
  519. {
  520. const char* log = shader->getInfoLog();
  521. if (NULL != log)
  522. {
  523. int32_t source = 0;
  524. int32_t line = 0;
  525. int32_t column = 0;
  526. int32_t start = 0;
  527. int32_t end = INT32_MAX;
  528. const char* err = bx::strFind(log, "ERROR:");
  529. bool found = false;
  530. if (NULL != err)
  531. {
  532. found = 2 == sscanf(err, "ERROR: %u:%u: '", &source, &line);
  533. if (found)
  534. {
  535. ++line;
  536. }
  537. }
  538. if (found)
  539. {
  540. start = bx::uint32_imax(1, line-10);
  541. end = start + 20;
  542. }
  543. printCode(_code.c_str(), line, start, end, column);
  544. fprintf(stderr, "%s\n", log);
  545. }
  546. }
  547. else
  548. {
  549. program->addShader(shader);
  550. linked = true
  551. && program->link(messages)
  552. && program->mapIO()
  553. ;
  554. if (!linked)
  555. {
  556. const char* log = program->getInfoLog();
  557. if (NULL != log)
  558. {
  559. fprintf(stderr, "%s\n", log);
  560. }
  561. }
  562. else
  563. {
  564. program->buildReflection();
  565. {
  566. uint16_t count = (uint16_t)program->getNumLiveUniformVariables();
  567. bx::write(_writer, count);
  568. uint32_t fragmentBit = type[0] == 'f' ? BGFX_UNIFORM_FRAGMENTBIT : 0;
  569. for (uint16_t ii = 0; ii < count; ++ii)
  570. {
  571. Uniform un;
  572. un.name = program->getUniformName(ii);
  573. switch (program->getUniformType(ii))
  574. {
  575. case 0x1404: // GL_INT:
  576. un.type = UniformType::Int1;
  577. break;
  578. case 0x8B52: // GL_FLOAT_VEC4:
  579. un.type = UniformType::Vec4;
  580. break;
  581. case 0x8B5B: // GL_FLOAT_MAT3:
  582. un.type = UniformType::Mat3;
  583. break;
  584. case 0x8B5C: // GL_FLOAT_MAT4:
  585. un.type = UniformType::Mat4;
  586. break;
  587. default:
  588. un.type = UniformType::End;
  589. break;
  590. }
  591. un.num = uint8_t(program->getUniformArraySize(ii) );
  592. un.regIndex = 0;
  593. un.regCount = un.num;
  594. uint8_t nameSize = (uint8_t)un.name.size();
  595. bx::write(_writer, nameSize);
  596. bx::write(_writer, un.name.c_str(), nameSize);
  597. bx::write(_writer, uint8_t(un.type | fragmentBit));
  598. bx::write(_writer, un.num);
  599. bx::write(_writer, un.regIndex);
  600. bx::write(_writer, un.regCount);
  601. BX_TRACE("%s, %s, %d, %d, %d"
  602. , un.name.c_str()
  603. , getUniformTypeName(un.type)
  604. , un.num
  605. , un.regIndex
  606. , un.regCount
  607. );
  608. }
  609. }
  610. if (g_verbose)
  611. {
  612. program->dumpReflection();
  613. }
  614. BX_UNUSED(spv::MemorySemanticsAllMemory);
  615. glslang::TIntermediate* intermediate = program->getIntermediate(stage);
  616. std::vector<uint32_t> spirv;
  617. glslang::GlslangToSpv(*intermediate, spirv);
  618. spv::spirvbin_t spvBin;
  619. spvBin.remap(
  620. spirv
  621. , 0
  622. | spv::spirvbin_t::DCE_ALL
  623. | spv::spirvbin_t::OPT_ALL
  624. | spv::spirvbin_t::MAP_ALL
  625. // | spv::spirvbin_t::STRIP
  626. );
  627. bx::Error err;
  628. DebugOutputWriter writer;
  629. bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) );
  630. disassemble(&writer, &reader, &err);
  631. #if 0
  632. spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
  633. tools.SetMessageConsumer(printError);
  634. validated = tools.Validate(spirv);
  635. if (!validated)
  636. {
  637. std::string out;
  638. tools.Disassemble(spirv, &out);
  639. printf("%s\n", out.c_str());
  640. }
  641. if (validated)
  642. {
  643. spvtools::Optimizer optm(SPV_ENV_VULKAN_1_0);
  644. optm.SetMessageConsumer(printError);
  645. optm
  646. .RegisterPass(spvtools::CreateStripDebugInfoPass() )
  647. // .RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass({ {1, "42" } }) )
  648. .RegisterPass(spvtools::CreateFreezeSpecConstantValuePass() )
  649. .RegisterPass(spvtools::CreateFoldSpecConstantOpAndCompositePass() )
  650. .RegisterPass(spvtools::CreateEliminateDeadConstantPass() )
  651. .RegisterPass(spvtools::CreateUnifyConstantPass() )
  652. ;
  653. optimized = optm.Run(spirv.data(), spirv.size(), &spirv);
  654. }
  655. #endif // 0
  656. if (optimized)
  657. {
  658. uint16_t shaderSize = (uint16_t)spirv.size()*sizeof(uint32_t);
  659. bx::write(_writer, shaderSize);
  660. bx::write(_writer, spirv.data(), shaderSize);
  661. uint8_t nul = 0;
  662. bx::write(_writer, nul);
  663. }
  664. }
  665. }
  666. delete program;
  667. delete shader;
  668. glslang::FinalizeProcess();
  669. return compiled && linked && validated && optimized;
  670. }
  671. } // namespace spirv
  672. bool compileSPIRVShader(bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  673. {
  674. return spirv::compile(_cmdLine, _version, _code, _writer);
  675. }
  676. } // namespace bgfx