MaterialResource.cpp 33 KB

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