ShaderSerialize.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. // Original file Copyright Crytek GMBH or its affiliates, used under license.
  13. #include "RenderDll_precompiled.h"
  14. #ifdef SHADERS_SERIALIZING
  15. bool CShaderSerialize::_OpenSResource(float fVersion, SSShaderRes* pSR, CShader* pSH, int nCache, CResFile* pRF, bool bReadOnly)
  16. {
  17. assert(nCache == CACHE_USER || nCache == CACHE_READONLY);
  18. SSShaderCacheHeader hd;
  19. ZeroStruct(hd);
  20. bool bValid = true;
  21. bool bCheckValid = true;
  22. if (!CRenderer::CV_r_shadersAllowCompilation)
  23. {
  24. bCheckValid = false;
  25. }
  26. //uint64 writeTimeCFX=0;
  27. //See if resfile is in assets dir
  28. if (!pRF->mfOpen(RA_READ | (CParserBin::m_bEndians ? RA_ENDIANS : 0), NULL, NULL))
  29. {
  30. pRF->mfClose();
  31. bValid = false;
  32. }
  33. if (bValid)
  34. {
  35. pRF->mfFileSeek(CShaderMan::s_cNameHEAD, 0, SEEK_SET);
  36. pRF->mfFileRead2(CShaderMan::s_cNameHEAD, sizeof(SSShaderCacheHeader), &hd);
  37. if (CParserBin::m_bEndians)
  38. {
  39. SwapEndian(hd, eBigEndian);
  40. }
  41. if (hd.m_SizeOf != sizeof(SSShaderCacheHeader))
  42. {
  43. bValid = false;
  44. }
  45. else if (fVersion && (hd.m_MajorVer != (int)fVersion || hd.m_MinorVer != (int)(((float)fVersion - (float)(int)fVersion) * 10.1f)))
  46. {
  47. bValid = false;
  48. //if (CRenderer::CV_r_shadersdebug==2)
  49. {
  50. LogWarning("WARNING: Shader resource '%s' version mismatch (Resource: %s, Expected: %.1f)", pRF->mfGetFileName(), hd.m_szVer, fVersion);
  51. }
  52. }
  53. if (bCheckValid)
  54. {
  55. char nameSrc[256];
  56. sprintf_s(nameSrc, "%sCryFX/%s.%s", gRenDev->m_cEF.m_ShadersPath.c_str(), pSH->GetName(), "cfx");
  57. uint32 srcCRC = pSH->m_SourceCRC32;
  58. if (!srcCRC)
  59. {
  60. srcCRC = gEnv->pCryPak->ComputeCRC(nameSrc);
  61. pSH->m_SourceCRC32 = srcCRC; //Propagate to shader, prevent recalculation
  62. }
  63. if (srcCRC && srcCRC != hd.m_SourceCRC32)
  64. {
  65. bValid = false;
  66. //if (CRenderer::CV_r_shadersdebug==2)
  67. {
  68. LogWarning("WARNING: Shader resource '%s' src CRC mismatch", pRF->mfGetFileName());
  69. }
  70. }
  71. }
  72. // If we failed a version or CRC check, close our resource file since we may try opening it again later
  73. if (!bValid)
  74. {
  75. pRF->mfClose();
  76. }
  77. if (bValid && nCache == CACHE_USER)
  78. {
  79. pRF->mfClose();
  80. if (!pRF->mfOpen(RA_READ | (CParserBin::m_bEndians ? RA_ENDIANS : 0) | RA_WRITE, NULL, NULL))
  81. {
  82. pRF->mfClose();
  83. bValid = false;
  84. }
  85. }
  86. }
  87. if (!bValid && nCache == CACHE_USER && !bReadOnly && pSH->m_CRC32) //Create ResFile
  88. {
  89. if (!pRF->mfOpen(RA_CREATE | (CParserBin::m_bEndians ? RA_ENDIANS : 0), NULL, NULL))
  90. {
  91. return false;
  92. }
  93. SDirEntry de;
  94. de.Name = CShaderMan::s_cNameHEAD;
  95. de.size = sizeof(SSShaderCacheHeader);
  96. hd.m_SizeOf = sizeof(SSShaderCacheHeader);
  97. hd.m_MinorVer = (int)(((float)fVersion - (float)(int)fVersion) * 10.1f);
  98. hd.m_MajorVer = (int)fVersion;
  99. hd.m_CRC32 = pSH->m_CRC32;
  100. hd.m_SourceCRC32 = pSH->m_SourceCRC32;
  101. sprintf_s(hd.m_szVer, "Ver: %.1f", fVersion);
  102. SSShaderCacheHeader hdTemp, * pHD;
  103. pHD = &hd;
  104. if (CParserBin::m_bEndians)
  105. {
  106. hdTemp = hd;
  107. SwapEndian(hdTemp, eBigEndian);
  108. pHD = &hdTemp;
  109. }
  110. //create dir
  111. pRF->mfFileAdd(&de);
  112. //open dir and populate data
  113. SDirEntryOpen* pOpenDir = pRF->mfOpenEntry(&de);
  114. pOpenDir->pData = pHD;
  115. pOpenDir->nSize = de.size;
  116. pRF->mfFlush();
  117. bValid = true;
  118. }
  119. if (!bValid)
  120. {
  121. SAFE_DELETE(pRF);
  122. }
  123. if (pSR->m_pRes[nCache] && (pSR->m_pRes[nCache] != pRF))
  124. {
  125. SAFE_DELETE(pSR->m_pRes[nCache]);
  126. }
  127. pSR->m_pRes[nCache] = pRF;
  128. pSR->m_Header[nCache] = hd;
  129. pSR->m_bReadOnly[nCache] = bReadOnly;
  130. if (bValid && !pSH->m_CRC32)
  131. {
  132. pSH->m_CRC32 = hd.m_CRC32;
  133. }
  134. return bValid;
  135. }
  136. bool CShaderSerialize::OpenSResource(const char* szName, SSShaderRes* pSR, CShader* pSH, bool bDontUseUserFolder, bool bReadOnly)
  137. {
  138. stack_string szReadOnly = szName;
  139. // ShaderCacheGen behavior:
  140. // CACHE_READONLY is not really used when exporting the .fxb, so we append the @usercache@ alias to the relative shader path
  141. // here as well. We cannot just leave this as the relative Shaders/Cache/Foo.fxb value because then it creates a new
  142. // file in the asset cache as @assets@/Shaders/Cache/Foo.fxb, which is illegal (since only AP has the authority to write here)
  143. // Game runtime behavior:
  144. // We can't simply set both the CACHE_READONLY and CACHE_USER entries to be the same file path because then the shader caching
  145. // system treats these entries the same. CACHE_READONLY acts more as a template while CACHE_USER is the actual file with all
  146. // of the shader permutation entries. They need different file names (that have the same relative shader path) in order
  147. // for the CResFiles to be treated differently by the caching system.
  148. if (gRenDev->IsShaderCacheGenMode())
  149. {
  150. szReadOnly = stack_string(gRenDev->m_cEF.m_szCachePath.c_str()) + stack_string(szName);
  151. }
  152. CResFile* rfRO = new CResFile(szReadOnly);
  153. float fVersion = FX_CACHE_VER + FX_SER_CACHE_VER;
  154. bool bValidRO = _OpenSResource(fVersion, pSR, pSH, bDontUseUserFolder ? CACHE_READONLY : CACHE_USER, rfRO, bReadOnly);
  155. bool bValidUser = false;
  156. #if !defined(SHADER_NO_SOURCES)
  157. CResFile* rfUser;
  158. if (!bDontUseUserFolder)
  159. {
  160. stack_string szUser = stack_string(gRenDev->m_cEF.m_szCachePath.c_str()) + stack_string(szName);
  161. rfUser = new CResFile(szUser.c_str());
  162. bValidUser = _OpenSResource(fVersion, pSR, pSH, CACHE_USER, rfUser, bReadOnly);
  163. }
  164. #endif
  165. return (bValidRO || bValidUser);
  166. }
  167. bool CShaderSerialize::CreateSResource(CShader* pSH, SSShaderRes* pSR, [[maybe_unused]] CCryNameTSCRC& SName, bool bDontUseUserFolder, bool bReadOnly)
  168. {
  169. AZStd::string dstName;
  170. dstName.reserve(512);
  171. if (m_customSerialisePath.size())
  172. {
  173. dstName = m_customSerialisePath.c_str();
  174. }
  175. dstName += gRenDev->m_cEF.m_ShadersCache;
  176. dstName += pSH->GetName();
  177. dstName += ".fxb";
  178. bool bRes = OpenSResource(dstName.c_str(), pSR, pSH, bDontUseUserFolder, bReadOnly);
  179. AZ_Error("CShaderSerialize", bRes, "Failed to open '%s' with bDontUseUserFolder=%s and bReadOnly=%s", dstName.c_str(), bDontUseUserFolder ? "True" : "False", bReadOnly ? "True" : "False");
  180. return bRes;
  181. }
  182. SSShaderRes* CShaderSerialize::InitSResource(CShader* pSH, bool bDontUseUserFolder, bool bReadOnly)
  183. {
  184. SSShaderRes* pSR = NULL;
  185. stack_string shaderName = pSH->GetName();
  186. shaderName += "_GLOBAL";
  187. CCryNameTSCRC SName = CCryNameTSCRC(shaderName.c_str());
  188. FXSShaderResItor itS = m_SShaderResources.find(SName);
  189. #if SHADER_NO_SOURCES
  190. bool bCheckValid = false;
  191. #else
  192. bool bCheckValid = true;
  193. #endif
  194. if (itS != m_SShaderResources.end())
  195. {
  196. pSR = itS->second;
  197. pSR->m_nRefCount++;
  198. if (bCheckValid)
  199. {
  200. int nCache[2] = {-1, -1};
  201. if (!bReadOnly || bDontUseUserFolder)
  202. {
  203. nCache[0] = CACHE_USER;
  204. }
  205. else
  206. if (!bDontUseUserFolder || bReadOnly)
  207. {
  208. nCache[0] = CACHE_USER;
  209. nCache[1] = CACHE_READONLY;
  210. }
  211. for (int i = 0; i < 2; i++)
  212. {
  213. if (nCache[i] < 0 || !pSR->m_pRes[i])
  214. {
  215. continue;
  216. }
  217. //if the shader has a CRC then we can test, generally it is only valid during cache gen
  218. if (pSH->m_CRC32 != 0 && pSR->m_Header[i].m_CRC32 != pSH->m_CRC32)
  219. {
  220. //CryLogAlways("CRC check failed in serialise: 0x%x source: 0x%x\n", pSR->m_Header[i].m_CRC32, pSH->m_CRC32);
  221. SAFE_DELETE(pSR->m_pRes[i]);
  222. }
  223. }
  224. bool bValid = true;
  225. if (!bReadOnly && !pSR->m_pRes[CACHE_USER])
  226. {
  227. bValid = false;
  228. }
  229. else
  230. if ((!bDontUseUserFolder || bReadOnly) && !pSR->m_pRes[CACHE_READONLY] && !pSR->m_pRes[CACHE_USER])
  231. {
  232. bValid = false;
  233. }
  234. if (!bValid)
  235. {
  236. CreateSResource(pSH, pSR, SName, bDontUseUserFolder, bReadOnly);
  237. }
  238. else
  239. {
  240. //printf("Reusing existing .fxb for %s\n", pSH->GetName() );
  241. }
  242. }
  243. }
  244. else
  245. {
  246. pSR = new SSShaderRes;
  247. bool bRes = CreateSResource(pSH, pSR, SName, bDontUseUserFolder, bReadOnly);
  248. if (bRes)
  249. {
  250. m_SShaderResources.insert(FXSShaderResItor::value_type(SName, pSR));
  251. }
  252. else
  253. {
  254. SAFE_DELETE(pSR);
  255. }
  256. }
  257. if (pSH->m_CRC32 == 0 && pSR)
  258. {
  259. if (pSR->m_pRes[CACHE_READONLY])
  260. {
  261. pSH->m_CRC32 = pSR->m_Header[CACHE_READONLY].m_CRC32;
  262. }
  263. else if (pSR->m_pRes[CACHE_USER])
  264. {
  265. pSH->m_CRC32 = pSR->m_Header[CACHE_USER].m_CRC32;
  266. }
  267. }
  268. return pSR;
  269. }
  270. void CShaderSerialize::ClearSResourceCache()
  271. {
  272. const FXSShaderResItor end_it = m_SShaderResources.end();
  273. FXSShaderResItor it = m_SShaderResources.begin();
  274. for (; it != end_it; it++)
  275. {
  276. SAFE_DELETE(it->second);
  277. }
  278. m_SShaderResources.clear();
  279. }
  280. bool CShaderSerialize::DoesSResourceExist(CShader* pSH)
  281. {
  282. SSShaderRes* pSR = NULL;
  283. stack_string shaderName = pSH->GetName();
  284. shaderName += "_GLOBAL";
  285. CCryNameTSCRC SName = CCryNameTSCRC(shaderName.c_str());
  286. FXSShaderResItor itS = m_SShaderResources.find(SName);
  287. if (itS != m_SShaderResources.end())
  288. {
  289. return true;
  290. }
  291. return false;
  292. }
  293. bool CShaderSerialize::ExportHWShader(CHWShader* pShader, SShaderSerializeContext& SC)
  294. {
  295. if (!pShader)
  296. {
  297. return false;
  298. }
  299. bool bRes = pShader->Export(SC);
  300. return bRes;
  301. }
  302. CHWShader* CShaderSerialize::ImportHWShader(SShaderSerializeContext& SC, int nOffs, uint32 CRC32, CShader* pSH)
  303. {
  304. CHWShader* pRes = CHWShader::Import(SC, nOffs, CRC32, pSH);
  305. return pRes;
  306. }
  307. void CShaderSerialize::ExportHWShaderStage(SShaderSerializeContext& SC, CHWShader* shader, uint32& outShaderOffset)
  308. {
  309. if ( shader )
  310. {
  311. outShaderOffset = SC.Data.Num();
  312. if ( !ExportHWShader(shader,SC) )
  313. {
  314. outShaderOffset = -1;
  315. CryFatalError("Shader export failed.");
  316. }
  317. }
  318. else
  319. {
  320. outShaderOffset = -1;
  321. }
  322. }
  323. bool CShaderSerialize::ExportShader(CShader* pSH, CShaderManBin& binShaderMgr)
  324. {
  325. #ifdef SHADER_SERIALIZE_VERBOSE
  326. CryLogAlways("[CShaderSerialize] ExportShader: %s flags: 0x%llx mdvFlags: 0x%x\n", pSH->GetName(), pSH->m_nMaskGenFX, pSH->m_nMDV);
  327. #endif
  328. bool bRes = true;
  329. //Use user folder on export?
  330. SSShaderRes* pSR = InitSResource(pSH, false /*((gRenDev->m_cEF.m_nCombinations > 0) || !CRenderer::CV_r_shadersuserfolder)*/, false);
  331. uint32 i;
  332. int j;
  333. if (!pSR || !pSR->m_pRes[CACHE_USER])
  334. {
  335. return false;
  336. }
  337. SShaderSerializeContext SC;
  338. SC.SSR.m_eSHDType = pSH->m_eSHDType;
  339. SC.SSR.m_Flags = pSH->m_Flags;
  340. SC.SSR.m_Flags2 = pSH->m_Flags2;
  341. SC.SSR.m_nMDV = pSH->m_nMDV;
  342. SC.SSR.m_vertexFormatEnum = pSH->m_vertexFormat.GetEnum();
  343. SC.SSR.m_eCull = pSH->m_eCull;
  344. //SC.SSR.m_nMaskCB = pSH->m_nMaskCB; //maskCB generated on HW shader activation
  345. SC.SSR.m_eShaderType = pSH->m_eShaderType;
  346. SC.SSR.m_nMaskGenFX = pSH->m_nMaskGenFX;
  347. SC.SSR.m_nTechniques = pSH->m_HWTechniques.Num();
  348. SShaderFXParams& params = binShaderMgr.mfGetFXParams(pSH);
  349. SC.SSR.m_nPublicParams = params.m_PublicParams.size();
  350. for (i = 0; i < SC.SSR.m_nPublicParams; i++)
  351. {
  352. SSShaderParam PR;
  353. SShaderParam& P = params.m_PublicParams[i];
  354. PR.m_nameIdx = SC.AddString(P.m_Name.c_str());
  355. PR.m_Type = P.m_Type;
  356. PR.m_Value = P.m_Value;
  357. PR.m_nScriptOffs = SC.AddString(P.m_Script.c_str());
  358. PR.m_eSemantic = P.m_eSemantic;
  359. SC.Params.Add(PR);
  360. }
  361. SC.SSR.m_nFXParams = params.m_FXParams.size();
  362. for (i = 0; i < SC.SSR.m_nFXParams; i++)
  363. {
  364. params.m_FXParams[i].Export(SC);
  365. }
  366. SC.SSR.m_nFXSamplers = params.m_FXSamplers.size();
  367. for (i = 0; i < SC.SSR.m_nFXSamplers; i++)
  368. {
  369. params.m_FXSamplers[i].Export(SC);
  370. }
  371. SC.SSR.m_nFXTextures = params.m_FXTextures.size();
  372. for (i = 0; i < SC.SSR.m_nFXTextures; i++)
  373. {
  374. params.m_FXTextures[i].Export(SC);
  375. }
  376. SC.SSR.m_nFXTexSamplers = params.m_FXSamplersOld.size();
  377. for (i = 0; i < SC.SSR.m_nFXTexSamplers; i++)
  378. {
  379. params.m_FXSamplersOld[i].Export(SC);
  380. }
  381. SC.SSR.m_nFXTexRTs = SC.FXTexRTs.Num();
  382. for (i = 0; i < SC.SSR.m_nTechniques; i++)
  383. {
  384. SSShaderTechnique ST;
  385. SShaderTechnique* pT = pSH->m_HWTechniques[i];
  386. ST.m_nPreprocessFlags = pT->m_nPreprocessFlags;
  387. ST.m_nNameOffs = SC.AddString(pT->m_NameStr.c_str());
  388. ST.m_Flags = pT->m_Flags;
  389. int TECH_MAX = TTYPE_MAX;
  390. for (j = 0; j < TECH_MAX; j++)
  391. {
  392. ST.m_nTechnique[j] = pT->m_nTechnique[j];
  393. }
  394. ST.m_nREs = pT->m_REs.Num();
  395. ST.m_nPassesOffs = SC.Passes.Num();
  396. ST.m_nPasses = pT->m_Passes.Num();
  397. SC.SSR.m_nPasses += ST.m_nPasses;
  398. for (j = 0; j < ST.m_nPasses; j++)
  399. {
  400. SSShaderPass PS;
  401. SShaderPass& P = pT->m_Passes[j];
  402. PS.m_RenderState = P.m_RenderState;
  403. PS.m_eCull = P.m_eCull;
  404. PS.m_AlphaRef = P.m_AlphaRef;
  405. PS.m_PassFlags = P.m_PassFlags;
  406. assert(!(SC.Data.Num() & 0x3));
  407. ExportHWShaderStage( SC, P.m_VShader, PS.m_nVShaderOffs );
  408. ExportHWShaderStage( SC, P.m_HShader, PS.m_nHShaderOffs );
  409. ExportHWShaderStage( SC, P.m_DShader, PS.m_nDShaderOffs );
  410. ExportHWShaderStage( SC, P.m_GShader, PS.m_nGShaderOffs );
  411. ExportHWShaderStage( SC, P.m_PShader, PS.m_nPShaderOffs );
  412. ExportHWShaderStage( SC, P.m_CShader, PS.m_nCShaderOffs );
  413. SC.Passes.Add(PS);
  414. }
  415. ST.m_nREsOffs = (ST.m_nREs > 0) ? SC.Data.Num() : -1;
  416. for (j = 0; j < ST.m_nREs; j++)
  417. {
  418. CRendElementBase* pRE = pT->m_REs[j];
  419. uint32 type = pRE->m_Type;
  420. sAddData(SC.Data, type);
  421. pRE->mfExport(SC);
  422. sAlignData(SC.Data, 4);
  423. }
  424. SC.Techniques.AddElem(ST);
  425. }
  426. TArray<byte> Data;
  427. //DEBUG - prevent Data reallocs
  428. //Data.Alloc(1024*1024);
  429. uint32 nPublicParamsOffset;
  430. uint32 nFXParamsOffset;
  431. uint32 nFXSamplersOffset;
  432. uint32 nFXTexturesOffset;
  433. uint32 nFXTexSamplersOffset;
  434. uint32 nFXTexRTsOffset;
  435. uint32 nTechOffset;
  436. uint32 nPassOffset;
  437. uint32 nStringsOffset;
  438. uint32 nDataOffset;
  439. //sAddData(Data, SC.SSR);
  440. SC.SSR.Export(Data);
  441. sAddDataArray(Data, SC.Params, nPublicParamsOffset);
  442. sAddDataArray(Data, SC.FXParams, nFXParamsOffset);
  443. sAddDataArray(Data, SC.FXSamplers, nFXSamplersOffset);
  444. sAddDataArray(Data, SC.FXTextures, nFXTexturesOffset);
  445. sAddDataArray(Data, SC.FXTexSamplers, nFXTexSamplersOffset);
  446. sAddDataArray(Data, SC.FXTexRTs, nFXTexRTsOffset);
  447. sAddDataArray(Data, SC.Techniques, nTechOffset);
  448. sAddDataArray(Data, SC.Passes, nPassOffset);
  449. sAddDataArray_POD(Data, SC.Strings, nStringsOffset);
  450. sAddDataArray_POD(Data, SC.Data, nDataOffset);
  451. SSShader* pSSR = (SSShader*)&Data[0];
  452. pSSR->m_nPublicParamsOffset = nPublicParamsOffset;
  453. pSSR->m_nFXParamsOffset = nFXParamsOffset;
  454. pSSR->m_nFXSamplersOffset = nFXSamplersOffset;
  455. pSSR->m_nFXTexturesOffset = nFXTexturesOffset;
  456. pSSR->m_nFXTexSamplersOffset = nFXTexSamplersOffset;
  457. pSSR->m_nFXTexRTsOffset = nFXTexRTsOffset;
  458. pSSR->m_nTechOffset = nTechOffset;
  459. pSSR->m_nPassOffset = nPassOffset;
  460. pSSR->m_nStringsOffset = nStringsOffset;
  461. pSSR->m_nDataOffset = nDataOffset;
  462. pSSR->m_nDataSize = SC.Data.Num();
  463. pSSR->m_nStringsSize = SC.Strings.Num();
  464. if (CParserBin::m_bEndians)
  465. {
  466. SwapEndian(pSSR->m_nPublicParamsOffset, eBigEndian);
  467. SwapEndian(pSSR->m_nFXParamsOffset, eBigEndian);
  468. SwapEndian(pSSR->m_nFXSamplersOffset, eBigEndian);
  469. SwapEndian(pSSR->m_nFXTexturesOffset, eBigEndian);
  470. SwapEndian(pSSR->m_nFXTexRTsOffset, eBigEndian);
  471. SwapEndian(pSSR->m_nTechOffset, eBigEndian);
  472. SwapEndian(pSSR->m_nPassOffset, eBigEndian);
  473. SwapEndian(pSSR->m_nStringsOffset, eBigEndian);
  474. SwapEndian(pSSR->m_nDataOffset, eBigEndian);
  475. SwapEndian(pSSR->m_nDataSize, eBigEndian);
  476. SwapEndian(pSSR->m_nStringsSize, eBigEndian);
  477. }
  478. int nLen = Data.Num();
  479. SDirEntry de;
  480. char sName[128];
  481. sprintf_s(sName, "(%llx)(%llx)", pSH->m_nMaskGenFX, pSH->m_maskGenStatic);
  482. de.Name = CCryNameTSCRC(sName);
  483. de.size = nLen;
  484. de.flags |= RF_COMPRESS;
  485. pSR->m_pRes[CACHE_USER]->mfFileAdd(&de);
  486. //create open dir and populate data
  487. SDirEntryOpen* pOpenDir = pSR->m_pRes[CACHE_USER]->mfOpenEntry(&de);
  488. pOpenDir->pData = &Data[0];
  489. pOpenDir->nSize = de.size;
  490. //Preserve modification time
  491. uint64 modTime = pSR->m_pRes[CACHE_USER]->mfGetModifTime();
  492. pSR->m_pRes[CACHE_USER]->mfFlush();
  493. return bRes;
  494. }
  495. float g_fTime0;
  496. float g_fTime1;
  497. float g_fTime2;
  498. bool CShaderSerialize::CheckFXBExists(CShader* pSH)
  499. {
  500. SSShaderRes* pSR = InitSResource(pSH, false, true);
  501. if (!pSR || (!pSR->m_Header[CACHE_USER].m_CRC32 && !pSR->m_Header[CACHE_READONLY].m_CRC32))
  502. {
  503. return false;
  504. }
  505. char sName[128];
  506. sprintf_s(sName, "(%llx)(%llx)", pSH->m_nMaskGenFX, pSH->m_maskGenStatic);
  507. CCryNameTSCRC CName = CCryNameTSCRC(sName);
  508. SDirEntry* pDE = NULL;
  509. CResFile* pRes = NULL;
  510. for (int i = 0; i < 2; i++)
  511. {
  512. pRes = pSR->m_pRes[i];
  513. if (!pRes)
  514. {
  515. continue;
  516. }
  517. pDE = pRes->mfGetEntry(CName);
  518. if (pDE)
  519. {
  520. return true;
  521. }
  522. }
  523. return false;
  524. }
  525. CShaderSerialize::ShaderImportResults CShaderSerialize::ImportShader(CShader* pSH, CShaderManBin& binShaderMgr)
  526. {
  527. if (CParserBin::m_bEndians)
  528. {
  529. CryFatalError("CShaderSerialize - cross platform import not supported");
  530. }
  531. float fTime0 = iTimer->GetAsyncCurTime();
  532. SSShaderRes* pSR = NULL;
  533. uint32 i;
  534. int j;
  535. char sName[128];
  536. sprintf_s(sName, "(%llx)(%llx)", pSH->m_nMaskGenFX, pSH->m_maskGenStatic);
  537. CCryNameTSCRC CName = CCryNameTSCRC(sName);
  538. SDirEntry* pDE = NULL;
  539. CResFile* pRes = NULL;
  540. // Not found yet
  541. if (!pDE || !pRes)
  542. {
  543. //try global cache
  544. pSR = InitSResource(pSH, !CRenderer::CV_r_shadersAllowCompilation, true);
  545. if (pSR && (pSR->m_Header[CACHE_USER].m_CRC32 != 0 || pSR->m_Header[CACHE_READONLY].m_CRC32 != 0))
  546. {
  547. for (i = 0; i < 2; i++)
  548. {
  549. pRes = pSR->m_pRes[i];
  550. if (!pRes)
  551. {
  552. continue;
  553. }
  554. pDE = pRes->mfGetEntry(CName);
  555. if (pDE)
  556. {
  557. break;
  558. }
  559. }
  560. }
  561. if (!pDE && !pSR)
  562. {
  563. // The .cfx has no associated .fxb, so this is a guaranteed failure on import.
  564. return SHADER_IMPORT_FAILURE;
  565. }
  566. else if (!pDE)
  567. {
  568. // We have a shader import table but this specific permutation is missing
  569. return SHADER_IMPORT_MISSING_ENTRY;
  570. }
  571. }
  572. CShader* pSave = gRenDev->m_RP.m_pShader;
  573. gRenDev->m_RP.m_pShader = pSH;
  574. assert(gRenDev->m_RP.m_pShader != 0);
  575. int nSize = pRes->mfFileRead(pDE);
  576. byte* pData = (byte*)pRes->mfFileGetBuf(pDE);
  577. if (!pData)
  578. {
  579. // Malformed fxb
  580. return SHADER_IMPORT_FAILURE;
  581. }
  582. //printf("[CShaderSerialize] Import Shader: %s flags: 0x%llx mdvFlags: 0x%x from %s cache %s\n", pSH->GetName(), pSH->m_nMaskGenFX, pSH->m_nMDV, bLoadedFromLevel ? "LEVEL" : "GLOBAL", pSR->m_pRes[i]->mfGetFileName());
  583. byte* pSrc = pData;
  584. g_fTime0 += iTimer->GetAsyncCurTime() - fTime0;
  585. float fTime1 = iTimer->GetAsyncCurTime();
  586. SShaderFXParams& fxParams = binShaderMgr.mfGetFXParams(pSH);
  587. SShaderSerializeContext SC;
  588. SC.SSR.Import(pSrc);
  589. #ifdef SHADER_SERIALIZE_VERBOSE
  590. CryLog("[CShaderSerialize] Import Shader: %s flags: 0x%llx mdvFlags: 0x%x from global cache %s\n", pSH->GetName(), pSH->m_nMaskGenFX, pSH->m_nMDV, pSR->m_pRes[i]->mfGetFileName());
  591. #endif
  592. if (SC.SSR.m_nPublicParams)
  593. {
  594. SC.Params.ReserveNoClear(SC.SSR.m_nPublicParams);
  595. if (!CParserBin::m_bEndians)
  596. {
  597. memcpy(&SC.Params[0], &pSrc[SC.SSR.m_nPublicParamsOffset], sizeof(SSShaderParam) * SC.SSR.m_nPublicParams);
  598. }
  599. else
  600. {
  601. uint32 offset = SC.SSR.m_nPublicParamsOffset;
  602. for (i = 0; i < SC.SSR.m_nPublicParams; i++)
  603. {
  604. SC.Params[i].Import(&pSrc[offset]);
  605. offset += sizeof(SSShaderParam);
  606. }
  607. }
  608. }
  609. if (SC.SSR.m_nFXParams)
  610. {
  611. SC.FXParams.ReserveNoClear(SC.SSR.m_nFXParams);
  612. if (!CParserBin::m_bEndians)
  613. {
  614. memcpy(&SC.FXParams[0], &pSrc[SC.SSR.m_nFXParamsOffset], sizeof(SSFXParam) * SC.SSR.m_nFXParams);
  615. }
  616. else
  617. {
  618. uint32 offset = SC.SSR.m_nFXParamsOffset;
  619. for (i = 0; i < SC.SSR.m_nFXParams; i++)
  620. {
  621. SC.FXParams[i].Import(&pSrc[offset]);
  622. offset += sizeof(SSFXParam);
  623. }
  624. }
  625. }
  626. if (SC.SSR.m_nFXSamplers)
  627. {
  628. SC.FXSamplers.ReserveNoClear(SC.SSR.m_nFXSamplers);
  629. if (!CParserBin::m_bEndians)
  630. {
  631. memcpy(&SC.FXSamplers[0], &pSrc[SC.SSR.m_nFXSamplersOffset], sizeof(SSFXSampler) * SC.SSR.m_nFXSamplers);
  632. }
  633. else
  634. {
  635. uint32 offset = SC.SSR.m_nFXSamplersOffset;
  636. for (i = 0; i < SC.SSR.m_nFXSamplers; i++)
  637. {
  638. SC.FXSamplers[i].Import(&pSrc[offset]);
  639. offset += sizeof(SSTexSamplerFX);
  640. }
  641. }
  642. }
  643. if (SC.SSR.m_nFXTextures)
  644. {
  645. SC.FXTextures.ReserveNoClear(SC.SSR.m_nFXTextures);
  646. memcpy(&SC.FXTextures[0], &pSrc[SC.SSR.m_nFXTexturesOffset], sizeof(SSFXTexture) * SC.SSR.m_nFXTextures);
  647. }
  648. if (SC.SSR.m_nFXTexSamplers)
  649. {
  650. SC.FXTexSamplers.ReserveNoClear(SC.SSR.m_nFXTexSamplers);
  651. if (!CParserBin::m_bEndians)
  652. {
  653. memcpy(&SC.FXTexSamplers[0], &pSrc[SC.SSR.m_nFXTexSamplersOffset], sizeof(SSTexSamplerFX) * SC.SSR.m_nFXTexSamplers);
  654. }
  655. else
  656. {
  657. uint32 offset = SC.SSR.m_nFXTexSamplersOffset;
  658. for (i = 0; i < SC.SSR.m_nFXTexSamplers; i++)
  659. {
  660. SC.FXTexSamplers[i].Import(&pSrc[offset]);
  661. offset += sizeof(SSTexSamplerFX);
  662. }
  663. }
  664. }
  665. if (SC.SSR.m_nFXTexRTs)
  666. {
  667. SC.FXTexRTs.ReserveNoClear(SC.SSR.m_nFXTexRTs);
  668. if (!CParserBin::m_bEndians)
  669. {
  670. memcpy(&SC.FXTexRTs[0], &pSrc[SC.SSR.m_nFXTexRTsOffset], sizeof(SSHRenderTarget) * SC.SSR.m_nFXTexRTs);
  671. }
  672. else
  673. {
  674. uint32 offset = SC.SSR.m_nFXTexRTsOffset;
  675. for (i = 0; i < SC.SSR.m_nFXTexRTs; i++)
  676. {
  677. SC.FXTexRTs[i].Import(&pSrc[offset]);
  678. offset += sizeof(SSHRenderTarget);
  679. }
  680. }
  681. }
  682. if (SC.SSR.m_nTechniques)
  683. {
  684. SC.Techniques.ReserveNoClear(SC.SSR.m_nTechniques);
  685. if (!CParserBin::m_bEndians)
  686. {
  687. memcpy(&SC.Techniques[0], &pSrc[SC.SSR.m_nTechOffset], sizeof(SSShaderTechnique) * SC.SSR.m_nTechniques);
  688. }
  689. else
  690. {
  691. uint32 offset = SC.SSR.m_nTechOffset;
  692. for (i = 0; i < SC.SSR.m_nTechniques; i++)
  693. {
  694. SC.Techniques[i].Import(&pSrc[offset]);
  695. offset += sizeof(SSShaderTechnique);
  696. }
  697. }
  698. }
  699. if (SC.SSR.m_nPasses)
  700. {
  701. SC.Passes.ReserveNoClear(SC.SSR.m_nPasses);
  702. if (!CParserBin::m_bEndians)
  703. {
  704. memcpy(&SC.Passes[0], &pSrc[SC.SSR.m_nPassOffset], sizeof(SSShaderPass) * SC.SSR.m_nPasses);
  705. }
  706. else
  707. {
  708. uint32 offset = SC.SSR.m_nPassOffset;
  709. for (i = 0; i < SC.SSR.m_nPasses; i++)
  710. {
  711. SC.Passes[i].Import(&pSrc[offset]);
  712. offset += sizeof(SSShaderPass);
  713. }
  714. }
  715. }
  716. if (SC.SSR.m_nStringsSize)
  717. {
  718. SC.Strings.ReserveNoClear(SC.SSR.m_nStringsSize);
  719. memcpy(&SC.Strings[0], &pSrc[SC.SSR.m_nStringsOffset], SC.SSR.m_nStringsSize);
  720. }
  721. if (SC.SSR.m_nDataSize)
  722. {
  723. SC.Data.ReserveNoClear(SC.SSR.m_nDataSize);
  724. memcpy(&SC.Data[0], &pSrc[SC.SSR.m_nDataOffset], SC.SSR.m_nDataSize);
  725. }
  726. pRes->mfFileClose(pDE);
  727. g_fTime1 += iTimer->GetAsyncCurTime() - fTime1;
  728. float fTime2 = iTimer->GetAsyncCurTime();
  729. pSH->m_eSHDType = SC.SSR.m_eSHDType;
  730. //TODO |= on flags? will we lose flags at runtime
  731. pSH->m_Flags = SC.SSR.m_Flags;
  732. pSH->m_Flags2 = SC.SSR.m_Flags2;
  733. pSH->m_nMDV = SC.SSR.m_nMDV;
  734. AZ_Assert(SC.SSR.m_vertexFormatEnum < eVF_Max, "Bad vertex format index. Is the shader cache out of date?");
  735. pSH->m_vertexFormat = gRenDev->m_RP.m_vertexFormats[SC.SSR.m_vertexFormatEnum];
  736. pSH->m_eCull = SC.SSR.m_eCull;
  737. pSH->m_eShaderType = SC.SSR.m_eShaderType;
  738. pSH->m_nMaskGenFX = SC.SSR.m_nMaskGenFX;
  739. fxParams.m_PublicParams.reserve(fxParams.m_PublicParams.size() + SC.SSR.m_nPublicParams);
  740. for (i = 0; i < SC.SSR.m_nPublicParams; i++)
  741. {
  742. SSShaderParam& PR = SC.Params[i];
  743. SShaderParam P;
  744. const char* pName = sString(PR.m_nameIdx, SC.Strings);
  745. P.m_Name = pName;
  746. P.m_Type = PR.m_Type;
  747. P.m_Value = PR.m_Value;
  748. P.m_Script = sString(PR.m_nScriptOffs, SC.Strings);
  749. fxParams.m_PublicParams.push_back(P);
  750. }
  751. fxParams.m_FXParams.reserve(fxParams.m_FXParams.size() + SC.SSR.m_nFXParams);
  752. for (i = 0; i < SC.SSR.m_nFXParams; i++)
  753. {
  754. SFXParam fxParam;
  755. fxParam.Import(SC, &SC.FXParams[i]);
  756. fxParams.m_FXParams.push_back(fxParam);
  757. }
  758. fxParams.m_FXSamplersOld.reserve(fxParams.m_FXSamplersOld.size() + SC.SSR.m_nFXTexSamplers);
  759. for (i = 0; i < SC.SSR.m_nFXTexSamplers; i++)
  760. {
  761. STexSamplerFX fxTexSampler;
  762. fxTexSampler.Import(SC, &SC.FXTexSamplers[i]);
  763. fxParams.m_FXSamplersOld.push_back(fxTexSampler);
  764. }
  765. fxParams.m_FXSamplers.reserve(fxParams.m_FXSamplers.size() + SC.SSR.m_nFXSamplers);
  766. for (i = 0; i < SC.SSR.m_nFXSamplers; i++)
  767. {
  768. SFXSampler fxSampler;
  769. fxSampler.Import(SC, &SC.FXSamplers[i]);
  770. fxParams.m_FXSamplers.push_back(fxSampler);
  771. }
  772. fxParams.m_FXTextures.reserve(fxParams.m_FXTextures.size() + SC.SSR.m_nFXTextures);
  773. for (i = 0; i < SC.SSR.m_nFXTextures; i++)
  774. {
  775. SFXTexture fxTexture;
  776. fxTexture.Import(SC, &SC.FXTextures[i]);
  777. fxParams.m_FXTextures.push_back(fxTexture);
  778. }
  779. for (i = 0; i < SC.SSR.m_nTechniques; i++)
  780. {
  781. SSShaderTechnique& ST = SC.Techniques[i];
  782. SShaderTechnique* pT = new SShaderTechnique(pSH);
  783. pT->m_NameStr = sString(ST.m_nNameOffs, SC.Strings);
  784. pT->m_NameCRC = pT->m_NameStr.c_str();
  785. pT->m_Flags = ST.m_Flags;
  786. pT->m_nPreprocessFlags = ST.m_nPreprocessFlags;
  787. for (j = 0; j < TTYPE_MAX; j++)
  788. {
  789. pT->m_nTechnique[j] = ST.m_nTechnique[j];
  790. }
  791. if (ST.m_nPasses)
  792. {
  793. int nOffs = ST.m_nPassesOffs;
  794. pT->m_Passes.reserve(ST.m_nPasses);
  795. for (j = 0; j < ST.m_nPasses; j++)
  796. {
  797. SSShaderPass& PS = SC.Passes[j + nOffs];
  798. SShaderPass* P = pT->m_Passes.AddIndex(1);
  799. P->m_RenderState = PS.m_RenderState;
  800. P->m_eCull = PS.m_eCull;
  801. P->m_AlphaRef = PS.m_AlphaRef;
  802. P->m_PassFlags = PS.m_PassFlags;
  803. P->m_VShader = ImportHWShader(SC, PS.m_nVShaderOffs, pSH->m_CRC32, pSH);
  804. P->m_PShader = ImportHWShader(SC, PS.m_nPShaderOffs, pSH->m_CRC32, pSH);
  805. P->m_GShader = ImportHWShader(SC, PS.m_nGShaderOffs, pSH->m_CRC32, pSH);
  806. P->m_HShader = ImportHWShader(SC, PS.m_nHShaderOffs, pSH->m_CRC32, pSH);
  807. P->m_DShader = ImportHWShader(SC, PS.m_nDShaderOffs, pSH->m_CRC32, pSH);
  808. P->m_CShader = ImportHWShader(SC, PS.m_nCShaderOffs, pSH->m_CRC32, pSH);
  809. }
  810. }
  811. uint32 nREOffset = ST.m_nREsOffs;
  812. for (j = 0; j < ST.m_nREs; j++)
  813. {
  814. EDataType dataType = *((EDataType*)&SC.Data[nREOffset]);
  815. if (CParserBin::m_bEndians)
  816. {
  817. SwapEndianEnum(dataType, eBigEndian);
  818. }
  819. nREOffset += sizeof(EDataType);
  820. switch (dataType)
  821. {
  822. case eDATA_LensOptics:
  823. {
  824. CRELensOptics* pLensOptics = new CRELensOptics;
  825. pLensOptics->mfImport(SC, nREOffset);
  826. pT->m_REs.push_back(pLensOptics);
  827. }
  828. break;
  829. case eDATA_Beam:
  830. {
  831. CREBeam* pBeam = new CREBeam;
  832. pBeam->mfImport(SC, nREOffset);
  833. pT->m_REs.push_back(pBeam);
  834. }
  835. break;
  836. default:
  837. CryFatalError("Render element not supported for shader serialising");
  838. break;
  839. }
  840. //expects 4 byte aligned
  841. assert(!(nREOffset & 3));
  842. }
  843. pSH->m_HWTechniques.AddElem(pT);
  844. }
  845. gRenDev->m_RP.m_pShader = pSave;
  846. g_fTime2 += iTimer->GetAsyncCurTime() - fTime2;
  847. return SHADER_IMPORT_SUCCESS;
  848. }
  849. #endif