shaderc_spirv.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. /*
  2. * Copyright 2011-2018 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(...) // bx::debugPrintf(__VA_ARGS__)
  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. static EShLanguage getLang(char _p)
  451. {
  452. switch (_p)
  453. {
  454. case 'c': return EShLangCompute;
  455. case 'f': return EShLangFragment;
  456. case 'v': return EShLangVertex;
  457. default: return EShLangCount;
  458. }
  459. }
  460. // static void printError(spv_message_level_t, const char*, const spv_position_t&, const char* _message)
  461. // {
  462. // fprintf(stderr, "%s\n", _message);
  463. // }
  464. static bool compile(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  465. {
  466. BX_UNUSED(_version);
  467. glslang::InitializeProcess();
  468. glslang::TProgram* program = new glslang::TProgram;
  469. EShLanguage stage = getLang(_options.shaderType);
  470. if (EShLangCount == stage)
  471. {
  472. fprintf(stderr, "Error: Unknown shader type '%c'.\n", _options.shaderType);
  473. return false;
  474. }
  475. glslang::TShader* shader = new glslang::TShader(stage);
  476. EShMessages messages = EShMessages(0
  477. | EShMsgDefault
  478. | EShMsgReadHlsl
  479. | EShMsgVulkanRules
  480. | EShMsgSpvRules
  481. );
  482. shader->setEntryPoint("main");
  483. const char* shaderStrings[] = { _code.c_str() };
  484. shader->setStrings(
  485. shaderStrings
  486. , BX_COUNTOF(shaderStrings)
  487. );
  488. bool compiled = shader->parse(&resourceLimits
  489. , 110
  490. , false
  491. , messages
  492. );
  493. bool linked = false;
  494. bool validated = true;
  495. bool optimized = true;
  496. if (!compiled)
  497. {
  498. const char* log = shader->getInfoLog();
  499. if (NULL != log)
  500. {
  501. int32_t source = 0;
  502. int32_t line = 0;
  503. int32_t column = 0;
  504. int32_t start = 0;
  505. int32_t end = INT32_MAX;
  506. const char* err = bx::strFind(log, "ERROR:");
  507. bool found = false;
  508. if (NULL != err)
  509. {
  510. found = 2 == sscanf(err, "ERROR: %u:%u: '", &source, &line);
  511. if (found)
  512. {
  513. ++line;
  514. }
  515. }
  516. if (found)
  517. {
  518. start = bx::uint32_imax(1, line-10);
  519. end = start + 20;
  520. }
  521. printCode(_code.c_str(), line, start, end, column);
  522. fprintf(stderr, "%s\n", log);
  523. }
  524. }
  525. else
  526. {
  527. program->addShader(shader);
  528. linked = true
  529. && program->link(messages)
  530. && program->mapIO()
  531. ;
  532. if (!linked)
  533. {
  534. const char* log = program->getInfoLog();
  535. if (NULL != log)
  536. {
  537. fprintf(stderr, "%s\n", log);
  538. }
  539. }
  540. else
  541. {
  542. program->buildReflection();
  543. {
  544. uint16_t count = (uint16_t)program->getNumLiveUniformVariables();
  545. bx::write(_writer, count);
  546. uint32_t fragmentBit = _options.shaderType == 'f' ? BGFX_UNIFORM_FRAGMENTBIT : 0;
  547. for (uint16_t ii = 0; ii < count; ++ii)
  548. {
  549. Uniform un;
  550. un.name = program->getUniformName(ii);
  551. switch (program->getUniformType(ii))
  552. {
  553. case 0x1404: // GL_INT:
  554. un.type = UniformType::Int1;
  555. break;
  556. case 0x8B52: // GL_FLOAT_VEC4:
  557. un.type = UniformType::Vec4;
  558. break;
  559. case 0x8B5B: // GL_FLOAT_MAT3:
  560. un.type = UniformType::Mat3;
  561. break;
  562. case 0x8B5C: // GL_FLOAT_MAT4:
  563. un.type = UniformType::Mat4;
  564. break;
  565. default:
  566. un.type = UniformType::End;
  567. break;
  568. }
  569. un.num = uint8_t(program->getUniformArraySize(ii) );
  570. un.regIndex = 0;
  571. un.regCount = un.num;
  572. uint8_t nameSize = (uint8_t)un.name.size();
  573. bx::write(_writer, nameSize);
  574. bx::write(_writer, un.name.c_str(), nameSize);
  575. bx::write(_writer, uint8_t(un.type | fragmentBit));
  576. bx::write(_writer, un.num);
  577. bx::write(_writer, un.regIndex);
  578. bx::write(_writer, un.regCount);
  579. BX_TRACE("%s, %s, %d, %d, %d"
  580. , un.name.c_str()
  581. , getUniformTypeName(un.type)
  582. , un.num
  583. , un.regIndex
  584. , un.regCount
  585. );
  586. }
  587. }
  588. if (g_verbose)
  589. {
  590. program->dumpReflection();
  591. }
  592. BX_UNUSED(spv::MemorySemanticsAllMemory);
  593. glslang::TIntermediate* intermediate = program->getIntermediate(stage);
  594. std::vector<uint32_t> spirv;
  595. glslang::GlslangToSpv(*intermediate, spirv);
  596. spv::spirvbin_t spvBin;
  597. spvBin.remap(
  598. spirv
  599. , 0
  600. | spv::spirvbin_t::DCE_ALL
  601. | spv::spirvbin_t::OPT_ALL
  602. | spv::spirvbin_t::MAP_ALL
  603. );
  604. bx::Error err;
  605. bx::WriterI* writer = bx::getDebugOut();
  606. bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) );
  607. disassemble(writer, &reader, &err);
  608. if (optimized)
  609. {
  610. uint32_t shaderSize = (uint32_t)spirv.size()*sizeof(uint32_t);
  611. bx::write(_writer, shaderSize);
  612. bx::write(_writer, spirv.data(), shaderSize);
  613. uint8_t nul = 0;
  614. bx::write(_writer, nul);
  615. }
  616. }
  617. }
  618. delete program;
  619. delete shader;
  620. glslang::FinalizeProcess();
  621. return compiled && linked && validated && optimized;
  622. }
  623. } // namespace spirv
  624. bool compileSPIRVShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _writer)
  625. {
  626. return spirv::compile(_options, _version, _code, _writer);
  627. }
  628. } // namespace bgfx