shaderc_spirv.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  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/GlslangToSpv.h>
  14. BX_PRAGMA_DIAGNOSTIC_POP()
  15. namespace bgfx
  16. {
  17. static bx::DefaultAllocator s_allocator;
  18. bx::AllocatorI* g_allocator = &s_allocator;
  19. struct TinyStlAllocator
  20. {
  21. static void* static_allocate(size_t _bytes);
  22. static void static_deallocate(void* _ptr, size_t /*_bytes*/);
  23. };
  24. void* TinyStlAllocator::static_allocate(size_t _bytes)
  25. {
  26. return BX_ALLOC(g_allocator, _bytes);
  27. }
  28. void TinyStlAllocator::static_deallocate(void* _ptr, size_t /*_bytes*/)
  29. {
  30. if (NULL != _ptr)
  31. {
  32. BX_FREE(g_allocator, _ptr);
  33. }
  34. }
  35. } // namespace bgfx
  36. #define TINYSTL_ALLOCATOR bgfx::TinyStlAllocator
  37. #include <tinystl/allocator.h>
  38. #include <tinystl/string.h>
  39. #include <tinystl/unordered_map.h>
  40. #include <tinystl/vector.h>
  41. namespace stl = tinystl;
  42. #include "../../src/shader_spirv.h"
  43. namespace bgfx { namespace spirv
  44. {
  45. const TBuiltInResource resourceLimits =
  46. {
  47. 32, // MaxLights
  48. 6, // MaxClipPlanes
  49. 32, // MaxTextureUnits
  50. 32, // MaxTextureCoords
  51. 64, // MaxVertexAttribs
  52. 4096, // MaxVertexUniformComponents
  53. 64, // MaxVaryingFloats
  54. 32, // MaxVertexTextureImageUnits
  55. 80, // MaxCombinedTextureImageUnits
  56. 32, // MaxTextureImageUnits
  57. 4096, // MaxFragmentUniformComponents
  58. 32, // MaxDrawBuffers
  59. 128, // MaxVertexUniformVectors
  60. 8, // MaxVaryingVectors
  61. 16, // MaxFragmentUniformVectors
  62. 16, // MaxVertexOutputVectors
  63. 15, // MaxFragmentInputVectors
  64. -8, // MinProgramTexelOffset
  65. 7, // MaxProgramTexelOffset
  66. 8, // MaxClipDistances
  67. 65535, // MaxComputeWorkGroupCountX
  68. 65535, // MaxComputeWorkGroupCountY
  69. 65535, // MaxComputeWorkGroupCountZ
  70. 1024, // MaxComputeWorkGroupSizeX
  71. 1024, // MaxComputeWorkGroupSizeY
  72. 64, // MaxComputeWorkGroupSizeZ
  73. 1024, // MaxComputeUniformComponents
  74. 16, // MaxComputeTextureImageUnits
  75. 8, // MaxComputeImageUniforms
  76. 8, // MaxComputeAtomicCounters
  77. 1, // MaxComputeAtomicCounterBuffers
  78. 60, // MaxVaryingComponents
  79. 64, // MaxVertexOutputComponents
  80. 64, // MaxGeometryInputComponents
  81. 128, // MaxGeometryOutputComponents
  82. 128, // MaxFragmentInputComponents
  83. 8, // MaxImageUnits
  84. 8, // MaxCombinedImageUnitsAndFragmentOutputs
  85. 8, // MaxCombinedShaderOutputResources
  86. 0, // MaxImageSamples
  87. 0, // MaxVertexImageUniforms
  88. 0, // MaxTessControlImageUniforms
  89. 0, // MaxTessEvaluationImageUniforms
  90. 0, // MaxGeometryImageUniforms
  91. 8, // MaxFragmentImageUniforms
  92. 8, // MaxCombinedImageUniforms
  93. 16, // MaxGeometryTextureImageUnits
  94. 256, // MaxGeometryOutputVertices
  95. 1024, // MaxGeometryTotalOutputComponents
  96. 1024, // MaxGeometryUniformComponents
  97. 64, // MaxGeometryVaryingComponents
  98. 128, // MaxTessControlInputComponents
  99. 128, // MaxTessControlOutputComponents
  100. 16, // MaxTessControlTextureImageUnits
  101. 1024, // MaxTessControlUniformComponents
  102. 4096, // MaxTessControlTotalOutputComponents
  103. 128, // MaxTessEvaluationInputComponents
  104. 128, // MaxTessEvaluationOutputComponents
  105. 16, // MaxTessEvaluationTextureImageUnits
  106. 1024, // MaxTessEvaluationUniformComponents
  107. 120, // MaxTessPatchComponents
  108. 32, // MaxPatchVertices
  109. 64, // MaxTessGenLevel
  110. 16, // MaxViewports
  111. 0, // MaxVertexAtomicCounters
  112. 0, // MaxTessControlAtomicCounters
  113. 0, // MaxTessEvaluationAtomicCounters
  114. 0, // MaxGeometryAtomicCounters
  115. 8, // MaxFragmentAtomicCounters
  116. 8, // MaxCombinedAtomicCounters
  117. 1, // MaxAtomicCounterBindings
  118. 0, // MaxVertexAtomicCounterBuffers
  119. 0, // MaxTessControlAtomicCounterBuffers
  120. 0, // MaxTessEvaluationAtomicCounterBuffers
  121. 0, // MaxGeometryAtomicCounterBuffers
  122. 1, // MaxFragmentAtomicCounterBuffers
  123. 1, // MaxCombinedAtomicCounterBuffers
  124. 16384, // MaxAtomicCounterBufferSize
  125. 4, // MaxTransformFeedbackBuffers
  126. 64, // MaxTransformFeedbackInterleavedComponents
  127. 8, // MaxCullDistances
  128. 8, // MaxCombinedClipAndCullDistances
  129. 4, // MaxSamples
  130. { // limits
  131. 1, // nonInductiveForLoops
  132. 1, // whileLoops
  133. 1, // doWhileLoops
  134. 1, // generalUniformIndexing
  135. 1, // generalAttributeMatrixVectorIndexing
  136. 1, // generalVaryingIndexing
  137. 1, // generalSamplerIndexing
  138. 1, // generalVariableIndexing
  139. 1, // generalConstantMatrixVectorIndexing
  140. },
  141. };
  142. bool printAsm(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
  143. {
  144. BX_UNUSED(_userData);
  145. char temp[512];
  146. toString(temp, sizeof(temp), _instruction);
  147. BX_TRACE("%5d: %s", _offset, temp);
  148. return true;
  149. }
  150. struct SpvReflection
  151. {
  152. struct TypeId
  153. {
  154. enum Enum
  155. {
  156. Void,
  157. Bool,
  158. Int32,
  159. Int64,
  160. Uint32,
  161. Uint64,
  162. Float,
  163. Double,
  164. Vector,
  165. Matrix,
  166. Count
  167. };
  168. TypeId()
  169. : baseType(Enum::Count)
  170. , type(Enum::Count)
  171. , numComponents(0)
  172. {
  173. }
  174. Enum baseType;
  175. Enum type;
  176. uint32_t numComponents;
  177. stl::string toString()
  178. {
  179. stl::string result;
  180. switch (type)
  181. {
  182. case Float:
  183. result.append("float");
  184. break;
  185. case Vector:
  186. bx::stringPrintf(result, "vec%d"
  187. , numComponents
  188. );
  189. break;
  190. case Matrix:
  191. bx::stringPrintf(result, "mat%d"
  192. , numComponents
  193. );
  194. default:
  195. break;
  196. }
  197. return result;
  198. }
  199. };
  200. struct Id
  201. {
  202. struct Variable
  203. {
  204. Variable()
  205. : decoration(SpvDecoration::Count)
  206. , builtin(SpvBuiltin::Count)
  207. , storageClass(SpvStorageClass::Count)
  208. , location(UINT32_MAX)
  209. , offset(UINT32_MAX)
  210. , type(UINT32_MAX)
  211. {
  212. }
  213. stl::string name;
  214. SpvDecoration::Enum decoration;
  215. SpvBuiltin::Enum builtin;
  216. SpvStorageClass::Enum storageClass;
  217. uint32_t location;
  218. uint32_t offset;
  219. uint32_t type;
  220. };
  221. typedef stl::vector<Variable> MemberArray;
  222. Variable var;
  223. MemberArray members;
  224. };
  225. typedef stl::unordered_map<uint32_t, TypeId> TypeIdMap;
  226. typedef stl::unordered_map<uint32_t, Id> IdMap;
  227. TypeIdMap typeIdMap;
  228. IdMap idMap;
  229. stl::string getTypeName(uint32_t _typeId)
  230. {
  231. return getTypeId(_typeId).toString();
  232. }
  233. Id& getId(uint32_t _id)
  234. {
  235. IdMap::iterator it = idMap.find(_id);
  236. if (it == idMap.end() )
  237. {
  238. Id id;
  239. stl::pair<IdMap::iterator, bool> result = idMap.insert(stl::make_pair(_id, id) );
  240. it = result.first;
  241. }
  242. return it->second;
  243. }
  244. Id::Variable& get(uint32_t _id, uint32_t _idx)
  245. {
  246. Id& id = getId(_id);
  247. id.members.resize(bx::uint32_max(_idx+1, uint32_t(id.members.size() ) ) );
  248. return id.members[_idx];
  249. }
  250. TypeId& getTypeId(uint32_t _id)
  251. {
  252. TypeIdMap::iterator it = typeIdMap.find(_id);
  253. if (it == typeIdMap.end() )
  254. {
  255. TypeId id;
  256. stl::pair<TypeIdMap::iterator, bool> result = typeIdMap.insert(stl::make_pair(_id, id) );
  257. it = result.first;
  258. }
  259. return it->second;
  260. }
  261. void update(uint32_t _id, const stl::string& _name)
  262. {
  263. getId(_id).var.name = _name;
  264. }
  265. BX_NO_INLINE void update(Id::Variable& _variable, SpvDecoration::Enum _decoration, uint32_t _literal)
  266. {
  267. _variable.decoration = _decoration;
  268. switch (_decoration)
  269. {
  270. case SpvDecoration::Location:
  271. _variable.location = _literal;
  272. break;
  273. case SpvDecoration::Offset:
  274. _variable.offset = _literal;
  275. break;
  276. case SpvDecoration::BuiltIn:
  277. _variable.builtin = SpvBuiltin::Enum(_literal);
  278. break;
  279. default:
  280. break;
  281. }
  282. }
  283. BX_NO_INLINE void update(Id::Variable& _variable, uint32_t _type, SpvStorageClass::Enum _storageClass)
  284. {
  285. _variable.type = _type;
  286. _variable.storageClass = _storageClass;
  287. }
  288. void update(uint32_t _id, SpvDecoration::Enum _decoration, uint32_t _literal)
  289. {
  290. update(getId(_id).var, _decoration, _literal);
  291. }
  292. void update(uint32_t _id, uint32_t _type, SpvStorageClass::Enum _storageClass)
  293. {
  294. update(getId(_id).var, _type, _storageClass);
  295. }
  296. void update(uint32_t _id, uint32_t _idx, const stl::string& _name)
  297. {
  298. Id::Variable& var = get(_id, _idx);
  299. var.name = _name;
  300. }
  301. BX_NO_INLINE void update(uint32_t _id, uint32_t _idx, SpvDecoration::Enum _decoration, uint32_t _literal)
  302. {
  303. update(get(_id, _idx), _decoration, _literal);
  304. }
  305. void update(uint32_t _id, TypeId::Enum _type)
  306. {
  307. TypeId& type = getTypeId(_id);
  308. type.type = _type;
  309. }
  310. void update(uint32_t _id, TypeId::Enum _type, uint32_t _baseTypeId, uint32_t _numComonents)
  311. {
  312. TypeId& type = getTypeId(_id);
  313. type.type = _type;
  314. type.baseType = getTypeId(_baseTypeId).type;
  315. type.numComponents = _numComonents;
  316. }
  317. };
  318. bool spvParse(uint32_t _offset, const SpvInstruction& _instruction, void* _userData)
  319. {
  320. BX_UNUSED(_offset);
  321. SpvReflection* spv = (SpvReflection*)_userData;
  322. switch (_instruction.opcode)
  323. {
  324. case SpvOpcode::Name:
  325. spv->update(_instruction.result
  326. , _instruction.operand[0].literalString
  327. );
  328. break;
  329. case SpvOpcode::Decorate:
  330. spv->update(_instruction.operand[0].data
  331. , SpvDecoration::Enum(_instruction.operand[1].data)
  332. , _instruction.operand[2].data
  333. );
  334. break;
  335. case SpvOpcode::MemberName:
  336. spv->update(_instruction.result
  337. , _instruction.operand[0].data
  338. , _instruction.operand[1].literalString
  339. );
  340. break;
  341. case SpvOpcode::MemberDecorate:
  342. spv->update(_instruction.operand[0].data
  343. , _instruction.operand[1].data
  344. , SpvDecoration::Enum(_instruction.operand[2].data)
  345. , _instruction.operand[3].data
  346. );
  347. break;
  348. case SpvOpcode::Variable:
  349. spv->update(_instruction.result
  350. , _instruction.type
  351. , SpvStorageClass::Enum(_instruction.operand[0].data)
  352. );
  353. break;
  354. case SpvOpcode::TypeVoid:
  355. spv->update(_instruction.result, SpvReflection::TypeId::Void);
  356. break;
  357. case SpvOpcode::TypeBool:
  358. spv->update(_instruction.result, SpvReflection::TypeId::Bool);
  359. break;
  360. case SpvOpcode::TypeInt:
  361. spv->update(_instruction.result
  362. , 32 == _instruction.operand[0].data
  363. ? 0 == _instruction.operand[1].data
  364. ? SpvReflection::TypeId::Uint32
  365. : SpvReflection::TypeId::Int32
  366. : 0 == _instruction.operand[1].data
  367. ? SpvReflection::TypeId::Uint64
  368. : SpvReflection::TypeId::Int64
  369. );
  370. break;
  371. case SpvOpcode::TypeFloat:
  372. spv->update(_instruction.result
  373. , 32 == _instruction.operand[0].data
  374. ? SpvReflection::TypeId::Float
  375. : SpvReflection::TypeId::Double
  376. );
  377. break;
  378. case SpvOpcode::TypeVector:
  379. spv->update(_instruction.result
  380. , SpvReflection::TypeId::Vector
  381. , _instruction.operand[0].data
  382. , _instruction.operand[1].data
  383. );
  384. break;
  385. case SpvOpcode::TypeMatrix:
  386. spv->update(_instruction.result
  387. , SpvReflection::TypeId::Matrix
  388. , _instruction.operand[0].data
  389. , _instruction.operand[1].data
  390. );
  391. break;
  392. case SpvOpcode::TypeImage:
  393. case SpvOpcode::TypeSampler:
  394. case SpvOpcode::TypeSampledImage:
  395. break;
  396. case SpvOpcode::TypeStruct:
  397. for (uint32_t ii = 0, num = _instruction.numOperands; ii < num; ++ii)
  398. {
  399. SpvReflection::Id::Variable& var = spv->get(_instruction.result, ii);
  400. var.type = _instruction.operand[ii].data;
  401. }
  402. break;
  403. default:
  404. break;
  405. }
  406. return true;
  407. }
  408. #define DBG(...)
  409. void disassemble(bx::WriterI* _writer, bx::ReaderSeekerI* _reader, bx::Error* _err)
  410. {
  411. BX_UNUSED(_writer);
  412. uint32_t magic;
  413. bx::peek(_reader, magic);
  414. SpvReflection spvx;
  415. if (magic == SPV_CHUNK_HEADER)
  416. {
  417. SpirV spirv;
  418. read(_reader, spirv, _err);
  419. parse(spirv.shader, spvParse, &spvx, _err);
  420. for (SpvReflection::IdMap::const_iterator it = spvx.idMap.begin(), itEnd = spvx.idMap.end(); it != itEnd; ++it)
  421. {
  422. const SpvReflection::Id& id = it->second;
  423. uint32_t num = uint32_t(id.members.size() );
  424. if (0 < num
  425. && 0 != bx::strCmp(id.var.name.c_str(), "gl_PerVertex") )
  426. {
  427. DBG("%3d: %s %d %s\n"
  428. , it->first
  429. , id.var.name.c_str()
  430. , id.var.location
  431. , getName(id.var.storageClass)
  432. );
  433. DBG("{\n");
  434. for (uint32_t ii = 0; ii < num; ++ii)
  435. {
  436. const SpvReflection::Id::Variable& var = id.members[ii];
  437. DBG("\t\t%s %s %d %s\n"
  438. , spvx.getTypeName(var.type).c_str()
  439. , var.name.c_str()
  440. , var.offset
  441. , getName(var.storageClass)
  442. );
  443. BX_UNUSED(var);
  444. }
  445. DBG("}\n");
  446. }
  447. }
  448. }
  449. }
  450. struct DebugOutputWriter : public bx::WriterI
  451. {
  452. virtual int32_t write(const void* _data, int32_t _size, bx::Error*) override
  453. {
  454. char* out = (char*)alloca(_size + 1);
  455. bx::memCopy(out, _data, _size);
  456. out[_size] = '\0';
  457. printf("%s", out);
  458. return _size;
  459. }
  460. };
  461. static EShLanguage getLang(char _p)
  462. {
  463. switch (_p)
  464. {
  465. case 'c': return EShLangCompute;
  466. case 'f': return EShLangFragment;
  467. case 'v': return EShLangVertex;
  468. default: return EShLangCount;
  469. }
  470. }
  471. // static void printError(spv_message_level_t, const char*, const spv_position_t&, const char* _message)
  472. // {
  473. // fprintf(stderr, "%s\n", _message);
  474. // }
  475. static bool compile(const bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  476. {
  477. BX_UNUSED(_cmdLine, _version, _code, _writer);
  478. const char* type = _cmdLine.findOption('\0', "type");
  479. if (NULL == type)
  480. {
  481. fprintf(stderr, "Error: Shader type must be specified.\n");
  482. return false;
  483. }
  484. glslang::InitializeProcess();
  485. glslang::TProgram* program = new glslang::TProgram;
  486. EShLanguage stage = getLang(type[0]);
  487. if (EShLangCount == stage)
  488. {
  489. fprintf(stderr, "Error: Unknown shader type %s.\n", type);
  490. return false;
  491. }
  492. glslang::TShader* shader = new glslang::TShader(stage);
  493. EShMessages messages = EShMessages(0
  494. | EShMsgDefault
  495. | EShMsgReadHlsl
  496. | EShMsgVulkanRules
  497. | EShMsgSpvRules
  498. );
  499. shader->setEntryPoint("main");
  500. const char* shaderStrings[] = { _code.c_str() };
  501. shader->setStrings(
  502. shaderStrings
  503. , BX_COUNTOF(shaderStrings)
  504. );
  505. bool compiled = shader->parse(&resourceLimits
  506. , 110
  507. , false
  508. , messages
  509. );
  510. bool linked = false;
  511. bool validated = true;
  512. bool optimized = true;
  513. if (!compiled)
  514. {
  515. const char* log = shader->getInfoLog();
  516. if (NULL != log)
  517. {
  518. int32_t source = 0;
  519. int32_t line = 0;
  520. int32_t column = 0;
  521. int32_t start = 0;
  522. int32_t end = INT32_MAX;
  523. const char* err = bx::strFind(log, INT32_MAX, "ERROR:");
  524. bool found = false;
  525. if (NULL != err)
  526. {
  527. found = 2 == sscanf(err, "ERROR: %u:%u: '", &source, &line);
  528. if (found)
  529. {
  530. ++line;
  531. }
  532. }
  533. if (found)
  534. {
  535. start = bx::uint32_imax(1, line-10);
  536. end = start + 20;
  537. }
  538. printCode(_code.c_str(), line, start, end, column);
  539. fprintf(stderr, "%s\n", log);
  540. }
  541. }
  542. else
  543. {
  544. program->addShader(shader);
  545. linked = true
  546. && program->link(messages)
  547. && program->mapIO()
  548. ;
  549. if (!linked)
  550. {
  551. const char* log = program->getInfoLog();
  552. if (NULL != log)
  553. {
  554. fprintf(stderr, "%s\n", log);
  555. }
  556. }
  557. else
  558. {
  559. program->buildReflection();
  560. {
  561. uint16_t count = (uint16_t)program->getNumLiveUniformVariables();
  562. bx::write(_writer, count);
  563. uint32_t fragmentBit = type[0] == 'f' ? BGFX_UNIFORM_FRAGMENTBIT : 0;
  564. for (uint16_t ii = 0; ii < count; ++ii)
  565. {
  566. Uniform un;
  567. un.name = program->getUniformName(ii);
  568. switch (program->getUniformType(ii))
  569. {
  570. case 0x1404: // GL_INT:
  571. un.type = UniformType::Int1;
  572. break;
  573. case 0x8B52: // GL_FLOAT_VEC4:
  574. un.type = UniformType::Vec4;
  575. break;
  576. case 0x8B5B: // GL_FLOAT_MAT3:
  577. un.type = UniformType::Mat3;
  578. break;
  579. case 0x8B5C: // GL_FLOAT_MAT4:
  580. un.type = UniformType::Mat4;
  581. break;
  582. default:
  583. un.type = UniformType::End;
  584. break;
  585. }
  586. un.num = uint8_t(program->getUniformArraySize(ii) );
  587. un.regIndex = 0;
  588. un.regCount = un.num;
  589. uint8_t nameSize = (uint8_t)un.name.size();
  590. bx::write(_writer, nameSize);
  591. bx::write(_writer, un.name.c_str(), nameSize);
  592. bx::write(_writer, uint8_t(un.type | fragmentBit));
  593. bx::write(_writer, un.num);
  594. bx::write(_writer, un.regIndex);
  595. bx::write(_writer, un.regCount);
  596. BX_TRACE("%s, %s, %d, %d, %d"
  597. , un.name.c_str()
  598. , getUniformTypeName(un.type)
  599. , un.num
  600. , un.regIndex
  601. , un.regCount
  602. );
  603. }
  604. }
  605. if (g_verbose)
  606. {
  607. program->dumpReflection();
  608. }
  609. BX_UNUSED(spv::MemorySemanticsAllMemory);
  610. glslang::TIntermediate* intermediate = program->getIntermediate(stage);
  611. std::vector<uint32_t> spirv;
  612. glslang::GlslangToSpv(*intermediate, spirv);
  613. spv::spirvbin_t spvBin;
  614. spvBin.remap(
  615. spirv
  616. , 0
  617. | spv::spirvbin_t::DCE_ALL
  618. | spv::spirvbin_t::OPT_ALL
  619. | spv::spirvbin_t::MAP_ALL
  620. // | spv::spirvbin_t::STRIP
  621. );
  622. bx::Error err;
  623. DebugOutputWriter writer;
  624. bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) );
  625. disassemble(&writer, &reader, &err);
  626. #if 0
  627. spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
  628. tools.SetMessageConsumer(printError);
  629. validated = tools.Validate(spirv);
  630. if (!validated)
  631. {
  632. std::string out;
  633. tools.Disassemble(spirv, &out);
  634. printf("%s\n", out.c_str());
  635. }
  636. if (validated)
  637. {
  638. spvtools::Optimizer optm(SPV_ENV_VULKAN_1_0);
  639. optm.SetMessageConsumer(printError);
  640. optm
  641. .RegisterPass(spvtools::CreateStripDebugInfoPass() )
  642. // .RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass({ {1, "42" } }) )
  643. .RegisterPass(spvtools::CreateFreezeSpecConstantValuePass() )
  644. .RegisterPass(spvtools::CreateFoldSpecConstantOpAndCompositePass() )
  645. .RegisterPass(spvtools::CreateEliminateDeadConstantPass() )
  646. .RegisterPass(spvtools::CreateUnifyConstantPass() )
  647. ;
  648. optimized = optm.Run(spirv.data(), spirv.size(), &spirv);
  649. }
  650. #endif // 0
  651. if (optimized)
  652. {
  653. uint32_t shaderSize = (uint32_t)spirv.size()*sizeof(uint32_t);
  654. bx::write(_writer, shaderSize);
  655. bx::write(_writer, spirv.data(), shaderSize);
  656. uint8_t nul = 0;
  657. bx::write(_writer, nul);
  658. }
  659. }
  660. }
  661. delete program;
  662. delete shader;
  663. glslang::FinalizeProcess();
  664. return compiled && linked && validated && optimized;
  665. }
  666. } // namespace spirv
  667. bool compileSPIRVShader(const bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  668. {
  669. return spirv::compile(_cmdLine, _version, _code, _writer);
  670. }
  671. } // namespace bgfx