MaterialResource.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. // Copyright (C) 2009-present, 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/Resource/MaterialResource.h>
  6. #include <AnKi/Resource/ResourceManager.h>
  7. #include <AnKi/Resource/ImageResource.h>
  8. #include <AnKi/Core/App.h>
  9. #include <AnKi/Util/Xml.h>
  10. namespace anki {
  11. inline constexpr Array<CString, U32(BuiltinMutatorId::kCount)> kBuiltinMutatorNames = {{"NONE", "ANKI_BONES", "ANKI_VELOCITY"}};
  12. // This is some trickery to select calling between XmlElement::getAttributeNumber and XmlElement::getAttributeNumbers
  13. namespace {
  14. template<typename T>
  15. class IsShaderVarDataTypeAnArray
  16. {
  17. public:
  18. static constexpr Bool kValue = false;
  19. };
  20. #define ANKI_SVDT_MACRO(type, baseType, rowCount, columnCount, isIntagralType) \
  21. template<> \
  22. class IsShaderVarDataTypeAnArray<type> \
  23. { \
  24. public: \
  25. static constexpr Bool kValue = rowCount * columnCount > 1; \
  26. };
  27. #include <AnKi/Gr/ShaderVariableDataType.def.h>
  28. template<typename T, Bool isArray = IsShaderVarDataTypeAnArray<T>::kValue>
  29. class GetAttribute
  30. {
  31. public:
  32. Error operator()(const XmlElement& el, T& out)
  33. {
  34. return el.getAttributeNumbers("value", out);
  35. }
  36. };
  37. template<typename T>
  38. class GetAttribute<T, false>
  39. {
  40. public:
  41. Error operator()(const XmlElement& el, T& out)
  42. {
  43. return el.getAttributeNumber("value", out);
  44. }
  45. };
  46. } // namespace
  47. static Bool mutatorValueExists(const ShaderBinaryMutator& m, MutatorValue val)
  48. {
  49. for(MutatorValue v : m.m_values)
  50. {
  51. if(v == val)
  52. {
  53. return true;
  54. }
  55. }
  56. return false;
  57. }
  58. MaterialVariable::MaterialVariable()
  59. {
  60. m_Mat4 = Mat4::getZero();
  61. }
  62. MaterialVariable::~MaterialVariable()
  63. {
  64. }
  65. MaterialResource::~MaterialResource()
  66. {
  67. ResourceMemoryPool::getSingleton().free(m_prefilledLocalConstants);
  68. }
  69. const MaterialVariable* MaterialResource::tryFindVariableInternal(CString name) const
  70. {
  71. for(const MaterialVariable& v : m_vars)
  72. {
  73. if(v.m_name == name)
  74. {
  75. return &v;
  76. }
  77. }
  78. return nullptr;
  79. }
  80. Error MaterialResource::load(const ResourceFilename& filename, Bool async)
  81. {
  82. ResourceXmlDocument doc;
  83. XmlElement el;
  84. ANKI_CHECK(openFileParseXml(filename, doc));
  85. // <material>
  86. XmlElement rootEl;
  87. ANKI_CHECK(doc.getChildElement("material", rootEl));
  88. // <shaderPrograms>
  89. XmlElement shaderProgramEl;
  90. ANKI_CHECK(rootEl.getChildElement("shaderProgram", shaderProgramEl));
  91. ANKI_CHECK(parseShaderProgram(shaderProgramEl, async));
  92. ANKI_ASSERT(!!m_techniquesMask);
  93. // <inputs>
  94. BitSet<128> varsSet(false);
  95. ANKI_CHECK(rootEl.getChildElementOptional("inputs", el));
  96. if(el)
  97. {
  98. XmlElement inputEl;
  99. ANKI_CHECK(el.getChildElement("input", inputEl));
  100. do
  101. {
  102. ANKI_CHECK(parseInput(inputEl, async, varsSet));
  103. ANKI_CHECK(inputEl.getNextSiblingElement("input", inputEl));
  104. } while(inputEl);
  105. }
  106. if(varsSet.getSetBitCount() != m_vars.getSize())
  107. {
  108. ANKI_RESOURCE_LOGV("Material doesn't contain default value for %u input variables", U32(m_vars.getSize() - varsSet.getSetBitCount()));
  109. // Remove unreferenced variables
  110. ResourceDynamicArray<MaterialVariable> newVars;
  111. for(U32 i = 0; i < m_vars.getSize(); ++i)
  112. {
  113. if(varsSet.get(i))
  114. {
  115. newVars.emplaceBack(std::move(m_vars[i]));
  116. }
  117. }
  118. m_vars = std::move(newVars);
  119. }
  120. prefillLocalConstants();
  121. return Error::kNone;
  122. }
  123. Error MaterialResource::parseShaderProgram(XmlElement shaderProgramEl, Bool async)
  124. {
  125. // name
  126. CString shaderName;
  127. ANKI_CHECK(shaderProgramEl.getAttributeText("name", shaderName));
  128. ResourceString fname;
  129. fname.sprintf("ShaderBinaries/%s.ankiprogbin", shaderName.cstr());
  130. ANKI_CHECK(ResourceManager::getSingleton().loadResource(fname, m_prog, async));
  131. // Find present techniques
  132. for(const ShaderBinaryTechnique& t : m_prog->getBinary().m_techniques)
  133. {
  134. if(t.m_name.getBegin() == CString("GBufferLegacy"))
  135. {
  136. m_techniquesMask |= RenderingTechniqueBit::kGBuffer;
  137. m_shaderTechniques |= ShaderTechniqueBit::kLegacy;
  138. }
  139. else if(t.m_name.getBegin() == CString("GBufferMeshShaders"))
  140. {
  141. m_techniquesMask |= RenderingTechniqueBit::kGBuffer;
  142. m_shaderTechniques |= ShaderTechniqueBit::kMeshSaders;
  143. }
  144. else if(t.m_name.getBegin() == CString("GBufferSwMeshletRendering"))
  145. {
  146. m_techniquesMask |= RenderingTechniqueBit::kGBuffer;
  147. m_shaderTechniques |= ShaderTechniqueBit::kSwMeshletRendering;
  148. }
  149. else if(t.m_name.getBegin() == CString("ShadowsLegacy"))
  150. {
  151. m_techniquesMask |= RenderingTechniqueBit::kDepth;
  152. m_shaderTechniques |= ShaderTechniqueBit::kLegacy;
  153. }
  154. else if(t.m_name.getBegin() == CString("ShadowsMeshShaders"))
  155. {
  156. m_techniquesMask |= RenderingTechniqueBit::kDepth;
  157. m_shaderTechniques |= ShaderTechniqueBit::kMeshSaders;
  158. }
  159. else if(t.m_name.getBegin() == CString("ShadowsSwMeshletRendering"))
  160. {
  161. m_techniquesMask |= RenderingTechniqueBit::kDepth;
  162. m_shaderTechniques |= ShaderTechniqueBit::kSwMeshletRendering;
  163. }
  164. else if(t.m_name.getBegin() == CString("RtShadows"))
  165. {
  166. if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled)
  167. {
  168. m_techniquesMask |= RenderingTechniqueBit::kRtShadow;
  169. }
  170. }
  171. else if(t.m_name.getBegin() == CString("ForwardSwMeshletRendering"))
  172. {
  173. m_techniquesMask |= RenderingTechniqueBit::kForward;
  174. m_shaderTechniques |= ShaderTechniqueBit::kSwMeshletRendering;
  175. }
  176. else if(t.m_name.getBegin() == CString("ForwardMeshShaders"))
  177. {
  178. m_techniquesMask |= RenderingTechniqueBit::kForward;
  179. m_shaderTechniques |= ShaderTechniqueBit::kMeshSaders;
  180. }
  181. else if(t.m_name.getBegin() == CString("ForwardLegacy"))
  182. {
  183. m_techniquesMask |= RenderingTechniqueBit::kForward;
  184. m_shaderTechniques |= ShaderTechniqueBit::kLegacy;
  185. }
  186. else if(t.m_name.getBegin() == CString("RtMaterialFetch"))
  187. {
  188. if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled)
  189. {
  190. m_techniquesMask |= RenderingTechniqueBit::kRtMaterialFetch;
  191. }
  192. }
  193. else
  194. {
  195. ANKI_RESOURCE_LOGE("Found unneeded technique in the shader: %s", t.m_name.getBegin());
  196. return Error::kUserData;
  197. }
  198. }
  199. // <mutation>
  200. XmlElement mutatorsEl;
  201. ANKI_CHECK(shaderProgramEl.getChildElementOptional("mutation", mutatorsEl));
  202. if(mutatorsEl)
  203. {
  204. ANKI_CHECK(parseMutators(mutatorsEl));
  205. }
  206. // And find the builtin mutators
  207. ANKI_CHECK(findBuiltinMutators());
  208. // Create the vars
  209. ANKI_CHECK(createVars());
  210. return Error::kNone;
  211. }
  212. Error MaterialResource::parseMutators(XmlElement mutatorsEl)
  213. {
  214. XmlElement mutatorEl;
  215. ANKI_CHECK(mutatorsEl.getChildElement("mutator", mutatorEl));
  216. U32 mutatorCount = 0;
  217. ANKI_CHECK(mutatorEl.getSiblingElementsCount(mutatorCount));
  218. ++mutatorCount;
  219. ANKI_ASSERT(mutatorCount > 0);
  220. m_partialMutation.resize(mutatorCount);
  221. mutatorCount = 0;
  222. do
  223. {
  224. PartialMutation& pmutation = m_partialMutation[mutatorCount];
  225. // name
  226. CString mutatorName;
  227. ANKI_CHECK(mutatorEl.getAttributeText("name", mutatorName));
  228. if(mutatorName.isEmpty())
  229. {
  230. ANKI_RESOURCE_LOGE("Mutator name is empty");
  231. return Error::kUserData;
  232. }
  233. for(BuiltinMutatorId id : EnumIterable<BuiltinMutatorId>())
  234. {
  235. if(id == BuiltinMutatorId::kNone)
  236. {
  237. continue;
  238. }
  239. if(mutatorName == kBuiltinMutatorNames[id])
  240. {
  241. ANKI_RESOURCE_LOGE("Materials shouldn't list builtin mutators: %s", mutatorName.cstr());
  242. return Error::kUserData;
  243. }
  244. }
  245. if(mutatorName.find("ANKI_") == 0)
  246. {
  247. ANKI_RESOURCE_LOGE("Mutators can't start with ANKI_: %s", mutatorName.cstr());
  248. return Error::kUserData;
  249. }
  250. // value
  251. ANKI_CHECK(mutatorEl.getAttributeNumber("value", pmutation.m_value));
  252. // Find mutator
  253. pmutation.m_mutator = m_prog->tryFindMutator(mutatorName);
  254. if(!pmutation.m_mutator)
  255. {
  256. ANKI_RESOURCE_LOGE("Mutator not found in program %s", &mutatorName[0]);
  257. return Error::kUserData;
  258. }
  259. if(!mutatorValueExists(*pmutation.m_mutator, pmutation.m_value))
  260. {
  261. ANKI_RESOURCE_LOGE("Value %d is not part of the mutator %s", pmutation.m_value, mutatorName.cstr());
  262. return Error::kUserData;
  263. }
  264. // Advance
  265. ++mutatorCount;
  266. ANKI_CHECK(mutatorEl.getNextSiblingElement("mutator", mutatorEl));
  267. } while(mutatorEl);
  268. ANKI_ASSERT(mutatorCount == m_partialMutation.getSize());
  269. return Error::kNone;
  270. }
  271. Error MaterialResource::findBuiltinMutators()
  272. {
  273. U builtinMutatorCount = 0;
  274. // ANKI_BONES
  275. CString bonesMutatorName = kBuiltinMutatorNames[BuiltinMutatorId::kBones];
  276. const ShaderBinaryMutator* bonesMutator = m_prog->tryFindMutator(bonesMutatorName);
  277. if(bonesMutator)
  278. {
  279. if(bonesMutator->m_values.getSize() != 2)
  280. {
  281. ANKI_RESOURCE_LOGE("Mutator %s should have 2 values in the program", bonesMutatorName.cstr());
  282. return Error::kUserData;
  283. }
  284. for(U32 i = 0; i < bonesMutator->m_values.getSize(); ++i)
  285. {
  286. if(bonesMutator->m_values[i] != MutatorValue(i))
  287. {
  288. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected", bonesMutatorName.cstr());
  289. return Error::kUserData;
  290. }
  291. }
  292. ++builtinMutatorCount;
  293. m_supportsSkinning = true;
  294. m_presentBuildinMutatorMask |= U32(1 << BuiltinMutatorId::kBones);
  295. }
  296. // VELOCITY
  297. CString velocityMutatorName = kBuiltinMutatorNames[BuiltinMutatorId::kVelocity];
  298. const ShaderBinaryMutator* velocityMutator = m_prog->tryFindMutator(velocityMutatorName);
  299. if(velocityMutator)
  300. {
  301. if(velocityMutator->m_values.getSize() != 2)
  302. {
  303. ANKI_RESOURCE_LOGE("Mutator %s should have 2 values in the program", velocityMutatorName.cstr());
  304. return Error::kUserData;
  305. }
  306. for(U32 i = 0; i < velocityMutator->m_values.getSize(); ++i)
  307. {
  308. if(velocityMutator->m_values[i] != MutatorValue(i))
  309. {
  310. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected", velocityMutatorName.cstr());
  311. return Error::kUserData;
  312. }
  313. }
  314. ++builtinMutatorCount;
  315. m_presentBuildinMutatorMask |= U32(1 << BuiltinMutatorId::kVelocity);
  316. }
  317. if(m_partialMutation.getSize() + builtinMutatorCount != m_prog->getBinary().m_mutators.getSize())
  318. {
  319. ANKI_RESOURCE_LOGE("Some mutatators are unacounted for");
  320. return Error::kUserData;
  321. }
  322. return Error::kNone;
  323. }
  324. Error MaterialResource::createVars()
  325. {
  326. const ShaderBinary& binary = m_prog->getBinary();
  327. // Find struct
  328. const ShaderBinaryStruct* localConstantsStruct = nullptr;
  329. for(const ShaderBinaryStruct& strct : binary.m_structs)
  330. {
  331. if(CString(strct.m_name.getBegin()) == "AnKiLocalConstants")
  332. {
  333. localConstantsStruct = &strct;
  334. break;
  335. }
  336. }
  337. // Create vars
  338. for(U32 i = 0; localConstantsStruct && i < localConstantsStruct->m_members.getSize(); ++i)
  339. {
  340. const ShaderBinaryStructMember& member = localConstantsStruct->m_members[i];
  341. const CString memberName = member.m_name.getBegin();
  342. MaterialVariable& var = *m_vars.emplaceBack();
  343. zeroMemory(var);
  344. var.m_name = memberName;
  345. var.m_dataType = member.m_type;
  346. var.m_offsetInLocalConstants = member.m_offset;
  347. }
  348. m_localConstantsSize = (localConstantsStruct) ? localConstantsStruct->m_size : 0;
  349. return Error::kNone;
  350. }
  351. Error MaterialResource::parseInput(XmlElement inputEl, Bool async, BitSet<128>& varsSet)
  352. {
  353. // Get var name
  354. CString varName;
  355. ANKI_CHECK(inputEl.getAttributeText("name", varName));
  356. // Try find var
  357. MaterialVariable* foundVar = tryFindVariable(varName);
  358. if(!foundVar)
  359. {
  360. ANKI_RESOURCE_LOGE("Input name is wrong, variable not found: %s", varName.cstr());
  361. return Error::kUserData;
  362. }
  363. // Set check
  364. const U32 idx = U32(foundVar - m_vars.getBegin());
  365. if(varsSet.get(idx))
  366. {
  367. ANKI_RESOURCE_LOGE("Input already has a value: %s", varName.cstr());
  368. return Error::kUserData;
  369. }
  370. varsSet.set(idx);
  371. // Set the value
  372. if(foundVar->m_dataType == ShaderVariableDataType::kU32)
  373. {
  374. // U32 is a bit special. It might be a number or a bindless texture
  375. CString value;
  376. ANKI_CHECK(inputEl.getAttributeText("value", value));
  377. // Check if the value has letters
  378. Bool containsAlpharithmetic = false;
  379. for(Char c : value)
  380. {
  381. if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'a'))
  382. {
  383. containsAlpharithmetic = true;
  384. break;
  385. }
  386. }
  387. // If it has letters it's a texture
  388. if(containsAlpharithmetic)
  389. {
  390. ANKI_CHECK(ResourceManager::getSingleton().loadResource(value, foundVar->m_image, async));
  391. foundVar->m_U32 = foundVar->m_image->getTexture().getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
  392. }
  393. else
  394. {
  395. ANKI_CHECK(GetAttribute<U32>()(inputEl, foundVar->m_U32));
  396. }
  397. }
  398. else
  399. {
  400. switch(foundVar->m_dataType)
  401. {
  402. #define ANKI_SVDT_MACRO(type, baseType, rowCount, columnCount, isIntagralType) \
  403. case ShaderVariableDataType::k##type: \
  404. ANKI_CHECK(GetAttribute<type>()(inputEl, foundVar->ANKI_CONCATENATE(m_, type))); \
  405. break;
  406. #include <AnKi/Gr/ShaderVariableDataType.def.h>
  407. default:
  408. ANKI_ASSERT(0);
  409. break;
  410. }
  411. }
  412. return Error::kNone;
  413. }
  414. void MaterialResource::prefillLocalConstants()
  415. {
  416. if(m_localConstantsSize == 0)
  417. {
  418. return;
  419. }
  420. m_prefilledLocalConstants = ResourceMemoryPool::getSingleton().allocate(m_localConstantsSize, 1);
  421. memset(m_prefilledLocalConstants, 0, m_localConstantsSize);
  422. for(const MaterialVariable& var : m_vars)
  423. {
  424. switch(var.m_dataType)
  425. {
  426. #define ANKI_SVDT_MACRO(type, baseType, rowCount, columnCount, isIntagralType) \
  427. case ShaderVariableDataType::k##type: \
  428. ANKI_ASSERT(var.m_offsetInLocalConstants + sizeof(type) <= m_localConstantsSize); \
  429. memcpy(static_cast<U8*>(m_prefilledLocalConstants) + var.m_offsetInLocalConstants, &var.m_##type, sizeof(type)); \
  430. break;
  431. #include <AnKi/Gr/ShaderVariableDataType.def.h>
  432. default:
  433. ANKI_ASSERT(0);
  434. break;
  435. }
  436. }
  437. }
  438. const MaterialVariant& MaterialResource::getOrCreateVariant(const RenderingKey& key_) const
  439. {
  440. RenderingKey key = key_;
  441. // Sanitize the key
  442. if(!(m_presentBuildinMutatorMask & U32(BuiltinMutatorId::kVelocity)) && key.getVelocity())
  443. {
  444. // Particles set their own velocity
  445. key.setVelocity(false);
  446. }
  447. if(key.getRenderingTechnique() != RenderingTechnique::kGBuffer && key.getVelocity())
  448. {
  449. // Only GBuffer technique can write to velocity buffers
  450. key.setVelocity(false);
  451. }
  452. const Bool meshShadersSupported = GrManager::getSingleton().getDeviceCapabilities().m_meshShaders;
  453. ANKI_ASSERT(!(key.getMeshletRendering() && (!meshShadersSupported && !g_cvarCoreMeshletRendering))
  454. && "Can't be asking for meshlet rendering if mesh shaders or SW meshlet rendering are not supported/enabled");
  455. if(key.getMeshletRendering() && !(m_shaderTechniques & (ShaderTechniqueBit::kMeshSaders | ShaderTechniqueBit::kSwMeshletRendering)))
  456. {
  457. key.setMeshletRendering(false);
  458. }
  459. ANKI_ASSERT(!key.getSkinned() || !!(m_presentBuildinMutatorMask & U32(1 << BuiltinMutatorId::kBones)));
  460. ANKI_ASSERT(!key.getVelocity() || !!(m_presentBuildinMutatorMask & U32(1 << BuiltinMutatorId::kVelocity)));
  461. MaterialVariant& variant = m_variantMatrix[key.getRenderingTechnique()][key.getSkinned()][key.getVelocity()][key.getMeshletRendering()];
  462. // Check if it's initialized
  463. {
  464. RLockGuard lock(m_variantMatrixMtx);
  465. if(variant.m_prog.isCreated()) [[likely]]
  466. {
  467. return variant;
  468. }
  469. }
  470. // Not initialized, init it
  471. WLockGuard lock(m_variantMatrixMtx);
  472. // Check again
  473. if(variant.m_prog.isCreated())
  474. {
  475. return variant;
  476. }
  477. ShaderProgramResourceVariantInitInfo initInfo(m_prog);
  478. for(const PartialMutation& m : m_partialMutation)
  479. {
  480. initInfo.addMutation(m.m_mutator->m_name.getBegin(), m.m_value);
  481. }
  482. if(!!(m_presentBuildinMutatorMask & U32(1 << BuiltinMutatorId::kBones)))
  483. {
  484. initInfo.addMutation(kBuiltinMutatorNames[BuiltinMutatorId::kBones], MutatorValue(key.getSkinned()));
  485. }
  486. if(!!(m_presentBuildinMutatorMask & U32(1 << BuiltinMutatorId::kVelocity)))
  487. {
  488. initInfo.addMutation(kBuiltinMutatorNames[BuiltinMutatorId::kVelocity], MutatorValue(key.getVelocity()));
  489. }
  490. switch(key.getRenderingTechnique())
  491. {
  492. case RenderingTechnique::kGBuffer:
  493. if(key.getMeshletRendering() && meshShadersSupported)
  494. {
  495. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kMesh | ShaderTypeBit::kPixel, "GBufferMeshShaders");
  496. }
  497. else if(key.getMeshletRendering())
  498. {
  499. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel, "GBufferSwMeshletRendering");
  500. }
  501. else
  502. {
  503. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel, "GBufferLegacy");
  504. }
  505. break;
  506. case RenderingTechnique::kDepth:
  507. if(key.getMeshletRendering() && meshShadersSupported)
  508. {
  509. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kMesh | ShaderTypeBit::kPixel, "ShadowsMeshShaders");
  510. }
  511. else if(key.getMeshletRendering())
  512. {
  513. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel, "ShadowsSwMeshletRendering");
  514. }
  515. else
  516. {
  517. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel, "ShadowsLegacy");
  518. }
  519. break;
  520. case RenderingTechnique::kForward:
  521. if(key.getMeshletRendering() && meshShadersSupported)
  522. {
  523. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kMesh | ShaderTypeBit::kPixel, "ForwardMeshShaders");
  524. }
  525. else if(key.getMeshletRendering())
  526. {
  527. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel, "ForwardSwMeshletRendering");
  528. }
  529. else
  530. {
  531. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kVertex | ShaderTypeBit::kPixel, "ForwardLegacy");
  532. }
  533. break;
  534. case RenderingTechnique::kRtShadow:
  535. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kAllHit, "RtShadows");
  536. break;
  537. case RenderingTechnique::kRtMaterialFetch:
  538. initInfo.requestTechniqueAndTypes(ShaderTypeBit::kAllHit, "RtMaterialFetch");
  539. break;
  540. default:
  541. ANKI_ASSERT(0);
  542. }
  543. const ShaderProgramResourceVariant* progVariant = nullptr;
  544. m_prog->getOrCreateVariant(initInfo, progVariant);
  545. if(!progVariant)
  546. {
  547. ANKI_RESOURCE_LOGF("Fetched skipped mutation on program %s", getFilename().cstr());
  548. }
  549. variant.m_prog.reset(&progVariant->getProgram());
  550. if(!!(RenderingTechniqueBit(1 << key.getRenderingTechnique()) & RenderingTechniqueBit::kAllRt))
  551. {
  552. variant.m_rtShaderGroupHandleIndex = progVariant->getShaderGroupHandleIndex();
  553. }
  554. return variant;
  555. }
  556. Bool MaterialResource::isLoaded() const
  557. {
  558. // Check the atomic first
  559. U32 loaded = m_loaded.load();
  560. if(loaded) [[likely]]
  561. {
  562. return true;
  563. }
  564. // Do expensive check after
  565. loaded = 1;
  566. for(const MaterialVariable& var : m_vars)
  567. {
  568. if(var.m_image)
  569. {
  570. loaded = loaded && var.m_image->isLoaded();
  571. }
  572. }
  573. if(loaded)
  574. {
  575. m_loaded.store(1);
  576. }
  577. return loaded;
  578. }
  579. } // end namespace anki