MaterialResource.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. // Copyright (C) 2009-2020, 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/TextureResource.h>
  8. #include <anki/util/Xml.h>
  9. namespace anki
  10. {
  11. static const Array<CString, U32(BuiltinMutatorId::COUNT)> BUILTIN_MUTATOR_NAMES = {
  12. {"NONE", "ANKI_INSTANCE_COUNT", "ANKI_PASS", "ANKI_LOD", "ANKI_BONES", "ANKI_VELOCITY"}};
  13. class BuiltinVarInfo
  14. {
  15. public:
  16. const char* m_name;
  17. ShaderVariableDataType m_type;
  18. Bool m_instanced;
  19. };
  20. static const Array<BuiltinVarInfo, U(BuiltinMaterialVariableId::COUNT)> BUILTIN_INFOS = {
  21. {{"NONE", ShaderVariableDataType::NONE, false},
  22. {"m_ankiMvp", ShaderVariableDataType::MAT4, true},
  23. {"m_ankiPreviousMvp", ShaderVariableDataType::MAT4, true},
  24. {"m_ankiModelMatrix", ShaderVariableDataType::MAT4, true},
  25. {"m_ankiViewMatrix", ShaderVariableDataType::MAT4, false},
  26. {"m_ankiProjectionMatrix", ShaderVariableDataType::MAT4, false},
  27. {"m_ankiModelViewMatrix", ShaderVariableDataType::MAT4, true},
  28. {"m_ankiViewProjectionMatrix", ShaderVariableDataType::MAT4, false},
  29. {"m_ankiNormalMatrix", ShaderVariableDataType::MAT3, true},
  30. {"m_ankiRotationMatrix", ShaderVariableDataType::MAT3, true},
  31. {"m_ankiCameraRotationMatrix", ShaderVariableDataType::MAT3, false},
  32. {"m_ankiCameraPosition", ShaderVariableDataType::VEC3, false},
  33. {"u_ankiGlobalSampler", ShaderVariableDataType::SAMPLER, false}}};
  34. static ANKI_USE_RESULT Error checkBuiltin(CString name, ShaderVariableDataType dataType, Bool instanced,
  35. BuiltinMaterialVariableId& outId)
  36. {
  37. outId = BuiltinMaterialVariableId::NONE;
  38. for(BuiltinMaterialVariableId id : EnumIterable<BuiltinMaterialVariableId>())
  39. {
  40. if(id == BuiltinMaterialVariableId::NONE)
  41. {
  42. continue;
  43. }
  44. if(BUILTIN_INFOS[id].m_name == name)
  45. {
  46. outId = id;
  47. if(BUILTIN_INFOS[id].m_type != dataType)
  48. {
  49. ANKI_RESOURCE_LOGE("Incorect type for builtin: %s", name.cstr());
  50. return Error::USER_DATA;
  51. }
  52. if(instanced && !BUILTIN_INFOS[id].m_instanced)
  53. {
  54. ANKI_RESOURCE_LOGE("Variable %s be instanced: %s",
  55. (BUILTIN_INFOS[id].m_instanced) ? "should" : "shouldn't", name.cstr());
  56. return Error::USER_DATA;
  57. }
  58. break;
  59. }
  60. }
  61. if(outId == BuiltinMaterialVariableId::NONE && (name.find("m_anki") == 0 || name.find("u_anki") == 0))
  62. {
  63. ANKI_RESOURCE_LOGE("Unknown builtin var: %s", name.cstr());
  64. return Error::USER_DATA;
  65. }
  66. return Error::NONE;
  67. }
  68. // This is some trickery to select calling between XmlElement::getAttributeNumber and XmlElement::getAttributeNumbers
  69. namespace
  70. {
  71. template<typename T>
  72. class IsShaderVarDataTypeAnArray
  73. {
  74. public:
  75. static constexpr Bool VALUE = false;
  76. };
  77. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  78. template<> \
  79. class IsShaderVarDataTypeAnArray<type> \
  80. { \
  81. public: \
  82. static constexpr Bool VALUE = rowCount * columnCount > 1; \
  83. };
  84. #include <anki/gr/ShaderVariableDataTypeDefs.h>
  85. #undef ANKI_SVDT_MACRO
  86. template<typename T, Bool isArray = IsShaderVarDataTypeAnArray<T>::VALUE>
  87. class GetAttribute
  88. {
  89. public:
  90. Error operator()(const XmlElement& el, T& out)
  91. {
  92. return el.getAttributeNumbers("value", out);
  93. }
  94. };
  95. template<typename T>
  96. class GetAttribute<T, false>
  97. {
  98. public:
  99. Error operator()(const XmlElement& el, T& out)
  100. {
  101. return el.getAttributeNumber("value", out);
  102. }
  103. };
  104. } // namespace
  105. MaterialVariable::MaterialVariable()
  106. {
  107. m_Mat4 = Mat4::getZero();
  108. }
  109. MaterialVariable::~MaterialVariable()
  110. {
  111. }
  112. MaterialResource::MaterialResource(ResourceManager* manager)
  113. : ResourceObject(manager)
  114. {
  115. }
  116. MaterialResource::~MaterialResource()
  117. {
  118. for(Pass p : EnumIterable<Pass>())
  119. {
  120. for(U32 l = 0; l < MAX_LOD_COUNT; ++l)
  121. {
  122. for(U32 inst = 0; inst < MAX_INSTANCE_GROUPS; ++inst)
  123. {
  124. for(U32 skinned = 0; skinned <= 1; ++skinned)
  125. {
  126. for(U32 vel = 0; vel <= 1; ++vel)
  127. {
  128. MaterialVariant& variant = m_variantMatrix[p][l][inst][skinned][vel];
  129. variant.m_blockInfos.destroy(getAllocator());
  130. variant.m_opaqueBindings.destroy(getAllocator());
  131. }
  132. }
  133. }
  134. }
  135. }
  136. for(MaterialVariable& var : m_vars)
  137. {
  138. var.m_name.destroy(getAllocator());
  139. }
  140. m_vars.destroy(getAllocator());
  141. m_nonBuiltinsMutation.destroy(getAllocator());
  142. }
  143. Error MaterialResource::load(const ResourceFilename& filename, Bool async)
  144. {
  145. XmlDocument doc;
  146. XmlElement el;
  147. Bool present = false;
  148. ANKI_CHECK(openFileParseXml(filename, doc));
  149. // <material>
  150. XmlElement rootEl;
  151. ANKI_CHECK(doc.getChildElement("material", rootEl));
  152. // shaderProgram
  153. CString fname;
  154. ANKI_CHECK(rootEl.getAttributeText("shaderProgram", fname));
  155. ANKI_CHECK(getManager().loadResource(fname, m_prog, async));
  156. // Good time to create the vars
  157. ANKI_CHECK(createVars());
  158. // shadow
  159. ANKI_CHECK(rootEl.getAttributeNumberOptional("shadow", m_shadow, present));
  160. m_shadow = m_shadow != 0;
  161. // forwardShading
  162. ANKI_CHECK(rootEl.getAttributeNumberOptional("forwardShading", m_forwardShading, present));
  163. m_forwardShading = m_forwardShading != 0;
  164. // <mutation>
  165. XmlElement mutatorsEl;
  166. ANKI_CHECK(rootEl.getChildElementOptional("mutation", mutatorsEl));
  167. if(mutatorsEl)
  168. {
  169. ANKI_CHECK(parseMutators(mutatorsEl));
  170. }
  171. // The rest of the mutators
  172. ANKI_CHECK(findBuiltinMutators());
  173. // <inputs>
  174. ANKI_CHECK(rootEl.getChildElementOptional("inputs", el));
  175. if(el)
  176. {
  177. ANKI_CHECK(parseInputs(el, async));
  178. }
  179. return Error::NONE;
  180. }
  181. Error MaterialResource::parseMutators(XmlElement mutatorsEl)
  182. {
  183. XmlElement mutatorEl;
  184. ANKI_CHECK(mutatorsEl.getChildElement("mutator", mutatorEl));
  185. //
  186. // Process the non-builtin mutators
  187. //
  188. U32 mutatorCount = 0;
  189. ANKI_CHECK(mutatorEl.getSiblingElementsCount(mutatorCount));
  190. ++mutatorCount;
  191. ANKI_ASSERT(mutatorCount > 0);
  192. m_nonBuiltinsMutation.create(getAllocator(), mutatorCount);
  193. mutatorCount = 0;
  194. do
  195. {
  196. SubMutation& smutation = m_nonBuiltinsMutation[mutatorCount];
  197. // name
  198. CString mutatorName;
  199. ANKI_CHECK(mutatorEl.getAttributeText("name", mutatorName));
  200. if(mutatorName.isEmpty())
  201. {
  202. ANKI_RESOURCE_LOGE("Mutator name is empty");
  203. return Error::USER_DATA;
  204. }
  205. for(BuiltinMutatorId id : EnumIterable<BuiltinMutatorId>())
  206. {
  207. if(id == BuiltinMutatorId::NONE)
  208. {
  209. continue;
  210. }
  211. if(mutatorName == BUILTIN_MUTATOR_NAMES[id])
  212. {
  213. ANKI_RESOURCE_LOGE("Cannot list builtin mutator: %s", mutatorName.cstr());
  214. return Error::USER_DATA;
  215. }
  216. }
  217. if(mutatorName.find("ANKI_") == 0)
  218. {
  219. ANKI_RESOURCE_LOGE("Mutators can't start with ANKI_: %s", mutatorName.cstr());
  220. return Error::USER_DATA;
  221. }
  222. // value
  223. ANKI_CHECK(mutatorEl.getAttributeNumber("value", smutation.m_value));
  224. // Find mutator
  225. smutation.m_mutator = m_prog->tryFindMutator(mutatorName);
  226. if(!smutation.m_mutator)
  227. {
  228. ANKI_RESOURCE_LOGE("Mutator not found in program %s", &mutatorName[0]);
  229. return Error::USER_DATA;
  230. }
  231. if(!smutation.m_mutator->valueExists(smutation.m_value))
  232. {
  233. ANKI_RESOURCE_LOGE("Value %d is not part of the mutator %s", smutation.m_value, &mutatorName[0]);
  234. return Error::USER_DATA;
  235. }
  236. // Advance
  237. ++mutatorCount;
  238. ANKI_CHECK(mutatorEl.getNextSiblingElement("mutator", mutatorEl));
  239. } while(mutatorEl);
  240. ANKI_ASSERT(mutatorCount == m_nonBuiltinsMutation.getSize());
  241. return Error::NONE;
  242. }
  243. Error MaterialResource::findBuiltinMutators()
  244. {
  245. // INSTANCE_COUNT
  246. U builtinMutatorCount = 0;
  247. m_builtinMutators[BuiltinMutatorId::INSTANCE_COUNT] =
  248. m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::INSTANCE_COUNT]);
  249. if(m_builtinMutators[BuiltinMutatorId::INSTANCE_COUNT])
  250. {
  251. if(m_builtinMutators[BuiltinMutatorId::INSTANCE_COUNT]->m_values.getSize() != MAX_INSTANCE_GROUPS)
  252. {
  253. ANKI_RESOURCE_LOGE("Mutator %s should have %u values in the program",
  254. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::INSTANCE_COUNT].cstr(), MAX_INSTANCE_GROUPS);
  255. return Error::USER_DATA;
  256. }
  257. for(U32 i = 0; i < MAX_INSTANCE_GROUPS; ++i)
  258. {
  259. if(m_builtinMutators[BuiltinMutatorId::INSTANCE_COUNT]->m_values[i] != (1 << i))
  260. {
  261. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected",
  262. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::INSTANCE_COUNT].cstr());
  263. return Error::USER_DATA;
  264. }
  265. }
  266. ++builtinMutatorCount;
  267. }
  268. // PASS
  269. m_builtinMutators[BuiltinMutatorId::PASS] = m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::PASS]);
  270. if(m_builtinMutators[BuiltinMutatorId::PASS] && m_forwardShading)
  271. {
  272. ANKI_RESOURCE_LOGE("Mutator is not required for forward shading: %s",
  273. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::PASS].cstr());
  274. return Error::USER_DATA;
  275. }
  276. else if(!m_builtinMutators[BuiltinMutatorId::PASS] && !m_forwardShading)
  277. {
  278. ANKI_RESOURCE_LOGE("Mutator is required for opaque shading: %s",
  279. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::PASS].cstr());
  280. return Error::USER_DATA;
  281. }
  282. if(m_builtinMutators[BuiltinMutatorId::PASS])
  283. {
  284. if(m_builtinMutators[BuiltinMutatorId::PASS]->m_values.getSize() != U32(Pass::COUNT) - 1)
  285. {
  286. ANKI_RESOURCE_LOGE("Mutator %s should have %u values in the program",
  287. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::PASS].cstr(), U32(Pass::COUNT) - 1);
  288. return Error::USER_DATA;
  289. }
  290. U32 count = 0;
  291. for(Pass p : EnumIterable<Pass>())
  292. {
  293. if(p == Pass::FS)
  294. {
  295. continue;
  296. }
  297. if(m_builtinMutators[BuiltinMutatorId::PASS]->m_values[count++] != I(p))
  298. {
  299. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected",
  300. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::PASS].cstr());
  301. return Error::USER_DATA;
  302. }
  303. }
  304. ++builtinMutatorCount;
  305. }
  306. if(!m_forwardShading && !m_builtinMutators[BuiltinMutatorId::PASS])
  307. {
  308. ANKI_RESOURCE_LOGE("%s mutator is required", BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::PASS].cstr());
  309. return Error::USER_DATA;
  310. }
  311. // LOD
  312. m_builtinMutators[BuiltinMutatorId::LOD] = m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::LOD]);
  313. if(m_builtinMutators[BuiltinMutatorId::LOD])
  314. {
  315. if(m_builtinMutators[BuiltinMutatorId::LOD]->m_values.getSize() > MAX_LOD_COUNT)
  316. {
  317. ANKI_RESOURCE_LOGE("Mutator %s should have at least %u values in the program",
  318. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::LOD].cstr(), U32(MAX_LOD_COUNT));
  319. return Error::USER_DATA;
  320. }
  321. for(U32 i = 0; i < m_builtinMutators[BuiltinMutatorId::LOD]->m_values.getSize(); ++i)
  322. {
  323. if(m_builtinMutators[BuiltinMutatorId::LOD]->m_values[i] != I(i))
  324. {
  325. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected",
  326. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::LOD].cstr());
  327. return Error::USER_DATA;
  328. }
  329. }
  330. m_lodCount = U8(m_builtinMutators[BuiltinMutatorId::LOD]->m_values.getSize());
  331. ++builtinMutatorCount;
  332. }
  333. // BONES
  334. m_builtinMutators[BuiltinMutatorId::BONES] = m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::BONES]);
  335. if(m_builtinMutators[BuiltinMutatorId::BONES])
  336. {
  337. if(m_builtinMutators[BuiltinMutatorId::BONES]->m_values.getSize() != 2)
  338. {
  339. ANKI_RESOURCE_LOGE("Mutator %s should have 2 values in the program",
  340. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::BONES].cstr());
  341. return Error::USER_DATA;
  342. }
  343. for(U32 i = 0; i < m_builtinMutators[BuiltinMutatorId::BONES]->m_values.getSize(); ++i)
  344. {
  345. if(m_builtinMutators[BuiltinMutatorId::BONES]->m_values[i] != I(i))
  346. {
  347. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected",
  348. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::BONES].cstr());
  349. return Error::USER_DATA;
  350. }
  351. }
  352. ++builtinMutatorCount;
  353. // Find the binding of the transforms
  354. const ShaderProgramBinary& binary = m_prog->getBinary();
  355. for(const ShaderProgramBinaryBlock& block : binary.m_storageBlocks)
  356. {
  357. if(block.m_name.getBegin() == CString("b_ankiBoneTransforms"))
  358. {
  359. if(block.m_set != m_descriptorSetIdx)
  360. {
  361. ANKI_RESOURCE_LOGE("The set of b_ankiBoneTransforms should be %u", m_descriptorSetIdx);
  362. return Error::USER_DATA;
  363. }
  364. m_boneTrfsBinding = block.m_binding;
  365. }
  366. else if(block.m_name.getBegin() == CString("b_ankiPrevFrameBoneTransforms"))
  367. {
  368. if(block.m_set != m_descriptorSetIdx)
  369. {
  370. ANKI_RESOURCE_LOGE("The set of b_ankiPrevFrameBoneTransforms should be %u", m_descriptorSetIdx);
  371. return Error::USER_DATA;
  372. }
  373. m_prevFrameBoneTrfsBinding = block.m_binding;
  374. }
  375. }
  376. if(m_boneTrfsBinding == MAX_U32 || m_prevFrameBoneTrfsBinding == MAX_U32)
  377. {
  378. ANKI_RESOURCE_LOGE("The program is using the %s mutator but b_ankiBoneTransforms or "
  379. "b_ankiPrevFrameBoneTransforms was not found",
  380. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::BONES].cstr());
  381. return Error::NONE;
  382. }
  383. }
  384. // VELOCITY
  385. m_builtinMutators[BuiltinMutatorId::VELOCITY] =
  386. m_prog->tryFindMutator(BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::VELOCITY]);
  387. if(m_builtinMutators[BuiltinMutatorId::VELOCITY])
  388. {
  389. if(m_builtinMutators[BuiltinMutatorId::VELOCITY]->m_values.getSize() != 2)
  390. {
  391. ANKI_RESOURCE_LOGE("Mutator %s should have 2 values in the program",
  392. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::VELOCITY].cstr());
  393. return Error::USER_DATA;
  394. }
  395. for(U32 i = 0; i < m_builtinMutators[BuiltinMutatorId::VELOCITY]->m_values.getSize(); ++i)
  396. {
  397. if(m_builtinMutators[BuiltinMutatorId::VELOCITY]->m_values[i] != I(i))
  398. {
  399. ANKI_RESOURCE_LOGE("Values of the %s mutator in the program are not the expected",
  400. BUILTIN_MUTATOR_NAMES[BuiltinMutatorId::VELOCITY].cstr());
  401. return Error::USER_DATA;
  402. }
  403. }
  404. ++builtinMutatorCount;
  405. }
  406. if(m_nonBuiltinsMutation.getSize() + builtinMutatorCount != m_prog->getMutators().getSize())
  407. {
  408. ANKI_RESOURCE_LOGE("Some mutatators are unacounted for");
  409. return Error::USER_DATA;
  410. }
  411. return Error::NONE;
  412. }
  413. Error MaterialResource::parseVariable(CString fullVarName, Bool& instanced, U32& idx, CString& name)
  414. {
  415. idx = 0;
  416. if(fullVarName.find("u_ankiPerDraw") != CString::NPOS)
  417. {
  418. instanced = false;
  419. }
  420. else if(fullVarName.find("u_ankiPerInstance") != CString::NPOS)
  421. {
  422. instanced = true;
  423. }
  424. else
  425. {
  426. ANKI_RESOURCE_LOGE("Wrong variable name: %s", fullVarName.cstr());
  427. return Error::USER_DATA;
  428. }
  429. const PtrSize leftBracket = fullVarName.find("[");
  430. const PtrSize rightBracket = fullVarName.find("]");
  431. if(instanced)
  432. {
  433. const Bool correct =
  434. (leftBracket == CString::NPOS && rightBracket == CString::NPOS)
  435. || (leftBracket != CString::NPOS && rightBracket != CString::NPOS && rightBracket > leftBracket);
  436. if(!correct)
  437. {
  438. ANKI_RESOURCE_LOGE("Wrong variable name: %s", fullVarName.cstr());
  439. return Error::USER_DATA;
  440. }
  441. if(leftBracket != CString::NPOS)
  442. {
  443. Array<char, 8> idxStr = {};
  444. for(PtrSize i = leftBracket + 1; i < rightBracket; ++i)
  445. {
  446. idxStr[i - (leftBracket + 1)] = fullVarName[i];
  447. }
  448. ANKI_CHECK(CString(idxStr.getBegin()).toNumber(idx));
  449. }
  450. else
  451. {
  452. idx = 0;
  453. }
  454. }
  455. else
  456. {
  457. if(leftBracket != CString::NPOS || rightBracket != CString::NPOS)
  458. {
  459. ANKI_RESOURCE_LOGE("Can't support non instanced array variables: %s", fullVarName.cstr());
  460. return Error::USER_DATA;
  461. }
  462. }
  463. const PtrSize dot = fullVarName.find(".");
  464. if(dot == CString::NPOS)
  465. {
  466. ANKI_RESOURCE_LOGE("Wrong variable name: %s", fullVarName.cstr());
  467. return Error::USER_DATA;
  468. }
  469. name = fullVarName.getBegin() + dot + 1;
  470. return Error::NONE;
  471. }
  472. Error MaterialResource::createVars()
  473. {
  474. const ShaderProgramBinary& binary = m_prog->getBinary();
  475. // Create the uniform vars
  476. U32 descriptorSet = MAX_U32;
  477. U32 maxDescriptorSet = 0;
  478. for(const ShaderProgramBinaryBlock& block : binary.m_uniformBlocks)
  479. {
  480. maxDescriptorSet = max(maxDescriptorSet, block.m_set);
  481. if(block.m_name.getBegin() != CString("b_ankiMaterial"))
  482. {
  483. continue;
  484. }
  485. descriptorSet = block.m_set;
  486. m_uboIdx = U32(&block - binary.m_uniformBlocks.getBegin());
  487. m_uboBinding = block.m_binding;
  488. for(const ShaderProgramBinaryVariable& var : block.m_variables)
  489. {
  490. Bool instanced;
  491. U32 idx;
  492. CString name;
  493. ANKI_CHECK(parseVariable(var.m_name.getBegin(), instanced, idx, name));
  494. ANKI_ASSERT(name.getLength() > 0 && (instanced || idx == 0));
  495. if(idx > 0)
  496. {
  497. if(idx > MAX_INSTANCES)
  498. {
  499. ANKI_RESOURCE_LOGE("Array variable exceeds the instance count: %s", var.m_name.getBegin());
  500. return Error::USER_DATA;
  501. }
  502. if(idx == 1)
  503. {
  504. // Find the idx==0
  505. MaterialVariable* other = tryFindVariable(name);
  506. ANKI_ASSERT(other);
  507. ANKI_ASSERT(other->m_indexInBinary2ndElement == MAX_U32);
  508. other->m_indexInBinary2ndElement = U32(&var - block.m_variables.getBegin());
  509. }
  510. // Skip var
  511. continue;
  512. }
  513. const MaterialVariable* other = tryFindVariable(name);
  514. if(other)
  515. {
  516. ANKI_RESOURCE_LOGE("Variable found twice: %s", name.cstr());
  517. return Error::USER_DATA;
  518. }
  519. MaterialVariable& in = *m_vars.emplaceBack(getAllocator());
  520. in.m_name.create(getAllocator(), name);
  521. in.m_index = m_vars.getSize() - 1;
  522. in.m_indexInBinary = U32(&var - block.m_variables.getBegin());
  523. in.m_constant = false;
  524. in.m_instanced = instanced;
  525. in.m_dataType = var.m_type;
  526. // Check if it's builtin
  527. ANKI_CHECK(checkBuiltin(name, in.m_dataType, instanced, in.m_builtin));
  528. }
  529. }
  530. if(descriptorSet == MAX_U32)
  531. {
  532. ANKI_RESOURCE_LOGE("The b_ankiMaterial UBO is missing");
  533. return Error::USER_DATA;
  534. }
  535. // Continue with the opaque if it's a material shader program
  536. for(const ShaderProgramBinaryOpaque& o : binary.m_opaques)
  537. {
  538. maxDescriptorSet = max(maxDescriptorSet, o.m_set);
  539. if(o.m_set != descriptorSet)
  540. {
  541. continue;
  542. }
  543. MaterialVariable& in = *m_vars.emplaceBack(getAllocator());
  544. in.m_name.create(getAllocator(), o.m_name.getBegin());
  545. in.m_index = m_vars.getSize() - 1;
  546. in.m_indexInBinary = U32(&o - binary.m_opaques.getBegin());
  547. in.m_constant = false;
  548. in.m_instanced = false;
  549. in.m_dataType = o.m_type;
  550. // Check if it's builtin
  551. ANKI_CHECK(checkBuiltin(in.m_name, in.m_dataType, false, in.m_builtin));
  552. }
  553. if(descriptorSet != maxDescriptorSet)
  554. {
  555. ANKI_RESOURCE_LOGE("All bindings of a material shader should be in the highest descriptor set");
  556. return Error::USER_DATA;
  557. }
  558. m_descriptorSetIdx = U8(descriptorSet);
  559. // Consts
  560. for(const ShaderProgramResourceConstant& c : m_prog->getConstants())
  561. {
  562. MaterialVariable& in = *m_vars.emplaceBack(getAllocator());
  563. in.m_name.create(getAllocator(), c.m_name);
  564. in.m_index = m_vars.getSize() - 1;
  565. in.m_constant = true;
  566. in.m_instanced = false;
  567. in.m_dataType = c.m_dataType;
  568. }
  569. return Error::NONE;
  570. }
  571. Error MaterialResource::parseInputs(XmlElement inputsEl, Bool async)
  572. {
  573. // Connect the input variables
  574. XmlElement inputEl;
  575. ANKI_CHECK(inputsEl.getChildElementOptional("input", inputEl));
  576. while(inputEl)
  577. {
  578. // Get var name
  579. CString varName;
  580. ANKI_CHECK(inputEl.getAttributeText("shaderVar", varName));
  581. // Try find var
  582. MaterialVariable* foundVar = tryFindVariable(varName);
  583. if(foundVar == nullptr)
  584. {
  585. ANKI_RESOURCE_LOGE("Variable \"%s\" not found", varName.cstr());
  586. return Error::USER_DATA;
  587. }
  588. if(foundVar->m_builtin != BuiltinMaterialVariableId::NONE)
  589. {
  590. ANKI_RESOURCE_LOGE("Shouldn't list builtin vars: %s", varName.cstr());
  591. return Error::USER_DATA;
  592. }
  593. // A value will be set
  594. foundVar->m_numericValueIsSet = true;
  595. // Process var
  596. if(foundVar->isConstant())
  597. {
  598. // Const
  599. switch(foundVar->getDataType())
  600. {
  601. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  602. case ShaderVariableDataType::capital: \
  603. ANKI_CHECK(GetAttribute<type>()(inputEl, foundVar->ANKI_CONCATENATE(m_, type))); \
  604. break;
  605. #include <anki/gr/ShaderVariableDataTypeDefs.h>
  606. #undef ANKI_SVDT_MACRO
  607. default:
  608. ANKI_ASSERT(0);
  609. break;
  610. }
  611. }
  612. else
  613. {
  614. // Not built-in
  615. if(foundVar->isInstanced())
  616. {
  617. ANKI_RESOURCE_LOGE("Only some builtin variables can be instanced: %s", foundVar->getName().cstr());
  618. return Error::USER_DATA;
  619. }
  620. switch(foundVar->getDataType())
  621. {
  622. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  623. case ShaderVariableDataType::capital: \
  624. ANKI_CHECK(GetAttribute<type>()(inputEl, foundVar->ANKI_CONCATENATE(m_, type))); \
  625. break;
  626. #include <anki/gr/ShaderVariableDataTypeDefs.h>
  627. #undef ANKI_SVDT_MACRO
  628. case ShaderVariableDataType::TEXTURE_2D:
  629. case ShaderVariableDataType::TEXTURE_2D_ARRAY:
  630. case ShaderVariableDataType::TEXTURE_3D:
  631. case ShaderVariableDataType::TEXTURE_CUBE:
  632. {
  633. CString texfname;
  634. ANKI_CHECK(inputEl.getAttributeText("value", texfname));
  635. ANKI_CHECK(getManager().loadResource(texfname, foundVar->m_tex, async));
  636. break;
  637. }
  638. default:
  639. ANKI_ASSERT(0);
  640. break;
  641. }
  642. }
  643. // Advance
  644. ANKI_CHECK(inputEl.getNextSiblingElement("input", inputEl));
  645. }
  646. return Error::NONE;
  647. }
  648. const MaterialVariant& MaterialResource::getOrCreateVariant(const RenderingKey& key_) const
  649. {
  650. RenderingKey key = key_;
  651. key.setLod(min<U32>(m_lodCount - 1, key.getLod()));
  652. if(!isInstanced())
  653. {
  654. ANKI_ASSERT(key.getInstanceCount() == 1);
  655. }
  656. ANKI_ASSERT(!key.isSkinned() || m_builtinMutators[BuiltinMutatorId::BONES]);
  657. ANKI_ASSERT(!key.hasVelocity() || m_builtinMutators[BuiltinMutatorId::VELOCITY]);
  658. key.setInstanceCount(1 << getInstanceGroupIdx(key.getInstanceCount()));
  659. MaterialVariant& variant = m_variantMatrix[key.getPass()][key.getLod()][getInstanceGroupIdx(key.getInstanceCount())]
  660. [key.isSkinned()][key.hasVelocity()];
  661. // Check if it's initialized
  662. {
  663. RLockGuard<RWMutex> lock(m_variantMatrixMtx);
  664. if(variant.m_prog.isCreated())
  665. {
  666. return variant;
  667. }
  668. }
  669. // Not initialized, init it
  670. WLockGuard<RWMutex> lock(m_variantMatrixMtx);
  671. // Check again
  672. if(variant.m_prog.isCreated())
  673. {
  674. return variant;
  675. }
  676. ShaderProgramResourceVariantInitInfo initInfo(m_prog);
  677. for(const SubMutation& m : m_nonBuiltinsMutation)
  678. {
  679. initInfo.addMutation(m.m_mutator->m_name, m.m_value);
  680. }
  681. if(m_builtinMutators[BuiltinMutatorId::INSTANCE_COUNT])
  682. {
  683. initInfo.addMutation(m_builtinMutators[BuiltinMutatorId::INSTANCE_COUNT]->m_name, key.getInstanceCount());
  684. }
  685. if(m_builtinMutators[BuiltinMutatorId::PASS])
  686. {
  687. initInfo.addMutation(m_builtinMutators[BuiltinMutatorId::PASS]->m_name, MutatorValue(key.getPass()));
  688. }
  689. if(m_builtinMutators[BuiltinMutatorId::LOD])
  690. {
  691. initInfo.addMutation(m_builtinMutators[BuiltinMutatorId::LOD]->m_name, MutatorValue(key.getLod()));
  692. }
  693. if(m_builtinMutators[BuiltinMutatorId::BONES])
  694. {
  695. initInfo.addMutation(m_builtinMutators[BuiltinMutatorId::BONES]->m_name, key.isSkinned() != 0);
  696. }
  697. if(m_builtinMutators[BuiltinMutatorId::VELOCITY])
  698. {
  699. initInfo.addMutation(m_builtinMutators[BuiltinMutatorId::VELOCITY]->m_name, key.hasVelocity() != 0);
  700. }
  701. for(const MaterialVariable& var : m_vars)
  702. {
  703. if(!var.isConstant())
  704. {
  705. continue;
  706. }
  707. if(!var.valueSetByMaterial())
  708. {
  709. continue;
  710. }
  711. switch(var.m_dataType)
  712. {
  713. #define ANKI_SVDT_MACRO(capital, type, baseType, rowCount, columnCount) \
  714. case ShaderVariableDataType::capital: \
  715. initInfo.addConstant(var.getName(), var.getValue<type>()); \
  716. break;
  717. #include <anki/gr/ShaderVariableDataTypeDefs.h>
  718. #undef ANKI_SVDT_MACRO
  719. default:
  720. ANKI_ASSERT(0);
  721. }
  722. }
  723. const ShaderProgramResourceVariant* progVariant;
  724. m_prog->getOrCreateVariant(initInfo, progVariant);
  725. // Init the variant
  726. initVariant(*progVariant, variant, key.getInstanceCount());
  727. return variant;
  728. }
  729. void MaterialResource::initVariant(const ShaderProgramResourceVariant& progVariant, MaterialVariant& variant,
  730. U32 instanceCount) const
  731. {
  732. // Find the block instance
  733. const ShaderProgramBinary& binary = m_prog->getBinary();
  734. const ShaderProgramBinaryVariant& binaryVariant = progVariant.getBinaryVariant();
  735. const ShaderProgramBinaryBlockInstance* binaryBlockInstance = nullptr;
  736. for(const ShaderProgramBinaryBlockInstance& instance : binaryVariant.m_uniformBlocks)
  737. {
  738. if(instance.m_index == m_uboIdx)
  739. {
  740. binaryBlockInstance = &instance;
  741. break;
  742. }
  743. }
  744. if(binaryBlockInstance == nullptr)
  745. {
  746. ANKI_RESOURCE_LOGF("The uniform block doesn't appear to be active for variant. Material: %s",
  747. getFilename().cstr());
  748. }
  749. // Some init
  750. variant.m_prog = progVariant.getProgram();
  751. variant.m_blockInfos.create(getAllocator(), m_vars.getSize());
  752. variant.m_opaqueBindings.create(getAllocator(), m_vars.getSize(), -1);
  753. variant.m_uniBlockSize = binaryBlockInstance->m_size;
  754. ANKI_ASSERT(variant.m_uniBlockSize > 0);
  755. // Initialize the block infos, active vars and bindings
  756. for(const MaterialVariable& var : m_vars)
  757. {
  758. if(var.m_constant)
  759. {
  760. for(const ShaderProgramResourceConstant& c : m_prog->getConstants())
  761. {
  762. if(c.m_name == var.m_name)
  763. {
  764. variant.m_activeVars.set(var.m_index, progVariant.isConstantActive(c));
  765. break;
  766. }
  767. }
  768. }
  769. else if(var.inBlock())
  770. {
  771. for(const ShaderProgramBinaryVariableInstance& instance : binaryBlockInstance->m_variables)
  772. {
  773. if(instance.m_index == var.m_indexInBinary)
  774. {
  775. variant.m_activeVars.set(var.m_index, true);
  776. variant.m_blockInfos[var.m_index] = instance.m_blockInfo;
  777. if(var.m_instanced)
  778. {
  779. variant.m_blockInfos[var.m_index].m_arraySize = I16(instanceCount);
  780. }
  781. else
  782. {
  783. break;
  784. }
  785. }
  786. else if(instance.m_index == var.m_indexInBinary2ndElement)
  787. {
  788. // Then we need to update the stride
  789. ANKI_ASSERT(variant.m_blockInfos[var.m_index].m_offset >= 0);
  790. const I16 stride = I16(instance.m_blockInfo.m_offset - variant.m_blockInfos[var.m_index].m_offset);
  791. ANKI_ASSERT(stride >= 4);
  792. variant.m_blockInfos[var.m_index].m_arrayStride = stride;
  793. }
  794. }
  795. }
  796. else
  797. {
  798. ANKI_ASSERT(var.isSampler() || var.isTexture());
  799. for(const ShaderProgramBinaryOpaqueInstance& instance : binaryVariant.m_opaques)
  800. {
  801. if(instance.m_index == var.m_indexInBinary)
  802. {
  803. variant.m_activeVars.set(var.m_index, true);
  804. variant.m_opaqueBindings[var.m_index] = I16(binary.m_opaques[instance.m_index].m_binding);
  805. break;
  806. }
  807. }
  808. }
  809. }
  810. // No make sure that the vars that are active
  811. for(const MaterialVariable& var : m_vars)
  812. {
  813. if(var.m_builtin == BuiltinMaterialVariableId::NONE && variant.m_activeVars.get(var.m_index)
  814. && !var.valueSetByMaterial())
  815. {
  816. ANKI_RESOURCE_LOGF("An active variable doesn't have its value set by the material: %s", var.m_name.cstr());
  817. }
  818. ANKI_ASSERT(!(var.m_instanced && var.m_indexInBinary2ndElement == MAX_U32));
  819. }
  820. // Debug print
  821. #if 0
  822. ANKI_RESOURCE_LOGI("binary variant idx %u\n", U32(&binaryVariant - binary.m_variants.getBegin()));
  823. for(const MaterialVariable& var : m_vars)
  824. {
  825. ANKI_RESOURCE_LOGI(
  826. "Var %s %s\n", var.m_name.cstr(), variant.m_activeVars.get(var.m_index) ? "active" : "inactive");
  827. if(var.inBlock() && variant.m_activeVars.get(var.m_index))
  828. {
  829. const ShaderVariableBlockInfo& inf = variant.m_blockInfos[var.m_index];
  830. ANKI_RESOURCE_LOGI(
  831. "\tblockInfo %d,%d,%d,%d\n", inf.m_offset, inf.m_arraySize, inf.m_arrayStride, inf.m_matrixStride);
  832. }
  833. }
  834. #endif
  835. }
  836. U32 MaterialResource::getInstanceGroupIdx(U32 instanceCount)
  837. {
  838. ANKI_ASSERT(instanceCount > 0);
  839. instanceCount = nextPowerOfTwo(instanceCount);
  840. ANKI_ASSERT(instanceCount <= MAX_INSTANCES);
  841. return U32(std::log2(F32(instanceCount)));
  842. }
  843. Error MaterialResource::parseRtMaterial(XmlElement rootEl)
  844. {
  845. XmlElement rtMaterialEl;
  846. ANKI_CHECK(rootEl.getChildElementOptional("rtMaterial", rtMaterialEl));
  847. if(!rtMaterialEl)
  848. {
  849. return Error::NONE;
  850. }
  851. // type
  852. CString typeStr;
  853. ANKI_CHECK(rtMaterialEl.getAttributeText("type", typeStr));
  854. RayTracingMaterialType type = RayTracingMaterialType::COUNT;
  855. if(typeStr == "SHADOWS")
  856. {
  857. type = RayTracingMaterialType::SHADOWS;
  858. }
  859. else if(typeStr == "GI")
  860. {
  861. type = RayTracingMaterialType::GI;
  862. }
  863. else if(typeStr == "REFLECTIONS")
  864. {
  865. type = RayTracingMaterialType::REFLECTIONS;
  866. }
  867. else if(typeStr == "PATH_TRACING")
  868. {
  869. type = RayTracingMaterialType::PATH_TRACING;
  870. }
  871. else
  872. {
  873. ANKI_RESOURCE_LOGE("Uknown ray tracing type: %s", typeStr.cstr());
  874. return Error::USER_DATA;
  875. }
  876. // shaderProgram
  877. CString fname;
  878. ANKI_CHECK(rtMaterialEl.getAttributeText("shaderProgram", fname));
  879. ANKI_CHECK(getManager().loadResource(fname, m_rt[type].m_prog, false));
  880. // mutation
  881. XmlElement mutationEl;
  882. ANKI_CHECK(rtMaterialEl.getChildElementOptional("mutation", mutationEl));
  883. DynamicArrayAuto<SubMutation> mutatorValues(getTempAllocator());
  884. if(mutationEl)
  885. {
  886. XmlElement mutatorEl;
  887. ANKI_CHECK(mutationEl.getChildElement("mutator", mutatorEl));
  888. U32 mutatorCount = 0;
  889. ANKI_CHECK(mutatorEl.getSiblingElementsCount(mutatorCount));
  890. ++mutatorCount;
  891. mutatorValues.resize(mutatorCount);
  892. mutatorCount = 0;
  893. do
  894. {
  895. // name
  896. CString mutatorName;
  897. ANKI_CHECK(mutatorEl.getAttributeText("name", mutatorName));
  898. if(mutatorName.isEmpty())
  899. {
  900. ANKI_RESOURCE_LOGE("Mutator name is empty");
  901. return Error::USER_DATA;
  902. }
  903. // value
  904. MutatorValue mutatorValue;
  905. ANKI_CHECK(mutatorEl.getAttributeNumber("value", mutatorValue));
  906. // Check
  907. const ShaderProgramResourceMutator* mutatorPtr = m_rt[type].m_prog->tryFindMutator(mutatorName);
  908. if(mutatorPtr == nullptr)
  909. {
  910. ANKI_RESOURCE_LOGE("Mutator not found: %s", mutatorName.cstr());
  911. return Error::USER_DATA;
  912. }
  913. if(mutatorPtr->valueExists(mutatorValue))
  914. {
  915. ANKI_RESOURCE_LOGE("Mutator value doesn't exist: %s", mutatorName.cstr());
  916. return Error::USER_DATA;
  917. }
  918. // All good
  919. mutatorValues[mutatorCount].m_mutator = mutatorPtr;
  920. mutatorValues[mutatorCount].m_value = mutatorValue;
  921. // Advance
  922. ++mutatorCount;
  923. ANKI_CHECK(mutatorEl.getNextSiblingElement("mutator", mutatorEl));
  924. } while(mutatorEl);
  925. ANKI_ASSERT(mutatorCount == mutatorValues.getSize());
  926. }
  927. if(mutatorValues.getSize() != m_rt[type].m_prog->getMutators().getSize())
  928. {
  929. ANKI_RESOURCE_LOGE("Forgot to set all mutators on some RT mutation");
  930. return Error::USER_DATA;
  931. }
  932. return Error::NONE;
  933. }
  934. } // end namespace anki