ShaderProgramCompiler.cpp 35 KB

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