BsMaterial.cpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsMaterial.h"
  4. #include "BsException.h"
  5. #include "BsShader.h"
  6. #include "BsTechnique.h"
  7. #include "BsPass.h"
  8. #include "BsRenderAPI.h"
  9. #include "BsHardwareBufferManager.h"
  10. #include "BsGpuProgram.h"
  11. #include "BsGpuParamBlockBuffer.h"
  12. #include "BsGpuParamDesc.h"
  13. #include "BsMaterialRTTI.h"
  14. #include "BsMaterialManager.h"
  15. #include "BsDebug.h"
  16. #include "BsResources.h"
  17. #include "BsFrameAlloc.h"
  18. #include "BsMatrixNxM.h"
  19. #include "BsVectorNI.h"
  20. #include "BsMemorySerializer.h"
  21. #include "BsMaterialParams.h"
  22. namespace BansheeEngine
  23. {
  24. struct ShaderBlockDesc
  25. {
  26. String name;
  27. GpuParamBlockUsage usage;
  28. int size;
  29. bool create;
  30. };
  31. enum MaterialLoadFlags
  32. {
  33. Load_None = 0,
  34. Load_Shader = 1,
  35. Load_All = 2
  36. };
  37. const UINT32 PassParameters::NUM_PARAMS = 6;
  38. const UINT32 PassParametersCore::NUM_PARAMS = 6;
  39. SPtr<PassParametersCore> convertParamsToCore(const SPtr<PassParameters>& passParams)
  40. {
  41. SPtr<PassParametersCore> passParameters = bs_shared_ptr_new<PassParametersCore>();
  42. if (passParams->mVertParams != nullptr)
  43. passParameters->mVertParams = passParams->mVertParams->getCore();
  44. else
  45. passParameters->mVertParams = nullptr;
  46. if (passParams->mFragParams != nullptr)
  47. passParameters->mFragParams = passParams->mFragParams->getCore();
  48. else
  49. passParameters->mFragParams = nullptr;
  50. if (passParams->mGeomParams != nullptr)
  51. passParameters->mGeomParams = passParams->mGeomParams->getCore();
  52. else
  53. passParameters->mGeomParams = nullptr;
  54. if (passParams->mHullParams != nullptr)
  55. passParameters->mHullParams = passParams->mHullParams->getCore();
  56. else
  57. passParameters->mHullParams = nullptr;
  58. if (passParams->mDomainParams != nullptr)
  59. passParameters->mDomainParams = passParams->mDomainParams->getCore();
  60. else
  61. passParameters->mDomainParams = nullptr;
  62. if (passParams->mComputeParams != nullptr)
  63. passParameters->mComputeParams = passParams->mComputeParams->getCore();
  64. else
  65. passParameters->mComputeParams = nullptr;
  66. return passParameters;
  67. }
  68. bool areParamsEqual(const GpuParamDataDesc& paramA, const GpuParamDataDesc& paramB, bool ignoreBufferOffsets)
  69. {
  70. bool equal = paramA.arraySize == paramB.arraySize && paramA.elementSize == paramB.elementSize
  71. && paramA.type == paramB.type && paramA.arrayElementStride == paramB.arrayElementStride;
  72. if (!ignoreBufferOffsets)
  73. equal &= paramA.cpuMemOffset == paramB.cpuMemOffset && paramA.gpuMemOffset == paramB.gpuMemOffset;
  74. return equal;
  75. }
  76. Map<String, const GpuParamDataDesc*> determineValidDataParameters(const Vector<SPtr<GpuParamDesc>>& paramDescs)
  77. {
  78. Map<String, const GpuParamDataDesc*> foundDataParams;
  79. Map<String, bool> validParams;
  80. for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  81. {
  82. const GpuParamDesc& curDesc = **iter;
  83. // Check regular data params
  84. for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
  85. {
  86. const GpuParamDataDesc& curParam = iter2->second;
  87. auto dataFindIter = validParams.find(iter2->first);
  88. if (dataFindIter == validParams.end())
  89. {
  90. validParams[iter2->first] = true;
  91. foundDataParams[iter2->first] = &curParam;
  92. }
  93. else
  94. {
  95. if (validParams[iter2->first])
  96. {
  97. auto dataFindIter2 = foundDataParams.find(iter2->first);
  98. const GpuParamDataDesc* otherParam = dataFindIter2->second;
  99. if (!areParamsEqual(curParam, *otherParam, true))
  100. {
  101. validParams[iter2->first] = false;
  102. foundDataParams.erase(dataFindIter2);
  103. }
  104. }
  105. }
  106. }
  107. }
  108. return foundDataParams;
  109. }
  110. Vector<const GpuParamObjectDesc*> determineValidObjectParameters(const Vector<SPtr<GpuParamDesc>>& paramDescs)
  111. {
  112. Vector<const GpuParamObjectDesc*> validParams;
  113. for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  114. {
  115. const GpuParamDesc& curDesc = **iter;
  116. // Check sampler params
  117. for (auto iter2 = curDesc.samplers.begin(); iter2 != curDesc.samplers.end(); ++iter2)
  118. {
  119. validParams.push_back(&iter2->second);
  120. }
  121. // Check texture params
  122. for (auto iter2 = curDesc.textures.begin(); iter2 != curDesc.textures.end(); ++iter2)
  123. {
  124. validParams.push_back(&iter2->second);
  125. }
  126. // Check load-store texture params
  127. for (auto iter2 = curDesc.loadStoreTextures.begin(); iter2 != curDesc.loadStoreTextures.end(); ++iter2)
  128. {
  129. validParams.push_back(&iter2->second);
  130. }
  131. // Check buffer params
  132. for (auto iter2 = curDesc.buffers.begin(); iter2 != curDesc.buffers.end(); ++iter2)
  133. {
  134. validParams.push_back(&iter2->second);
  135. }
  136. }
  137. return validParams;
  138. }
  139. Set<String> determineValidShareableParamBlocks(const Vector<SPtr<GpuParamDesc>>& paramDescs)
  140. {
  141. // Make sure param blocks with the same name actually are the same
  142. Map<String, std::pair<String, SPtr<GpuParamDesc>>> uniqueParamBlocks;
  143. Map<String, bool> validParamBlocks;
  144. for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  145. {
  146. const GpuParamDesc& curDesc = **iter;
  147. for (auto blockIter = curDesc.paramBlocks.begin(); blockIter != curDesc.paramBlocks.end(); ++blockIter)
  148. {
  149. bool isBlockValid = true;
  150. const GpuParamBlockDesc& curBlock = blockIter->second;
  151. if (!curBlock.isShareable) // Non-shareable buffers are handled differently, they're allowed same names
  152. continue;
  153. auto iterFind = uniqueParamBlocks.find(blockIter->first);
  154. if (iterFind == uniqueParamBlocks.end())
  155. {
  156. uniqueParamBlocks[blockIter->first] = std::make_pair(blockIter->first, *iter);
  157. validParamBlocks[blockIter->first] = true;
  158. continue;
  159. }
  160. String otherBlockName = iterFind->second.first;
  161. SPtr<GpuParamDesc> otherDesc = iterFind->second.second;
  162. for (auto myParamIter = curDesc.params.begin(); myParamIter != curDesc.params.end(); ++myParamIter)
  163. {
  164. const GpuParamDataDesc& myParam = myParamIter->second;
  165. if (myParam.paramBlockSlot != curBlock.slot)
  166. continue; // Param is in another block, so we will check it when its time for that block
  167. auto otherParamFind = otherDesc->params.find(myParamIter->first);
  168. // Cannot find other param, blocks aren't equal
  169. if (otherParamFind == otherDesc->params.end())
  170. {
  171. isBlockValid = false;
  172. break;
  173. }
  174. const GpuParamDataDesc& otherParam = otherParamFind->second;
  175. if (!areParamsEqual(myParam, otherParam, false) || curBlock.name != otherBlockName)
  176. {
  177. isBlockValid = false;
  178. break;
  179. }
  180. }
  181. if (!isBlockValid)
  182. {
  183. if (validParamBlocks[blockIter->first])
  184. {
  185. LOGWRN("Found two param blocks with the same name but different contents: " + blockIter->first);
  186. validParamBlocks[blockIter->first] = false;
  187. }
  188. }
  189. }
  190. }
  191. Set<String> validParamBlocksReturn;
  192. for (auto iter = validParamBlocks.begin(); iter != validParamBlocks.end(); ++iter)
  193. {
  194. if (iter->second)
  195. validParamBlocksReturn.insert(iter->first);
  196. }
  197. return validParamBlocksReturn;
  198. }
  199. Map<String, String> determineParameterToBlockMapping(const Vector<SPtr<GpuParamDesc>>& paramDescs)
  200. {
  201. Map<String, String> paramToParamBlock;
  202. for (auto iter = paramDescs.begin(); iter != paramDescs.end(); ++iter)
  203. {
  204. const GpuParamDesc& curDesc = **iter;
  205. for (auto iter2 = curDesc.params.begin(); iter2 != curDesc.params.end(); ++iter2)
  206. {
  207. const GpuParamDataDesc& curParam = iter2->second;
  208. auto iterFind = paramToParamBlock.find(curParam.name);
  209. if (iterFind != paramToParamBlock.end())
  210. continue;
  211. for (auto iterBlock = curDesc.paramBlocks.begin(); iterBlock != curDesc.paramBlocks.end(); ++iterBlock)
  212. {
  213. if (iterBlock->second.slot == curParam.paramBlockSlot)
  214. {
  215. paramToParamBlock[curParam.name] = iterBlock->second.name;
  216. break;
  217. }
  218. }
  219. }
  220. }
  221. return paramToParamBlock;
  222. }
  223. Map<String, String> determineParamMappings(const Vector<SPtr<GpuParamDesc>>& paramDescs,
  224. const Map<String, SHADER_DATA_PARAM_DESC>& dataParams,
  225. const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams,
  226. const Map<String, SHADER_OBJECT_PARAM_DESC>& bufferParams,
  227. const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams)
  228. {
  229. Map<String, String> validParams;
  230. Map<String, const GpuParamDataDesc*> validDataParameters = determineValidDataParameters(paramDescs);
  231. Vector<const GpuParamObjectDesc*> validObjectParameters = determineValidObjectParameters(paramDescs);
  232. Map<String, String> paramToParamBlockMap = determineParameterToBlockMapping(paramDescs);
  233. // Create data param mappings
  234. for (auto iter = dataParams.begin(); iter != dataParams.end(); ++iter)
  235. {
  236. auto findIter = validDataParameters.find(iter->second.gpuVariableName);
  237. // Not valid so we skip it
  238. if (findIter == validDataParameters.end())
  239. continue;
  240. if (findIter->second->type != iter->second.type && !(iter->second.type == GPDT_COLOR && findIter->second->type == GPDT_FLOAT4))
  241. {
  242. LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Type doesn't match the one defined in the gpu program. "
  243. + "Shader defined type: " + toString(iter->second.type) + " - Gpu program defined type: " + toString(findIter->second->type));
  244. continue;
  245. }
  246. if (findIter->second->arraySize != iter->second.arraySize)
  247. {
  248. LOGWRN("Ignoring shader parameter \"" + iter->first + "\". Array size doesn't match the one defined in the gpu program."
  249. + "Shader defined array size: " + toString(iter->second.arraySize) + " - Gpu program defined array size: " + toString(findIter->second->arraySize));
  250. continue;
  251. }
  252. auto findBlockIter = paramToParamBlockMap.find(iter->second.gpuVariableName);
  253. if (findBlockIter == paramToParamBlockMap.end())
  254. BS_EXCEPT(InternalErrorException, "Parameter doesn't exist in param to param block map but exists in valid param map.");
  255. validParams[iter->first] = iter->second.gpuVariableName;
  256. }
  257. // Create object param mappings
  258. auto determineObjectMappings = [&](const Map<String, SHADER_OBJECT_PARAM_DESC>& params)
  259. {
  260. for (auto iter = params.begin(); iter != params.end(); ++iter)
  261. {
  262. const Vector<String>& gpuVariableNames = iter->second.gpuVariableNames;
  263. for (auto iter2 = gpuVariableNames.begin(); iter2 != gpuVariableNames.end(); ++iter2)
  264. {
  265. for (auto iter3 = validObjectParameters.begin(); iter3 != validObjectParameters.end(); ++iter3)
  266. {
  267. if ((*iter3)->name == (*iter2) && (*iter3)->type == iter->second.type)
  268. {
  269. validParams[iter->first] = *iter2;
  270. break;
  271. }
  272. }
  273. }
  274. }
  275. };
  276. determineObjectMappings(textureParams);
  277. determineObjectMappings(samplerParams);
  278. determineObjectMappings(bufferParams);
  279. return validParams;
  280. }
  281. Vector<ShaderBlockDesc> determineShaderBlockData(const Set<String>& paramBlocks, const Vector<SPtr<GpuParamDesc>>& paramDescs,
  282. const Map<String, SHADER_PARAM_BLOCK_DESC>& shaderDesc)
  283. {
  284. Vector<ShaderBlockDesc> output;
  285. for (auto iter = paramBlocks.begin(); iter != paramBlocks.end(); ++iter)
  286. {
  287. ShaderBlockDesc shaderBlockDesc;
  288. shaderBlockDesc.create = true;
  289. shaderBlockDesc.usage = GPBU_STATIC;
  290. shaderBlockDesc.size = 0;
  291. shaderBlockDesc.name = *iter;
  292. auto iterFind = shaderDesc.find(*iter);
  293. if (iterFind != shaderDesc.end())
  294. {
  295. shaderBlockDesc.create = !iterFind->second.shared && iterFind->second.rendererSemantic == StringID::NONE;
  296. shaderBlockDesc.usage = iterFind->second.usage;
  297. }
  298. for (auto iter2 = paramDescs.begin(); iter2 != paramDescs.end(); ++iter2)
  299. {
  300. auto findParamBlockDesc = (*iter2)->paramBlocks.find(*iter);
  301. if (findParamBlockDesc != (*iter2)->paramBlocks.end())
  302. {
  303. shaderBlockDesc.size = findParamBlockDesc->second.blockSize * sizeof(UINT32);
  304. break;
  305. }
  306. }
  307. output.push_back(shaderBlockDesc);
  308. }
  309. return output;
  310. }
  311. template<class T>
  312. bool isShaderValid(const T& shader) { return false; }
  313. template<>
  314. bool isShaderValid(const HShader& shader) { return shader.isLoaded(); }
  315. template<>
  316. bool isShaderValid(const SPtr<ShaderCore>& shader) { return shader != nullptr; }
  317. Vector<SPtr<GpuParamDesc>> MaterialBase::getAllParamDescs(const SPtr<Technique>& technique)
  318. {
  319. Vector<SPtr<GpuParamDesc>> allParamDescs;
  320. // Make sure all gpu programs are fully loaded
  321. for (UINT32 i = 0; i < technique->getNumPasses(); i++)
  322. {
  323. SPtr<Pass> curPass = technique->getPass(i);
  324. SPtr<GpuProgram> vertProgram = curPass->getVertexProgram();
  325. if (vertProgram)
  326. {
  327. vertProgram->blockUntilCoreInitialized();
  328. allParamDescs.push_back(vertProgram->getParamDesc());
  329. }
  330. SPtr<GpuProgram> fragProgram = curPass->getFragmentProgram();
  331. if (fragProgram)
  332. {
  333. fragProgram->blockUntilCoreInitialized();
  334. allParamDescs.push_back(fragProgram->getParamDesc());
  335. }
  336. SPtr<GpuProgram> geomProgram = curPass->getGeometryProgram();
  337. if (geomProgram)
  338. {
  339. geomProgram->blockUntilCoreInitialized();
  340. allParamDescs.push_back(geomProgram->getParamDesc());
  341. }
  342. SPtr<GpuProgram> hullProgram = curPass->getHullProgram();
  343. if (hullProgram)
  344. {
  345. hullProgram->blockUntilCoreInitialized();
  346. allParamDescs.push_back(hullProgram->getParamDesc());
  347. }
  348. SPtr<GpuProgram> domainProgram = curPass->getDomainProgram();
  349. if (domainProgram)
  350. {
  351. domainProgram->blockUntilCoreInitialized();
  352. allParamDescs.push_back(domainProgram->getParamDesc());
  353. }
  354. SPtr<GpuProgram> computeProgram = curPass->getComputeProgram();
  355. if (computeProgram)
  356. {
  357. computeProgram->blockUntilCoreInitialized();
  358. allParamDescs.push_back(computeProgram->getParamDesc());
  359. }
  360. }
  361. return allParamDescs;
  362. }
  363. Vector<SPtr<GpuParamDesc>> MaterialBase::getAllParamDescs(const SPtr<TechniqueCore>& technique)
  364. {
  365. Vector<SPtr<GpuParamDesc>> allParamDescs;
  366. // Make sure all gpu programs are fully loaded
  367. for (UINT32 i = 0; i < technique->getNumPasses(); i++)
  368. {
  369. SPtr<PassCore> curPass = technique->getPass(i);
  370. SPtr<GpuProgramCore> vertProgram = curPass->getVertexProgram();
  371. if (vertProgram)
  372. allParamDescs.push_back(vertProgram->getParamDesc());
  373. SPtr<GpuProgramCore> fragProgram = curPass->getFragmentProgram();
  374. if (fragProgram)
  375. allParamDescs.push_back(fragProgram->getParamDesc());
  376. SPtr<GpuProgramCore> geomProgram = curPass->getGeometryProgram();
  377. if (geomProgram)
  378. allParamDescs.push_back(geomProgram->getParamDesc());
  379. SPtr<GpuProgramCore> hullProgram = curPass->getHullProgram();
  380. if (hullProgram)
  381. allParamDescs.push_back(hullProgram->getParamDesc());
  382. SPtr<GpuProgramCore> domainProgram = curPass->getDomainProgram();
  383. if (domainProgram)
  384. allParamDescs.push_back(domainProgram->getParamDesc());
  385. SPtr<GpuProgramCore> computeProgram = curPass->getComputeProgram();
  386. if (computeProgram)
  387. allParamDescs.push_back(computeProgram->getParamDesc());
  388. }
  389. return allParamDescs;
  390. }
  391. template<bool Core>
  392. UINT32 TMaterial<Core>::getNumPasses() const
  393. {
  394. if (mShader == nullptr)
  395. return 0;
  396. return mShader->getBestTechnique()->getNumPasses();
  397. }
  398. template<bool Core>
  399. SPtr<typename TMaterial<Core>::PassType> TMaterial<Core>::getPass(UINT32 passIdx) const
  400. {
  401. if (passIdx < 0 || passIdx >= mShader->getBestTechnique()->getNumPasses())
  402. BS_EXCEPT(InvalidParametersException, "Invalid pass index.");
  403. return mShader->getBestTechnique()->getPass(passIdx);
  404. }
  405. template<bool Core>
  406. TMaterialParamStruct<Core> TMaterial<Core>::getParamStruct(const String& name) const
  407. {
  408. throwIfNotInitialized();
  409. SPtr<Vector<TGpuParamStruct<Core>>> gpuParams;
  410. auto iterFind = mValidParams.find(name);
  411. if (iterFind != mValidParams.end())
  412. {
  413. const String& gpuVarName = iterFind->second;
  414. gpuParams = bs_shared_ptr_new<Vector<TGpuParamStruct<Core>>>();
  415. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  416. {
  417. SPtr<PassParamsType> params = *iter;
  418. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  419. {
  420. GpuParamsType& paramPtr = params->getParamByIdx(i);
  421. if (paramPtr)
  422. {
  423. if (paramPtr->hasParam(gpuVarName))
  424. {
  425. gpuParams->push_back(TGpuParamStruct<Core>());
  426. paramPtr->getStructParam(gpuVarName, gpuParams->back());
  427. }
  428. }
  429. }
  430. }
  431. }
  432. return createStructParam(name, gpuParams);
  433. }
  434. template<bool Core>
  435. TMaterialParamTexture<Core> TMaterial<Core>::getParamTexture(const String& name) const
  436. {
  437. throwIfNotInitialized();
  438. SPtr<Vector<TGpuParamTexture<Core>>> gpuParams;
  439. auto iterFind = mValidParams.find(name);
  440. if (iterFind != mValidParams.end())
  441. {
  442. const String& gpuVarName = iterFind->second;
  443. gpuParams = bs_shared_ptr_new<Vector<TGpuParamTexture<Core>>>();
  444. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  445. {
  446. SPtr<PassParamsType> params = *iter;
  447. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  448. {
  449. GpuParamsType& paramPtr = params->getParamByIdx(i);
  450. if (paramPtr)
  451. {
  452. if (paramPtr->hasTexture(gpuVarName))
  453. {
  454. gpuParams->push_back(TGpuParamTexture<Core>());
  455. paramPtr->getTextureParam(gpuVarName, gpuParams->back());
  456. }
  457. }
  458. }
  459. }
  460. }
  461. return createTextureParam(name, gpuParams);
  462. }
  463. template<bool Core>
  464. TMaterialParamLoadStoreTexture<Core> TMaterial<Core>::getParamLoadStoreTexture(const String& name) const
  465. {
  466. throwIfNotInitialized();
  467. SPtr<Vector<TGpuParamLoadStoreTexture<Core>>> gpuParams;
  468. auto iterFind = mValidParams.find(name);
  469. if (iterFind != mValidParams.end())
  470. {
  471. const String& gpuVarName = iterFind->second;
  472. gpuParams = bs_shared_ptr_new<Vector<TGpuParamLoadStoreTexture<Core>>>();
  473. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  474. {
  475. SPtr<PassParamsType> params = *iter;
  476. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  477. {
  478. GpuParamsType& paramPtr = params->getParamByIdx(i);
  479. if (paramPtr)
  480. {
  481. if (paramPtr->hasLoadStoreTexture(gpuVarName))
  482. {
  483. gpuParams->push_back(TGpuParamLoadStoreTexture<Core>());
  484. paramPtr->getLoadStoreTextureParam(gpuVarName, gpuParams->back());
  485. }
  486. }
  487. }
  488. }
  489. }
  490. return createLoadStoreTextureParam(name, gpuParams);
  491. }
  492. template<bool Core>
  493. TMaterialParamBuffer<Core> TMaterial<Core>::getParamBuffer(const String& name) const
  494. {
  495. throwIfNotInitialized();
  496. SPtr<Vector<TGpuParamBuffer<Core>>> gpuParams;
  497. auto iterFind = mValidParams.find(name);
  498. if (iterFind != mValidParams.end())
  499. {
  500. const String& gpuVarName = iterFind->second;
  501. gpuParams = bs_shared_ptr_new<Vector<TGpuParamBuffer<Core>>>();
  502. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  503. {
  504. SPtr<PassParamsType> params = *iter;
  505. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  506. {
  507. GpuParamsType& paramPtr = params->getParamByIdx(i);
  508. if (paramPtr)
  509. {
  510. if (paramPtr->hasBuffer(gpuVarName))
  511. {
  512. gpuParams->push_back(TGpuParamBuffer<Core>());
  513. paramPtr->getBufferParam(gpuVarName, gpuParams->back());
  514. }
  515. }
  516. }
  517. }
  518. }
  519. return createBufferParam(name, gpuParams);
  520. }
  521. template<bool Core>
  522. TMaterialParamSampState<Core> TMaterial<Core>::getParamSamplerState(const String& name) const
  523. {
  524. throwIfNotInitialized();
  525. SPtr<Vector<TGpuParamSampState<Core>>> gpuParams;
  526. auto iterFind = mValidParams.find(name);
  527. if (iterFind != mValidParams.end())
  528. {
  529. const String& gpuVarName = iterFind->second;
  530. gpuParams = bs_shared_ptr_new<Vector<TGpuParamSampState<Core>>>();
  531. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  532. {
  533. SPtr<PassParamsType> params = *iter;
  534. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  535. {
  536. GpuParamsType& paramPtr = params->getParamByIdx(i);
  537. if (paramPtr)
  538. {
  539. if (paramPtr->hasSamplerState(gpuVarName))
  540. {
  541. gpuParams->push_back(TGpuParamSampState<Core>());
  542. paramPtr->getSamplerStateParam(gpuVarName, gpuParams->back());
  543. }
  544. }
  545. }
  546. }
  547. }
  548. return createSamplerStateParam(name, gpuParams);
  549. }
  550. template<bool Core>
  551. typename TMaterial<Core>::GpuParamsType TMaterial<Core>::getGpuParams(UINT32 passIdx, BansheeEngine::GpuProgramType type)
  552. {
  553. if (passIdx >= mParametersPerPass.size())
  554. return nullptr;
  555. switch(type)
  556. {
  557. case GPT_VERTEX_PROGRAM:
  558. return mParametersPerPass[passIdx]->mVertParams;
  559. case GPT_FRAGMENT_PROGRAM:
  560. return mParametersPerPass[passIdx]->mFragParams;
  561. case GPT_GEOMETRY_PROGRAM:
  562. return mParametersPerPass[passIdx]->mGeomParams;
  563. case GPT_HULL_PROGRAM:
  564. return mParametersPerPass[passIdx]->mHullParams;
  565. case GPT_DOMAIN_PROGRAM:
  566. return mParametersPerPass[passIdx]->mDomainParams;
  567. case GPT_COMPUTE_PROGRAM:
  568. return mParametersPerPass[passIdx]->mComputeParams;
  569. }
  570. return nullptr;
  571. }
  572. template<bool Core>
  573. void TMaterial<Core>::setParamBlockBuffer(const String& name, const ParamBlockPtrType& paramBlock)
  574. {
  575. auto iterFind = mValidShareableParamBlocks.find(name);
  576. if (iterFind == mValidShareableParamBlocks.end())
  577. {
  578. LOGWRN_VERBOSE("Material doesn't have a parameter block named " + name);
  579. return;
  580. }
  581. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  582. {
  583. SPtr<PassParamsType> params = *iter;
  584. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  585. {
  586. GpuParamsType& paramPtr = params->getParamByIdx(i);
  587. if (paramPtr)
  588. {
  589. if (paramPtr->hasParamBlock(name))
  590. paramPtr->setParamBlockBuffer(name, paramBlock);
  591. }
  592. }
  593. }
  594. }
  595. template<bool Core>
  596. void TMaterial<Core>::initBestTechnique()
  597. {
  598. mBestTechnique = nullptr;
  599. mParametersPerPass.clear();
  600. if (isShaderValid(mShader))
  601. {
  602. createCachedParams(mShader);
  603. mBestTechnique = mShader->getBestTechnique();
  604. if (mBestTechnique == nullptr)
  605. return;
  606. mValidShareableParamBlocks.clear();
  607. Vector<SPtr<GpuParamDesc>> allParamDescs = getAllParamDescs(mBestTechnique);
  608. mValidParams = determineParamMappings(allParamDescs, mShader->getDataParams(), mShader->getTextureParams(),
  609. mShader->getBufferParams(), mShader->getSamplerParams());
  610. // Fill out various helper structures
  611. Set<String> validShareableParamBlocks = determineValidShareableParamBlocks(allParamDescs);
  612. Vector<ShaderBlockDesc> paramBlockData = determineShaderBlockData(validShareableParamBlocks, allParamDescs, mShader->getParamBlocks());
  613. Map<String, ParamBlockPtrType> paramBlockBuffers;
  614. // Create param blocks
  615. for (auto& paramBlock : paramBlockData)
  616. {
  617. ParamBlockPtrType newParamBlockBuffer;
  618. if (paramBlock.create)
  619. {
  620. newParamBlockBuffer = ParamBlockType::create(paramBlock.size, paramBlock.usage);
  621. }
  622. paramBlockBuffers[paramBlock.name] = newParamBlockBuffer;
  623. mValidShareableParamBlocks.insert(paramBlock.name);
  624. }
  625. for (UINT32 i = 0; i < mBestTechnique->getNumPasses(); i++)
  626. {
  627. SPtr<PassType> curPass = mBestTechnique->getPass(i);
  628. SPtr<PassParamsType> params = SPtr<PassParamsType>(new PassParamsType());
  629. GpuProgramType vertProgram = curPass->getVertexProgram();
  630. if (vertProgram)
  631. params->mVertParams = vertProgram->createParameters();
  632. GpuProgramType fragProgram = curPass->getFragmentProgram();
  633. if (fragProgram)
  634. params->mFragParams = fragProgram->createParameters();
  635. GpuProgramType geomProgram = curPass->getGeometryProgram();
  636. if (geomProgram)
  637. params->mGeomParams = geomProgram->createParameters();
  638. GpuProgramType hullProgram = curPass->getHullProgram();
  639. if (hullProgram)
  640. params->mHullParams = hullProgram->createParameters();
  641. GpuProgramType domainProgram = curPass->getDomainProgram();
  642. if (domainProgram)
  643. params->mDomainParams = domainProgram->createParameters();
  644. GpuProgramType computeProgram = curPass->getComputeProgram();
  645. if (computeProgram)
  646. params->mComputeParams = computeProgram->createParameters();
  647. mParametersPerPass.push_back(params);
  648. }
  649. // Assign param block buffers
  650. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  651. {
  652. SPtr<PassParamsType> params = *iter;
  653. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  654. {
  655. GpuParamsType& paramPtr = params->getParamByIdx(i);
  656. if (paramPtr)
  657. {
  658. // Assign shareable buffers
  659. for (auto iterBlock = mValidShareableParamBlocks.begin(); iterBlock != mValidShareableParamBlocks.end(); ++iterBlock)
  660. {
  661. const String& paramBlockName = *iterBlock;
  662. if (paramPtr->hasParamBlock(paramBlockName))
  663. {
  664. ParamBlockPtrType blockBuffer = paramBlockBuffers[paramBlockName];
  665. paramPtr->setParamBlockBuffer(paramBlockName, blockBuffer);
  666. }
  667. }
  668. // Create non-shareable ones
  669. const GpuParamDesc& desc = paramPtr->getParamDesc();
  670. for (auto iterBlockDesc = desc.paramBlocks.begin(); iterBlockDesc != desc.paramBlocks.end(); ++iterBlockDesc)
  671. {
  672. if (!iterBlockDesc->second.isShareable)
  673. {
  674. ParamBlockPtrType newParamBlockBuffer = ParamBlockType::create(iterBlockDesc->second.blockSize * sizeof(UINT32));
  675. paramPtr->setParamBlockBuffer(iterBlockDesc->first, newParamBlockBuffer);
  676. }
  677. }
  678. }
  679. }
  680. }
  681. // Assign default parameters
  682. initDefaultParameters();
  683. }
  684. _markDependenciesDirty();
  685. }
  686. template <bool Core>
  687. template <typename T>
  688. void TMaterial<Core>::setParamValue(const String& name, UINT8* buffer, UINT32 numElements)
  689. {
  690. TMaterialDataParam<T, Core> param;
  691. getParam(name, param);
  692. T* ptr = (T*)buffer;
  693. for (UINT32 i = 0; i < numElements; i++)
  694. param.set(ptr[i], i);
  695. }
  696. template <bool Core>
  697. void TMaterial<Core>::initDefaultParameters()
  698. {
  699. const Map<String, SHADER_DATA_PARAM_DESC>& dataParams = mShader->getDataParams();
  700. for (auto& paramData : dataParams)
  701. {
  702. if (paramData.second.defaultValueIdx == (UINT32)-1)
  703. continue;
  704. auto iterFind = mValidParams.find(paramData.first);
  705. if (iterFind == mValidParams.end())
  706. continue;
  707. UINT8* buffer = (UINT8*)mShader->getDefaultValue(paramData.second.defaultValueIdx);
  708. if (buffer == nullptr)
  709. continue;
  710. switch (paramData.second.type)
  711. {
  712. case GPDT_FLOAT1:
  713. setParamValue<float>(iterFind->first, buffer, paramData.second.arraySize);
  714. break;
  715. case GPDT_FLOAT2:
  716. setParamValue<Vector2>(iterFind->first, buffer, paramData.second.arraySize);
  717. break;
  718. case GPDT_FLOAT3:
  719. setParamValue<Vector3>(iterFind->first, buffer, paramData.second.arraySize);
  720. break;
  721. case GPDT_FLOAT4:
  722. setParamValue<Vector4>(iterFind->first, buffer, paramData.second.arraySize);
  723. break;
  724. case GPDT_MATRIX_2X2:
  725. setParamValue<Matrix2>(iterFind->first, buffer, paramData.second.arraySize);
  726. break;
  727. case GPDT_MATRIX_2X3:
  728. setParamValue<Matrix2x3>(iterFind->first, buffer, paramData.second.arraySize);
  729. break;
  730. case GPDT_MATRIX_2X4:
  731. setParamValue<Matrix2x4>(iterFind->first, buffer, paramData.second.arraySize);
  732. break;
  733. case GPDT_MATRIX_3X2:
  734. setParamValue<Matrix3x2>(iterFind->first, buffer, paramData.second.arraySize);
  735. break;
  736. case GPDT_MATRIX_3X3:
  737. setParamValue<Matrix3>(iterFind->first, buffer, paramData.second.arraySize);
  738. break;
  739. case GPDT_MATRIX_3X4:
  740. setParamValue<Matrix3x4>(iterFind->first, buffer, paramData.second.arraySize);
  741. break;
  742. case GPDT_MATRIX_4X2:
  743. setParamValue<Matrix4x2>(iterFind->first, buffer, paramData.second.arraySize);
  744. break;
  745. case GPDT_MATRIX_4X3:
  746. setParamValue<Matrix4x3>(iterFind->first, buffer, paramData.second.arraySize);
  747. break;
  748. case GPDT_MATRIX_4X4:
  749. setParamValue<Matrix4>(iterFind->first, buffer, paramData.second.arraySize);
  750. break;
  751. case GPDT_INT1:
  752. setParamValue<int>(iterFind->first, buffer, paramData.second.arraySize);
  753. break;
  754. case GPDT_INT2:
  755. setParamValue<Vector2I>(iterFind->first, buffer, paramData.second.arraySize);
  756. break;
  757. case GPDT_INT3:
  758. setParamValue<Vector3I>(iterFind->first, buffer, paramData.second.arraySize);
  759. break;
  760. case GPDT_INT4:
  761. setParamValue<Vector4I>(iterFind->first, buffer, paramData.second.arraySize);
  762. break;
  763. case GPDT_BOOL:
  764. setParamValue<int>(iterFind->first, buffer, paramData.second.arraySize);
  765. break;
  766. case GPDT_COLOR:
  767. setParamValue<Color>(iterFind->first, buffer, paramData.second.arraySize);
  768. break;
  769. case GPDT_STRUCT:
  770. {
  771. TMaterialParamStruct<Core> param = getParamStruct(paramData.first);
  772. UINT32 elementSizeBytes = paramData.second.elementSize * sizeof(UINT32);
  773. UINT8* ptr = buffer;
  774. for (UINT32 i = 0; i < paramData.second.arraySize; i++)
  775. {
  776. param.set(ptr, elementSizeBytes, i);
  777. ptr += elementSizeBytes;
  778. }
  779. }
  780. break;
  781. default:
  782. break;
  783. }
  784. }
  785. const Map<String, SHADER_OBJECT_PARAM_DESC>& textureParams = mShader->getTextureParams();
  786. for (auto& param : textureParams)
  787. {
  788. if (param.second.defaultValueIdx == (UINT32)-1)
  789. continue;
  790. auto iterFind = mValidParams.find(param.first);
  791. if (iterFind == mValidParams.end())
  792. continue;
  793. TextureType defaultTex = mShader->getDefaultTexture(param.second.defaultValueIdx);
  794. getParamTexture(param.first).set(defaultTex);
  795. }
  796. const Map<String, SHADER_OBJECT_PARAM_DESC>& samplerParams = mShader->getSamplerParams();
  797. for (auto& param : samplerParams)
  798. {
  799. if (param.second.defaultValueIdx == (UINT32)-1)
  800. continue;
  801. auto iterFind = mValidParams.find(param.first);
  802. if (iterFind == mValidParams.end())
  803. continue;
  804. SamplerStateType defaultSampler = mShader->getDefaultSampler(param.second.defaultValueIdx);
  805. getParamSamplerState(param.first).set(defaultSampler);
  806. }
  807. }
  808. template <bool Core>
  809. template <typename T>
  810. void TMaterial<Core>::getParam(const String& name, TMaterialDataParam<T, Core>& output) const
  811. {
  812. throwIfNotInitialized();
  813. SPtr<Vector<TGpuDataParam<T, Core>>> gpuParams;
  814. auto iterFind = mValidParams.find(name);
  815. if (iterFind != mValidParams.end())
  816. {
  817. const String& gpuVarName = iterFind->second;
  818. gpuParams = bs_shared_ptr_new<Vector<TGpuDataParam<T, Core>>>();
  819. for (auto iter = mParametersPerPass.begin(); iter != mParametersPerPass.end(); ++iter)
  820. {
  821. SPtr<PassParamsType> params = *iter;
  822. for (UINT32 i = 0; i < PassParamsType::NUM_PARAMS; i++)
  823. {
  824. GpuParamsType& paramPtr = params->getParamByIdx(i);
  825. if (paramPtr)
  826. {
  827. if (paramPtr->hasParam(gpuVarName))
  828. {
  829. gpuParams->push_back(TGpuDataParam<T, Core>());
  830. paramPtr->template getParam<T>(gpuVarName, gpuParams->back());
  831. }
  832. }
  833. }
  834. }
  835. }
  836. output = createDataParam(name, gpuParams);
  837. }
  838. template<bool Core>
  839. void TMaterial<Core>::throwIfNotInitialized() const
  840. {
  841. if (mShader == nullptr)
  842. {
  843. BS_EXCEPT(InternalErrorException, "Material does not have shader set.");
  844. }
  845. if (mBestTechnique == nullptr)
  846. {
  847. BS_EXCEPT(InternalErrorException, "Shader does not contain a supported technique.");
  848. }
  849. }
  850. template class TMaterial < false > ;
  851. template class TMaterial < true > ;
  852. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<float, false>&) const;
  853. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<int, false>&) const;
  854. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Color, false>&) const;
  855. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector2, false>&) const;
  856. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector3, false>&) const;
  857. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector4, false>&) const;
  858. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector2I, false>&) const;
  859. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector3I, false>&) const;
  860. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Vector4I, false>&) const;
  861. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix2, false>&) const;
  862. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix2x3, false>&) const;
  863. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix2x4, false>&) const;
  864. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix3, false>&) const;
  865. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix3x2, false>&) const;
  866. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix3x4, false>&) const;
  867. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix4, false>&) const;
  868. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix4x2, false>&) const;
  869. template BS_CORE_EXPORT void TMaterial<false>::getParam(const String&, TMaterialDataParam<Matrix4x3, false>&) const;
  870. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<float, true>&) const;
  871. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<int, true>&) const;
  872. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Color, true>&) const;
  873. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector2, true>&) const;
  874. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector3, true>&) const;
  875. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector4, true>&) const;
  876. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector2I, true>&) const;
  877. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector3I, true>&) const;
  878. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Vector4I, true>&) const;
  879. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix2, true>&) const;
  880. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix2x3, true>&) const;
  881. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix2x4, true>&) const;
  882. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix3, true>&) const;
  883. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix3x2, true>&) const;
  884. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix3x4, true>&) const;
  885. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix4, true>&) const;
  886. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix4x2, true>&) const;
  887. template BS_CORE_EXPORT void TMaterial<true>::getParam(const String&, TMaterialDataParam<Matrix4x3, true>&) const;
  888. MaterialCore::MaterialCore(const SPtr<ShaderCore>& shader)
  889. {
  890. setShader(shader);
  891. }
  892. MaterialCore::MaterialCore(const SPtr<ShaderCore>& shader, const SPtr<TechniqueCore>& bestTechnique,
  893. const Set<String>& validShareableParamBlocks, const Map<String, String>& validParams,
  894. const Vector<SPtr<PassParametersCore>>& passParams)
  895. {
  896. mShader = shader;
  897. mBestTechnique = bestTechnique;
  898. mValidShareableParamBlocks = validShareableParamBlocks;
  899. mValidParams = validParams;
  900. UINT32 numPassParams = (UINT32)passParams.size();
  901. mParametersPerPass.resize(numPassParams);
  902. for (UINT32 i = 0; i < numPassParams; i++)
  903. mParametersPerPass[i] = passParams[i];
  904. }
  905. void MaterialCore::setShader(const SPtr<ShaderCore>& shader)
  906. {
  907. mShader = shader;
  908. initBestTechnique();
  909. _markCoreDirty();
  910. }
  911. void MaterialCore::syncToCore(const CoreSyncData& data)
  912. {
  913. char* dataPtr = (char*)data.getBuffer();
  914. mValidShareableParamBlocks.clear();
  915. mValidParams.clear();
  916. mParametersPerPass.clear();
  917. UINT32 numPasses = 0;
  918. dataPtr = rttiReadElem(mValidShareableParamBlocks, dataPtr);
  919. dataPtr = rttiReadElem(mValidParams, dataPtr);
  920. dataPtr = rttiReadElem(numPasses, dataPtr);
  921. for (UINT32 i = 0; i < numPasses; i++)
  922. {
  923. SPtr<PassParametersCore>* passParameters = (SPtr<PassParametersCore>*)dataPtr;
  924. mParametersPerPass.push_back(*passParameters);
  925. passParameters->~SPtr<PassParametersCore>();
  926. dataPtr += sizeof(SPtr<PassParametersCore>);
  927. }
  928. SPtr<ShaderCore>* shader = (SPtr<ShaderCore>*)dataPtr;
  929. mShader = *shader;
  930. shader->~SPtr<ShaderCore>();
  931. dataPtr += sizeof(SPtr<ShaderCore>);
  932. SPtr<TechniqueCore>* technique = (SPtr<TechniqueCore>*)dataPtr;
  933. mBestTechnique = *technique;
  934. technique->~SPtr<TechniqueCore>();
  935. dataPtr += sizeof(SPtr<TechniqueCore>);
  936. }
  937. SPtr<MaterialCore> MaterialCore::create(const SPtr<ShaderCore>& shader)
  938. {
  939. MaterialCore* material = new (bs_alloc<MaterialCore>()) MaterialCore(shader);
  940. SPtr<MaterialCore> materialPtr = bs_shared_ptr<MaterialCore>(material);
  941. materialPtr->_setThisPtr(materialPtr);
  942. materialPtr->initialize();
  943. return materialPtr;
  944. }
  945. Material::Material()
  946. :mLoadFlags(Load_None)
  947. { }
  948. Material::Material(const HShader& shader)
  949. :mLoadFlags(Load_None)
  950. {
  951. mShader = shader;
  952. }
  953. void Material::initialize()
  954. {
  955. _markResourcesDirty();
  956. initializeIfLoaded();
  957. Resource::initialize();
  958. }
  959. void Material::setShader(const HShader& shader)
  960. {
  961. if (mShader == shader)
  962. return;
  963. mShader = shader;
  964. mBestTechnique = nullptr;
  965. mLoadFlags = Load_None;
  966. _markResourcesDirty();
  967. initializeIfLoaded();
  968. }
  969. void Material::_markCoreDirty()
  970. {
  971. markCoreDirty();
  972. }
  973. void Material::_markDependenciesDirty()
  974. {
  975. markDependenciesDirty();
  976. }
  977. void Material::_markResourcesDirty()
  978. {
  979. markListenerResourcesDirty();
  980. }
  981. SPtr<MaterialCore> Material::getCore() const
  982. {
  983. return std::static_pointer_cast<MaterialCore>(mCoreSpecific);
  984. }
  985. SPtr<CoreObjectCore> Material::createCore() const
  986. {
  987. MaterialCore* material = nullptr;
  988. SPtr<ShaderCore> shader;
  989. if (mShader.isLoaded())
  990. {
  991. shader = mShader->getCore();
  992. if (mBestTechnique != nullptr)
  993. {
  994. SPtr<TechniqueCore> technique = mBestTechnique->getCore();
  995. Vector<SPtr<PassParametersCore>> passParams;
  996. for (auto& passParam : mParametersPerPass)
  997. passParams.push_back(convertParamsToCore(passParam));
  998. material = new (bs_alloc<MaterialCore>()) MaterialCore(shader, technique, mValidShareableParamBlocks, mValidParams, passParams);
  999. }
  1000. }
  1001. if (material == nullptr)
  1002. material = new (bs_alloc<MaterialCore>()) MaterialCore(shader);
  1003. SPtr<MaterialCore> materialPtr = bs_shared_ptr<MaterialCore>(material);
  1004. materialPtr->_setThisPtr(materialPtr);
  1005. return materialPtr;
  1006. }
  1007. CoreSyncData Material::syncToCore(FrameAlloc* allocator)
  1008. {
  1009. UINT32 numPasses = (UINT32)mParametersPerPass.size();
  1010. UINT32 size = sizeof(UINT32) + numPasses * sizeof(SPtr<PassParametersCore>)
  1011. + sizeof(SPtr<ShaderCore>) + sizeof(SPtr<TechniqueCore>) + rttiGetElemSize(mValidShareableParamBlocks)
  1012. + rttiGetElemSize(mValidParams);
  1013. UINT8* buffer = allocator->alloc(size);
  1014. char* dataPtr = (char*)buffer;
  1015. dataPtr = rttiWriteElem(mValidShareableParamBlocks, dataPtr);
  1016. dataPtr = rttiWriteElem(mValidParams, dataPtr);
  1017. dataPtr = rttiWriteElem(numPasses, dataPtr);
  1018. for (UINT32 i = 0; i < numPasses; i++)
  1019. {
  1020. SPtr<PassParametersCore>* passParameters = new (dataPtr) SPtr<PassParametersCore>();
  1021. *passParameters = convertParamsToCore(mParametersPerPass[i]);
  1022. dataPtr += sizeof(SPtr<PassParametersCore>);
  1023. }
  1024. SPtr<ShaderCore>* shader = new (dataPtr)SPtr<ShaderCore>();
  1025. if (mShader.isLoaded(false))
  1026. *shader = mShader->getCore();
  1027. else
  1028. *shader = nullptr;
  1029. dataPtr += sizeof(SPtr<ShaderCore>);
  1030. SPtr<TechniqueCore>* technique = new (dataPtr)SPtr<TechniqueCore>();
  1031. if (mBestTechnique != nullptr)
  1032. *technique = mBestTechnique->getCore();
  1033. else
  1034. *technique = nullptr;
  1035. dataPtr += sizeof(SPtr<TechniqueCore>);
  1036. return CoreSyncData(buffer, size);
  1037. }
  1038. void Material::getCoreDependencies(Vector<CoreObject*>& dependencies)
  1039. {
  1040. if (mShader.isLoaded())
  1041. dependencies.push_back(mShader.get());
  1042. for (auto& params : mParametersPerPass)
  1043. {
  1044. for (UINT32 i = 0; i < PassParameters::NUM_PARAMS; i++)
  1045. {
  1046. SPtr<GpuParams> gpuParams = params->getParamByIdx(i);
  1047. if (gpuParams != nullptr)
  1048. dependencies.push_back(gpuParams.get());
  1049. }
  1050. }
  1051. }
  1052. void Material::getListenerResources(Vector<HResource>& resources)
  1053. {
  1054. if (mShader != nullptr)
  1055. resources.push_back(mShader);
  1056. }
  1057. void Material::getResourceDependencies(FrameVector<HResource>& dependencies) const
  1058. {
  1059. if (mShader != nullptr)
  1060. dependencies.push_back(mShader);
  1061. }
  1062. void Material::initializeIfLoaded()
  1063. {
  1064. if (areDependenciesLoaded())
  1065. {
  1066. if (mLoadFlags != Load_All)
  1067. {
  1068. mLoadFlags = Load_All;
  1069. // Shader about to change, so save parameters, rebuild material and restore parameters
  1070. SPtr<MaterialParams> oldParams = mCachedParams;
  1071. initBestTechnique();
  1072. markCoreDirty();
  1073. if (mBestTechnique == nullptr) // Wasn't initialized
  1074. return;
  1075. setParams(oldParams);
  1076. }
  1077. }
  1078. else
  1079. {
  1080. if (mShader.isLoaded() && mLoadFlags == Load_None)
  1081. {
  1082. mLoadFlags = Load_Shader;
  1083. markListenerResourcesDirty(); // Need to register resources dependent on shader now
  1084. }
  1085. }
  1086. }
  1087. void Material::createCachedParams(const HShader& shader)
  1088. {
  1089. mCachedParams = bs_shared_ptr_new<MaterialParams>(shader);
  1090. }
  1091. void Material::notifyResourceLoaded(const HResource& resource)
  1092. {
  1093. initializeIfLoaded();
  1094. }
  1095. void Material::notifyResourceChanged(const HResource& resource)
  1096. {
  1097. mLoadFlags = Load_None;
  1098. initializeIfLoaded();
  1099. }
  1100. HMaterial Material::clone()
  1101. {
  1102. UINT32 bufferSize = 0;
  1103. MemorySerializer serializer;
  1104. UINT8* buffer = serializer.encode(this, bufferSize, (void*(*)(UINT32))&bs_alloc);
  1105. SPtr<Material> cloneObj = std::static_pointer_cast<Material>(serializer.decode(buffer, bufferSize));
  1106. bs_free(buffer);
  1107. return static_resource_cast<Material>(gResources()._createResourceHandle(cloneObj));
  1108. }
  1109. template<class T>
  1110. void copyParam(const SPtr<MaterialParams>& from, Material* to, const String& name, UINT32 index, UINT32 arraySize)
  1111. {
  1112. TMaterialDataParam<T, false> param;
  1113. to->getParam(name, param);
  1114. T paramData;
  1115. for (UINT32 i = 0; i < arraySize; i++)
  1116. {
  1117. from->getDataParam(index, i, paramData);
  1118. param.set(paramData, i);
  1119. }
  1120. }
  1121. void Material::setParams(const SPtr<MaterialParams>& params)
  1122. {
  1123. if (params == nullptr)
  1124. return;
  1125. std::function<void(const SPtr<MaterialParams>&, Material*, const String&, UINT32, UINT32)> copyParamLookup[GPDT_COUNT];
  1126. copyParamLookup[GPDT_FLOAT1] = &copyParam<float>;
  1127. copyParamLookup[GPDT_FLOAT2] = &copyParam<Vector2>;
  1128. copyParamLookup[GPDT_FLOAT3] = &copyParam<Vector3>;
  1129. copyParamLookup[GPDT_FLOAT4] = &copyParam<Vector4>;
  1130. copyParamLookup[GPDT_INT1] = &copyParam<int>;
  1131. copyParamLookup[GPDT_INT2] = &copyParam<Vector2I>;
  1132. copyParamLookup[GPDT_INT3] = &copyParam<Vector3I>;
  1133. copyParamLookup[GPDT_INT4] = &copyParam<Vector4I>;
  1134. copyParamLookup[GPDT_MATRIX_2X2] = &copyParam<Matrix2>;
  1135. copyParamLookup[GPDT_MATRIX_2X3] = &copyParam<Matrix2x3>;
  1136. copyParamLookup[GPDT_MATRIX_2X4] = &copyParam<Matrix2x4>;
  1137. copyParamLookup[GPDT_MATRIX_3X3] = &copyParam<Matrix3>;
  1138. copyParamLookup[GPDT_MATRIX_3X2] = &copyParam<Matrix3x2>;
  1139. copyParamLookup[GPDT_MATRIX_3X4] = &copyParam<Matrix3x4>;
  1140. copyParamLookup[GPDT_MATRIX_4X4] = &copyParam<Matrix4>;
  1141. copyParamLookup[GPDT_MATRIX_4X2] = &copyParam<Matrix4x2>;
  1142. copyParamLookup[GPDT_MATRIX_4X3] = &copyParam<Matrix4x3>;
  1143. copyParamLookup[GPDT_BOOL] = &copyParam<int>;
  1144. copyParamLookup[GPDT_COLOR] = &copyParam<Color>;
  1145. auto& dataParams = mShader->getDataParams();
  1146. for (auto& param : dataParams)
  1147. {
  1148. UINT32 arraySize = param.second.arraySize > 1 ? param.second.arraySize : 1;
  1149. const MaterialParams::ParamData* paramData = nullptr;
  1150. auto result = params->getParamData(param.first, MaterialParams::ParamType::Data, param.second.type, 0, &paramData);
  1151. if (result != MaterialParams::GetParamResult::Success)
  1152. continue;
  1153. UINT32 elemsToCopy = std::min(arraySize, paramData->arraySize);
  1154. auto& copyFunction = copyParamLookup[param.second.type];
  1155. if (copyFunction != nullptr)
  1156. copyFunction(params, this, param.first, paramData->index, elemsToCopy);
  1157. else
  1158. {
  1159. if(param.second.type == GPDT_STRUCT)
  1160. {
  1161. TMaterialParamStruct<false> curParam = getParamStruct(param.first);
  1162. UINT32 structSize = params->getStructSize(paramData->index);
  1163. if (param.second.elementSize != structSize)
  1164. continue;
  1165. UINT8* structData = (UINT8*)bs_stack_alloc(structSize);
  1166. for (UINT32 i = 0; i < elemsToCopy; i++)
  1167. {
  1168. params->getStructData(paramData->index + i, structData, structSize);
  1169. curParam.set(structData, structSize, i);
  1170. }
  1171. bs_stack_free(structData);
  1172. }
  1173. }
  1174. }
  1175. auto& textureParams = mShader->getTextureParams();
  1176. for (auto& param : textureParams)
  1177. {
  1178. const MaterialParams::ParamData* paramData = nullptr;
  1179. auto result = params->getParamData(param.first, MaterialParams::ParamType::Texture, GPDT_UNKNOWN, 0, &paramData);
  1180. if (result != MaterialParams::GetParamResult::Success)
  1181. continue;
  1182. bool isLoadStore = params->getIsTextureLoadStore(paramData->index);
  1183. if(!isLoadStore)
  1184. {
  1185. TMaterialParamTexture<false> curParam = getParamTexture(param.first);
  1186. HTexture texture;
  1187. params->getTexture(paramData->index, texture);
  1188. curParam.set(texture);
  1189. }
  1190. else
  1191. {
  1192. TMaterialParamLoadStoreTexture<false> curParam = getParamLoadStoreTexture(param.first);
  1193. HTexture texture;
  1194. TextureSurface surface;
  1195. params->getLoadStoreTexture(paramData->index, texture, surface);
  1196. curParam.set(texture, surface);
  1197. }
  1198. }
  1199. auto& bufferParams = mShader->getBufferParams();
  1200. for (auto& param : bufferParams)
  1201. {
  1202. const MaterialParams::ParamData* paramData = nullptr;
  1203. auto result = params->getParamData(param.first, MaterialParams::ParamType::Buffer, GPDT_UNKNOWN, 0, &paramData);
  1204. if (result != MaterialParams::GetParamResult::Success)
  1205. continue;
  1206. TMaterialParamBuffer<false> curParam = getParamBuffer(param.first);
  1207. SPtr<GpuBuffer> buffer;
  1208. params->getBuffer(paramData->index, buffer);
  1209. curParam.set(buffer);
  1210. }
  1211. auto& samplerParams = mShader->getSamplerParams();
  1212. for (auto& param : samplerParams)
  1213. {
  1214. const MaterialParams::ParamData* paramData = nullptr;
  1215. auto result = params->getParamData(param.first, MaterialParams::ParamType::Sampler, GPDT_UNKNOWN, 0, &paramData);
  1216. if (result != MaterialParams::GetParamResult::Success)
  1217. continue;
  1218. TMaterialParamSampState<false> curParam = getParamSamplerState(param.first);
  1219. SPtr<SamplerState> samplerState;
  1220. params->getSamplerState(paramData->index, samplerState);
  1221. curParam.set(samplerState);
  1222. }
  1223. }
  1224. HMaterial Material::create()
  1225. {
  1226. SPtr<Material> materialPtr = MaterialManager::instance().create();
  1227. return static_resource_cast<Material>(gResources()._createResourceHandle(materialPtr));
  1228. }
  1229. HMaterial Material::create(const HShader& shader)
  1230. {
  1231. SPtr<Material> materialPtr = MaterialManager::instance().create(shader);
  1232. return static_resource_cast<Material>(gResources()._createResourceHandle(materialPtr));
  1233. }
  1234. RTTITypeBase* Material::getRTTIStatic()
  1235. {
  1236. return MaterialRTTI::instance();
  1237. }
  1238. RTTITypeBase* Material::getRTTI() const
  1239. {
  1240. return Material::getRTTIStatic();
  1241. }
  1242. }