MaterialResource.cpp 35 KB

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