shaderc_spirv.cpp 17 KB

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