1 // Copyright 2001-2017 Crytek GmbH / Crytek Group. All rights reserved.
3 /*=============================================================================
4 ShaderCache.cpp : implementation of the Shaders cache management.
7 * Created by Honich Andrey
9 =============================================================================*/
12 #include <Cry3DEngine/I3DEngine.h>
13 #include "RemoteCompiler.h"
14 #include <CryCore/Base64.h>
16 bool SShaderCombIdent::operator==(const SShaderCombIdent
& other
) const
18 if ((m_MDVMask
& ~SF_PLATFORM
) == other
.m_MDVMask
&& m_RTMask
== other
.m_RTMask
19 && m_GLMask
== other
.m_GLMask
&& m_FastCompare1
== other
.m_FastCompare1
20 && m_pipelineState
.opaque
== other
.m_pipelineState
.opaque
)
25 uint32
SShaderCombIdent::PostCreate()
27 FUNCTION_PROFILER_RENDER_FLAT
28 // using actual CRC is to expensive, so replace with cheaper version with
29 // has more changes of hits
30 //uint32 hash = CCrc32::Compute(&m_RTMask, sizeof(SShaderCombIdent)-sizeof(uint32));
31 const uint32
* acBuffer
= alias_cast
<uint32
*>(&m_RTMask
);
32 int len
= (sizeof(SShaderCombIdent
) - sizeof(uint32
)) / sizeof(uint32
);
38 hash
= ((hash
<< 5) + hash
) + c
;
42 m_MDVMask
&= ~SF_PLATFORM
;
46 bool CShader::mfPrecache(SShaderCombination
& cmb
, bool bForce
, CShaderResources
* pRes
)
50 if (!CRenderer::CV_r_shadersAllowCompilation
&& !bForce
)
53 int nAsync
= CRenderer::CV_r_shadersasynccompiling
;
54 CRenderer::CV_r_shadersasynccompiling
= 0;
58 for (i
= 0; i
< m_HWTechniques
.Num(); i
++)
60 SShaderTechnique
* pTech
= m_HWTechniques
[i
];
61 for (j
= 0; j
< pTech
->m_Passes
.Num(); j
++)
63 SShaderPass
& Pass
= pTech
->m_Passes
[j
];
64 SShaderCombination c
= cmb
;
66 CHWShader
* const shadersToCompile
[] = {
67 Pass
.m_VShader
, // Vertex shader
68 Pass
.m_PShader
, // Pixel shader
69 Pass
.m_GShader
, // Geometry shader
70 Pass
.m_HShader
, // Hull shader
71 Pass
.m_DShader
, // Domain shader
72 Pass
.m_CShader
, // Compute shader
75 for (const auto &shader
: shadersToCompile
)
77 uint32 nFlagsShader_MD
= cmb
.m_MDMask
;
79 bRes
&= shader
->mfPrecache(cmb
, bForce
, false, this, pRes
);
80 cmb
.m_MDMask
= nFlagsShader_MD
;
86 CRenderer::CV_r_shadersasynccompiling
= nAsync
;
91 SShaderGenComb
* CShaderMan::mfGetShaderGenInfo(const char* nmFX
)
93 SShaderGenComb
* c
= NULL
;
95 for (i
= 0; i
< m_SGC
.size(); i
++)
98 if (!stricmp(c
->Name
.c_str(), nmFX
))
102 if (i
== m_SGC
.size())
104 cmb
.pGen
= mfCreateShaderGenInfo(nmFX
, false);
105 cmb
.Name
= CCryNameR(nmFX
);
106 m_SGC
.push_back(cmb
);
112 static uint64
sGetGL(char** s
, CCryNameR
& name
, uint32
& nHWFlags
)
117 SShaderGenComb
* c
= NULL
;
118 const char* m
= strchr(name
.c_str(), '@');
120 m
= strchr(name
.c_str(), '/');
127 cry_strcpy(nmFX
, name
.c_str(), (size_t)(m
- name
.c_str()));
128 c
= gRenDev
->m_cEF
.mfGetShaderGenInfo(nmFX
);
129 if (!c
|| !c
->pGen
|| !c
->pGen
->m_BitMask
.Num())
132 SShaderGen
* pG
= c
->pGen
;
137 while ((theChar
= **s
) != 0)
139 if (theChar
== ')' || theChar
== '|')
144 nameExt
[n
++] = theChar
;
149 for (i
= 0; i
< pG
->m_BitMask
.Num(); i
++)
151 SShaderGenBit
* pBit
= pG
->m_BitMask
[i
];
152 if (!stricmp(pBit
->m_ParamName
.c_str(), nameExt
))
158 if (i
== pG
->m_BitMask
.Num())
160 if (!strncmp(nameExt
, "0x", 2))
162 //nGL |= shGetHex(&nameExt[2]);
167 if (CRenderer::CV_r_shadersdebug
)
168 iLog
->Log("WARNING: Couldn't find global flag '%s' in shader '%s' (skipped)", nameExt
, c
->Name
.c_str());
177 static uint64
sGetRT(char** s
)
181 SShaderGen
* pG
= gRenDev
->m_cEF
.m_pGlobalExt
;
185 char nm
[128] = { 0 };
190 while ((theChar
= **s
) != 0)
192 if (theChar
== ')' || theChar
== '|')
202 for (i
= 0; i
< pG
->m_BitMask
.Num(); i
++)
204 SShaderGenBit
* pBit
= pG
->m_BitMask
[i
];
205 if (!stricmp(pBit
->m_ParamName
.c_str(), nm
))
211 if (i
== pG
->m_BitMask
.Num())
214 // iLog->Log("WARNING: Couldn't find runtime flag '%s' (skipped)", nm);
222 static int sEOF(bool bFromFile
, char* pPtr
, FILE* fp
)
226 nStatus
= gEnv
->pCryPak
->FEof(fp
);
229 SkipCharacters(&pPtr
, kWhiteSpace
);
238 void CShaderMan::mfCloseShadersCache(int nID
)
240 if (m_FPCacheCombinations
[nID
])
242 gEnv
->pCryPak
->FClose(m_FPCacheCombinations
[nID
]);
243 m_FPCacheCombinations
[nID
] = NULL
;
247 void sSkipLine(char*& s
)
251 char* sEnd
= strchr(s
, '\n');
259 static void sIterateHW_r(FXShaderCacheCombinations
* Combinations
, SCacheCombination
& cmb
, int i
, uint64 nHW
, const char* szName
)
262 gRenDev
->m_cEF
.mfInsertNewCombination(cmb
.Ident
, cmb
.eCL
, szName
, 0, &str
, false);
263 CCryNameR nm
= CCryNameR(str
.c_str());
264 FXShaderCacheCombinationsItor it
= Combinations
->find(nm
);
265 if (it
== Combinations
->end())
267 cmb
.CacheName
= str
.c_str();
268 Combinations
->insert(FXShaderCacheCombinationsItor::value_type(nm
, cmb
));
270 for (int j
= i
; j
< 64; j
++)
272 if (((uint64
)1 << j
) & nHW
)
274 cmb
.Ident
.m_GLMask
&= ~((uint64
)1 << j
);
275 sIterateHW_r(Combinations
, cmb
, j
+ 1, nHW
, szName
);
276 cmb
.Ident
.m_GLMask
|= ((uint64
)1 << j
);
277 sIterateHW_r(Combinations
, cmb
, j
+ 1, nHW
, szName
);
283 void CShaderMan::mfGetShaderListPath(stack_string
& nameOut
, int nType
)
286 nameOut
= stack_string(m_szUserPath
.c_str()) + stack_string("shaders/shaderlist.txt");
288 nameOut
= stack_string(m_szUserPath
.c_str()) + stack_string("shaders/cache/shaderlistactivate.txt");
291 void CShaderMan::mfMergeShadersCombinations(FXShaderCacheCombinations
* Combinations
, int nType
)
293 FXShaderCacheCombinationsItor itor
;
294 for (itor
= m_ShaderCacheCombinations
[nType
].begin(); itor
!= m_ShaderCacheCombinations
[nType
].end(); itor
++)
296 SCacheCombination
* cmb
= &itor
->second
;
297 FXShaderCacheCombinationsItor it
= Combinations
->find(cmb
->CacheName
);
298 if (it
== Combinations
->end())
300 Combinations
->insert(FXShaderCacheCombinationsItor::value_type(cmb
->CacheName
, *cmb
));
305 //==========================================================================================================================================
307 struct CompareCombItem
309 bool operator()(const SCacheCombination
& p1
, const SCacheCombination
& p2
) const
311 int n
= stricmp(p1
.Name
.c_str(), p2
.Name
.c_str());
314 n
= p1
.nCount
- p2
.nCount
;
317 return (stricmp(p1
.CacheName
.c_str(), p2
.CacheName
.c_str()) < 0);
321 #define g_szTestResults "%USER%/TestResults"
323 void CShaderMan::mfInitShadersCacheMissLog()
325 m_ShaderCacheMissCallback
= 0;
326 m_ShaderCacheMissPath
= "";
328 // don't access the HD if we don't have any logging to file enabled
329 if (!CRenderer::CV_r_shaderslogcachemisses
)
334 // create valid path (also for xbox dvd emu)
335 gEnv
->pCryPak
->MakeDir(g_szTestResults
);
337 char path
[ICryPak::g_nMaxPath
];
338 path
[sizeof(path
) - 1] = 0;
339 gEnv
->pCryPak
->AdjustFileName("%USER%\\Shaders\\ShaderCacheMisses.txt",
340 path
, ICryPak::FLAGS_PATH_REAL
| ICryPak::FLAGS_FOR_WRITING
);
342 m_ShaderCacheMissPath
= string(path
);
344 // load data which is already stored
345 FILE* fp
= fopen(path
, "r");
355 fgets(str
, 2047, fp
);
359 // remove new line at end
360 int len
= strlen(str
);
362 str
[strlen(str
) - 1] = 0;
364 m_ShaderCacheMisses
.push_back(str
);
367 std::sort(m_ShaderCacheMisses
.begin(), m_ShaderCacheMisses
.end());
374 static inline bool IsHexDigit(int ch
)
376 const int nDigit
= (ch
- int('0'));
377 const int bHex
= (ch
- int('a'));
378 return ((nDigit
>= 0) && (nDigit
<= 9)) || ((bHex
>= 0) && (bHex
< 6));
381 void CShaderMan::mfInitShadersCache(byte bForLevel
, FXShaderCacheCombinations
* Combinations
, const char* pCombinations
, int nType
)
383 static_assert(SHADER_LIST_VER
!= SHADER_SERIALISE_VER
, "Version mismatch!");
386 bool bFromFile
= (Combinations
== NULL
);
387 stack_string nameComb
;
388 m_ShaderCacheExportCombinations
.clear();
392 if (!gRenDev
->IsEditorMode() && !CRenderer::CV_r_shadersdebug
&& !gRenDev
->IsShaderCacheGenMode())
394 mfGetShaderListPath(nameComb
, nType
);
395 fp
= gEnv
->pCryPak
->FOpen(nameComb
.c_str(), "r+");
397 fp
= gEnv
->pCryPak
->FOpen(nameComb
.c_str(), "w+");
400 gEnv
->pCryPak
->AdjustFileName(nameComb
.c_str(), str
, 0);
401 FILE* statusdst
= fopen(str
, "rb");
405 CrySetFileAttributes(str
, FILE_ATTRIBUTE_ARCHIVE
);
406 fp
= gEnv
->pCryPak
->FOpen(nameComb
.c_str(), "r+");
409 m_FPCacheCombinations
[nType
] = fp
;
410 Combinations
= &m_ShaderCacheCombinations
[nType
];
414 char* pPtr
= (char*)pCombinations
;
416 if (fp
|| !bFromFile
)
418 while (!sEOF(bFromFile
, pPtr
, fp
))
424 gEnv
->pCryPak
->FGets(str
, 2047, fp
);
426 fxFillCR(&pPtr
, str
);
429 bool bNewFormat
= false;
431 if (str
[0] == '/' && str
[1] == '/') // commented line e.g. // BadLine: Metal@Common_ShadowPS(%BIllum@IlluminationPS(%DIFFUSE|%ENVCMAMB|%ALPHAGLOW|%STAT_BRANCHING)(%_RT_AMBIENT|%_RT_BUMP|%_RT_GLOW)(101)(0)(0)(ps_2_0)
434 bool bExportEntry
= false;
435 int size
= strlen(str
);
436 if (str
[size
- 1] == 0xa)
438 SCacheCombination cmb
;
440 SkipCharacters(&s
, kWhiteSpace
);
446 int nVer
= atoi(&s
[1]);
447 if (nVer
!= SHADER_LIST_VER
)
449 if (nVer
== SHADER_SERIALISE_VER
&& bFromFile
)
465 s
= strchr(&st
[1], '>');
468 cmb
.nCount
= atoi(st
);
479 int nVer
= atoi(&st
[1]);
481 if (nVer
!= SHADER_LIST_VER
)
483 if (nVer
== SHADER_SERIALISE_VER
)
499 memcpy(name
, st
, s
- st
);
509 cmb
.Ident
.m_GLMask
= sGetGL(&s
, cmb
.Name
, nHW
);
510 if (cmb
.Ident
.m_GLMask
== -1)
512 const char* szFileName
= nameComb
.c_str();
515 iLog
->Log("Error: Error in '%s' file (Line: %d)", szFileName
, nLine
);
520 iLog
->Log("Error: Error in non-file shader (Line: %d)", nLine
);
533 cmb
.Ident
.m_RTMask
= sGetRT(&s
);
542 cmb
.Ident
.m_LightMask
= shGetHex(s
);
551 cmb
.Ident
.m_MDMask
= shGetHex(s
);
560 cmb
.Ident
.m_MDVMask
= shGetHex(s
);
568 if (IsHexDigit(ss
[1]) && (ss
[2] != 'S'))
571 cmb
.Ident
.m_pipelineState
.opaque
= shGetHex64(s
);
577 cmb
.Ident
.m_pipelineState
.opaque
= 0;
583 cmb
.eCL
= CHWShader::mfStringClass(s
);
584 assert(cmb
.eCL
< eHWSC_Num
);
591 #if CRY_RENDERER_VULKAN
598 const char* descriptorSetBegin
= ss
+ 1;
599 const char* descriptorSetEnd
= strchr(descriptorSetBegin
, ')');
600 const unsigned int descriptorSetLength
= static_cast<int>(descriptorSetEnd
- descriptorSetBegin
);
601 if (descriptorSetLength
> 0)
603 unsigned int decodedBufferSize
= Base64::decodedsize_base64(descriptorSetLength
);
604 std::vector
<uint8
> encodedLayout(decodedBufferSize
);
605 Base64::decode_base64((char*)&encodedLayout
[0], descriptorSetBegin
, descriptorSetLength
, false);
606 encodedLayout
.resize(GetDeviceObjectFactory().GetEncodedResourceLayoutSize(encodedLayout
));
608 if (!GetDeviceObjectFactory().LookupResourceLayoutEncoding(cmb
.Ident
.m_pipelineState
.VULKAN
.resourceLayoutHash
))
610 GetDeviceObjectFactory().RegisterEncodedResourceLayout(cmb
.Ident
.m_pipelineState
.VULKAN
.resourceLayoutHash
, std::move(encodedLayout
));
616 CCryNameR nm
= CCryNameR(st
);
619 FXShaderCacheCombinationsItor it
= m_ShaderCacheExportCombinations
.find(nm
);
620 if (it
== m_ShaderCacheExportCombinations
.end())
623 m_ShaderCacheExportCombinations
.insert(FXShaderCacheCombinationsItor::value_type(nm
, cmb
));
628 FXShaderCacheCombinationsItor it
= Combinations
->find(nm
);
629 if (it
!= Combinations
->end())
636 Combinations
->insert(FXShaderCacheCombinationsItor::value_type(nm
, cmb
));
640 for (int j
= 0; j
< 64; j
++)
642 if (((uint64
)1 << j
) & nHW
)
644 cmb
.Ident
.m_GLMask
&= ~((uint64
)1 << j
);
645 sIterateHW_r(Combinations
, cmb
, j
+ 1, nHW
, name
);
646 cmb
.Ident
.m_GLMask
|= ((uint64
)1 << j
);
647 sIterateHW_r(Combinations
, cmb
, j
+ 1, nHW
, name
);
648 cmb
.Ident
.m_GLMask
&= ~((uint64
)1 << j
);
656 iLog
->Log("Error: Error in '%s' file (Line: %d)", nameComb
.c_str(), nLine
);
661 #if CRY_PLATFORM_DESKTOP
662 static void sResetDepend_r(SShaderGen
* pGen
, SShaderGenBit
* pBit
, SCacheCombination
& cm
)
664 if (!pBit
->m_DependResets
.size())
668 for (i
= 0; i
< pBit
->m_DependResets
.size(); i
++)
670 const char* c
= pBit
->m_DependResets
[i
].c_str();
671 for (j
= 0; j
< pGen
->m_BitMask
.Num(); j
++)
673 SShaderGenBit
* pBit1
= pGen
->m_BitMask
[j
];
674 if (!stricmp(pBit1
->m_ParamName
.c_str(), c
))
676 cm
.Ident
.m_RTMask
&= ~pBit1
->m_Mask
;
677 sResetDepend_r(pGen
, pBit1
, cm
);
684 static void sSetDepend_r(SShaderGen
* pGen
, SShaderGenBit
* pBit
, SCacheCombination
& cm
)
686 if (!pBit
->m_DependSets
.size())
690 for (i
= 0; i
< pBit
->m_DependSets
.size(); i
++)
692 const char* c
= pBit
->m_DependSets
[i
].c_str();
693 for (j
= 0; j
< pGen
->m_BitMask
.Num(); j
++)
695 SShaderGenBit
* pBit1
= pGen
->m_BitMask
[j
];
696 if (!stricmp(pBit1
->m_ParamName
.c_str(), c
))
698 cm
.Ident
.m_RTMask
|= pBit1
->m_Mask
;
699 sSetDepend_r(pGen
, pBit1
, cm
);
706 // Support for single light only
707 static bool sIterateDL(DWORD
& dwDL
)
709 int nLights
= dwDL
& 0xf;
718 for (i
= 0; i
< nLights
; i
++)
720 nType
[i
] = (dwDL
>> (SLMF_LTYPE_SHIFT
+ (i
* SLMF_LTYPE_BITS
))) & ((1 << SLMF_LTYPE_BITS
) - 1);
725 if ((nType
[0] & 3) < 2)
733 nType
[0] = SLMF_DIRECT
;
734 nType
[1] = SLMF_POINT
;
738 if ((nType
[0] & 3) == SLMF_DIRECT
)
740 nType
[0] = SLMF_POINT
;
741 nType
[1] = SLMF_POINT
;
746 nType
[0] = SLMF_DIRECT
;
747 nType
[1] = SLMF_POINT
;
748 nType
[2] = SLMF_POINT
;
752 if ((nType
[0] & 3) == SLMF_DIRECT
)
754 nType
[0] = SLMF_POINT
;
755 nType
[1] = SLMF_POINT
;
756 nType
[2] = SLMF_POINT
;
761 nType
[0] = SLMF_DIRECT
;
762 nType
[1] = SLMF_POINT
;
763 nType
[2] = SLMF_POINT
;
764 nType
[3] = SLMF_POINT
;
768 if ((nType
[0] & 3) == SLMF_DIRECT
)
770 nType
[0] = SLMF_POINT
;
771 nType
[1] = SLMF_POINT
;
772 nType
[2] = SLMF_POINT
;
773 nType
[3] = SLMF_POINT
;
779 for (i
= 0; i
< nLights
; i
++)
781 dwDL
|= nType
[i
] << (SLMF_LTYPE_SHIFT
+ i
* SLMF_LTYPE_BITS
);
786 /*static bool sIterateDL(DWORD& dwDL)
788 int nLights = dwDL & 0xf;
797 for (i=0; i<nLights; i++)
799 nType[i] = (dwDL >> (SLMF_LTYPE_SHIFT + (i*SLMF_LTYPE_BITS))) & ((1<<SLMF_LTYPE_BITS)-1);
804 if (!(nType[0] & SLMF_RAE_ENABLED))
805 nType[0] |= SLMF_RAE_ENABLED;
812 nType[0] = SLMF_DIRECT;
813 nType[1] = SLMF_POINT;
817 if (!(nType[0] & SLMF_RAE_ENABLED))
818 nType[0] |= SLMF_RAE_ENABLED;
820 if (!(nType[1] & SLMF_RAE_ENABLED))
821 nType[1] |= SLMF_RAE_ENABLED;
823 if (nType[0] == SLMF_DIRECT)
824 nType[0] = SLMF_POINT;
828 nType[0] = SLMF_DIRECT;
829 nType[1] = SLMF_POINT;
830 nType[2] = SLMF_POINT;
834 if (!(nType[0] & SLMF_RAE_ENABLED))
835 nType[0] |= SLMF_RAE_ENABLED;
837 if (!(nType[1] & SLMF_RAE_ENABLED))
838 nType[1] |= SLMF_RAE_ENABLED;
840 if (!(nType[2] & SLMF_RAE_ENABLED))
841 nType[2] |= SLMF_RAE_ENABLED;
843 if (nType[0] == SLMF_DIRECT)
844 nType[0] = SLMF_POINT;
848 nType[0] = SLMF_DIRECT;
849 nType[1] = SLMF_POINT;
850 nType[2] = SLMF_POINT;
851 nType[3] = SLMF_POINT;
855 if (!(nType[0] & SLMF_RAE_ENABLED))
856 nType[0] |= SLMF_RAE_ENABLED;
858 if (!(nType[1] & SLMF_RAE_ENABLED))
859 nType[1] |= SLMF_RAE_ENABLED;
861 if (!(nType[2] & SLMF_RAE_ENABLED))
862 nType[2] |= SLMF_RAE_ENABLED;
864 if (!(nType[3] & SLMF_RAE_ENABLED))
865 nType[3] |= SLMF_RAE_ENABLED;
867 if (nType[0] == SLMF_DIRECT)
868 nType[0] = SLMF_POINT;
873 for (i=0; i<nLights; i++)
875 dwDL |= nType[i] << (SLMF_LTYPE_SHIFT + i*SLMF_LTYPE_BITS);
880 void CShaderMan::mfAddLTCombination(SCacheCombination
* cmb
, FXShaderCacheCombinations
& CmbsMapDst
, DWORD dwL
)
885 SCacheCombination cm
;
887 cm
.Ident
.m_LightMask
= dwL
;
889 const char* c
= strchr(cmb
->CacheName
.c_str(), ')');
890 c
= strchr(&c
[1], ')');
891 int len
= (int)(c
- cmb
->CacheName
.c_str() + 1);
892 assert(len
< sizeof(str
));
893 cry_strcpy(str
, cmb
->CacheName
.c_str(), len
);
894 cry_strcat(str
, "(");
895 cry_sprintf(sLT
, "%x", (uint32
)dwL
);
896 cry_strcat(str
, sLT
);
897 c
= strchr(&c
[2], ')');
899 CCryNameR nm
= CCryNameR(str
);
901 FXShaderCacheCombinationsItor it
= CmbsMapDst
.find(nm
);
902 if (it
== CmbsMapDst
.end())
904 CmbsMapDst
.insert(FXShaderCacheCombinationsItor::value_type(nm
, cm
));
908 void CShaderMan::mfAddLTCombinations(SCacheCombination
* cmb
, FXShaderCacheCombinations
& CmbsMapDst
)
910 if (!CRenderer::CV_r_shadersprecachealllights
)
913 DWORD dwL
= 0; // 0 lights
917 // !HACK: Do not iterate multiple lights for low spec
918 if ((cmb
->Ident
.m_RTMask
& (g_HWSR_MaskBit
[HWSR_QUALITY
] | g_HWSR_MaskBit
[HWSR_QUALITY1
])) || (dwL
& 0xf) <= 1)
919 mfAddLTCombination(cmb
, CmbsMapDst
, dwL
);
920 bRes
= sIterateDL(dwL
);
925 void CShaderMan::mfAddRTCombination_r(int nComb
, FXShaderCacheCombinations
& CmbsMapDst
, SCacheCombination
* cmb
, CHWShader
* pSH
, bool bAutoPrecache
)
928 uint32 dwType
= pSH
->m_dwShaderType
;
931 for (i
= nComb
; i
< m_pGlobalExt
->m_BitMask
.Num(); i
++)
933 SShaderGenBit
* pBit
= m_pGlobalExt
->m_BitMask
[i
];
934 if (bAutoPrecache
&& !(pBit
->m_Flags
& (SHGF_AUTO_PRECACHE
| SHGF_LOWSPEC_AUTO_PRECACHE
)))
937 // Precache this flag on low-spec only
938 if (pBit
->m_Flags
& SHGF_LOWSPEC_AUTO_PRECACHE
)
940 if (cmb
->Ident
.m_RTMask
& (g_HWSR_MaskBit
[HWSR_QUALITY
] | g_HWSR_MaskBit
[HWSR_QUALITY1
]))
943 // Only in runtime used
944 if (pBit
->m_Flags
& SHGF_RUNTIME
)
946 for (n
= 0; n
< pBit
->m_PrecacheNames
.size(); n
++)
948 if (pBit
->m_PrecacheNames
[n
] == dwType
)
951 if (n
< pBit
->m_PrecacheNames
.size())
953 SCacheCombination cm
;
955 cm
.Ident
.m_RTMask
&= ~pBit
->m_Mask
;
956 cm
.Ident
.m_RTMask
|= (pBit
->m_Mask
^ cmb
->Ident
.m_RTMask
) & pBit
->m_Mask
;
959 uint64 nBitSet
= pBit
->m_Mask
& cmb
->Ident
.m_RTMask
;
961 sSetDepend_r(m_pGlobalExt
, pBit
, cm
);
963 sResetDepend_r(m_pGlobalExt
, pBit
, cm
);
967 const char* c
= strchr(cmb
->CacheName
.c_str(), '(');
968 const size_t len
= (size_t)(c
- cmb
->CacheName
.c_str());
969 cry_strcpy(str
, cmb
->CacheName
.c_str(), len
);
970 const char* c1
= strchr(&c
[1], '(');
971 cry_strcat(str
, c
, (size_t)(c1
- c
));
972 cry_strcat(str
, "(");
973 SShaderGen
* pG
= m_pGlobalExt
;
975 for (j
= 0; j
< pG
->m_BitMask
.Num(); j
++)
977 SShaderGenBit
* pBit
= pG
->m_BitMask
[j
];
978 if (pBit
->m_Mask
& cm
.Ident
.m_RTMask
)
982 sRT
+= pBit
->m_ParamName
.c_str();
985 cry_strcat(str
, sRT
.c_str());
986 c1
= strchr(&c1
[1], ')');
988 CCryNameR nm
= CCryNameR(str
);
990 // HACK: don't allow unsupported quality mode
991 uint64 nQMask
= g_HWSR_MaskBit
[HWSR_QUALITY
] | g_HWSR_MaskBit
[HWSR_QUALITY1
];
992 if ((cm
.Ident
.m_RTMask
& nQMask
) != nQMask
)
994 FXShaderCacheCombinationsItor it
= CmbsMapDst
.find(nm
);
995 if (it
== CmbsMapDst
.end())
997 CmbsMapDst
.insert(FXShaderCacheCombinationsItor::value_type(nm
, cm
));
1000 if (pSH
->m_Flags
& (HWSG_SUPPORTS_MULTILIGHTS
| HWSG_SUPPORTS_LIGHTING
))
1001 mfAddLTCombinations(&cm
, CmbsMapDst
);
1002 mfAddRTCombination_r(i
+ 1, CmbsMapDst
, &cm
, pSH
, bAutoPrecache
);
1007 void CShaderMan::mfAddRTCombinations(FXShaderCacheCombinations
& CmbsMapSrc
, FXShaderCacheCombinations
& CmbsMapDst
, CHWShader
* pSH
, bool bListOnly
)
1009 if (pSH
->m_nFrameLoad
== gRenDev
->GetMainFrameID())
1011 pSH
->m_nFrameLoad
= gRenDev
->GetMainFrameID();
1012 uint32 dwType
= pSH
->m_dwShaderType
;
1015 const char* str2
= pSH
->mfGetEntryName();
1016 FXShaderCacheCombinationsItor itor
;
1017 for (itor
= CmbsMapSrc
.begin(); itor
!= CmbsMapSrc
.end(); itor
++)
1019 SCacheCombination
* cmb
= &itor
->second
;
1020 const char* c
= strchr(cmb
->Name
.c_str(), '@');
1022 c
= strchr(cmb
->Name
.c_str(), '/');
1026 if (stricmp(&c
[1], str2
))
1028 /*if (!stricmp(str2, "MetalReflVS"))
1030 if (cmb->nGL == 0x1093)
1037 if (pSH
->m_Flags
& (HWSG_SUPPORTS_MULTILIGHTS
| HWSG_SUPPORTS_LIGHTING
))
1038 mfAddLTCombinations(cmb
, CmbsMapDst
);
1039 mfAddRTCombination_r(0, CmbsMapDst
, cmb
, pSH
, true);
1042 mfAddRTCombination_r(0, CmbsMapDst
, cmb
, pSH
, false);
1045 #endif // CRY_PLATFORM_DESKTOP
1047 void CShaderMan::mfInsertNewCombination(SShaderCombIdent
& Ident
, EHWShaderClass eCL
, const char* name
, int nID
, string
* Str
, byte bStore
)
1050 if (!m_FPCacheCombinations
[nID
] && bStore
)
1056 SShaderGenComb
* c
= NULL
;
1059 const char* m
= strchr(name
, '@');
1061 m
= strchr(name
, '/');
1066 cry_strcpy(nmFX
, name
, (size_t)(m
- name
));
1067 c
= mfGetShaderGenInfo(nmFX
);
1068 if (c
&& c
->pGen
&& c
->pGen
->m_BitMask
.Num())
1070 SShaderGen
* pG
= c
->pGen
;
1071 for (i
= 0; i
< 64; i
++)
1073 if (Ident
.m_GLMask
& ((uint64
)1 << i
))
1075 for (j
= 0; j
< pG
->m_BitMask
.Num(); j
++)
1077 SShaderGenBit
* pBit
= pG
->m_BitMask
[j
];
1078 if (pBit
->m_Mask
& (Ident
.m_GLMask
& ((uint64
)1 << i
)))
1082 sGL
+= pBit
->m_ParamName
.c_str();
1093 SShaderGen
* pG
= m_pGlobalExt
;
1096 for (i
= 0; i
< pG
->m_BitMask
.Num(); i
++)
1098 SShaderGenBit
* pBit
= pG
->m_BitMask
[i
];
1099 if (pBit
->m_Mask
& Ident
.m_RTMask
)
1103 sRT
+= pBit
->m_ParamName
.c_str();
1108 uint32 nLT
= Ident
.m_LightMask
;
1109 if (bStore
== 1 && Ident
.m_LightMask
)
1112 #ifdef CRY_RENDERER_VULKAN
1113 std::string base64EncodedLayout
;
1114 const std::vector
<uint8
>* pEncodedLayout
= GetDeviceObjectFactory().LookupResourceLayoutEncoding(Ident
.m_pipelineState
.VULKAN
.resourceLayoutHash
);
1117 size_t base64EncodedLayoutSize
= (Base64::encodedsize_base64(pEncodedLayout
->size()));
1118 base64EncodedLayout
.resize(base64EncodedLayoutSize
);
1119 Base64::encode_base64((char*)&base64EncodedLayout
[0], (const char*)pEncodedLayout
->data(), pEncodedLayout
->size(), false);
1121 sprintf(str
, "<%d>%s(%s)(%s)(%x)(%x)(%x)(%llx)(%s)(%s)", SHADER_LIST_VER
, name
, sGL
.c_str(), sRT
.c_str(), nLT
, Ident
.m_MDMask
, Ident
.m_MDVMask
, Ident
.m_pipelineState
.opaque
, CHWShader::mfClassString(eCL
), base64EncodedLayout
.c_str());
1123 sprintf(str
, "<%d>%s(%s)(%s)(%x)(%x)(%x)(%llx)(%s)", SHADER_LIST_VER
, name
, sGL
.c_str(), sRT
.c_str(), nLT
, Ident
.m_MDMask
, Ident
.m_MDVMask
, Ident
.m_pipelineState
.opaque
, CHWShader::mfClassString(eCL
));
1132 if (str
[0] == '<' && str
[2] == '>')
1133 nm
= CCryNameR(&str
[3]);
1135 nm
= CCryNameR(str
);
1136 FXShaderCacheCombinationsItor it
= m_ShaderCacheCombinations
[nID
].find(nm
);
1137 if (it
!= m_ShaderCacheCombinations
[nID
].end())
1139 SCacheCombination cmb
;
1145 stack_string nameOut
;
1146 mfGetShaderListPath(nameOut
, nID
);
1148 static CryCriticalSection s_cResLock
;
1149 AUTO_LOCK(s_cResLock
); // Not thread safe without this
1151 if (m_FPCacheCombinations
[nID
])
1153 m_ShaderCacheCombinations
[nID
].insert(FXShaderCacheCombinationsItor::value_type(nm
, cmb
));
1154 gEnv
->pCryPak
->FPrintf(m_FPCacheCombinations
[nID
], "%s\n", str
);
1155 gEnv
->pCryPak
->FFlush(m_FPCacheCombinations
[nID
]);
1162 string
CShaderMan::mfGetShaderCompileFlags(EHWShaderClass eClass
, UPipelineState pipelineState
) const
1166 #define STRICT_MODE " /Ges"
1167 #define COMPATIBLE_MODE " /Gec"
1168 // NOTE: when updating remote compiler folders, please ensure folders path is matching
1169 const char* pCompilerOrbis
= "ORBIS/V033/DXOrbisShaderCompiler.exe %s %s %s %s";
1170 const char* pCompilerDurango
= "Durango/March2017/fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Fo %s %s";
1171 const char* pCompilerD3D11
= "PCD3D11/v007/fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Fo %s %s";
1172 const char *pCompilerSPIRV
= "SPIRV/V002/HLSL2SPIRV.exe %s %s %s %s";
1174 #define ESSL_VERSION "es310"
1175 #if DXGL_REQUIRED_VERSION >= DXGL_VERSION_45
1176 #define GLSL_VERSION "450"
1177 #elif DXGL_REQUIRED_VERSION >= DXGL_VERSION_44
1178 #define GLSL_VERSION "440"
1179 #elif DXGL_REQUIRED_VERSION >= DXGL_VERSION_43
1180 #define GLSL_VERSION "430"
1181 #elif DXGL_REQUIRED_VERSION >= DXGL_VERSION_42
1182 #define GLSL_VERSION "420"
1183 #elif DXGL_REQUIRED_VERSION >= DXGL_VERSION_41
1184 #define GLSL_VERSION "410"
1185 #elif DXGLES_REQUIRED_VERSION >= DXGLES_VERSION_31
1186 #define GLSL_VERSION "310"
1187 #elif DXGLES_REQUIRED_VERSION >= DXGLES_VERSION_30
1188 #define GLSL_VERSION "300"
1190 #error "Shading language revision not defined for this GL version"
1193 const char* pCompilerGL4
= "PCGL/V012/HLSLcc.exe -lang=" GLSL_VERSION
" -flags=36609 -fxc=\"..\\..\\PCD3D11\\v007\\fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Fo\" -out=%s -in=%s";
1194 const char* pCompilerGLES3
= "PCGL/V012/HLSLcc.exe -lang=" ESSL_VERSION
" -flags=36609 -fxc=\"..\\..\\PCD3D11\\v007\\fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Fo\" -out=%s -in=%s";
1196 if (CRenderer::CV_r_shadersdebug
== 3)
1198 // Set debug information
1199 pCompilerD3D11
= "PCD3D11/v007/fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Zi /Od /Fo %s %s";
1200 pCompilerDurango
= "Durango/March2017/fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Zi /Od /Fo %s %s";
1202 else if (CRenderer::CV_r_shadersdebug
== 4)
1204 // Set debug information, optimized shaders
1205 pCompilerD3D11
= "PCD3D11/v007/fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Zi /O3 /Fo %s %s";
1206 pCompilerDurango
= "Durango/March2017/fxc.exe /nologo /E %s /T %s /Zpr" COMPATIBLE_MODE
"" STRICT_MODE
" /Zi /O3 /Fo %s %s";
1209 if (pipelineState
.opaque
!= 0)
1211 if (CParserBin::m_nPlatform
== SF_ORBIS
)
1213 const char* const pCompilerGnm
= "ORBIS/V033/GnmShaderCompiler.exe %s %s %s %s --RowMajorMatrixStorage --UpgradeLegacySamplers --DebugHelperFiles";
1215 static const char* kVsStages
[] =
1226 static const int kPsDepthBits
[] =
1233 static const char kISA
[] =
1244 result
.Format("%s -HwStage=%s -HwISA=%c", pCompilerGnm
, kVsStages
[pipelineState
.GNM
.VS
.targetStage
& 7], kISA
[(pipelineState
.GNM
.VS
.targetStage
>> 5) & 3]);
1247 result
.Format("%s -HwStage=%s -HwISA=%c", pCompilerGnm
, (pipelineState
.GNM
.HS
.targetStage
& 1) ? "H2D" : "H2M", kISA
[(pipelineState
.GNM
.HS
.targetStage
>> 5) & 3]);
1250 result
.Format("%s -HwStage=%s -HwISA=%c", pCompilerGnm
, (pipelineState
.GNM
.DS
.targetStage
& 1) ? "D2P" : "M2P", kISA
[(pipelineState
.GNM
.DS
.targetStage
>> 5) & 3]);
1252 case eHWSC_Geometry
:
1253 result
.Format("%s -HwStage=%s -HwISA=%c", pCompilerGnm
, (pipelineState
.GNM
.GS
.targetStage
& 1) ? "L2C2P" : "G2C2P", kISA
[(pipelineState
.GNM
.GS
.targetStage
>> 5) & 3]);
1256 result
.Format("%s -HwStage=%s -HwISA=%c -PsColor=0x%x -PsDepth=%d -PsStencil=%d", pCompilerGnm
, "P", kISA
[(pipelineState
.GNM
.PS
.depthStencilInfo
>> 29) & 3], pipelineState
.GNM
.PS
.targetFormats
, kPsDepthBits
[(pipelineState
.GNM
.PS
.depthStencilInfo
>> 1) & 3], pipelineState
.GNM
.PS
.depthStencilInfo
& 1 ? 8 : 0);
1259 result
.Format("%s -HwStage=%s -HwISA=%c", pCompilerGnm
, "C", kISA
[(pipelineState
.GNM
.CS
.targetStage
>> 5) & 3]);
1262 CRY_ASSERT(false && "Unknown stage");
1270 #if CRY_PLATFORM_ORBIS
1271 result
= pCompilerOrbis
;
1272 #elif CRY_PLATFORM_DURANGO
1273 result
= pCompilerDurango
;
1274 #elif CRY_RENDERER_OPENGLES && DXGL_INPUT_GLSL
1275 result
= pCompilerGLES3
;
1276 #elif CRY_RENDERER_OPENGL && DXGL_INPUT_GLSL
1277 result
= pCompilerGL4
;
1279 if (CParserBin::m_nPlatform
== SF_D3D11
)
1280 result
= pCompilerD3D11
;
1281 else if (CParserBin::m_nPlatform
== SF_ORBIS
)
1282 result
= pCompilerOrbis
;
1283 else if (CParserBin::m_nPlatform
== SF_DURANGO
)
1284 result
= pCompilerDurango
;
1285 else if (CParserBin::m_nPlatform
== SF_GL4
)
1286 result
= pCompilerGL4
;
1287 else if (CParserBin::m_nPlatform
== SF_GLES3
)
1288 result
= pCompilerGLES3
;
1289 else if (CParserBin::m_nPlatform
== SF_VULKAN
)
1290 result
= pCompilerSPIRV
;
1293 CryFatalError("Compiling shaders for unsupported platform");
1298 if (!CRenderer::CV_r_shadersCompileStrict
)
1300 result
= result
.replace("" STRICT_MODE
"", "");
1303 if (!CRenderer::CV_r_shadersCompileCompatible
)
1305 result
= result
.replace("" COMPATIBLE_MODE
"", "");
1311 inline bool sCompareComb(const SCacheCombination
& a
, const SCacheCombination
& b
)
1315 char shader1
[128], shader2
[128];
1316 char* tech1
= NULL
, * tech2
= NULL
;
1317 cry_strcpy(shader1
, a
.Name
.c_str());
1318 cry_strcpy(shader2
, b
.Name
.c_str());
1319 char* c
= strchr(shader1
, '@');
1321 c
= strchr(shader1
, '/');
1328 c
= strchr(shader2
, '@');
1330 c
= strchr(shader2
, '/');
1338 dif
= stricmp(shader1
, shader2
);
1342 if (tech1
== NULL
&& tech2
!= NULL
)
1344 if (tech1
!= NULL
&& tech2
== NULL
)
1347 if (tech1
!= NULL
&& tech2
!= NULL
)
1349 dif
= stricmp(tech1
, tech2
);
1354 if (a
.Ident
.m_GLMask
!= b
.Ident
.m_GLMask
)
1355 return a
.Ident
.m_GLMask
< b
.Ident
.m_GLMask
;
1357 if (a
.Ident
.m_RTMask
!= b
.Ident
.m_RTMask
)
1358 return a
.Ident
.m_RTMask
< b
.Ident
.m_RTMask
;
1360 if (a
.Ident
.m_pipelineState
.opaque
!= b
.Ident
.m_pipelineState
.opaque
)
1361 return a
.Ident
.m_pipelineState
.opaque
< b
.Ident
.m_pipelineState
.opaque
;
1363 if (a
.Ident
.m_FastCompare1
!= b
.Ident
.m_FastCompare1
)
1364 return a
.Ident
.m_FastCompare1
< b
.Ident
.m_FastCompare1
;
1366 if (a
.Ident
.m_FastCompare2
!= b
.Ident
.m_FastCompare2
)
1367 return a
.Ident
.m_FastCompare2
< b
.Ident
.m_FastCompare2
;
1372 #if CRY_PLATFORM_DESKTOP
1374 void CShaderMan::AddGLCombinations(CShader
* pSH
, std::vector
<SCacheCombination
>& CmbsGL
)
1378 if (pSH
->m_pGenShader
)
1380 SShaderGen
* pG
= pSH
->m_pGenShader
->m_ShaderGenParams
;
1381 for (i
= 0; i
< pG
->m_BitMask
.size(); i
++)
1383 SShaderGenBit
* pB
= pG
->m_BitMask
[i
];
1384 SCacheCombination cc
;
1385 cc
.Name
= pB
->m_ParamName
;
1386 for (j
= 0; j
< m_pGlobalExt
->m_BitMask
.size(); j
++)
1388 SShaderGenBit
* pB1
= m_pGlobalExt
->m_BitMask
[j
];
1389 if (pB1
->m_ParamName
== pB
->m_ParamName
)
1391 nMask
|= pB1
->m_Mask
;
1395 assert(j
!= m_pGlobalExt
->m_BitMask
.size());
1396 for (i
= 0; i
< 64; i
++)
1398 //if (nMask & (1<<i))
1399 // SetBit_r(i, CmbsGL);
1405 SCacheCombination cc
;
1406 cc
.Ident
.m_GLMask
= 0;
1407 CmbsGL
.push_back(cc
);
1411 void CShaderMan::AddGLCombination(FXShaderCacheCombinations
& CmbsMap
, SCacheCombination
& cmb
)
1414 const char* st
= cmb
.CacheName
.c_str();
1417 const char* s
= strchr(st
, '@');
1420 s
= strchr(st
, '/');
1423 memcpy(name
, st
, s
- st
);
1427 cry_strcpy(name
, st
);
1429 cry_sprintf(str
, "%s(%llx)(%x)(%x)", name
, cmb
.Ident
.m_GLMask
, cmb
.Ident
.m_MDMask
, cmb
.Ident
.m_MDVMask
);
1431 cry_sprintf(str
, "%s(%I64x)(%x)(%x)", name
, cmb
.Ident
.m_GLMask
, cmb
.Ident
.m_MDMask
, cmb
.Ident
.m_MDVMask
);
1433 CCryNameR nm
= CCryNameR(str
);
1434 FXShaderCacheCombinationsItor it
= CmbsMap
.find(nm
);
1435 if (it
== CmbsMap
.end())
1439 CmbsMap
.insert(FXShaderCacheCombinationsItor::value_type(nm
, cmb
));
1444 gRenDev->m_cEF.mfInsertNewCombination(cmb.nGL, cmb.nRT, cmb.nLT, cmb.nMD, cmb.nMDV, cmb.ePR, szName, 0, &str, false);
1445 CCryNameTSCRC nm = CCryNameTSCRC(str.c_str());
1446 FXShaderCacheCombinationsItor it = Combinations->find(nm);
1447 if (it == Combinations->end())
1450 Combinations->insert(FXShaderCacheCombinationsItor::value_type(nm, cmb));
1452 for (int j=i; j<64; j++)
1454 if (((uint64)1<<j) & nHW)
1456 cmb.nGL &= ~((uint64)1<<j);
1457 sIterateHW_r(Combinations, cmb, j+1, nHW, szName);
1458 cmb.nGL |= ((uint64)1<<j);
1459 sIterateHW_r(Combinations, cmb, j+1, nHW, szName);
1463 void CShaderMan::AddCombination(SCacheCombination
& cmb
, FXShaderCacheCombinations
& CmbsMap
, CHWShader
* pHWS
)
1467 sprintf(str
, "%s(%llx)(%llx)(%d)(%d)(%d)(%llx)", cmb
.Name
.c_str(), cmb
.Ident
.m_GLMask
, cmb
.Ident
.m_RTMask
, cmb
.Ident
.m_LightMask
, cmb
.Ident
.m_MDMask
, cmb
.Ident
.m_MDVMask
, cmb
.Ident
.m_pipelineState
.opaque
);
1469 sprintf(str
, "%s(%I64x)(%I64x)(%d)(%d)(%d)(%llx)", cmb
.Name
.c_str(), cmb
.Ident
.m_GLMask
, cmb
.Ident
.m_RTMask
, cmb
.Ident
.m_LightMask
, cmb
.Ident
.m_MDMask
, cmb
.Ident
.m_MDVMask
, cmb
.Ident
.m_pipelineState
.opaque
);
1471 CCryNameR nm
= CCryNameR(str
);
1472 FXShaderCacheCombinationsItor it
= CmbsMap
.find(nm
);
1473 if (it
== CmbsMap
.end())
1476 CmbsMap
.insert(FXShaderCacheCombinationsItor::value_type(nm
, cmb
));
1480 void CShaderMan::AddLTCombinations(SCacheCombination
& cmb
, FXShaderCacheCombinations
& CmbsMap
, CHWShader
* pHWS
)
1482 assert(pHWS
->m_Flags
& HWSG_SUPPORTS_LIGHTING
);
1484 // Just single light support
1486 // Directional light
1487 cmb
.Ident
.m_LightMask
= 1;
1488 AddCombination(cmb
, CmbsMap
, pHWS
);
1491 cmb
.Ident
.m_LightMask
= 0x101;
1492 AddCombination(cmb
, CmbsMap
, pHWS
);
1495 cmb
.Ident
.m_LightMask
= 0x201;
1496 AddCombination(cmb
, CmbsMap
, pHWS
);
1499 void CShaderMan::AddRTCombinations(FXShaderCacheCombinations
& CmbsMap
, CHWShader
* pHWS
, CShader
* pSH
, FXShaderCacheCombinations
* Combinations
)
1501 SCacheCombination cmb
;
1503 uint32 nType
= pHWS
->m_dwShaderType
;
1506 SShaderGen
* pGen
= m_pGlobalExt
;
1509 uint32 nBitsPlatform
= 0;
1510 if (CParserBin::m_nPlatform
== SF_ORBIS
)
1511 nBitsPlatform
|= SHGD_HW_ORBIS
;
1512 else if (CParserBin::m_nPlatform
== SF_DURANGO
)
1513 nBitsPlatform
|= SHGD_HW_DURANGO
;
1514 else if (CParserBin::m_nPlatform
== SF_D3D11
)
1515 nBitsPlatform
|= SHGD_HW_DX11
;
1516 else if (CParserBin::m_nPlatform
== SF_GL4
)
1517 nBitsPlatform
|= SHGD_HW_GL4
;
1518 else if (CParserBin::m_nPlatform
== SF_GLES3
)
1519 nBitsPlatform
|= SHGD_HW_GLES3
;
1520 else if (CParserBin::m_nPlatform
== SF_VULKAN
)
1521 nBitsPlatform
|= SHGD_HW_VULKAN
;
1524 memset(BitMask
, 0, sizeof(BitMask
));
1526 // Make a mask of flags affected by this type of shader
1528 uint64 nSetMask
= 0;
1532 for (i
= 0; i
< pGen
->m_BitMask
.size(); i
++)
1534 SShaderGenBit
* pBit
= pGen
->m_BitMask
[i
];
1537 if (pBit
->m_Flags
& SHGF_RUNTIME
)
1539 if (nBitsPlatform
& pBit
->m_nDependencyReset
)
1541 for (j
= 0; j
< pBit
->m_PrecacheNames
.size(); j
++)
1543 if (pBit
->m_PrecacheNames
[j
] == nType
)
1545 if (nBitsPlatform
& pBit
->m_nDependencySet
)
1547 nSetMask
|= pBit
->m_Mask
;
1550 BitMask
[nBits
++] = pBit
->m_Mask
;
1551 nRTMask
|= pBit
->m_Mask
;
1558 CryLog("WARNING: Number of runtime bits for shader '%s' - %d: exceed 10 (too many combinations will be produced)...", pHWS
->GetName(), nBits
);
1561 CryLog("Error: Ignore...");
1565 cmb
.eCL
= pHWS
->m_eSHClass
;
1566 string szName
= string(pSH
->GetName());
1567 szName
+= string("@") + string(pHWS
->m_EntryFunc
.c_str());
1569 cmb
.Ident
.m_GLMask
= pHWS
->m_nMaskGenShader
;
1571 // For unknown shader type just add combinations from the list
1574 FXShaderCacheCombinationsItor itor
;
1575 for (itor
= Combinations
->begin(); itor
!= Combinations
->end(); itor
++)
1577 SCacheCombination
* c
= &itor
->second
;
1578 if (c
->Name
== cmb
.Name
&& c
->Ident
.m_GLMask
== pHWS
->m_nMaskGenFX
)
1581 AddCombination(cmb
, CmbsMap
, pHWS
);
1587 cmb
.Ident
.m_LightMask
= 0;
1588 cmb
.Ident
.m_MDMask
= 0;
1589 cmb
.Ident
.m_MDVMask
= 0;
1590 cmb
.Ident
.m_RTMask
= 0;
1592 int nIterations
= 1 << nBits
;
1593 for (i
= 0; i
< nIterations
; i
++)
1595 cmb
.Ident
.m_RTMask
= nSetMask
;
1596 cmb
.Ident
.m_LightMask
= 0;
1597 for (j
= 0; j
< nBits
; j
++)
1600 cmb
.Ident
.m_RTMask
|= BitMask
[j
];
1602 /*if (cmb.nRT == 0x40002)
1606 AddCombination(cmb
, CmbsMap
, pHWS
);
1607 if (pHWS
->m_Flags
& HWSG_SUPPORTS_LIGHTING
)
1608 AddLTCombinations(cmb
, CmbsMap
, pHWS
);
1612 void CShaderMan::_PrecacheShaderList(bool bStatsOnly
)
1614 float t0
= gEnv
->pTimer
->GetAsyncCurTime();
1619 m_eCacheMode
= eSC_BuildGlobalList
;
1621 uint32 nSaveFeatures
= gRenDev
->m_Features
;
1622 int nAsync
= CRenderer::CV_r_shadersasynccompiling
;
1624 CRenderer::CV_r_shadersasynccompiling
= 0;
1626 // Command line shaders precaching
1627 gRenDev
->m_Features
|= RFT_HW_SM20
| RFT_HW_SM2X
| RFT_HW_SM30
;
1628 FXShaderCacheCombinations
* Combinations
= &m_ShaderCacheCombinations
[0];
1630 std::vector
<SCacheCombination
> Cmbs
;
1631 std::vector
<SCacheCombination
> CmbsRT
;
1632 FXShaderCacheCombinations CmbsMap
;
1633 char str1
[128], str2
[128];
1635 // Extract global combinations only (including MD and MDV)
1636 for (FXShaderCacheCombinationsItor itor
= Combinations
->begin(); itor
!= Combinations
->end(); itor
++)
1638 SCacheCombination
* cmb
= &itor
->second
;
1639 FXShaderCacheCombinationsItor it
= CmbsMap
.find(cmb
->CacheName
);
1640 if (it
== CmbsMap
.end())
1642 CmbsMap
.insert(FXShaderCacheCombinationsItor::value_type(cmb
->CacheName
, *cmb
));
1645 for (FXShaderCacheCombinationsItor itor
= CmbsMap
.begin(); itor
!= CmbsMap
.end(); itor
++)
1647 SCacheCombination
* cmb
= &itor
->second
;
1648 Cmbs
.push_back(*cmb
);
1656 int nMaterialCombinations
= 0;
1658 if (Cmbs
.size() >= 1)
1660 std::stable_sort(Cmbs
.begin(), Cmbs
.end(), sCompareComb
);
1662 nMaterialCombinations
= Cmbs
.size();
1664 m_nCombinationsProcess
= Cmbs
.size();
1666 m_nCombinationsCompiled
= 0;
1667 m_nCombinationsEmpty
= 0;
1668 uint64 nGLLast
= -1;
1669 for (int i
= 0; i
< Cmbs
.size(); i
++)
1671 SCacheCombination
* cmb
= &Cmbs
[i
];
1672 cry_strcpy(str1
, cmb
->Name
.c_str());
1673 char* c
= strchr(str1
, '@');
1675 c
= strchr(str1
, '/');
1680 m_szShaderPrecache
= &c
[1];
1684 c
= strchr(str1
, '(');
1688 m_szShaderPrecache
= "";
1692 CShader
* pSH
= CShaderMan::mfForName(str1
, 0, NULL
, cmb
->Ident
.m_GLMask
);
1696 std::vector
<SCacheCombination
>* pCmbs
= &Cmbs
;
1697 FXShaderCacheCombinations CmbsMapRTSrc
;
1698 FXShaderCacheCombinations CmbsMapRTDst
;
1700 for (int m
= 0; m
< pSH
->m_HWTechniques
.Num(); m
++)
1702 SShaderTechnique
* pTech
= pSH
->m_HWTechniques
[m
];
1703 for (int n
= 0; n
< pTech
->m_Passes
.Num(); n
++)
1705 SShaderPass
* pPass
= &pTech
->m_Passes
[n
];
1706 if (pPass
->m_PShader
)
1707 pPass
->m_PShader
->m_nFrameLoad
= -10;
1708 if (pPass
->m_VShader
)
1709 pPass
->m_VShader
->m_nFrameLoad
= -10;
1713 for (; i
< Cmbs
.size(); i
++)
1715 SCacheCombination
* cmba
= &Cmbs
[i
];
1716 cry_strcpy(str2
, cmba
->Name
.c_str());
1717 c
= strchr(str2
, '@');
1719 c
= strchr(str2
, '/');
1723 if (stricmp(str1
, str2
) || cmb
->Ident
.m_GLMask
!= cmba
->Ident
.m_GLMask
)
1725 CmbsMapRTSrc
.insert(FXShaderCacheCombinationsItor::value_type(cmba
->CacheName
, *cmba
));
1727 // surrounding for(;;i++) will increment this again
1729 m_nCombinationsProcess
-= CmbsMapRTSrc
.size();
1731 for (FXShaderCacheCombinationsItor itor
= CmbsMapRTSrc
.begin(); itor
!= CmbsMapRTSrc
.end(); itor
++)
1733 SCacheCombination
* cmb
= &itor
->second
;
1734 cry_strcpy(str2
, cmb
->Name
.c_str());
1735 FXShaderCacheCombinationsItor it
= CmbsMapRTDst
.find(cmb
->CacheName
);
1736 if (it
== CmbsMapRTDst
.end())
1738 CmbsMapRTDst
.insert(FXShaderCacheCombinationsItor::value_type(cmb
->CacheName
, *cmb
));
1742 for (int m
= 0; m
< pSH
->m_HWTechniques
.Num(); m
++)
1744 SShaderTechnique
* pTech
= pSH
->m_HWTechniques
[m
];
1745 for (int n
= 0; n
< pTech
->m_Passes
.Num(); n
++)
1747 SShaderPass
* pPass
= &pTech
->m_Passes
[n
];
1748 if (pPass
->m_PShader
)
1749 mfAddRTCombinations(CmbsMapRTSrc
, CmbsMapRTDst
, pPass
->m_PShader
, true);
1750 if (pPass
->m_VShader
)
1751 mfAddRTCombinations(CmbsMapRTSrc
, CmbsMapRTDst
, pPass
->m_VShader
, true);
1756 for (FXShaderCacheCombinationsItor itor
= CmbsMapRTDst
.begin(); itor
!= CmbsMapRTDst
.end(); itor
++)
1758 SCacheCombination
* cmb
= &itor
->second
;
1759 CmbsRT
.push_back(*cmb
);
1762 m_nCombinationsProcessOverall
= CmbsRT
.size();
1763 m_nCombinationsProcess
= 0;
1765 CmbsMapRTDst
.clear();
1766 CmbsMapRTSrc
.clear();
1767 uint32 nFlags
= HWSF_PRECACHE
;
1768 if (CParserBin::m_nPlatform
& (SF_D3D11
| SF_DURANGO
| SF_ORBIS
| SF_GL4
| SF_GLES3
| SF_VULKAN
))
1769 nFlags
|= HWSF_STOREDATA
;
1771 nFlags
|= HWSF_FAKE
;
1772 for (int jj
= 0; jj
< pCmbs
->size(); jj
++)
1774 m_nCombinationsProcess
++;
1775 SCacheCombination
* cmba
= &(*pCmbs
)[jj
];
1776 c
= (char*)strchr(cmba
->Name
.c_str(), '@');
1778 c
= (char*)strchr(cmba
->Name
.c_str(), '/');
1782 m_szShaderPrecache
= &c
[1];
1783 /*if (!stricmp(m_szShaderPrecache, "IlluminationVS") && cmba->nRT == 0x10050000)
1787 //if (!stricmp(pSH->GetName(), "ParticlesNoMat"))*/
1788 /*if (!stricmp(cmba->CacheName.c_str(), "Cloth@Common_SG_VS(%STAT_BRANCHING|%WIND_BENDING)(%_RT_ALPHATEST|%_RT_QUALITY1|%_RT_INSTANCING_ROT|%_RT_INSTANCING_ATTR|%_RT_PSM|%_RT_HW_PCF_COMPARE)(0)(0)(800)(vs_2_0)"))
1792 /*if ((cmba->nRT == 0x10902200402)) // && cmba->nLT == 0)
1797 for (int m
= 0; m
< pSH
->m_HWTechniques
.Num(); m
++)
1799 SShaderTechnique
* pTech
= pSH
->m_HWTechniques
[m
];
1800 for (int n
= 0; n
< pTech
->m_Passes
.Num(); n
++)
1802 SShaderPass
* pPass
= &pTech
->m_Passes
[n
];
1803 SCacheCombination cmbSaved
= *cmba
;
1805 // Adjust some flags for low spec
1806 CHWShader
* shaders
[] = { pPass
->m_PShader
, pPass
->m_VShader
};
1807 for (int i
= 0; i
< 2; i
++)
1809 CHWShader
* shader
= shaders
[i
];
1810 if (shader
&& (!m_szShaderPrecache
|| !stricmp(m_szShaderPrecache
, shader
->m_EntryFunc
.c_str()) != 0))
1812 uint64 nFlagsOrigShader_RT
= cmbSaved
.Ident
.m_RTMask
& shader
->m_nMaskAnd_RT
| shader
->m_nMaskOr_RT
;
1813 uint64 nFlagsOrigShader_GL
= shader
->m_nMaskGenShader
;
1814 uint32 nFlagsOrigShader_LT
= cmbSaved
.Ident
.m_LightMask
;
1816 shader
->PrecacheShader(pSH
, cmba
->Ident
, nFlags
);
1818 if (nFlagsOrigShader_RT
!= cmbSaved
.Ident
.m_RTMask
|| nFlagsOrigShader_GL
!= shader
->m_nMaskGenShader
|| nFlagsOrigShader_LT
!= cmbSaved
.Ident
.m_LightMask
)
1820 m_nCombinationsEmpty
++;
1822 shader
->mfAddEmptyCombination(pSH
, nFlagsOrigShader_RT
, nFlagsOrigShader_GL
, nFlagsOrigShader_LT
, cmbSaved
);
1828 if (CParserBin::m_nPlatform
& (SF_D3D11
| SF_DURANGO
| SF_ORBIS
| SF_GL4
| SF_VULKAN
))
1830 CHWShader
* d3d11Shaders
[] = { pPass
->m_GShader
, pPass
->m_HShader
, pPass
->m_CShader
, pPass
->m_DShader
};
1831 for (int i
= 0; i
< 4; i
++)
1833 CHWShader
* shader
= d3d11Shaders
[i
];
1834 if (shader
&& (!m_szShaderPrecache
|| !stricmp(m_szShaderPrecache
, shader
->m_EntryFunc
.c_str()) != 0))
1836 shader
->PrecacheShader(pSH
,cmba
->Ident
,nFlags
);
1843 static int nLastCombs
= 0;
1844 if (m_nCombinationsCompiled
!= nLastCombs
&& !(m_nCombinationsCompiled
& 0x7f))
1846 nLastCombs
= m_nCombinationsCompiled
;
1847 CryLog("-- Processed: %d, Compiled: %d, Referenced (Empty): %d...", m_nCombinationsProcess
, m_nCombinationsCompiled
, m_nCombinationsEmpty
);
1850 #if CRY_PLATFORM_WINDOWS
1851 gEnv
->pSystem
->PumpWindowMessage(true);
1855 pSH
->mfFlushPendedShaders();
1859 pSH
->mfFlushCache();
1862 // should be bigger than 0, but could cause issues right now when checking for RT
1863 // combinations when no shadertype is defined and the previous shader line
1864 // was still async compiling -- needs fix in HWShader for m_nMaskGenFX
1865 CHWShader::mfFlushPendedShadersWait(0);
1868 nProcessed
+= m_nCombinationsProcess
;
1869 nCompiled
+= m_nCombinationsCompiled
;
1870 nEmpty
+= m_nCombinationsEmpty
;
1872 m_nCombinationsProcess
= 0;
1873 m_nCombinationsCompiled
= 0;
1874 m_nCombinationsEmpty
= 0;
1877 CHWShader::mfFlushPendedShadersWait(-1);
1879 // Optimise shader resources
1880 SOptimiseStats Stats
;
1881 for (FXShaderCacheNamesItor it
= CHWShader::m_ShaderCacheList
.begin(); it
!= CHWShader::m_ShaderCacheList
.end(); it
++)
1883 const char* szName
= it
->first
.c_str();
1884 SShaderCache
* c
= CHWShader::mfInitCache(szName
, NULL
, false, it
->second
, false);
1887 SOptimiseStats _Stats
;
1888 CHWShader::mfOptimiseCacheFile(c
, false, &_Stats
);
1889 Stats
.nEntries
+= _Stats
.nEntries
;
1890 Stats
.nUniqueEntries
+= _Stats
.nUniqueEntries
;
1891 Stats
.nSizeCompressed
+= _Stats
.nSizeCompressed
;
1892 Stats
.nSizeUncompressed
+= _Stats
.nSizeUncompressed
;
1893 Stats
.nTokenDataSize
+= _Stats
.nTokenDataSize
;
1898 string
sShaderPath(gRenDev
->m_cEF
.m_szUserPath
);
1899 sShaderPath
+= gRenDev
->m_cEF
.m_ShadersCache
;
1901 //CResFileLookupDataMan kLookupDataMan;
1902 //kDirDataMan.LoadData(sShaderPath + "direntrydata.bin", CParserBin::m_bEndians);
1903 //GenerateResFileDirData(sShaderPath, &kLookupDataMan);
1904 //kLookupDataMan.SaveData(sShaderPath + "lookupdata.bin", CParserBin::m_bEndians);
1906 /*FILE *FP = gEnv->pCryPak->FOpen("Shaders/Cache/ShaderListDone", "w");
1909 gEnv->pCryPak->FPrintf(FP, "done: %d", m_nCombinationsProcess);
1910 gEnv->pCryPak->FClose(FP);
1912 CHWShader::m_ShaderCacheList
.clear();
1914 m_eCacheMode
= eSC_Normal
;
1916 m_szShaderPrecache
= NULL
;
1917 CRenderer::CV_r_shadersasynccompiling
= nAsync
;
1919 gRenDev
->m_Features
= nSaveFeatures
;
1921 float t1
= gEnv
->pTimer
->GetAsyncCurTime();
1922 CryLogAlways("All shaders combinations compiled in %.2f seconds", (t1
- t0
));
1923 CryLogAlways("Combinations: (Material: %d, Processed: %d; Compiled: %d; Removed: %d)", nMaterialCombinations
, nProcessed
, nCompiled
, nEmpty
);
1924 CryLogAlways("-- Shader cache overall stats: Entries: %d, Unique Entries: %d, Size: %d, Compressed Size: %d, Token data size: %d", Stats
.nEntries
, Stats
.nUniqueEntries
, Stats
.nSizeUncompressed
, Stats
.nSizeCompressed
, Stats
.nTokenDataSize
);
1926 m_nCombinationsProcess
= -1;
1927 m_nCombinationsCompiled
= -1;
1928 m_nCombinationsEmpty
= -1;
1933 void CHWShader::mfGenName(uint64 GLMask
, uint64 RTMask
, uint32 LightMask
, uint32 MDMask
, uint32 MDVMask
, uint64 PSS
, EHWShaderClass eClass
, char* dstname
, int nSize
, byte bType
)
1939 if (bType
!= 0 && GLMask
)
1941 #if defined(__GNUC__)
1942 cry_sprintf(str
, "(GL%llx)", GLMask
);
1944 cry_sprintf(str
, "(GL%I64x)", GLMask
);
1946 cry_strcat(dstname
, nSize
, str
);
1950 #if defined(__GNUC__)
1951 cry_sprintf(str
, "(RT%llx)", RTMask
);
1953 cry_sprintf(str
, "(RT%I64x)", RTMask
);
1955 cry_strcat(dstname
, nSize
, str
);
1957 if (bType
!= 0 && LightMask
)
1959 cry_sprintf(str
, "(LT%x)", LightMask
);
1960 cry_strcat(dstname
, nSize
, str
);
1962 if (bType
!= 0 && MDMask
)
1964 cry_sprintf(str
, "(MD%x)", MDMask
);
1965 cry_strcat(dstname
, nSize
, str
);
1967 if (bType
!= 0 && MDVMask
)
1969 cry_sprintf(str
, "(MDV%x)", MDVMask
);
1970 cry_strcat(dstname
, nSize
, str
);
1972 if (bType
!= 0 && PSS
)
1974 sprintf(str
, "(PSS%llx)", PSS
);
1975 cry_strcat(dstname
, nSize
, str
);
1979 cry_sprintf(str
, "(%s)", mfClassString(eClass
));
1980 cry_strcat(dstname
, nSize
, str
);
1984 #if CRY_PLATFORM_DESKTOP
1986 void CShaderMan::mfPrecacheShaders(bool bStatsOnly
)
1988 CHWShader::mfFlushPendedShadersWait(-1);
1990 if (CRenderer::ShaderTargetFlag
& SF_ORBIS
)
1992 #ifdef WATER_TESSELLATION_RENDERER
1993 CRenderer::CV_r_WaterTessellationHW
= 0;
1997 gRenDev
->m_bDeviceSupportsTessellation
= CRenderer::ShaderTargetFlag
& (SF_D3D11
| SF_GL4
| SF_VULKAN
);
1998 gRenDev
->m_bDeviceSupportsGeometryShaders
= CRenderer::ShaderTargetFlag
& (SF_D3D11
| SF_GL4
| SF_VULKAN
| SF_DURANGO
| SF_ORBIS
);
2000 CParserBin::m_bShaderCacheGen
= true;
2001 gRenDev
->m_Features
|= RFT_HW_SM50
;
2002 CParserBin::SetupForPlatform(CRenderer::ShaderTargetFlag
);
2003 CryLogAlways("\nStarting shader compilation for %s...", CRenderer::CV_r_ShaderTarget
->GetString());
2004 mfInitShadersList(NULL
);
2005 mfPreloadShaderExts();
2006 _PrecacheShaderList(bStatsOnly
);
2008 if (CRenderer::ShaderTargetFlag
& SF_ORBIS
)
2009 CRenderer::ShaderTargetFlag
&= ~SF_ORBIS
;
2011 CParserBin::SetupForPlatform(SF_D3D11
);
2013 gRenDev
->m_cEF
.m_Bin
.InvalidateCache();
2016 static SResFileLookupData
* sStoreLookupData(CResFileLookupDataMan
& LevelLookup
, CResFile
* pRF
, uint32 CRC
, float fVersion
)
2018 CCryNameTSCRC name
= pRF
->mfGetFileName();
2019 SResFileLookupData
* pData
= LevelLookup
.GetData(name
);
2020 uint32 nMinor
= (int)(((float)fVersion
- (float)(int)fVersion
) * 10.1f
);
2021 uint32 nMajor
= (int)fVersion
;
2022 if (!pData
|| (CRC
&& pData
->m_CRC32
!= CRC
) || pData
->m_CacheMinorVer
!= nMinor
|| pData
->m_CacheMajorVer
!= nMajor
)
2024 LevelLookup
.AddData(pRF
, CRC
);
2025 pData
= LevelLookup
.GetData(name
);
2026 LevelLookup
.MarkDirty(true);
2032 void CShaderMan::mfExportShaders()
2036 void CShaderMan::mfOptimiseShaders(const char* szFolder
, bool bForce
)
2038 CHWShader::mfFlushPendedShadersWait(-1);
2040 float t0
= gEnv
->pTimer
->GetAsyncCurTime();
2041 SShaderCache
* pCache
;
2044 std::vector
<CCryNameR
> Names
;
2045 mfGatherFilesList(szFolder
, Names
, 0, false);
2047 SOptimiseStats Stats
;
2048 for (i
= 0; i
< Names
.size(); i
++)
2050 const char* szName
= Names
[i
].c_str();
2051 if (!strncmp(szName
, "%USER%/", 7))
2053 pCache
= CHWShader::mfInitCache(szName
, NULL
, false, 0, false);
2054 if (!pCache
|| !pCache
->m_pRes
[CACHE_USER
])
2056 SOptimiseStats _Stats
;
2057 CHWShader::mfOptimiseCacheFile(pCache
, bForce
, &_Stats
);
2058 Stats
.nEntries
+= _Stats
.nEntries
;
2059 Stats
.nUniqueEntries
+= _Stats
.nUniqueEntries
;
2060 Stats
.nSizeCompressed
+= _Stats
.nSizeCompressed
;
2061 Stats
.nSizeUncompressed
+= _Stats
.nSizeUncompressed
;
2062 Stats
.nTokenDataSize
+= _Stats
.nTokenDataSize
;
2063 Stats
.nDirDataSize
+= _Stats
.nDirDataSize
;
2067 float t1
= gEnv
->pTimer
->GetAsyncCurTime();
2068 CryLog("-- All shaders combinations optimized in %.2f seconds", t1
- t0
);
2069 CryLog("-- Shader cache overall stats: Entries: %d, Unique Entries: %d, Size: %.3f, Compressed Size: %.3f, Token data size: %.3f, Directory Size: %.3f Mb", Stats
.nEntries
, Stats
.nUniqueEntries
, Stats
.nSizeUncompressed
/ 1024.0f
/ 1024.0f
, Stats
.nSizeCompressed
/ 1024.0f
/ 1024.0f
, Stats
.nTokenDataSize
/ 1024.0f
/ 1024.0f
, Stats
.nDirDataSize
/ 1024.0f
/ 1024.0f
);
2083 static int snCurListID
;
2084 typedef std::map
<CCryNameTSCRC
, SMgData
> ShaderData
;
2085 typedef ShaderData::iterator ShaderDataItor
;
2093 //////////////////////////////////////////////////////////////////////////
2094 bool CShaderMan::CheckAllFilesAreWritable(const char* szDir
) const
2096 #if CRY_PLATFORM_WINDOWS
2099 ICryPak
* pack
= gEnv
->pCryPak
;
2102 string sPathWithFilter
= string(szDir
) + "/*.*";
2104 // Search files that match filter specification.
2108 if ((handle
= pack
->FindFirst(sPathWithFilter
.c_str(), &fd
)) != -1)
2112 if ((fd
.attrib
& _A_SUBDIR
) == 0)
2114 string fullpath
= string(szDir
) + "/" + fd
.name
;
2116 FILE* out
= pack
->FOpen(fullpath
.c_str(), "rb");
2119 res
= pack
->FindNext(handle
, &fd
);
2122 if (pack
->IsInPak(out
))
2125 res
= pack
->FindNext(handle
, &fd
);
2130 out
= pack
->FOpen(fullpath
.c_str(), "ab");
2136 gEnv
->pLog
->LogError("ERROR: Shader cache is not writable (file: '%s')", fullpath
.c_str());
2141 res
= pack
->FindNext(handle
, &fd
);
2145 pack
->FindClose(handle
);
2147 gEnv
->pLog
->LogToFile("Shader cache directory '%s' was successfully tested for being writable", szDir
);
2150 CryLog("Shader cache directory '%s' does not exist", szDir
);
2157 #endif // CRY_PLATFORM_DESKTOP
2159 bool CShaderMan::mfPreloadBinaryShaders()
2161 LOADING_TIME_PROFILE_SECTION
;
2162 // don't preload binary shaders if we are in editing mode
2163 if (CRenderer::CV_r_shadersediting
)
2166 // don't load all binary shaders twice
2167 if (m_Bin
.m_bBinaryShadersLoaded
)
2170 //bool bFound = iSystem->GetIPak()->LoadPakToMemory("Engine/ShadersBin.pak", ICryPak::eInMemoryPakLocale_CPU);
2175 // also load shaders pak file to memory because shaders are also read, when data not found in bin, and to check the CRC
2176 // of the source shaders against the binary shaders in non release mode
2177 iSystem
->GetIPak()->LoadPakToMemory("%ENGINE%/Shaders.pak", ICryPak::eInMemoryPakLocale_CPU
);
2180 stack_string szPath
= stack_string("%ENGINE%/") + m_ShadersCache
;
2182 struct _finddata_t fileinfo
;
2185 handle
= gEnv
->pCryPak
->FindFirst(szPath
+ "/*.*", &fileinfo
);
2188 std::vector
<string
> FilesCFX
;
2189 std::vector
<string
> FilesCFI
;
2193 if (gEnv
->pSystem
&& gEnv
->pSystem
->IsQuitting())
2195 if (fileinfo
.name
[0] == '.')
2197 if (fileinfo
.attrib
& _A_SUBDIR
)
2199 const char* szExt
= PathUtil::GetExt(fileinfo
.name
);
2200 if (!stricmp(szExt
, "cfib"))
2201 FilesCFI
.push_back(fileinfo
.name
);
2202 else if (!stricmp(szExt
, "cfxb"))
2203 FilesCFX
.push_back(fileinfo
.name
);
2205 while (gEnv
->pCryPak
->FindNext(handle
, &fileinfo
) != -1);
2207 if (FilesCFX
.size() + FilesCFI
.size() > MAX_FXBIN_CACHE
)
2208 SShaderBin::s_nMaxFXBinCache
= FilesCFX
.size() + FilesCFI
.size();
2213 LOADING_TIME_PROFILE_SECTION_NAMED("CShaderMan::mfPreloadBinaryShaders(): FilesCFI");
2214 for (i
= 0; i
< FilesCFI
.size(); i
++)
2216 if (gEnv
->pSystem
&& gEnv
->pSystem
->IsQuitting())
2219 const string
& file
= FilesCFI
[i
];
2220 cry_strcpy(sName
, file
.c_str());
2221 PathUtil::RemoveExtension(sName
);
2222 SShaderBin
* pBin
= m_Bin
.GetBinShader(sName
, true, 0);
2228 LOADING_TIME_PROFILE_SECTION_NAMED("CShaderMan::mfPreloadBinaryShaders(): FilesCFX");
2229 for (i
= 0; i
< FilesCFX
.size(); i
++)
2231 if (gEnv
->pSystem
&& gEnv
->pSystem
->IsQuitting())
2234 const string
& file
= FilesCFX
[i
];
2235 cry_strcpy(sName
, file
.c_str());
2236 PathUtil::RemoveExtension(sName
);
2237 SShaderBin
* pBin
= m_Bin
.GetBinShader(sName
, false, 0);
2242 gEnv
->pCryPak
->FindClose(handle
);
2244 // Unload pak from memory.
2245 //iSystem->GetIPak()->LoadPakToMemory("Engine/ShadersBin.pak", ICryPak::eInMemoryPakLocale_Unload);
2248 iSystem
->GetIPak()->LoadPakToMemory("%ENGINE%/Shaders.pak", ICryPak::eInMemoryPakLocale_Unload
);
2251 m_Bin
.m_bBinaryShadersLoaded
= true;
2253 return SShaderBin::s_nMaxFXBinCache
> 0;