ShaderProgramCompiler.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/ShaderCompiler/ShaderProgramCompiler.h>
  6. #include <AnKi/ShaderCompiler/ShaderProgramParser.h>
  7. #include <AnKi/ShaderCompiler/Glslang.h>
  8. #include <AnKi/ShaderCompiler/Dxc.h>
  9. #include <AnKi/ShaderCompiler/ShaderProgramReflection.h>
  10. #include <AnKi/Util/Serializer.h>
  11. #include <AnKi/Util/HashMap.h>
  12. namespace anki {
  13. Error ShaderProgramBinaryWrapper::serializeToFile(CString fname) const
  14. {
  15. ANKI_ASSERT(m_binary);
  16. File file;
  17. ANKI_CHECK(file.open(fname, FileOpenFlag::kWrite | FileOpenFlag::kBinary));
  18. BinarySerializer serializer;
  19. ANKI_CHECK(serializer.serialize(*m_binary, *m_pool, file));
  20. return Error::kNone;
  21. }
  22. Error ShaderProgramBinaryWrapper::deserializeFromFile(CString fname)
  23. {
  24. File file;
  25. ANKI_CHECK(file.open(fname, FileOpenFlag::kRead | FileOpenFlag::kBinary));
  26. ANKI_CHECK(deserializeFromAnyFile(file));
  27. return Error::kNone;
  28. }
  29. void ShaderProgramBinaryWrapper::cleanup()
  30. {
  31. if(m_binary == nullptr)
  32. {
  33. return;
  34. }
  35. BaseMemoryPool& mempool = *m_pool;
  36. if(!m_singleAllocation)
  37. {
  38. for(ShaderProgramBinaryMutator& mutator : m_binary->m_mutators)
  39. {
  40. mempool.free(mutator.m_values.getBegin());
  41. }
  42. mempool.free(m_binary->m_mutators.getBegin());
  43. for(ShaderProgramBinaryCodeBlock& code : m_binary->m_codeBlocks)
  44. {
  45. mempool.free(code.m_binary.getBegin());
  46. }
  47. mempool.free(m_binary->m_codeBlocks.getBegin());
  48. for(ShaderProgramBinaryMutation& m : m_binary->m_mutations)
  49. {
  50. mempool.free(m.m_values.getBegin());
  51. }
  52. mempool.free(m_binary->m_mutations.getBegin());
  53. for(ShaderProgramBinaryBlock& block : m_binary->m_uniformBlocks)
  54. {
  55. mempool.free(block.m_variables.getBegin());
  56. }
  57. mempool.free(m_binary->m_uniformBlocks.getBegin());
  58. for(ShaderProgramBinaryBlock& block : m_binary->m_storageBlocks)
  59. {
  60. mempool.free(block.m_variables.getBegin());
  61. }
  62. mempool.free(m_binary->m_storageBlocks.getBegin());
  63. if(m_binary->m_pushConstantBlock)
  64. {
  65. mempool.free(m_binary->m_pushConstantBlock->m_variables.getBegin());
  66. mempool.free(m_binary->m_pushConstantBlock);
  67. }
  68. mempool.free(m_binary->m_opaques.getBegin());
  69. mempool.free(m_binary->m_constants.getBegin());
  70. for(ShaderProgramBinaryStruct& s : m_binary->m_structs)
  71. {
  72. mempool.free(s.m_members.getBegin());
  73. }
  74. mempool.free(m_binary->m_structs.getBegin());
  75. for(ShaderProgramBinaryVariant& variant : m_binary->m_variants)
  76. {
  77. for(ShaderProgramBinaryBlockInstance& block : variant.m_uniformBlocks)
  78. {
  79. mempool.free(block.m_variableInstances.getBegin());
  80. }
  81. for(ShaderProgramBinaryBlockInstance& block : variant.m_storageBlocks)
  82. {
  83. mempool.free(block.m_variableInstances.getBegin());
  84. }
  85. if(variant.m_pushConstantBlock)
  86. {
  87. mempool.free(variant.m_pushConstantBlock->m_variableInstances.getBegin());
  88. }
  89. for(ShaderProgramBinaryStructInstance& struct_ : variant.m_structs)
  90. {
  91. mempool.free(struct_.m_memberInstances.getBegin());
  92. }
  93. mempool.free(variant.m_uniformBlocks.getBegin());
  94. mempool.free(variant.m_storageBlocks.getBegin());
  95. mempool.free(variant.m_pushConstantBlock);
  96. mempool.free(variant.m_constants.getBegin());
  97. mempool.free(variant.m_opaques.getBegin());
  98. mempool.free(variant.m_structs.getBegin());
  99. }
  100. mempool.free(m_binary->m_variants.getBegin());
  101. }
  102. mempool.free(m_binary);
  103. m_binary = nullptr;
  104. m_singleAllocation = false;
  105. }
  106. /// Spin the dials. Used to compute all mutator combinations.
  107. static Bool spinDials(DynamicArrayRaii<U32>& dials, ConstWeakArray<ShaderProgramParserMutator> mutators)
  108. {
  109. ANKI_ASSERT(dials.getSize() == mutators.getSize() && dials.getSize() > 0);
  110. Bool done = true;
  111. U32 crntDial = dials.getSize() - 1;
  112. while(true)
  113. {
  114. // Turn dial
  115. ++dials[crntDial];
  116. if(dials[crntDial] >= mutators[crntDial].getValues().getSize())
  117. {
  118. if(crntDial == 0)
  119. {
  120. // Reached the 1st dial, stop spinning
  121. done = true;
  122. break;
  123. }
  124. else
  125. {
  126. dials[crntDial] = 0;
  127. --crntDial;
  128. }
  129. }
  130. else
  131. {
  132. done = false;
  133. break;
  134. }
  135. }
  136. return done;
  137. }
  138. static Error compileSpirv(ConstWeakArray<MutatorValue> mutation, const ShaderProgramParser& parser,
  139. BaseMemoryPool& tempPool, Array<DynamicArrayRaii<U8>, U32(ShaderType::kCount)>& spirv,
  140. StringRaii& errorLog)
  141. {
  142. // Generate the source and the rest for the variant
  143. ShaderProgramParserVariant parserVariant;
  144. ANKI_CHECK(parser.generateVariant(mutation, parserVariant));
  145. // Compile stages
  146. for(ShaderType shaderType : EnumIterable<ShaderType>())
  147. {
  148. if(!(ShaderTypeBit(1 << shaderType) & parser.getShaderTypes()))
  149. {
  150. continue;
  151. }
  152. // Compile
  153. if(!parser.isHlsl())
  154. {
  155. ANKI_CHECK(compileGlslToSpirv(parserVariant.getSource(shaderType), shaderType, tempPool, spirv[shaderType],
  156. errorLog));
  157. }
  158. else
  159. {
  160. ANKI_CHECK(compileHlslToSpirv(parserVariant.getSource(shaderType), shaderType,
  161. parser.compileWith16bitTypes(), tempPool, spirv[shaderType], errorLog));
  162. }
  163. ANKI_ASSERT(spirv[shaderType].getSize() > 0);
  164. }
  165. return Error::kNone;
  166. }
  167. static void compileVariantAsync(ConstWeakArray<MutatorValue> mutation, const ShaderProgramParser& parser,
  168. ShaderProgramBinaryVariant& variant,
  169. DynamicArrayRaii<ShaderProgramBinaryCodeBlock>& codeBlocks,
  170. DynamicArrayRaii<U64>& codeBlockHashes, BaseMemoryPool& tmpPool,
  171. BaseMemoryPool& binaryPool, ShaderProgramAsyncTaskInterface& taskManager, Mutex& mtx,
  172. Atomic<I32>& error)
  173. {
  174. variant = {};
  175. class Ctx
  176. {
  177. public:
  178. BaseMemoryPool* m_tmpPool;
  179. BaseMemoryPool* m_binaryPool;
  180. DynamicArrayRaii<MutatorValue> m_mutation = {m_tmpPool};
  181. const ShaderProgramParser* m_parser;
  182. ShaderProgramBinaryVariant* m_variant;
  183. DynamicArrayRaii<ShaderProgramBinaryCodeBlock>* m_codeBlocks;
  184. DynamicArrayRaii<U64>* m_codeBlockHashes;
  185. Mutex* m_mtx;
  186. Atomic<I32>* m_err;
  187. Ctx(BaseMemoryPool* tmpPool)
  188. : m_tmpPool(tmpPool)
  189. {
  190. }
  191. };
  192. Ctx* ctx = newInstance<Ctx>(tmpPool, &tmpPool);
  193. ctx->m_binaryPool = &binaryPool;
  194. ctx->m_mutation.create(mutation.getSize());
  195. memcpy(ctx->m_mutation.getBegin(), mutation.getBegin(), mutation.getSizeInBytes());
  196. ctx->m_parser = &parser;
  197. ctx->m_variant = &variant;
  198. ctx->m_codeBlocks = &codeBlocks;
  199. ctx->m_codeBlockHashes = &codeBlockHashes;
  200. ctx->m_mtx = &mtx;
  201. ctx->m_err = &error;
  202. auto callback = [](void* userData) {
  203. Ctx& ctx = *static_cast<Ctx*>(userData);
  204. BaseMemoryPool& tmpPool = *ctx.m_tmpPool;
  205. if(ctx.m_err->load() != 0)
  206. {
  207. // Cleanup and return
  208. deleteInstance(tmpPool, &ctx);
  209. return;
  210. }
  211. // All good, compile the variant
  212. Array<DynamicArrayRaii<U8>, U32(ShaderType::kCount)> spirvs = {{{&tmpPool},
  213. {&tmpPool},
  214. {&tmpPool},
  215. {&tmpPool},
  216. {&tmpPool},
  217. {&tmpPool},
  218. {&tmpPool},
  219. {&tmpPool},
  220. {&tmpPool},
  221. {&tmpPool},
  222. {&tmpPool},
  223. {&tmpPool}}};
  224. StringRaii errorLog(&tmpPool);
  225. const Error err = compileSpirv(ctx.m_mutation, *ctx.m_parser, tmpPool, spirvs, errorLog);
  226. if(!err)
  227. {
  228. // No error, check if the spirvs are common with some other variant and store it
  229. LockGuard<Mutex> lock(*ctx.m_mtx);
  230. for(ShaderType shaderType : EnumIterable<ShaderType>())
  231. {
  232. DynamicArrayRaii<U8>& spirv = spirvs[shaderType];
  233. if(spirv.isEmpty())
  234. {
  235. ctx.m_variant->m_codeBlockIndices[shaderType] = kMaxU32;
  236. continue;
  237. }
  238. // Check if the spirv is already generated
  239. const U64 newHash = computeHash(&spirv[0], spirv.getSize());
  240. Bool found = false;
  241. for(U32 i = 0; i < ctx.m_codeBlockHashes->getSize(); ++i)
  242. {
  243. if((*ctx.m_codeBlockHashes)[i] == newHash)
  244. {
  245. // Found it
  246. ctx.m_variant->m_codeBlockIndices[shaderType] = i;
  247. found = true;
  248. break;
  249. }
  250. }
  251. // Create it if not found
  252. if(!found)
  253. {
  254. U8* code = static_cast<U8*>(ctx.m_binaryPool->allocate(spirv.getSizeInBytes(), 1));
  255. memcpy(code, &spirv[0], spirv.getSizeInBytes());
  256. ShaderProgramBinaryCodeBlock block;
  257. block.m_binary.setArray(code, U32(spirv.getSizeInBytes()));
  258. block.m_hash = newHash;
  259. ctx.m_codeBlocks->emplaceBack(block);
  260. ctx.m_codeBlockHashes->emplaceBack(newHash);
  261. ctx.m_variant->m_codeBlockIndices[shaderType] = ctx.m_codeBlocks->getSize() - 1;
  262. }
  263. }
  264. }
  265. else
  266. {
  267. // Inform about the error and print only one error message. Ignore other messages
  268. const Error prevErr = ctx.m_err->exchange(err._getCode());
  269. if(!prevErr)
  270. {
  271. ANKI_SHADER_COMPILER_LOGE("GLSL compilation failed:\n%s", errorLog.cstr());
  272. }
  273. }
  274. // Cleanup
  275. deleteInstance(tmpPool, &ctx);
  276. };
  277. taskManager.enqueueTask(callback, ctx);
  278. }
  279. class Refl final : public ShaderReflectionVisitorInterface
  280. {
  281. public:
  282. BaseMemoryPool* m_pool = nullptr;
  283. const StringList* m_symbolsToReflect = nullptr;
  284. /// Will be stored in the binary
  285. /// @{
  286. /// [blockType][blockIdx]
  287. Array<DynamicArrayRaii<ShaderProgramBinaryBlock>, 3> m_blocks = {{{m_pool}, {m_pool}, {m_pool}}};
  288. /// [blockType][blockIdx][varIdx]
  289. Array<DynamicArrayRaii<DynamicArrayRaii<ShaderProgramBinaryVariable>>, 3> m_vars = {{{m_pool}, {m_pool}, {m_pool}}};
  290. DynamicArrayRaii<ShaderProgramBinaryOpaque> m_opaque = {m_pool};
  291. DynamicArrayRaii<ShaderProgramBinaryConstant> m_consts = {m_pool};
  292. DynamicArrayRaii<ShaderProgramBinaryStruct> m_structs = {m_pool};
  293. /// [structIndex][memberIndex]
  294. DynamicArrayRaii<DynamicArrayRaii<ShaderProgramBinaryStructMember>> m_structMembers = {m_pool};
  295. /// @}
  296. /// Will be stored in a variant
  297. /// @{
  298. /// [blockType][blockInstanceIdx]
  299. Array<DynamicArrayRaii<ShaderProgramBinaryBlockInstance>, 3> m_blockInstances = {{{m_pool}, {m_pool}, {m_pool}}};
  300. DynamicArrayRaii<ShaderProgramBinaryOpaqueInstance> m_opaqueInstances = {m_pool};
  301. DynamicArrayRaii<ShaderProgramBinaryConstantInstance> m_constInstances = {m_pool};
  302. DynamicArrayRaii<ShaderProgramBinaryStructInstance> m_structInstances = {m_pool};
  303. /// [structInstance][memberInstance]
  304. DynamicArrayRaii<DynamicArrayRaii<ShaderProgramBinaryStructMemberInstance>> m_structMemberInstances = {m_pool};
  305. Array<U32, 3> m_workgroupSizes = {kMaxU32, kMaxU32, kMaxU32};
  306. Array<U32, 3> m_workgroupSizesConstants = {kMaxU32, kMaxU32, kMaxU32};
  307. /// @}
  308. Refl(BaseMemoryPool* pool, const StringList* symbolsToReflect)
  309. : m_pool(pool)
  310. , m_symbolsToReflect(symbolsToReflect)
  311. {
  312. }
  313. Error setWorkgroupSizes(U32 x, U32 y, U32 z, U32 specConstMask) final
  314. {
  315. m_workgroupSizesConstants = {kMaxU32, kMaxU32, kMaxU32};
  316. m_workgroupSizes = {kMaxU32, kMaxU32, kMaxU32};
  317. const Array<U32, 3> input = {x, y, z};
  318. for(U32 i = 0; i < 3; ++i)
  319. {
  320. if(specConstMask & (1 << i))
  321. {
  322. for(const ShaderProgramBinaryConstantInstance& c : m_constInstances)
  323. {
  324. if(m_consts[c.m_index].m_constantId == input[i])
  325. {
  326. m_workgroupSizesConstants[i] = c.m_index;
  327. break;
  328. }
  329. }
  330. if(m_workgroupSizesConstants[i] == kMaxU32)
  331. {
  332. ANKI_SHADER_COMPILER_LOGE("Reflection identified workgroup size dimension %u as spec constant but "
  333. "not such spec constant was found",
  334. i);
  335. return Error::kUserData;
  336. }
  337. }
  338. else
  339. {
  340. m_workgroupSizes[i] = input[i];
  341. }
  342. }
  343. return Error::kNone;
  344. }
  345. Error setCounts(U32 uniformBlockCount, U32 storageBlockCount, U32 opaqueCount, Bool pushConstantBlock,
  346. U32 constCount, U32 structCount) final
  347. {
  348. m_blockInstances[0].create(uniformBlockCount);
  349. m_blockInstances[1].create(storageBlockCount);
  350. if(pushConstantBlock)
  351. {
  352. m_blockInstances[2].create(1);
  353. }
  354. m_opaqueInstances.create(opaqueCount);
  355. m_constInstances.create(constCount);
  356. m_structInstances.create(structCount);
  357. m_structMemberInstances.create(structCount, {m_pool});
  358. return Error::kNone;
  359. }
  360. Error visitUniformBlock(U32 idx, CString name, U32 set, U32 binding, U32 size, U32 varCount) final
  361. {
  362. return visitAnyBlock(idx, name, set, binding, size, varCount, 0);
  363. }
  364. Error visitUniformVariable(U32 blockIdx, U32 idx, CString name, ShaderVariableDataType type,
  365. const ShaderVariableBlockInfo& blockInfo) final
  366. {
  367. return visitAnyVariable(blockIdx, idx, name, type, blockInfo, 0);
  368. }
  369. Error visitStorageBlock(U32 idx, CString name, U32 set, U32 binding, U32 size, U32 varCount) final
  370. {
  371. return visitAnyBlock(idx, name, set, binding, size, varCount, 1);
  372. }
  373. Error visitStorageVariable(U32 blockIdx, U32 idx, CString name, ShaderVariableDataType type,
  374. const ShaderVariableBlockInfo& blockInfo) final
  375. {
  376. return visitAnyVariable(blockIdx, idx, name, type, blockInfo, 1);
  377. }
  378. Error visitPushConstantsBlock(CString name, U32 size, U32 varCount) final
  379. {
  380. return visitAnyBlock(0, name, 0, 0, size, varCount, 2);
  381. }
  382. Error visitPushConstant(U32 idx, CString name, ShaderVariableDataType type,
  383. const ShaderVariableBlockInfo& blockInfo) final
  384. {
  385. return visitAnyVariable(0, idx, name, type, blockInfo, 2);
  386. }
  387. Error visitOpaque(U32 instanceIdx, CString name, ShaderVariableDataType type, U32 set, U32 binding,
  388. U32 arraySize) final
  389. {
  390. // Find the opaque
  391. U32 opaqueIdx = kMaxU32;
  392. for(U32 i = 0; i < m_opaque.getSize(); ++i)
  393. {
  394. if(name == m_opaque[i].m_name.getBegin())
  395. {
  396. if(type != m_opaque[i].m_type || set != m_opaque[i].m_set || binding != m_opaque[i].m_binding)
  397. {
  398. ANKI_SHADER_COMPILER_LOGE(
  399. "The set, binding and type can't difer between shader variants for opaque: %s", name.cstr());
  400. return Error::kUserData;
  401. }
  402. opaqueIdx = i;
  403. break;
  404. }
  405. }
  406. // Create the opaque
  407. if(opaqueIdx == kMaxU32)
  408. {
  409. ShaderProgramBinaryOpaque& o = *m_opaque.emplaceBack();
  410. ANKI_CHECK(setName(name, o.m_name));
  411. o.m_type = type;
  412. o.m_binding = binding;
  413. o.m_set = set;
  414. opaqueIdx = m_opaque.getSize() - 1;
  415. }
  416. // Create the instance
  417. ShaderProgramBinaryOpaqueInstance& instance = m_opaqueInstances[instanceIdx];
  418. instance.m_index = opaqueIdx;
  419. instance.m_arraySize = arraySize;
  420. return Error::kNone;
  421. }
  422. Bool skipSymbol(CString symbol) const final
  423. {
  424. Bool skip = true;
  425. for(const String& s : *m_symbolsToReflect)
  426. {
  427. if(symbol == s)
  428. {
  429. skip = false;
  430. break;
  431. }
  432. }
  433. return skip;
  434. }
  435. Error visitConstant(U32 instanceIdx, CString name, ShaderVariableDataType type, U32 constantId) final
  436. {
  437. // Find const
  438. U32 constIdx = kMaxU32;
  439. for(U32 i = 0; i < m_consts.getSize(); ++i)
  440. {
  441. if(name == m_consts[i].m_name.getBegin())
  442. {
  443. if(type != m_consts[i].m_type || constantId != m_consts[i].m_constantId)
  444. {
  445. ANKI_SHADER_COMPILER_LOGE(
  446. "The type, constantId and stages can't difer between shader variants for const: %s",
  447. name.cstr());
  448. return Error::kUserData;
  449. }
  450. constIdx = i;
  451. break;
  452. }
  453. }
  454. // Create the const
  455. if(constIdx == kMaxU32)
  456. {
  457. ShaderProgramBinaryConstant& c = *m_consts.emplaceBack();
  458. ANKI_CHECK(setName(name, c.m_name));
  459. c.m_type = type;
  460. c.m_constantId = constantId;
  461. constIdx = m_consts.getSize() - 1;
  462. }
  463. // Create the instance
  464. ShaderProgramBinaryConstantInstance& instance = m_constInstances[instanceIdx];
  465. instance.m_index = constIdx;
  466. return Error::kNone;
  467. }
  468. [[nodiscard]] Bool findStruct(CString name, U32& idx) const
  469. {
  470. idx = kMaxU32;
  471. for(U32 i = 0; i < m_structs.getSize(); ++i)
  472. {
  473. const ShaderProgramBinaryStruct& s = m_structs[i];
  474. if(s.m_name.getBegin() == name)
  475. {
  476. idx = i;
  477. break;
  478. }
  479. }
  480. return idx != kMaxU32;
  481. }
  482. Error visitStruct(U32 instanceIdx, CString name, U32 memberCount, U32 size) final
  483. {
  484. ANKI_ASSERT(size && memberCount);
  485. // Init the struct
  486. U32 structIdx;
  487. const Bool structFound = findStruct(name, structIdx);
  488. if(!structFound)
  489. {
  490. // Create a new struct
  491. structIdx = m_structs.getSize();
  492. ShaderProgramBinaryStruct& s = *m_structs.emplaceBack();
  493. ANKI_CHECK(setName(name, s.m_name));
  494. // Allocate members
  495. m_structMembers.emplaceBack(m_pool);
  496. ANKI_ASSERT(m_structs.getSize() == m_structMembers.getSize());
  497. }
  498. // Create the instance
  499. ShaderProgramBinaryStructInstance& instance = m_structInstances[instanceIdx];
  500. instance.m_index = structIdx;
  501. instance.m_size = size;
  502. m_structMemberInstances[instanceIdx].create(memberCount);
  503. return Error::kNone;
  504. }
  505. Error visitStructMember(U32 structInstanceIdx, CString structName, U32 memberInstanceIdx, CString memberName,
  506. ShaderVariableDataType type, CString typeStructName, U32 offset, U32 arraySize) final
  507. {
  508. // Refresh the structIdx because we have a different global mapping
  509. U32 realStructIdx;
  510. [[maybe_unused]] const Bool structFound = findStruct(structName, realStructIdx);
  511. ANKI_ASSERT(structFound);
  512. const ShaderProgramBinaryStruct& s = m_structs[realStructIdx];
  513. DynamicArrayRaii<ShaderProgramBinaryStructMember>& members = m_structMembers[realStructIdx];
  514. // Find member
  515. U32 realMemberIdx = kMaxU32;
  516. for(U32 i = 0; i < members.getSize(); ++i)
  517. {
  518. if(memberName == &members[i].m_name[0])
  519. {
  520. if(members[i].m_type != type)
  521. {
  522. ANKI_SHADER_COMPILER_LOGE("Member %s of struct %s has different type between variants",
  523. memberName.cstr(), &s.m_name[0]);
  524. return Error::kUserData;
  525. }
  526. realMemberIdx = i;
  527. break;
  528. }
  529. }
  530. // If member not found in some previous variant create it
  531. if(realMemberIdx == kMaxU32)
  532. {
  533. realMemberIdx = members.getSize();
  534. ShaderProgramBinaryStructMember& member = *members.emplaceBack();
  535. ANKI_CHECK(setName(memberName, member.m_name));
  536. member.m_type = type;
  537. if(type == ShaderVariableDataType::kNone)
  538. {
  539. // Type is a struct, find the right index
  540. [[maybe_unused]] const Bool structFound = findStruct(typeStructName, member.m_structIndex);
  541. ANKI_ASSERT(structFound);
  542. }
  543. }
  544. // Update the instance
  545. ShaderProgramBinaryStructMemberInstance& memberInstance =
  546. m_structMemberInstances[structInstanceIdx][memberInstanceIdx];
  547. memberInstance.m_index = realMemberIdx;
  548. memberInstance.m_arraySize = arraySize;
  549. memberInstance.m_offset = offset;
  550. return Error::kNone;
  551. }
  552. static Error setName(CString in, Array<char, kMaxShaderBinaryNameLength + 1>& out)
  553. {
  554. if(in.getLength() + 1 > kMaxShaderBinaryNameLength)
  555. {
  556. ANKI_SHADER_COMPILER_LOGE("Name too long: %s", in.cstr());
  557. return Error::kUserData;
  558. }
  559. else if(in.getLength() == 0)
  560. {
  561. ANKI_SHADER_COMPILER_LOGE("Found an empty string as name");
  562. return Error::kUserData;
  563. }
  564. else
  565. {
  566. memcpy(out.getBegin(), in.getBegin(), in.getLength() + 1);
  567. }
  568. return Error::kNone;
  569. }
  570. static Error findBlock(CString name, U32 set, U32 binding, ConstWeakArray<ShaderProgramBinaryBlock> arr, U32& idx)
  571. {
  572. idx = kMaxU32;
  573. for(U32 i = 0; i < arr.getSize(); ++i)
  574. {
  575. const ShaderProgramBinaryBlock& block = arr[i];
  576. if(block.m_name.getBegin() == name)
  577. {
  578. if(set != block.m_set || binding != block.m_binding)
  579. {
  580. ANKI_SHADER_COMPILER_LOGE("The set and binding can't difer between shader variants for block: %s",
  581. name.cstr());
  582. return Error::kUserData;
  583. }
  584. idx = i;
  585. break;
  586. }
  587. }
  588. return Error::kNone;
  589. }
  590. Error visitAnyBlock(U32 blockInstanceIdx, CString name, U32 set, U32 binding, U32 size, U32 varSize, U32 blockType)
  591. {
  592. // Init the block
  593. U32 blockIdx;
  594. ANKI_CHECK(findBlock(name, set, binding, m_blocks[blockType], blockIdx));
  595. if(blockIdx == kMaxU32)
  596. {
  597. // Not found, create it
  598. ShaderProgramBinaryBlock& block = *m_blocks[blockType].emplaceBack();
  599. ANKI_CHECK(setName(name, block.m_name));
  600. block.m_set = set;
  601. block.m_binding = binding;
  602. blockIdx = m_blocks[blockType].getSize() - 1;
  603. // Create some storage for vars as well
  604. m_vars[blockType].emplaceBack(m_pool);
  605. ANKI_ASSERT(m_vars[blockType].getSize() == m_blocks[blockType].getSize());
  606. }
  607. // Init the instance
  608. ShaderProgramBinaryBlockInstance& instance = m_blockInstances[blockType][blockInstanceIdx];
  609. instance.m_index = blockIdx;
  610. instance.m_size = size;
  611. newArray(*m_pool, varSize, instance.m_variableInstances);
  612. return Error::kNone;
  613. }
  614. Error visitAnyVariable(U32 blockInstanceIdx, U32 varInstanceIdx, CString name, ShaderVariableDataType type,
  615. const ShaderVariableBlockInfo& blockInfo, U32 blockType)
  616. {
  617. // Find the variable
  618. U32 varIdx = kMaxU32;
  619. const U32 blockIdx = m_blockInstances[blockType][blockInstanceIdx].m_index;
  620. for(U32 i = 0; i < m_vars[blockType][blockIdx].getSize(); ++i)
  621. {
  622. const ShaderProgramBinaryVariable& var = m_vars[blockType][blockIdx][i];
  623. if(var.m_name.getBegin() == name)
  624. {
  625. if(var.m_type != type)
  626. {
  627. ANKI_SHADER_COMPILER_LOGE("The type should not differ between variants for variable: %s",
  628. name.cstr());
  629. return Error::kUserData;
  630. }
  631. varIdx = i;
  632. break;
  633. }
  634. }
  635. // Create the variable
  636. if(varIdx == kMaxU32)
  637. {
  638. ShaderProgramBinaryVariable& var = *m_vars[blockType][blockIdx].emplaceBack();
  639. ANKI_CHECK(setName(name, var.m_name));
  640. var.m_type = type;
  641. varIdx = m_vars[blockType][blockIdx].getSize() - 1;
  642. }
  643. // Init the instance
  644. ShaderProgramBinaryVariableInstance& instance =
  645. m_blockInstances[blockType][blockInstanceIdx].m_variableInstances[varInstanceIdx];
  646. instance.m_blockInfo = blockInfo;
  647. instance.m_index = varIdx;
  648. return Error::kNone;
  649. }
  650. };
  651. static Error doGhostStructReflection(const StringList& symbolsToReflect,
  652. ConstWeakArray<ShaderProgramParserGhostStruct> ghostStructs,
  653. ShaderProgramBinary& binary, BaseMemoryPool& tmpPool, BaseMemoryPool& binaryPool)
  654. {
  655. // Count reflectable ghost structs
  656. DynamicArrayRaii<U32> ghostStructIndices(&tmpPool);
  657. for(U32 i = 0; i < ghostStructs.getSize(); ++i)
  658. {
  659. for(const String& s : symbolsToReflect)
  660. {
  661. if(s == ghostStructs[i].m_name)
  662. {
  663. ghostStructIndices.emplaceBack(i);
  664. break;
  665. }
  666. }
  667. }
  668. if(ghostStructIndices.getSize() == 0)
  669. {
  670. return Error::kNone;
  671. }
  672. // Add the ghost structs to binary structs
  673. const U32 nonGhostStructCount = binary.m_structs.getSize();
  674. DynamicArrayRaii<ShaderProgramBinaryStruct> structs(&binaryPool,
  675. nonGhostStructCount + ghostStructIndices.getSize());
  676. for(U32 i = 0; i < binary.m_structs.getSize(); ++i)
  677. {
  678. structs[i] = binary.m_structs[i];
  679. }
  680. for(U32 i = 0; i < ghostStructIndices.getSize(); ++i)
  681. {
  682. const ShaderProgramParserGhostStruct& in = ghostStructs[ghostStructIndices[i]];
  683. ShaderProgramBinaryStruct& out = structs[nonGhostStructCount + i];
  684. ANKI_CHECK(Refl::setName(in.m_name, out.m_name));
  685. DynamicArrayRaii<ShaderProgramBinaryStructMember> members(&binaryPool, in.m_members.getSize());
  686. for(U32 j = 0; j < in.m_members.getSize(); ++j)
  687. {
  688. const ShaderProgramParserMember& inMember = in.m_members[j];
  689. ShaderProgramBinaryStructMember& outMember = members[j];
  690. ANKI_CHECK(Refl::setName(inMember.m_name, outMember.m_name));
  691. outMember.m_type = inMember.m_type;
  692. outMember.m_dependentMutator = inMember.m_dependentMutator;
  693. outMember.m_dependentMutatorValue = inMember.m_mutatorValue;
  694. }
  695. members.moveAndReset(out.m_members);
  696. }
  697. deleteArray(binaryPool, binary.m_structs);
  698. structs.moveAndReset(binary.m_structs);
  699. return Error::kNone;
  700. }
  701. static Error doReflection(const StringList& symbolsToReflect, ShaderProgramBinary& binary, BaseMemoryPool& tmpPool,
  702. BaseMemoryPool& binaryPool)
  703. {
  704. ANKI_ASSERT(binary.m_variants.getSize() > 0);
  705. Refl refl(&binaryPool, &symbolsToReflect);
  706. for(ShaderProgramBinaryVariant& variant : binary.m_variants)
  707. {
  708. Array<ConstWeakArray<U8>, U32(ShaderType::kCount)> spirvs;
  709. for(ShaderType stage : EnumIterable<ShaderType>())
  710. {
  711. if(variant.m_codeBlockIndices[stage] != kMaxU32)
  712. {
  713. spirvs[stage] = binary.m_codeBlocks[variant.m_codeBlockIndices[stage]].m_binary;
  714. }
  715. }
  716. ANKI_CHECK(performSpirvReflection(spirvs, tmpPool, refl));
  717. // Store the instances
  718. if(refl.m_blockInstances[0].getSize())
  719. {
  720. ShaderProgramBinaryBlockInstance* instances;
  721. U32 size, storageSize;
  722. refl.m_blockInstances[0].moveAndReset(instances, size, storageSize);
  723. variant.m_uniformBlocks.setArray(instances, size);
  724. }
  725. if(refl.m_blockInstances[1].getSize())
  726. {
  727. ShaderProgramBinaryBlockInstance* instances;
  728. U32 size, storageSize;
  729. refl.m_blockInstances[1].moveAndReset(instances, size, storageSize);
  730. variant.m_storageBlocks.setArray(instances, size);
  731. }
  732. if(refl.m_blockInstances[2].getSize())
  733. {
  734. ShaderProgramBinaryBlockInstance* instances;
  735. U32 size, storageSize;
  736. refl.m_blockInstances[2].moveAndReset(instances, size, storageSize);
  737. ANKI_ASSERT(size == 1);
  738. variant.m_pushConstantBlock = instances;
  739. }
  740. if(refl.m_opaqueInstances.getSize())
  741. {
  742. ShaderProgramBinaryOpaqueInstance* instances;
  743. U32 size, storageSize;
  744. refl.m_opaqueInstances.moveAndReset(instances, size, storageSize);
  745. variant.m_opaques.setArray(instances, size);
  746. }
  747. if(refl.m_constInstances.getSize())
  748. {
  749. ShaderProgramBinaryConstantInstance* instances;
  750. U32 size, storageSize;
  751. refl.m_constInstances.moveAndReset(instances, size, storageSize);
  752. variant.m_constants.setArray(instances, size);
  753. }
  754. if(refl.m_structInstances.getSize())
  755. {
  756. ShaderProgramBinaryStructInstance* instances;
  757. U32 size, storageSize;
  758. refl.m_structInstances.moveAndReset(instances, size, storageSize);
  759. variant.m_structs.setArray(instances, size);
  760. for(U32 structIdx = 0; structIdx < refl.m_structMemberInstances.getSize(); ++structIdx)
  761. {
  762. ShaderProgramBinaryStructMemberInstance* memberInstances;
  763. refl.m_structMemberInstances[structIdx].moveAndReset(memberInstances, size, storageSize);
  764. variant.m_structs[structIdx].m_memberInstances.setArray(memberInstances, size);
  765. }
  766. }
  767. refl.m_structMemberInstances.destroy();
  768. variant.m_workgroupSizes = refl.m_workgroupSizes;
  769. variant.m_workgroupSizesConstants = refl.m_workgroupSizesConstants;
  770. }
  771. if(refl.m_blocks[0].getSize())
  772. {
  773. ShaderProgramBinaryBlock* blocks;
  774. U32 size, storageSize;
  775. refl.m_blocks[0].moveAndReset(blocks, size, storageSize);
  776. binary.m_uniformBlocks.setArray(blocks, size);
  777. for(U32 i = 0; i < size; ++i)
  778. {
  779. ShaderProgramBinaryVariable* vars;
  780. U32 varSize, varStorageSize;
  781. refl.m_vars[0][i].moveAndReset(vars, varSize, varStorageSize);
  782. binary.m_uniformBlocks[i].m_variables.setArray(vars, varSize);
  783. }
  784. }
  785. if(refl.m_blocks[1].getSize())
  786. {
  787. ShaderProgramBinaryBlock* blocks;
  788. U32 size, storageSize;
  789. refl.m_blocks[1].moveAndReset(blocks, size, storageSize);
  790. binary.m_storageBlocks.setArray(blocks, size);
  791. for(U32 i = 0; i < size; ++i)
  792. {
  793. ShaderProgramBinaryVariable* vars;
  794. U32 varSize, varStorageSize;
  795. refl.m_vars[1][i].moveAndReset(vars, varSize, varStorageSize);
  796. binary.m_storageBlocks[i].m_variables.setArray(vars, varSize);
  797. }
  798. }
  799. if(refl.m_blocks[2].getSize())
  800. {
  801. ShaderProgramBinaryBlock* blocks;
  802. U32 size, storageSize;
  803. refl.m_blocks[2].moveAndReset(blocks, size, storageSize);
  804. ANKI_ASSERT(size == 1);
  805. binary.m_pushConstantBlock = blocks;
  806. ShaderProgramBinaryVariable* vars;
  807. U32 varSize, varStorageSize;
  808. refl.m_vars[2][0].moveAndReset(vars, varSize, varStorageSize);
  809. binary.m_pushConstantBlock->m_variables.setArray(vars, varSize);
  810. }
  811. if(refl.m_opaque.getSize())
  812. {
  813. ShaderProgramBinaryOpaque* opaques;
  814. U32 size, storageSize;
  815. refl.m_opaque.moveAndReset(opaques, size, storageSize);
  816. binary.m_opaques.setArray(opaques, size);
  817. }
  818. if(refl.m_consts.getSize())
  819. {
  820. ShaderProgramBinaryConstant* consts;
  821. U32 size, storageSize;
  822. refl.m_consts.moveAndReset(consts, size, storageSize);
  823. binary.m_constants.setArray(consts, size);
  824. }
  825. if(refl.m_structs.getSize())
  826. {
  827. ShaderProgramBinaryStruct* storage;
  828. U32 size, storageSize;
  829. refl.m_structs.moveAndReset(storage, size, storageSize);
  830. binary.m_structs.setArray(storage, size);
  831. for(U32 i = 0; i < size; ++i)
  832. {
  833. ShaderProgramBinaryStructMember* memberStorage;
  834. U32 memberSize, memberStorageSize;
  835. refl.m_structMembers[i].moveAndReset(memberStorage, memberSize, memberStorageSize);
  836. binary.m_structs[i].m_members.setArray(memberStorage, memberSize);
  837. }
  838. }
  839. return Error::kNone;
  840. }
  841. Error compileShaderProgramInternal(CString fname, ShaderProgramFilesystemInterface& fsystem,
  842. ShaderProgramPostParseInterface* postParseCallback,
  843. ShaderProgramAsyncTaskInterface* taskManager_, BaseMemoryPool& tempPool,
  844. const ShaderCompilerOptions& compilerOptions, ShaderProgramBinaryWrapper& binaryW)
  845. {
  846. // Initialize the binary
  847. binaryW.cleanup();
  848. binaryW.m_singleAllocation = false;
  849. BaseMemoryPool& binaryPool = *binaryW.m_pool;
  850. binaryW.m_binary = newInstance<ShaderProgramBinary>(binaryPool);
  851. ShaderProgramBinary& binary = *binaryW.m_binary;
  852. binary = {};
  853. memcpy(&binary.m_magic[0], kShaderBinaryMagic, 8);
  854. // Parse source
  855. ShaderProgramParser parser(fname, &fsystem, &tempPool, compilerOptions);
  856. ANKI_CHECK(parser.parse());
  857. if(postParseCallback && postParseCallback->skipCompilation(parser.getHash()))
  858. {
  859. return Error::kNone;
  860. }
  861. // Get mutators
  862. U32 mutationCount = 0;
  863. if(parser.getMutators().getSize() > 0)
  864. {
  865. newArray(binaryPool, parser.getMutators().getSize(), binary.m_mutators);
  866. for(U32 i = 0; i < binary.m_mutators.getSize(); ++i)
  867. {
  868. ShaderProgramBinaryMutator& out = binary.m_mutators[i];
  869. const ShaderProgramParserMutator& in = parser.getMutators()[i];
  870. ANKI_CHECK(Refl::setName(in.getName(), out.m_name));
  871. newArray(binaryPool, in.getValues().getSize(), out.m_values);
  872. memcpy(out.m_values.getBegin(), in.getValues().getBegin(), in.getValues().getSizeInBytes());
  873. // Update the count
  874. mutationCount = (i == 0) ? out.m_values.getSize() : mutationCount * out.m_values.getSize();
  875. }
  876. }
  877. else
  878. {
  879. ANKI_ASSERT(binary.m_mutators.getSize() == 0);
  880. }
  881. // Create all variants
  882. Mutex mtx;
  883. Atomic<I32> errorAtomic(0);
  884. class SyncronousShaderProgramAsyncTaskInterface : public ShaderProgramAsyncTaskInterface
  885. {
  886. public:
  887. void enqueueTask(void (*callback)(void* userData), void* userData) final
  888. {
  889. callback(userData);
  890. }
  891. Error joinTasks() final
  892. {
  893. // Nothing
  894. return Error::kNone;
  895. }
  896. } syncTaskManager;
  897. ShaderProgramAsyncTaskInterface& taskManager = (taskManager_) ? *taskManager_ : syncTaskManager;
  898. if(parser.getMutators().getSize() > 0)
  899. {
  900. // Initialize
  901. DynamicArrayRaii<MutatorValue> mutationValues(&tempPool, parser.getMutators().getSize());
  902. DynamicArrayRaii<U32> dials(&tempPool, parser.getMutators().getSize(), 0);
  903. DynamicArrayRaii<ShaderProgramBinaryVariant> variants(&binaryPool);
  904. DynamicArrayRaii<ShaderProgramBinaryCodeBlock> codeBlocks(&binaryPool);
  905. DynamicArrayRaii<ShaderProgramBinaryMutation> mutations(&binaryPool, mutationCount);
  906. DynamicArrayRaii<U64> codeBlockHashes(&tempPool);
  907. HashMapRaii<U64, U32> mutationHashToIdx(&tempPool);
  908. // Grow the storage of the variants array. Can't have it resize, threads will work on stale data
  909. variants.resizeStorage(mutationCount);
  910. const ShaderProgramBinaryVariant* baseVariant = nullptr;
  911. mutationCount = 0;
  912. // Spin for all possible combinations of mutators and
  913. // - Create the spirv
  914. // - Populate the binary variant
  915. do
  916. {
  917. // Create the mutation
  918. for(U32 i = 0; i < parser.getMutators().getSize(); ++i)
  919. {
  920. mutationValues[i] = parser.getMutators()[i].getValues()[dials[i]];
  921. }
  922. ShaderProgramBinaryMutation& mutation = mutations[mutationCount++];
  923. newArray(binaryPool, mutationValues.getSize(), mutation.m_values);
  924. memcpy(mutation.m_values.getBegin(), mutationValues.getBegin(), mutationValues.getSizeInBytes());
  925. mutation.m_hash = computeHash(mutationValues.getBegin(), mutationValues.getSizeInBytes());
  926. ANKI_ASSERT(mutation.m_hash > 0);
  927. if(parser.skipMutation(mutationValues))
  928. {
  929. mutation.m_variantIndex = kMaxU32;
  930. }
  931. else
  932. {
  933. // New and unique mutation and thus variant, add it
  934. ShaderProgramBinaryVariant& variant = *variants.emplaceBack();
  935. baseVariant = (baseVariant == nullptr) ? variants.getBegin() : baseVariant;
  936. compileVariantAsync(mutationValues, parser, variant, codeBlocks, codeBlockHashes, tempPool, binaryPool,
  937. taskManager, mtx, errorAtomic);
  938. mutation.m_variantIndex = variants.getSize() - 1;
  939. ANKI_ASSERT(mutationHashToIdx.find(mutation.m_hash) == mutationHashToIdx.getEnd());
  940. mutationHashToIdx.emplace(mutation.m_hash, mutationCount - 1);
  941. }
  942. } while(!spinDials(dials, parser.getMutators()));
  943. ANKI_ASSERT(mutationCount == mutations.getSize());
  944. ANKI_ASSERT(baseVariant == variants.getBegin() && "Can't have the variants array grow");
  945. // Done, wait the threads
  946. ANKI_CHECK(taskManager.joinTasks());
  947. ANKI_CHECK(Error(errorAtomic.getNonAtomically()));
  948. // Store temp containers to binary
  949. U32 size, storage;
  950. ShaderProgramBinaryVariant* firstVariant;
  951. variants.moveAndReset(firstVariant, size, storage);
  952. binary.m_variants.setArray(firstVariant, size);
  953. ShaderProgramBinaryCodeBlock* firstCodeBlock;
  954. codeBlocks.moveAndReset(firstCodeBlock, size, storage);
  955. binary.m_codeBlocks.setArray(firstCodeBlock, size);
  956. ShaderProgramBinaryMutation* firstMutation;
  957. mutations.moveAndReset(firstMutation, size, storage);
  958. binary.m_mutations.setArray(firstMutation, size);
  959. }
  960. else
  961. {
  962. DynamicArrayRaii<MutatorValue> mutation(&tempPool);
  963. DynamicArrayRaii<ShaderProgramBinaryCodeBlock> codeBlocks(&binaryPool);
  964. DynamicArrayRaii<U64> codeBlockHashes(&tempPool);
  965. binary.m_variants.setArray(newInstance<ShaderProgramBinaryVariant>(binaryPool), 1);
  966. compileVariantAsync(mutation, parser, binary.m_variants[0], codeBlocks, codeBlockHashes, tempPool, binaryPool,
  967. taskManager, mtx, errorAtomic);
  968. ANKI_CHECK(taskManager.joinTasks());
  969. ANKI_CHECK(Error(errorAtomic.getNonAtomically()));
  970. ANKI_ASSERT(codeBlocks.getSize() == U32(__builtin_popcount(U32(parser.getShaderTypes()))));
  971. ShaderProgramBinaryCodeBlock* firstCodeBlock;
  972. U32 size, storage;
  973. codeBlocks.moveAndReset(firstCodeBlock, size, storage);
  974. binary.m_codeBlocks.setArray(firstCodeBlock, size);
  975. binary.m_mutations.setArray(newInstance<ShaderProgramBinaryMutation>(binaryPool), 1);
  976. binary.m_mutations[0].m_hash = 1;
  977. binary.m_mutations[0].m_variantIndex = 0;
  978. }
  979. // Sort the mutations
  980. std::sort(binary.m_mutations.getBegin(), binary.m_mutations.getEnd(),
  981. [](const ShaderProgramBinaryMutation& a, const ShaderProgramBinaryMutation& b) {
  982. return a.m_hash < b.m_hash;
  983. });
  984. // Lib name
  985. if(parser.getLibraryName().getLength() > 0)
  986. {
  987. if(parser.getLibraryName().getLength() >= sizeof(binary.m_libraryName))
  988. {
  989. ANKI_SHADER_COMPILER_LOGE("Library name too long: %s", parser.getLibraryName().cstr());
  990. return Error::kUserData;
  991. }
  992. memcpy(&binary.m_libraryName[0], &parser.getLibraryName()[0], parser.getLibraryName().getLength());
  993. }
  994. binary.m_rayType = parser.getRayType();
  995. // Misc
  996. binary.m_presentShaderTypes = parser.getShaderTypes();
  997. // Reflection
  998. ANKI_CHECK(doReflection(parser.getSymbolsToReflect(), binary, tempPool, binaryPool));
  999. ANKI_CHECK(
  1000. doGhostStructReflection(parser.getSymbolsToReflect(), parser.getGhostStructs(), binary, tempPool, binaryPool));
  1001. return Error::kNone;
  1002. }
  1003. Error compileShaderProgram(CString fname, ShaderProgramFilesystemInterface& fsystem,
  1004. ShaderProgramPostParseInterface* postParseCallback,
  1005. ShaderProgramAsyncTaskInterface* taskManager, BaseMemoryPool& tempPool,
  1006. const ShaderCompilerOptions& compilerOptions, ShaderProgramBinaryWrapper& binaryW)
  1007. {
  1008. const Error err = compileShaderProgramInternal(fname, fsystem, postParseCallback, taskManager, tempPool,
  1009. compilerOptions, binaryW);
  1010. if(err)
  1011. {
  1012. ANKI_SHADER_COMPILER_LOGE("Failed to compile: %s", fname.cstr());
  1013. }
  1014. return err;
  1015. }
  1016. } // end namespace anki