1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
6 #include <lzma/Lzma86.h>
8 #if !CRY_PLATFORM_ORBIS && !CRY_RENDERER_OPENGL && !CRY_RENDERER_OPENGLES && !CRY_RENDERER_VULKAN
9 #if CRY_PLATFORM_DURANGO
10 #include <D3D11Shader_x.h>
11 #include <D3DCompiler_x.h>
13 #include <D3D11Shader.h>
14 #include <D3DCompiler.h>
18 #if defined(USE_NV_API)
19 #include NV_API_HEADER
22 #include "../Common/Shaders/RemoteCompiler.h"
24 static CryCriticalSection g_cAILock
;
25 static SShaderAsyncInfo g_PendingList
;
26 static SShaderAsyncInfo g_PendingListT
;
27 #ifdef SHADER_ASYNC_COMPILATION
28 static SShaderAsyncInfo g_BuildList
;
31 SShaderAsyncInfo
& SShaderAsyncInfo::PendingList() { return g_PendingList
; }
32 SShaderAsyncInfo
& SShaderAsyncInfo::PendingListT() { return g_PendingListT
; }
33 #ifdef SHADER_ASYNC_COMPILATION
34 SShaderAsyncInfo
& CAsyncShaderTask::BuildList() { return g_BuildList
; }
37 CryEvent
SShaderAsyncInfo::s_RequestEv
;
39 int CHWShader_D3D::s_nDevicePSDataSize
= 0;
40 int CHWShader_D3D::s_nDeviceVSDataSize
= 0;
44 inline int GetCurrentFrameID()
46 return (gRenDev
->m_pRT
->IsRenderThread()) ? gRenDev
->GetRenderFrameID() : gRenDev
->GetMainFrameID();
55 #if CRY_PLATFORM_WINDOWS || CRY_PLATFORM_LINUX || CRY_PLATFORM_ANDROID || CRY_PLATFORM_APPLE
56 while (CryInterlockedCompareExchange(&s_locked
, 1L, 0L) == 1L)
63 #if CRY_PLATFORM_WINDOWS
64 InterlockedExchange(&s_locked
, 0L);
65 #elif CRY_PLATFORM_LINUX || CRY_PLATFORM_ANDROID || CRY_PLATFORM_APPLE
66 while (CryInterlockedCompareExchange(&s_locked
, 0L, 1L) == 0L);
71 static volatile LONG s_locked
;
74 volatile LONG
CSpinLock::s_locked
= 0L;
76 volatile int SShaderAsyncInfo::s_nPendingAsyncShaders
= 0;
77 int SShaderAsyncInfo::s_nPendingAsyncShadersFXC
= 0;
79 //==============================================================================================================
81 bool CHWShader_D3D::mfAddFXSampler(SHWSInstance
* pInst
, SShaderFXParams
& FXParams
, SFXSampler
* pr
, const char* ParamName
, SCGBind
* pBind
, CShader
* ef
, EHWShaderClass eSHClass
)
87 std::vector
<SCGSampler
>* pParams
;
88 pParams
= &pInst
->m_Samplers
;
89 uint32 nOffs
= pParams
->size();
90 bool bRes
= gRenDev
->m_cEF
.mfParseFXSampler(FXParams
, pr
, ParamName
, ef
, pBind
->m_nParameters
, pParams
, eSHClass
);
91 if (pParams
->size() > nOffs
)
93 for (uint32 i
= 0; i
< pParams
->size() - nOffs
; i
++)
95 SCGSampler
& p
= (*pParams
)[nOffs
+ i
];
96 p
.m_dwBind
= pBind
->m_dwBind
+ i
;
97 p
.m_dwCBufSlot
= pBind
->m_dwCBufSlot
;
98 p
.m_Name
= pBind
->m_Name
;
101 // Parameter without semantic
105 bool CHWShader_D3D::mfAddFXTexture(SHWSInstance
* pInst
, SShaderFXParams
& FXParams
, SFXTexture
* pr
, const char* ParamName
, SCGBind
* pBind
, CShader
* ef
, EHWShaderClass eSHClass
)
111 std::vector
<SCGTexture
>* pParams
;
112 pParams
= &pInst
->m_Textures
;
113 uint32 nOffs
= pParams
->size();
114 bool bRes
= gRenDev
->m_cEF
.mfParseFXTexture(FXParams
, pr
, ParamName
, ef
, pBind
->m_nParameters
, pParams
, eSHClass
);
119 if (pParams
->size() > nOffs
)
121 for (uint32 i
= 0; i
< pParams
->size() - nOffs
; i
++)
123 SCGTexture
& p
= (*pParams
)[nOffs
+ i
];
124 p
.m_dwBind
= pBind
->m_dwBind
+ i
;
125 p
.m_dwCBufSlot
= pBind
->m_dwCBufSlot
;
126 p
.m_Name
= pBind
->m_Name
;
129 // Parameter without semantic
133 void CHWShader_D3D::mfAddFXParameter(SHWSInstance
* pInst
, SParamsGroup
& OutParams
, SShaderFXParams
& FXParams
, SFXParam
* pr
, const char* ParamName
, SCGBind
* pBind
, CShader
* ef
, bool bInstParam
, EHWShaderClass eSHClass
)
142 int nParams
= pBind
->m_nParameters
;
143 if (!pr
->m_Semantic
.empty())
144 nComps
= pr
->m_nComps
;
147 for (int i
= 0; i
< pr
->m_nComps
; i
++)
149 CryFixedStringT
<128> cur
;
150 pr
->GetParamComp(i
, cur
);
156 // Process parameters only with semantics
157 if (nComps
&& nParams
)
159 std::vector
<SCGParam
>* pParams
;
160 if (pr
->m_nParameters
> 1)
164 //if (!pInst->m_pParams[0])
165 // pInst->m_pParams[0] = new std::vector<SCGParam>;
166 pParams
= &OutParams
.Params
[0];
170 //if (!pInst->m_pParams_Inst)
171 // pInst->m_pParams_Inst = new std::vector<SCGParam>;
172 pParams
= &OutParams
.Params_Inst
;
177 //if (!pInst->m_pParams_Inst)
178 // pInst->m_pParams_Inst = new std::vector<SCGParam>;
179 pParams
= &OutParams
.Params_Inst
;
183 //if (!pInst->m_pParams[0])
184 // pInst->m_pParams[0] = new std::vector<SCGParam>;
185 pParams
= &OutParams
.Params
[0];
187 uint32 nOffs
= pParams
->size();
188 bool bRes
= gRenDev
->m_cEF
.mfParseFXParameter(FXParams
, pr
, ParamName
, ef
, bInstParam
, pBind
->m_nParameters
, pParams
, eSHClass
, false);
190 if (pParams
->size() > nOffs
)
192 for (uint32 i
= 0; i
< pParams
->size() - nOffs
; i
++)
194 //assert(pBind->m_nComponents == 1);
195 SCGParam
& p
= (*pParams
)[nOffs
+ i
];
196 p
.m_dwBind
= pBind
->m_dwBind
+ i
;
197 p
.m_dwCBufSlot
= pBind
->m_dwCBufSlot
;
201 // Parameter without semantic
206 STexSamplerRT Sampler
;
210 bool CHWShader_D3D::mfAddFXParameter(SHWSInstance
* pInst
, SParamsGroup
& OutParams
, SShaderFXParams
& FXParams
, const char* param
, SCGBind
* bn
, bool bInstParam
, EHWShaderClass eSHClass
, CShader
* pFXShader
)
212 if (bn
->m_dwBind
& SHADER_BIND_TEXTURE
)
214 SFXTexture
* pr
= gRenDev
->m_cEF
.mfGetFXTexture(FXParams
.m_FXTextures
, param
);
217 if (bn
->m_nParameters
< 0)
218 bn
->m_nParameters
= pr
->m_nArray
;
219 bool bRes
= mfAddFXTexture(pInst
, FXParams
, pr
, param
, bn
, pFXShader
, eSHClass
);
223 else if (bn
->m_dwBind
& SHADER_BIND_SAMPLER
)
225 SFXSampler
* pr
= gRenDev
->m_cEF
.mfGetFXSampler(FXParams
.m_FXSamplers
, param
);
228 if (bn
->m_nParameters
< 0)
229 bn
->m_nParameters
= pr
->m_nArray
;
230 bool bRes
= mfAddFXSampler(pInst
, FXParams
, pr
, param
, bn
, pFXShader
, eSHClass
);
236 SFXParam
* pr
= gRenDev
->m_cEF
.mfGetFXParameter(FXParams
.m_FXParams
, param
);
239 if (bn
->m_nParameters
< 0)
240 bn
->m_nParameters
= pr
->m_nParameters
;
241 mfAddFXParameter(pInst
, OutParams
, FXParams
, pr
, param
, bn
, pFXShader
, bInstParam
, eSHClass
);
248 //==================================================================================================================
250 int CGBindCallback(const VOID
* arg1
, const VOID
* arg2
)
252 SCGBind
* pi1
= (SCGBind
*)arg1
;
253 SCGBind
* pi2
= (SCGBind
*)arg2
;
255 if (pi1
->m_dwBind
< pi2
->m_dwBind
)
257 if (pi1
->m_dwBind
> pi2
->m_dwBind
)
263 const char* szNamesCB
[CB_NUM
] = { "PER_BATCH", "PER_INSTANCE", "PER_FRAME", "PER_MATERIAL", "PER_LIGHT", "PER_SHADOWGEN", "SKIN_DATA", "INSTANCE_DATA" };
265 void CHWShader_D3D::mfCreateBinds(SHWSInstance
* pInst
, void* pConstantTable
, byte
* pShader
, int nSize
)
268 ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pConstantTable
;
269 D3D11_SHADER_DESC Desc
;
270 pShaderReflection
->GetDesc(&Desc
);
271 ID3D11ShaderReflectionConstantBuffer
* pCB
= NULL
;
272 for (uint32 n
= 0; n
< Desc
.ConstantBuffers
; n
++)
274 pCB
= pShaderReflection
->GetConstantBufferByIndex(n
);
275 D3D11_SHADER_BUFFER_DESC SBDesc
;
276 pCB
->GetDesc(&SBDesc
);
277 if (SBDesc
.Type
== D3D11_CT_RESOURCE_BIND_INFO
)
280 if (!strcmp("$Globals", SBDesc
.Name
))
283 for (nCB
= 0; nCB
< CB_NUM
; nCB
++)
285 if (!strcmp(szNamesCB
[nCB
], SBDesc
.Name
))
288 //assert(nCB != CB_NUM);
289 if (nCB
>= CB_NUM
) // Allow having custom cbuffers in shaders
291 for (i
= 0; i
< SBDesc
.Variables
; i
++)
294 ID3D11ShaderReflectionVariable
* pCV
= pCB
->GetVariableByIndex(i
);
295 ID3D11ShaderReflectionType
* pVT
= pCV
->GetType();
296 D3D11_SHADER_VARIABLE_DESC CDesc
;
297 D3D11_SHADER_TYPE_DESC CTDesc
;
298 pVT
->GetDesc(&CTDesc
);
299 pCV
->GetDesc(&CDesc
);
300 if (!(CDesc
.uFlags
& D3D10_SVF_USED
))
302 if (CTDesc
.Class
== D3D10_SVC_VECTOR
|| CTDesc
.Class
== D3D10_SVC_SCALAR
|| CTDesc
.Class
== D3D10_SVC_MATRIX_COLUMNS
|| CTDesc
.Class
== D3D10_SVC_MATRIX_ROWS
)
305 assert(!(CDesc
.StartOffset
& 0xf));
306 //assert(!(CDesc.Size & 0xf));
307 int nReg
= CDesc
.StartOffset
>> 4;
308 cgp
.m_dwBind
= nReg
; //<<2;
309 cgp
.m_dwCBufSlot
= nCB
;
310 cgp
.m_nParameters
= (CDesc
.Size
+ 15) >> 4;
311 cgp
.m_Name
= CDesc
.Name
;
312 cgp
.m_Flags
= CParserBin::GetCRC32(CDesc
.Name
);
313 pInst
->m_pBindVars
.push_back(cgp
);
322 D3D11_SHADER_INPUT_BIND_DESC IBDesc
;
323 for (i
= 0; i
< Desc
.BoundResources
; i
++)
326 pShaderReflection
->GetResourceBindingDesc(i
, &IBDesc
);
328 if (IBDesc
.Type
== D3D10_SIT_TEXTURE
)
329 cgp
.m_dwBind
= IBDesc
.BindPoint
| SHADER_BIND_TEXTURE
;
330 else if (IBDesc
.Type
== D3D10_SIT_SAMPLER
)
331 cgp
.m_dwBind
= IBDesc
.BindPoint
| SHADER_BIND_SAMPLER
;
335 if (IBDesc
.Dimension
== D3D10_SRV_DIMENSION_BUFFER
)
338 cgp
.m_dwCBufSlot
= IBDesc
.BindPoint
;
339 cgp
.m_nParameters
= IBDesc
.BindCount
;
340 cgp
.m_Name
= IBDesc
.Name
;
341 cgp
.m_Flags
= CParserBin::GetCRC32(IBDesc
.Name
);
342 pInst
->m_pBindVars
.push_back(cgp
);
346 void CHWShader_D3D::mfGatherFXParameters(SHWSInstance
* pInst
, std::vector
<SCGBind
>* BindVars
, std::vector
<SCGBind
>* InstBindVars
, CHWShader_D3D
* pSH
, int nFlags
, CShader
* pFXShader
)
348 // LOADING_TIME_PROFILE_SECTION(iSystem);
351 SAliasSampler samps
[MAX_TMU
];
352 int nMaxSampler
= -1;
355 SShaderFXParams
& FXParams
= gRenDev
->m_cEF
.m_Bin
.mfGetFXParams(pInst
->m_bFallback
? CShaderMan::s_ShaderFallback
: pFXShader
);
356 if (pInst
->m_pBindVars
.size())
358 std::list
<uint32
> skipped
;
360 for (i
= 0; i
< pInst
->m_pBindVars
.size(); i
++)
362 SCGBind
* bn
= &(*BindVars
)[i
];
363 const char* param
= bn
->m_Name
.c_str();
365 if (!strncmp(param
, "_g_", 3))
367 bool bRes
= mfAddFXParameter(pInst
, Group
, FXParams
, param
, bn
, false, pSH
->m_eSHClass
, pFXShader
);
368 if (!bRes
&& !(bn
->m_dwBind
& (SHADER_BIND_TEXTURE
| SHADER_BIND_SAMPLER
)))
370 //iLog->LogWarning("WARNING: Couldn't find parameter '%s' for shader '%s'", param, pSH->GetName());
371 // const parameters aren't listed in Params
374 else if (!bRes
&& (bn
->m_dwBind
& SHADER_BIND_TEXTURE
)) // try to find old samplers (Without semantics)
376 skipped
.push_back(i
);
380 bool setSamplers
[256] = { false };
381 bool setTextures
[256] = { false };
383 for (i
= 0; i
< pInst
->m_Samplers
.size(); i
++)
384 setSamplers
[pInst
->m_Samplers
[i
].m_dwBind
& 0xff] = true;
385 for (i
= 0; i
< pInst
->m_Textures
.size(); i
++)
386 setTextures
[pInst
->m_Textures
[i
].m_dwBind
& 0xff] = true;
388 while (skipped
.size() > 0)
393 SCGBind
* bn
= &(*BindVars
)[i
];
394 const char* param
= bn
->m_Name
.c_str();
397 for (j
= 0; j
< (uint32
)FXParams
.m_FXSamplersOld
.size(); j
++)
399 STexSamplerFX
* sm
= &FXParams
.m_FXSamplersOld
[j
];
400 if (!stricmp(sm
->m_szName
.c_str(), param
))
402 int nSampler
= bn
->m_dwBind
& 0x7f;
403 if (nSampler
< MAX_TMU
)
405 nMaxSampler
= max(nSampler
, nMaxSampler
);
406 samps
[nSampler
].Sampler
= STexSamplerRT(*sm
);
407 samps
[nSampler
].NameTex
= sm
->m_szTexture
;
408 samps
[nSampler
].Sampler
.m_nSamplerSlot
= (int8
)(bn
->m_dwCBufSlot
& 0xff);
409 samps
[nSampler
].Sampler
.m_nTextureSlot
= nSampler
;
411 // Solve slot-assignment when Sampler2D gets distinct t? and s? slot assigned by fxc (2 binds exist then)
412 for (int k
= 0; k
< pInst
->m_pBindVars
.size(); k
++)
413 if ((*BindVars
)[k
].m_dwBind
& SHADER_BIND_TEXTURE
)
414 if (!stricmp((*BindVars
)[k
].m_Name
.c_str(), param
))
415 samps
[nSampler
].Sampler
.m_nTextureSlot
= (int8
)(*BindVars
)[k
].m_dwCBufSlot
;
417 for (int k
= 0; k
< pInst
->m_pBindVars
.size(); k
++)
418 if ((*BindVars
)[k
].m_dwBind
& SHADER_BIND_SAMPLER
)
419 if (!stricmp((*BindVars
)[k
].m_Name
.c_str(), param
))
420 samps
[nSampler
].Sampler
.m_nSamplerSlot
= (int8
)(*BindVars
)[k
].m_dwCBufSlot
;
422 // Texture slot occupied, search an alternative
423 if (setSamplers
[samps
[nSampler
].Sampler
.m_nSamplerSlot
])
426 while (setSamplers
[f
])
428 samps
[nSampler
].Sampler
.m_nSamplerSlot
= f
;
432 // Sampler slot occupied, search an alternative
433 if (setTextures
[samps
[nSampler
].Sampler
.m_nTextureSlot
])
436 while (setTextures
[f
])
438 samps
[nSampler
].Sampler
.m_nTextureSlot
= f
;
442 setTextures
[samps
[nSampler
].Sampler
.m_nTextureSlot
] = true;
443 setSamplers
[samps
[nSampler
].Sampler
.m_nSamplerSlot
] = true;
450 if (j
== FXParams
.m_FXSamplersOld
.size())
452 for (j
= 0; j
< (uint32
)FXParams
.m_FXSamplersOld
.size(); j
++)
454 STexSamplerFX
* sm
= &FXParams
.m_FXSamplersOld
[j
];
455 const char* src
= sm
->m_szName
.c_str();
460 if (src
[n
] <= 0x20 || src
[n
] == '[')
466 if (!stricmp(name
, param
))
468 int nSampler
= bn
->m_dwBind
& 0x7f;
469 if (nSampler
< MAX_TMU
)
471 samps
[nSampler
].Sampler
= STexSamplerRT(*sm
);
472 samps
[nSampler
].NameTex
= sm
->m_szTexture
;
473 samps
[nSampler
].Sampler
.m_nSamplerSlot
= (int8
)(bn
->m_dwCBufSlot
& 0xff);
474 samps
[nSampler
].Sampler
.m_nTextureSlot
= nSampler
;
476 // Solve slot-assignment when Sampler2D gets distinct t? and s? slot assigned by fxc (2 binds exist then)
477 for (int k
= 0; k
< pInst
->m_pBindVars
.size(); k
++)
478 if ((*BindVars
)[k
].m_dwBind
& SHADER_BIND_TEXTURE
)
479 if (!stricmp((*BindVars
)[k
].m_Name
.c_str(), param
))
480 samps
[nSampler
].Sampler
.m_nTextureSlot
= (int8
)(*BindVars
)[k
].m_dwCBufSlot
;
482 for (int k
= 0; k
< pInst
->m_pBindVars
.size(); k
++)
483 if ((*BindVars
)[k
].m_dwBind
& SHADER_BIND_SAMPLER
)
484 if (!stricmp((*BindVars
)[k
].m_Name
.c_str(), param
))
485 samps
[nSampler
].Sampler
.m_nSamplerSlot
= (int8
)(*BindVars
)[k
].m_dwCBufSlot
;
487 // Texture slot occupied, search an alternative
488 if (setSamplers
[samps
[nSampler
].Sampler
.m_nSamplerSlot
])
491 while (setSamplers
[f
])
493 samps
[nSampler
].Sampler
.m_nSamplerSlot
= f
;
497 // Sampler slot occupied, search an alternative
498 if (setTextures
[samps
[nSampler
].Sampler
.m_nTextureSlot
])
501 while (setTextures
[f
])
503 samps
[nSampler
].Sampler
.m_nTextureSlot
= f
;
507 setTextures
[samps
[nSampler
].Sampler
.m_nTextureSlot
] = true;
508 setSamplers
[samps
[nSampler
].Sampler
.m_nSamplerSlot
] = true;
510 for (int nS
= 0; nS
< bn
->m_nParameters
; nS
++)
512 nMaxSampler
= max(nSampler
+ nS
, nMaxSampler
);
513 samps
[nSampler
+ nS
].Sampler
= samps
[nSampler
].Sampler
;
514 samps
[nSampler
+ nS
].NameTex
= sm
->m_szTexture
;
520 if (j
== FXParams
.m_FXSamplersOld
.size())
522 // const parameters aren't listed in Params
523 //iLog->LogWarning("WARNING: Couldn't find parameter '%s' for shader '%s'", param, pSH->GetName());
532 for (i
= 0; (int)i
<= nMaxSampler
; i
++)
534 STexSamplerRT
& smp
= samps
[i
].Sampler
;
535 smp
.m_pTex
= gRenDev
->m_cEF
.mfParseFXTechnique_LoadShaderTexture(&smp
, samps
[i
].NameTex
.c_str(), NULL
, NULL
, i
, eCO_NOSET
, eCO_NOSET
, DEF_TEXARG0
, DEF_TEXARG0
);
538 assert(!smp
.m_pDynTexSource
);
541 //mfAddGlobalSampler(smp);
544 pInst
->m_pSamplers
.push_back(smp
);
549 assert(pInst
->m_pAsync
);
550 if (pInst
->m_pAsync
&& nMaxSampler
>= 0)
551 pInst
->m_pAsync
->m_bPendedSamplers
= true;
554 pInst
->m_nMaxVecs
[0] = pInst
->m_nMaxVecs
[1] = 0;
555 if (pInst
->m_pBindVars
.size())
557 for (i
= 0; i
< pInst
->m_pBindVars
.size(); i
++)
559 SCGBind
* pB
= &pInst
->m_pBindVars
[i
];
560 if (pB
->m_dwBind
& (SHADER_BIND_SAMPLER
| SHADER_BIND_TEXTURE
))
562 if (pB
->m_dwCBufSlot
< 0 || pB
->m_dwCBufSlot
> 2)
564 for (j
= 0; j
< Group
.Params
[0].size(); j
++)
566 SCGParam
* pr
= &Group
.Params
[0][j
];
567 if (pr
->m_dwBind
== pB
->m_dwBind
&& pr
->m_Name
== pB
->m_Name
)
570 if (j
!= Group
.Params
[0].size())
572 if (pB
->m_dwCBufSlot
< 3)
573 pInst
->m_nMaxVecs
[pB
->m_dwCBufSlot
] = max(pB
->m_dwBind
+ pB
->m_nParameters
, pInst
->m_nMaxVecs
[pB
->m_dwCBufSlot
]);
576 if (Group
.Params
[0].size())
578 for (i
= 0; i
< Group
.Params
[0].size(); i
++)
580 SCGParam
* pr
= &Group
.Params
[0][i
];
582 if (pr
->m_Flags
& PF_MATERIAL
)
583 pInst
->m_bHasPMParams
= true;
586 gRenDev
->m_cEF
.mfCheckObjectDependParams(Group
.Params
[0], Group
.Params
[1], pSH
->m_eSHClass
, pFXShader
);
589 for (i
= 0; i
< 2; i
++)
591 if (Group
.Params
[i
].size())
593 for (j
= 0; j
< Group
.Params
[i
].size(); j
++)
595 SCGParam
* pr
= &Group
.Params
[i
][j
];
596 pInst
->m_nMaxVecs
[i
] = max(pr
->m_dwBind
+ pr
->m_nParameters
, pInst
->m_nMaxVecs
[i
]);
601 if (pSH
->m_eSHClass
== eHWSC_Vertex
)
602 nMax
= MAX_CONSTANTS_VS
;
603 else if (pSH
->m_eSHClass
== eHWSC_Pixel
)
604 nMax
= MAX_CONSTANTS_PS
;
605 else if (pSH
->m_eSHClass
== eHWSC_Geometry
)
606 nMax
= MAX_CONSTANTS_GS
;
607 else if (pSH
->m_eSHClass
== eHWSC_Domain
)
608 nMax
= MAX_CONSTANTS_DS
;
609 else if (pSH
->m_eSHClass
== eHWSC_Hull
)
610 nMax
= MAX_CONSTANTS_HS
;
611 else if (pSH
->m_eSHClass
== eHWSC_Compute
)
612 nMax
= MAX_CONSTANTS_CS
;
613 assert(pInst
->m_nMaxVecs
[0] < nMax
);
614 assert(pInst
->m_nMaxVecs
[1] < nMax
);
616 if (Group
.Params
[0].size() > 0)
618 qsort(&Group
.Params
[0][0], Group
.Params
[0].size(), sizeof(SCGParam
), CGBindCallback
);
619 pInst
->m_nParams
[0] = CGParamManager::GetParametersGroup(Group
, 0);
621 if (Group
.Params
[1].size() > 0)
623 qsort(&Group
.Params
[1][0], Group
.Params
[1].size(), sizeof(SCGParam
), CGBindCallback
);
624 pInst
->m_nParams
[1] = CGParamManager::GetParametersGroup(Group
, 1);
628 // Vertex shader specific
629 void CHWShader_D3D::mfUpdateFXVertexFormat(SHWSInstance
* pInst
, CShader
* pSH
)
631 // Update global FX shader's vertex format / flags
634 InputLayoutHandle eVFormat
= pSH
->m_eVertexFormat
;
635 bool bCurrent
= false;
636 for (uint32 i
= 0; i
< pSH
->m_HWTechniques
.Num(); i
++)
638 SShaderTechnique
* hw
= pSH
->m_HWTechniques
[i
];
639 for (uint32 j
= 0; j
< hw
->m_Passes
.Num(); j
++)
641 SShaderPass
* pass
= &hw
->m_Passes
[j
];
644 if (pass
->m_VShader
== this)
647 bool bUseTangs
= false;
648 bool bUseHWSkin
= false;
649 InputLayoutHandle eCurVFormat
= pass
->m_VShader
->mfVertexFormat(bUseTangs
, bUseLM
, bUseHWSkin
);
650 if (eCurVFormat
>= EDefaultInputLayouts::Empty
)
651 eVFormat
= max(eVFormat
, eCurVFormat
);
653 pass
->m_PassFlags
|= VSM_TANGENTS
;
656 pass
->m_PassFlags
|= VSM_HWSKIN
;
657 pass
->m_PassFlags
|= VSM_VERTEX_VELOCITY
;
663 pSH
->m_eVertexFormat
= eVFormat
;
667 void CHWShader_D3D::mfPostVertexFormat(SHWSInstance
* pInst
, CHWShader_D3D
* pHWSH
, bool bCol
, byte bNormal
, bool bTC0
, bool bTC1
[2], bool bPSize
, bool bTangent
[2], bool bBitangent
[2], bool bHWSkin
, bool bSH
[2], bool bVelocity
, bool bMorph
)
670 pInst
->m_VStreamMask_Decl
|= 1 << VSF_TANGENTS
;
671 else if (bTangent
[0])
672 pInst
->m_VStreamMask_Decl
|= 1 << VSF_QTANGENTS
;
674 pInst
->m_VStreamMask_Stream
|= 1 << VSF_TANGENTS
;
675 else if (bTangent
[1])
676 pInst
->m_VStreamMask_Stream
|= 1 << VSF_QTANGENTS
;
677 if (pInst
->m_VStreamMask_Decl
& (1 << VSF_TANGENTS
))
682 pInst
->m_VStreamMask_Decl
|= VSM_HWSKIN
;
683 pInst
->m_VStreamMask_Stream
|= VSM_HWSKIN
;
688 pInst
->m_VStreamMask_Decl
|= VSM_VERTEX_VELOCITY
;
689 pInst
->m_VStreamMask_Stream
|= VSM_VERTEX_VELOCITY
;
693 pInst
->m_VStreamMask_Decl
|= VSM_MORPHBUDDY
;
694 pInst
->m_VStreamMask_Stream
|= VSM_MORPHBUDDY
;
697 InputLayoutHandle eVF
= VertFormatForComponents(bCol
, bTC0
, bPSize
, bNormal
!= 0);
698 pInst
->m_nVertexFormat
= eVF
;
701 InputLayoutHandle
CHWShader_D3D::mfVertexFormat(bool& bUseTangents
, bool& bUseLM
, bool& bUseHWSkin
)
705 assert(m_eSHClass
== eHWSC_Vertex
);
707 InputLayoutHandle eVFormat
= EDefaultInputLayouts::P3F_C4B_T2F
;
709 for (i
= 0; i
< m_Insts
.size(); i
++)
711 SHWSInstance
* pInst
= m_Insts
[i
];
712 eVFormat
= (InputLayoutHandle
)max((uint32
)eVFormat
, (uint32
)pInst
->m_nVertexFormat
);
713 nStream
|= pInst
->m_VStreamMask_Stream
;
715 bUseTangents
= (nStream
& VSM_TANGENTS
) != 0;
717 bUseHWSkin
= (nStream
& VSM_HWSKIN
) != 0;
718 assert(eVFormat
< EDefaultInputLayouts::PreAllocated
);
723 InputLayoutHandle
CHWShader_D3D::mfVertexFormat(SHWSInstance
* pInst
, CHWShader_D3D
* pSH
, D3DBlob
* pShader
, void* pConstantTable
)
725 /*if (!stricmp(pSH->m_EntryFunc.c_str(), "ParticleVS"))
730 assert(pSH
->m_eSHClass
== eHWSC_Vertex
);
732 byte bNormal
= false;
733 bool bTangent
[2] = { false, false };
734 bool bBitangent
[2] = { false, false };
735 bool bHWSkin
= false;
736 bool bVelocity
= false;
738 bool bBoneSpace
= false;
740 bool bSH
[2] = { false, false };
742 bool bTC1
[2] = { false, false };
744 bool bSecCol
= false;
746 InputLayoutHandle eVFormat
= EDefaultInputLayouts::P3F_C4B_T2F
;
748 size_t nSize
= pShader
->GetBufferSize();
749 void* pData
= pShader
->GetBufferPointer();
750 void* pShaderReflBuf
= pConstantTable
;
751 HRESULT hr
= pConstantTable
? S_OK
: D3DReflect(pData
, nSize
, IID_ID3D11ShaderReflection
, &pShaderReflBuf
);
752 assert(SUCCEEDED(hr
));
753 ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pShaderReflBuf
;
755 return InputLayoutHandle::Unspecified
;
756 D3D11_SHADER_DESC Desc
;
757 pShaderReflection
->GetDesc(&Desc
);
758 if (!Desc
.InputParameters
)
759 return InputLayoutHandle::Unspecified
;
760 D3D11_SIGNATURE_PARAMETER_DESC IDesc
;
761 for (uint32 i
= 0; i
< Desc
.InputParameters
; i
++)
763 pShaderReflection
->GetInputParameterDesc(i
, &IDesc
);
764 //if (!IDesc.ReadWriteMask)
766 if (!IDesc
.SemanticName
)
769 if (!strnicmp(IDesc
.SemanticName
, "POSITION", 8) || !strnicmp(IDesc
.SemanticName
, "SV_POSITION", 11))
771 nIndex
= IDesc
.SemanticIndex
;
774 else if (nIndex
== 3)
776 else if (nIndex
== 4)
778 else if (nIndex
== 8)
783 else if (!strnicmp(IDesc
.SemanticName
, "NORMAL", 6))
787 else if (!strnicmp(IDesc
.SemanticName
, "TEXCOORD", 8))
789 nIndex
= IDesc
.SemanticIndex
;
797 if (IDesc
.ReadWriteMask
)
800 else if (nIndex
== 8)
804 else if (!strnicmp(IDesc
.SemanticName
, "COLOR", 5))
806 nIndex
= IDesc
.SemanticIndex
;
809 else if (nIndex
== 1)
813 if (nIndex
== 2 || nIndex
== 3)
816 if (IDesc
.ReadWriteMask
)
823 else if (!stricmp(IDesc
.SemanticName
, "TANGENT"))
826 if (IDesc
.ReadWriteMask
)
829 else if (!stricmp(IDesc
.SemanticName
, "BITANGENT"))
831 bBitangent
[0] = true;
832 if (IDesc
.ReadWriteMask
)
833 bBitangent
[1] = true;
835 else if (!strnicmp(IDesc
.SemanticName
, "PSIZE", 5) || !strnicmp(IDesc
.SemanticName
, "AXIS", 4))
839 else if (!strnicmp(IDesc
.SemanticName
, "BLENDWEIGHT", 11) || !strnicmp(IDesc
.SemanticName
, "BLENDINDICES", 12))
841 nIndex
= IDesc
.SemanticIndex
;
844 else if (nIndex
== 1)
849 else if (!strnicmp(IDesc
.SemanticName
, "SV_", 3))
851 // SV_ are valid semantics
853 #if CRY_PLATFORM_ORBIS
854 else if (!strnicmp(IDesc
.SemanticName
, "S_VERTEX_ID", 11) || !strnicmp(IDesc
.SemanticName
, "S_INSTANCE_ID", 13))
856 // S_VERTEX_ID and S_INSTANCE_ID are valid names
861 CRY_ASSERT_TRACE(0, ("Invalid SemanticName %s", IDesc
.SemanticName
));
864 #if CRY_RENDERER_VULKAN
865 pInst
->m_VSInputStreams
.emplace_back(IDesc
.SemanticName
, IDesc
.SemanticIndex
, IDesc
.AttributeLocation
);
869 mfPostVertexFormat(pInst
, pSH
, bCol
, bNormal
, bTC0
, bTC1
, bPSize
, bTangent
, bBitangent
, bHWSkin
, bSH
, bVelocity
, bMorph
);
871 if (pConstantTable
!= pShaderReflection
)
873 SAFE_RELEASE(pShaderReflection
);
876 return (InputLayoutHandle
)pInst
->m_nVertexFormat
;
879 void CHWShader_D3D::mfSetDefaultRT(uint64
& nAndMask
, uint64
& nOrMask
)
882 SShaderGen
* pGen
= gRenDev
->m_cEF
.m_pGlobalExt
;
884 uint32 nBitsPlatform
= 0;
885 if (CParserBin::m_nPlatform
== SF_ORBIS
)
886 nBitsPlatform
|= SHGD_HW_ORBIS
;
887 else if (CParserBin::m_nPlatform
== SF_DURANGO
)
888 nBitsPlatform
|= SHGD_HW_DURANGO
;
889 else if (CParserBin::m_nPlatform
== SF_D3D11
)
890 nBitsPlatform
|= SHGD_HW_DX11
;
891 else if (CParserBin::m_nPlatform
== SF_GL4
)
892 nBitsPlatform
|= SHGD_HW_GL4
;
893 else if (CParserBin::m_nPlatform
== SF_GLES3
)
894 nBitsPlatform
|= SHGD_HW_GLES3
;
895 else if (CParserBin::m_nPlatform
== SF_VULKAN
)
896 nBitsPlatform
|= SHGD_HW_VULKAN
;
898 // Make a mask of flags affected by this type of shader
899 uint32 nType
= m_dwShaderType
;
902 for (i
= 0; i
< pGen
->m_BitMask
.size(); i
++)
904 SShaderGenBit
* pBit
= pGen
->m_BitMask
[i
];
907 if (nBitsPlatform
& pBit
->m_nDependencyReset
)
909 nAndMask
&= ~pBit
->m_Mask
;
912 for (j
= 0; j
< pBit
->m_PrecacheNames
.size(); j
++)
914 if (pBit
->m_PrecacheNames
[j
] == nType
)
916 if (nBitsPlatform
& pBit
->m_nDependencySet
)
917 nOrMask
|= pBit
->m_Mask
;
925 //==================================================================================================================
927 static bool sGetMask(char* str
, SShaderGen
* pGen
, uint64
& nMask
)
931 for (i
= 0; i
< pGen
->m_BitMask
.Num(); i
++)
933 SShaderGenBit
* pBit
= pGen
->m_BitMask
[i
];
934 if (!strcmp(str
, pBit
->m_ParamName
.c_str()))
936 nMask
|= pBit
->m_Mask
;
943 void CHWShader::mfValidateTokenData(CResFile
* pRes
)
949 bool bTokenValid
= true;
950 ResDir
* Dir
= pRes
->mfGetDirectory();
951 for (unsigned int i
= 0; i
< Dir
->size(); i
++)
953 CDirEntry
* pDE
= &(*Dir
)[i
];
954 if (pDE
->GetFlags() & RF_RES_$TOKENS
)
956 uint32 nSize
= pRes
->mfFileRead(pDE
);
957 byte
* pData
= (byte
*)pRes
->mfFileGetBuf(pDE
);
964 uint32 nL
= *(uint32
*)pData
;
965 if (CParserBin::m_bEndians
)
966 SwapEndian(nL
, eBigEndian
);
968 if (nL
* sizeof(uint32
) > nSize
)
974 int nTableSize
= nSize
- (4 + nL
* sizeof(uint32
));
981 pRes
->mfCloseEntry(pDE
->GetName(), pDE
->GetFlags());
986 CryFatalError("Invalid token data in shader cache file");
990 void CHWShader::mfValidateDirEntries(CResFile
* pRF
)
993 auto dirEntries
= pRF
->mfGetDirectory();
994 for (auto it1
= dirEntries
->begin(); it1
!= dirEntries
->end(); it1
++)
996 for (auto it2
= it1
+ 1; it2
!= dirEntries
->end(); ++it2
)
998 if (it1
->GetName() == it2
->GetName())
1000 CryFatalError("Duplicate dir entry in shader cache file");
1008 bool CHWShader_D3D::mfStoreCacheTokenMap(FXShaderToken
*& Table
, TArray
<uint32
>*& pSHData
, const char* szName
)
1012 FXShaderTokenItor itor
;
1013 uint32 nSize
= pSHData
->size();
1014 if (CParserBin::m_bEndians
)
1016 uint32 nSizeEnd
= nSize
;
1017 SwapEndian(nSizeEnd
, eBigEndian
);
1018 Data
.Copy((byte
*)&nSizeEnd
, sizeof(uint32
));
1019 for (uint32 i
= 0; i
< nSize
; i
++)
1021 uint32 nToken
= (*pSHData
)[i
];
1022 SwapEndian(nToken
, eBigEndian
);
1023 Data
.Copy((byte
*)&nToken
, sizeof(uint32
));
1028 Data
.Copy((byte
*)&nSize
, sizeof(uint32
));
1029 Data
.Copy((byte
*)&(*pSHData
)[0], nSize
* sizeof(uint32
));
1031 for (itor
= Table
->begin(); itor
!= Table
->end(); itor
++)
1034 if (CParserBin::m_bEndians
)
1035 SwapEndian(T
.Token
, eBigEndian
);
1036 Data
.Copy((byte
*)&T
.Token
, sizeof(DWORD
));
1037 Data
.Copy((byte
*)T
.SToken
.c_str(), T
.SToken
.size() + 1);
1042 CDirEntry
de(szName
, Data
.size(), RF_RES_$TOKENS
);
1043 m_pGlobalCache
->m_pRes
[CACHE_USER
]->mfFileAdd(&de
);
1044 SDirEntryOpen
* pOE
= m_pGlobalCache
->m_pRes
[CACHE_USER
]->mfOpenEntry(de
.GetName());
1045 pOE
->pData
= &Data
[0];
1046 m_pGlobalCache
->m_pRes
[CACHE_USER
]->mfFlush();
1047 m_pGlobalCache
->m_pRes
[CACHE_USER
]->mfCloseEntry(de
.GetName(), de
.GetFlags());
1052 void CHWShader_D3D::mfGetTokenMap(CResFile
* pRes
, CDirEntry
* pDE
, FXShaderToken
*& Table
, TArray
<uint32
>*& pSHData
)
1055 int nSize
= pRes
->mfFileRead(pDE
);
1056 byte
* pData
= (byte
*)pRes
->mfFileGetBuf(pDE
);
1062 Table
= new FXShaderToken
;
1063 pSHData
= new TArray
<uint32
>;
1064 uint32 nL
= *(uint32
*)pData
;
1065 if (CParserBin::m_bEndians
)
1066 SwapEndian(nL
, eBigEndian
);
1067 pSHData
->resize(nL
);
1068 if (CParserBin::m_bEndians
)
1070 uint32
* pTokens
= (uint32
*)&pData
[4];
1071 for (i
= 0; i
< nL
; i
++)
1073 uint32 nToken
= pTokens
[i
];
1074 SwapEndian(nToken
, eBigEndian
);
1075 (*pSHData
)[i
] = nToken
;
1080 memcpy(&(*pSHData
)[0], &pData
[4], nL
* sizeof(uint32
));
1082 pData
+= 4 + nL
* sizeof(uint32
);
1083 nSize
-= 4 + nL
* sizeof(uint32
);
1086 while (nOffs
< nSize
)
1088 char* pStr
= (char*)&pData
[nOffs
+ sizeof(DWORD
)];
1090 LoadUnaligned(pData
+ nOffs
, nToken
);
1091 if (CParserBin::m_bEndians
)
1092 SwapEndian(nToken
, eBigEndian
);
1093 int nLen
= strlen(pStr
) + 1;
1097 Table
->push_back(TD
);
1098 nOffs
+= sizeof(DWORD
) + nLen
;
1102 bool CHWShader_D3D::mfGetCacheTokenMap(FXShaderToken
*& Table
, TArray
<uint32
>*& pSHData
, uint64 nMaskGenFX
)
1104 if (!m_pGlobalCache
|| !m_pGlobalCache
->isValid())
1107 m_pGlobalCache
->Release(false);
1109 const bool initReadOnly
= CRenderer::CV_r_shadersAllowCompilation
== 0;
1110 const bool initAsync
= CRenderer::CV_r_shadersasyncactivation
!= 0;
1111 m_pGlobalCache
= mfInitCache(NULL
, this, true, m_CRC32
, initReadOnly
, initAsync
);
1113 if (!m_pGlobalCache
)
1120 #if defined(__GNUC__)
1121 cry_sprintf(strName
, "$MAP_%llx", nMaskGenFX
);
1123 cry_sprintf(strName
, "$MAP_%I64x", nMaskGenFX
);
1128 if (m_pGlobalCache
->m_pRes
[CACHE_READONLY
] && m_pGlobalCache
->m_pRes
[CACHE_READONLY
]->mfFileExist(strName
))
1130 if (!m_pGlobalCache
->m_pRes
[CACHE_USER
])
1132 m_pGlobalCache
->Release(false);
1133 m_pGlobalCache
= mfInitCache(NULL
, this, true, m_CRC32
, false);
1135 if (!m_pGlobalCache
|| !m_pGlobalCache
->m_pRes
[CACHE_USER
])
1140 if (!m_pGlobalCache
->m_pRes
[CACHE_USER
]->mfFileExist(strName
))
1142 if (!CRenderer::CV_r_shadersAllowCompilation
)
1145 //CryLogAlways("Storing MAP entry '%s' in shader cache file '%s'", strName, m_pGlobalCache->m_Name.c_str());
1147 return mfStoreCacheTokenMap(Table
, pSHData
, strName
);
1151 CDirEntry
* pDE
= nullptr;
1152 CResFile
* pRes
= nullptr;
1153 for (int i
= 0; i
< 2; i
++)
1155 pRes
= m_pGlobalCache
->m_pRes
[i
];
1158 pDE
= pRes
->mfGetEntry(strName
);
1164 Warning("Couldn't find tokens MAP entry '%s' in shader cache file '%s'", strName
, m_pGlobalCache
->m_Name
.c_str());
1165 ASSERT_IN_SHADER(0);
1168 mfGetTokenMap(pRes
, pDE
, Table
, pSHData
);
1169 pRes
->mfFileClose(pDE
->GetName(), pDE
->GetFlags());
1174 //==============================================================================================================================================================
1176 bool CHWShader_D3D::mfGenerateScript(CShader
* pSH
, SHWSInstance
* pInst
, std::vector
<SCGBind
>& InstBindVars
, uint32 nFlags
, FXShaderToken
* Table
, TArray
<uint32
>* pSHData
, TArray
<char>& sNewScr
)
1180 uint32 nSFlags
= m_Flags
;
1181 bool bTempMap
= (Table
== NULL
);
1182 assert((Table
&& pSHData
) || (!Table
&& !pSHData
));
1183 assert(m_pGlobalCache
);
1184 if (CParserBin::m_bEditable
&& !Table
) // Fast path for offline shaders builder
1186 Table
= &m_TokenTable
;
1187 pSHData
= &m_TokenData
;
1192 if (m_pGlobalCache
&& !(nSFlags
& HWSG_GS_MULTIRES
))
1193 mfGetCacheTokenMap(Table
, pSHData
, m_nMaskGenShader
);
1194 if (CParserBin::m_bEditable
)
1199 SAFE_DELETE(pSHData
);
1201 Table
= &m_TokenTable
;
1202 pSHData
= &m_TokenData
;
1206 if (!(nSFlags
& HWSG_GS_MULTIRES
))
1208 assert(Table
&& pSHData
);
1209 if (!Table
|| !pSHData
)
1213 ShaderTokensVec NewTokens
;
1215 uint32 eT
= eT_unknown
;
1217 switch (pInst
->m_eClass
)
1225 case eHWSC_Geometry
:
1241 if (eT
!= eT_unknown
)
1242 CParserBin::AddDefineToken(eT
, NewTokens
);
1244 if (nSFlags
& HWSG_GS_MULTIRES
)
1246 // Generate script vor VS first;
1247 //@TODO: Do this without global variable
1248 //pInst = s_pCurInstVS;
1251 CHWShader_D3D
* curVS
= (CHWShader_D3D
*)s_pCurHWVS
;
1252 Table
= &curVS
->m_TokenTable
;
1253 pSHData
= &curVS
->m_TokenData
;
1254 nSFlags
= curVS
->m_Flags
;
1259 // Include runtime mask definitions in the script
1260 SShaderGen
* shg
= gRenDev
->m_cEF
.m_pGlobalExt
;
1261 if (shg
&& pInst
->m_Ident
.m_RTMask
)
1263 for (uint32 i
= 0; i
< shg
->m_BitMask
.Num(); i
++)
1265 SShaderGenBit
* bit
= shg
->m_BitMask
[i
];
1266 if (!(bit
->m_Mask
& pInst
->m_Ident
.m_RTMask
))
1268 CParserBin::AddDefineToken(bit
->m_dwToken
, NewTokens
);
1272 // Include light mask definitions in the script
1273 if (nSFlags
& HWSG_SUPPORTS_MULTILIGHTS
)
1275 int nLights
= pInst
->m_Ident
.m_LightMask
& 0xf;
1277 CParserBin::AddDefineToken(eT__LT_LIGHTS
, NewTokens
);
1278 CParserBin::AddDefineToken(eT__LT_NUM
, nLights
+ eT_0
, NewTokens
);
1279 bool bHasProj
= false;
1280 for (int i
= 0; i
< 4; i
++)
1282 int nLightType
= (pInst
->m_Ident
.m_LightMask
>> (SLMF_LTYPE_SHIFT
+ i
* SLMF_LTYPE_BITS
)) & SLMF_TYPE_MASK
;
1283 if (nLightType
== SLMF_PROJECTED
)
1286 CParserBin::AddDefineToken(eT__LT_0_TYPE
+ i
, nLightType
+ eT_0
, NewTokens
);
1289 CParserBin::AddDefineToken(eT__LT_HASPROJ
, eT_1
, NewTokens
);
1291 else if (nSFlags
& HWSG_SUPPORTS_LIGHTING
)
1293 CParserBin::AddDefineToken(eT__LT_LIGHTS
, NewTokens
);
1294 int nLightType
= (pInst
->m_Ident
.m_LightMask
>> SLMF_LTYPE_SHIFT
) & SLMF_TYPE_MASK
;
1295 if (nLightType
== SLMF_PROJECTED
)
1296 CParserBin::AddDefineToken(eT__LT_HASPROJ
, eT_1
, NewTokens
);
1299 // Include modificator mask definitions in the script
1300 if ((nSFlags
& HWSG_SUPPORTS_MODIF
) && pInst
->m_Ident
.m_MDMask
)
1302 const uint32 tcProjMask
= HWMD_TEXCOORD_PROJ
;
1303 const uint32 tcMatrixMask
= HWMD_TEXCOORD_MATRIX
;
1304 const uint32 tcGenObjectLinearMask
= HWMD_TEXCOORD_GEN_OBJECT_LINEAR
;
1306 if (pInst
->m_Ident
.m_MDMask
& tcProjMask
)
1307 CParserBin::AddDefineToken(eT__TT_TEXCOORD_PROJ
, NewTokens
);
1308 if (pInst
->m_Ident
.m_MDMask
& tcMatrixMask
)
1309 CParserBin::AddDefineToken(eT__TT_TEXCOORD_MATRIX
, NewTokens
);
1310 if (pInst
->m_Ident
.m_MDMask
& tcGenObjectLinearMask
)
1311 CParserBin::AddDefineToken(eT__TT_TEXCOORD_GEN_OBJECT_LINEAR
, NewTokens
);
1314 // Include vertex modificator mask definitions in the script
1315 if ((nSFlags
& HWSG_SUPPORTS_VMODIF
) && pInst
->m_Ident
.m_MDVMask
)
1317 int nMDV
= pInst
->m_Ident
.m_MDVMask
& 0x0fffffff;
1318 int nType
= nMDV
& 0xf;
1320 CParserBin::AddDefineToken(eT__VT_TYPE
, eT_0
+ nType
, NewTokens
);
1321 if ((nMDV
& MDV_BENDING
) || nType
== eDT_Bending
)
1323 CParserBin::AddDefineToken(eT__VT_BEND
, eT_1
, NewTokens
);
1326 nType
= eDT_Bending
;
1327 CParserBin::AddDefineToken(eT__VT_TYPE
, eT_0
+ nType
, NewTokens
);
1330 if (nMDV
& MDV_DEPTH_OFFSET
)
1331 CParserBin::AddDefineToken(eT__VT_DEPTH_OFFSET
, eT_1
, NewTokens
);
1332 if (nMDV
& MDV_WIND
)
1333 CParserBin::AddDefineToken(eT__VT_WIND
, eT_1
, NewTokens
);
1334 if (nMDV
& MDV_DET_BENDING
)
1335 CParserBin::AddDefineToken(eT__VT_DET_BEND
, eT_1
, NewTokens
);
1336 if (nMDV
& MDV_DET_BENDING_GRASS
)
1337 CParserBin::AddDefineToken(eT__VT_GRASS
, eT_1
, NewTokens
);
1339 CParserBin::AddDefineToken(eT__VT_TYPE_MODIF
, eT_1
, NewTokens
);
1342 if (nSFlags
& HWSG_FP_EMULATION
)
1344 CParserBin::AddDefineToken(eT__FT0_COP
, eT_0
+ (pInst
->m_Ident
.m_LightMask
& 0xff), NewTokens
);
1345 CParserBin::AddDefineToken(eT__FT0_AOP
, eT_0
+ ((pInst
->m_Ident
.m_LightMask
& 0xff00) >> 8), NewTokens
);
1347 byte CO_0
= ((pInst
->m_Ident
.m_LightMask
& 0xff0000) >> 16) & 7;
1348 CParserBin::AddDefineToken(eT__FT0_CARG1
, eT_0
+ CO_0
, NewTokens
);
1350 byte CO_1
= ((pInst
->m_Ident
.m_LightMask
& 0xff0000) >> 19) & 7;
1351 CParserBin::AddDefineToken(eT__FT0_CARG2
, eT_0
+ CO_1
, NewTokens
);
1353 byte AO_0
= ((pInst
->m_Ident
.m_LightMask
& 0xff000000) >> 24) & 7;
1354 CParserBin::AddDefineToken(eT__FT0_AARG1
, eT_0
+ AO_0
, NewTokens
);
1356 byte AO_1
= ((pInst
->m_Ident
.m_LightMask
& 0xff000000) >> 27) & 7;
1357 CParserBin::AddDefineToken(eT__FT0_AARG2
, eT_0
+ AO_1
, NewTokens
);
1359 if (CO_0
== eCA_Specular
|| CO_1
== eCA_Specular
|| AO_0
== eCA_Specular
|| AO_1
== eCA_Specular
)
1360 CParserBin::AddDefineToken(eT__FT_SPECULAR
, NewTokens
);
1361 if (CO_0
== eCA_Diffuse
|| CO_1
== eCA_Diffuse
|| AO_0
== eCA_Diffuse
|| AO_1
== eCA_Diffuse
)
1362 CParserBin::AddDefineToken(eT__FT_DIFFUSE
, NewTokens
);
1363 if (CO_0
== eCA_Texture
|| CO_1
== eCA_Texture
|| AO_0
== eCA_Texture
|| AO_1
== eCA_Texture
)
1364 CParserBin::AddDefineToken(eT__FT_TEXTURE
, NewTokens
);
1365 if (CO_0
== eCA_Texture1
|| (CO_1
== eCA_Texture1
) || AO_0
== eCA_Texture1
|| AO_1
== eCA_Texture1
1366 || CO_0
== eCA_Previous
|| (CO_1
== eCA_Previous
) || AO_0
== eCA_Previous
|| AO_1
== eCA_Previous
)
1367 CParserBin::AddDefineToken(eT__FT_TEXTURE1
, NewTokens
);
1368 if (CO_0
== eCA_Normal
|| CO_1
== eCA_Normal
|| AO_0
== eCA_Normal
|| AO_1
== eCA_Normal
)
1369 CParserBin::AddDefineToken(eT__FT_NORMAL
, NewTokens
);
1370 if (CO_0
== eCA_Constant
|| (CO_1
== eCA_Constant
) || AO_0
== eCA_Constant
|| AO_1
== eCA_Constant
1371 || CO_0
== eCA_Previous
|| (CO_1
== eCA_Previous
) || AO_0
== eCA_Previous
|| AO_1
== eCA_Previous
)
1372 CParserBin::AddDefineToken(eT__FT_PSIZE
, NewTokens
);
1374 if (nFlags
& HWSF_STOREDATA
)
1376 int nStreams
= pInst
->m_Ident
.m_LightMask
& 0xff;
1377 if (nStreams
& (1 << VSF_QTANGENTS
))
1378 CParserBin::AddDefineToken(eT__FT_QTANGENT_STREAM
, NewTokens
);
1379 if (nStreams
& (1 << VSF_TANGENTS
))
1380 CParserBin::AddDefineToken(eT__FT_TANGENT_STREAM
, NewTokens
);
1381 if (nStreams
& VSM_HWSKIN
)
1382 CParserBin::AddDefineToken(eT__FT_SKIN_STREAM
, NewTokens
);
1383 #if ENABLE_NORMALSTREAM_SUPPORT
1384 if (CParserBin::m_nPlatform
& (SF_D3D11
| SF_DURANGO
| SF_ORBIS
| SF_GL4
| SF_GLES3
))
1386 if (nStreams
& VSM_NORMALS
)
1387 CParserBin::AddDefineToken(eT__FT_NORMAL
, NewTokens
);
1390 if (nStreams
& VSM_VERTEX_VELOCITY
)
1391 CParserBin::AddDefineToken(eT__FT_VERTEX_VELOCITY_STREAM
, NewTokens
);
1395 int nT
= NewTokens
.size();
1396 NewTokens
.resize(nT
+ pSHData
->size());
1397 memcpy(&NewTokens
[nT
], &(*pSHData
)[0], pSHData
->size() * sizeof(uint32
));
1399 CParserBin
Parser(NULL
, pSH
);
1400 Parser
.Preprocess(1, NewTokens
, Table
);
1401 CorrectScriptEnums(Parser
, pInst
, InstBindVars
, Table
);
1402 RemoveUnaffectedParameters_D3D10(Parser
, pInst
, InstBindVars
);
1403 ConvertBinScriptToASCII(Parser
, pInst
, InstBindVars
, Table
, sNewScr
);
1404 AddResourceLayoutToScript(pInst
, mfProfileString(pInst
->m_eClass
), m_EntryFunc
.c_str(), sNewScr
);
1406 // Generate geometry shader
1407 if (m_Flags
& HWSG_GS_MULTIRES
)
1409 bool bResult
= AutoGenMultiresGS(sNewScr
, pSH
);
1417 SAFE_DELETE(pSHData
);
1420 /* FILE *fp = gEnv->pCryPak->FOpen("fff", "w");
1423 gEnv->pCryPak->FPrintf(fp, "%s", &sNewScr[0]);
1424 gEnv->pCryPak->FClose (fp);
1427 return sNewScr
.Num() && sNewScr
[0];
1430 bool CHWShader_D3D::AutoGenMultiresGS(TArray
<char>& sNewScr
, CShader
*pSH
)
1432 CHWShader_D3D
* curVS
= (CHWShader_D3D
*)s_pCurHWVS
;
1433 char szEntryVS
[128];
1434 strcpy(szEntryVS
, curVS
->m_EntryFunc
.c_str());
1435 strcat(szEntryVS
, "(");
1436 char *szStart
= strstr(&sNewScr
[0], szEntryVS
);
1440 char *szEnd
= szStart
- 1;
1441 while (*szEnd
== 0x20) --szEnd
;
1443 while (*szS
> 0x20) --szS
;
1444 char szStrName
[128];
1445 ptrdiff_t nSize
= szEnd
- szS
;
1446 strncpy(szStrName
, &szS
[1], nSize
);
1447 szStrName
[nSize
] = 0;
1450 strcpy(szStruct
, "struct ");
1451 strcat(szStruct
, szStrName
);
1452 char *szStrStart
= strstr(&sNewScr
[0], szStruct
);
1455 char *szStrEnd
= strstr(szStrStart
, "};");
1458 char szPosName
[128];
1459 char *szPosA
= strstr(szStrStart
, ":POSITION");
1460 if (!szPosA
|| szPosA
>= szStrEnd
)
1461 szPosA
= strstr(szStrStart
, ":SV_Position");
1462 if (!szPosA
|| szPosA
>= szStrEnd
)
1464 #if !defined(_RELEASE)
1465 CRY_ASSERT_MESSAGE(false, "Cannot generate a GS for a VS with no SV_Position output");
1469 char *szPosAB
= szPosA
- 1;
1470 while (*szPosAB
== 0x20) --szPosAB
;
1471 char *szP
= szPosAB
;
1472 while (*szP
> 0x20) --szP
;
1473 nSize
= szPosAB
- szP
;
1474 strncpy(szPosName
, &szP
[1], nSize
);
1475 szPosName
[nSize
] = 0;
1477 TArray
<char> szNewS
;
1478 //szNewS.Copy(&sNewScr[0], szStrStart - &sNewScr[0]);
1479 szNewS
.Copy(szStrStart
, uint32(szStrEnd
-szStrStart
)+1);
1481 m_EntryFunc
.Format("%s_GS", curVS
->m_EntryFunc
.c_str());
1485 "#define NV_VR_FASTGS_FUNCTION_NAME %s\n"
1486 "#define NV_VR_FASTGS_PASSTHROUGH_STRUCT %s\n"
1487 "#define NV_VR_FASTGS_OUTPUT_STRUCT %s_gs\n"
1488 "#define NV_VR_FASTGS_POSITION_ATTRIBUTE %s\n\n",
1489 m_EntryFunc
.c_str(), szStrName
, szStrName
, szPosName
);
1490 szNewS
.Copy(GSDefine
.c_str(), GSDefine
.size());
1492 ShaderTokensVec NewTokens
;
1495 CParserBin::AddDefineToken(eT
, NewTokens
);
1497 // Include runtime mask definitions in the script
1498 SShaderGen
* shg
= gRenDev
->m_cEF
.m_pGlobalExt
;
1499 if (shg
&& m_pCurInst
->m_Ident
.m_RTMask
)
1501 for (uint32 i
= 0; i
< shg
->m_BitMask
.Num(); i
++)
1503 SShaderGenBit
* bit
= shg
->m_BitMask
[i
];
1504 if (!(bit
->m_Mask
& m_pCurInst
->m_Ident
.m_RTMask
))
1506 CParserBin::AddDefineToken(bit
->m_dwToken
, NewTokens
);
1509 int nT
= NewTokens
.size();
1510 NewTokens
.resize(nT
+ m_TokenData
.size());
1511 memcpy(&NewTokens
[nT
], &m_TokenData
[0], m_TokenData
.size() * sizeof(uint32
));
1513 std::vector
<SCGBind
> InstBindVars
;
1514 CParserBin
Parser(NULL
, pSH
);
1515 Parser
.Preprocess(1, NewTokens
, &m_TokenTable
);
1516 ConvertBinScriptToASCII(Parser
, m_pCurInst
, InstBindVars
, &m_TokenTable
, szNewS
);
1518 sNewScr
.Copy(szNewS
);
1526 /*static uint32 sFindVar(CParserBin& Parser, int& nStart)
1528 const uint32 *pTokens = Parser.GetTokens(0);
1529 int nLast = Parser.GetNumTokens()-1;
1531 while (nStart <= nLast)
1533 if (pTokens[nStart] == eT_br_cv_1)
1537 while(nStart <= nLast)
1539 if (pTokens[nStart++] == eT_br_cv_1)
1542 if (pTokens[nStart++] == eT_br_cv_2)
1550 if (nStart <= nLast)
1552 if (pTokens[nStart] >= eT_float && pTokens[nStart] <= eT_int)
1554 if (nStart+3 <= nLast)
1556 uint32 nName = pTokens[nStart+1];
1557 uint32 nN = pTokens[nStart+2];
1560 if (nN == eT_br_sq_1)
1562 assert(pTokens[nStart+4] == eT_br_sq_2);
1563 if (pTokens[nStart+4] == eT_br_sq_2)
1564 nN = pTokens[nStart+5];
1580 bool sIsAffectFuncs(CParserBin& Parser, uint32 nName)
1582 const uint32 *pTokens = Parser.GetTokens(0);
1584 int nLast = Parser.GetNumTokens()-1;
1586 while (nStart <= nLast)
1588 if (pTokens[nStart] == eT_br_cv_1)
1592 int nBegin = nStart;
1593 while(nStart <= nLast)
1595 if (pTokens[nStart++] == eT_br_cv_1)
1598 if (pTokens[nStart++] == eT_br_cv_2)
1605 if (nStart <= nLast)
1607 int nPos = Parser.FindToken(nBegin, nStart, nName);
1616 void CHWShader_D3D::RemoveUnaffectedParameters_D3D10(CParserBin
& Parser
, SHWSInstance
* pInst
, std::vector
<SCGBind
>& InstBindVars
)
1618 int nPos
= Parser
.FindToken(0, Parser
.m_Tokens
.size() - 1, eT_cbuffer
);
1621 uint32 nName
= Parser
.m_Tokens
[nPos
+ 1];
1622 if (nName
== eT_PER_BATCH
|| nName
== eT_PER_INSTANCE
)
1624 int nPosEnd
= Parser
.FindToken(nPos
+ 3, Parser
.m_Tokens
.size() - 1, eT_br_cv_2
);
1625 assert(nPosEnd
>= 0);
1626 int nPosN
= Parser
.FindToken(nPos
+ 1, Parser
.m_Tokens
.size() - 1, eT_br_cv_1
);
1629 while (nPosN
< nPosEnd
)
1631 uint32 nT
= Parser
.m_Tokens
[nPosN
+ 1];
1632 int nPosCode
= Parser
.FindToken(nPosEnd
+ 1, Parser
.m_Tokens
.size() - 1, nT
);
1635 assert(nPosN
> 0 && nPosN
< (int)Parser
.m_Tokens
.size());
1636 if (InstBindVars
.size())
1639 CCryNameR
nm(Parser
.GetString(nT
));
1640 for (; i
< InstBindVars
.size(); i
++)
1642 SCGBind
& b
= InstBindVars
[i
];
1646 if (i
== InstBindVars
.size())
1647 Parser
.m_Tokens
[nPosN
] = eT_comment
;
1650 Parser
.m_Tokens
[nPosN
] = eT_comment
;
1652 nPosN
= Parser
.FindToken(nPosN
+ 2, nPosEnd
, eT_semicolumn
);
1656 nPos
= Parser
.FindToken(nPosEnd
+ 1, Parser
.m_Tokens
.size() - 1, eT_cbuffer
);
1659 nPos
= Parser
.FindToken(nPos
+ 2, Parser
.m_Tokens
.size() - 1, eT_cbuffer
);
1665 uint32 nName = sFindVar(Parser, nStart);
1668 bool bAffect = sIsAffectFuncs(Parser, nName);
1670 Parser.m_Tokens[nStart] = eT_comment;
1683 void CHWShader_D3D::CorrectScriptEnums(CParserBin
& Parser
, SHWSInstance
* pInst
, std::vector
<SCGBind
>& InstBindVars
, FXShaderToken
* Table
)
1685 // correct enumeration of TEXCOORD# interpolators after preprocessing
1687 int nSize
= Parser
.m_Tokens
.size();
1688 uint32
* pTokens
= &Parser
.m_Tokens
[0];
1690 const uint32 Toks
[] = { eT_TEXCOORDN
, eT_TEXCOORDN_centroid
, eT_unknown
};
1692 std::vector
<SStructData
> SData
;
1696 nCur
= Parser
.FindToken(nCur
, nSize
- 1, eT_struct
);
1699 int nLastStr
= Parser
.FindToken(nCur
, nSize
- 1, eT_br_cv_2
);
1700 assert(nLastStr
>= 0);
1703 bool bNested
= false;
1704 for (i
= 0; i
< SData
.size(); i
++)
1706 SStructData
& Data
= SData
[i
];
1707 Data
.m_nPos
= Parser
.FindToken(nCur
, nLastStr
, Data
.m_nName
);
1708 if (Data
.m_nPos
> 0)
1711 uint32 nName
= pTokens
[nCur
+ 1];
1713 while (nCur
< nLastStr
)
1715 int nTN
= Parser
.FindToken(nCur
, nLastStr
, Toks
);
1718 nCur
= nLastStr
+ 1;
1724 for (i
= 0; i
< SData
.size(); i
++)
1726 SStructData
& Data
= SData
[i
];
1727 if (Data
.m_nPos
> 0 && nTN
> Data
.m_nPos
)
1728 nNested
+= Data
.m_nTCs
;
1731 assert(pTokens
[nTN
- 1] == eT_colon
);
1734 if (pTokens
[nTN
- 2] == eT_br_sq_2
)
1736 nArrSize
= pTokens
[nTN
- 3] - eT_0
;
1737 if ((unsigned int) nArrSize
> 15)
1739 const char* szArrSize
= Parser
.GetString(pTokens
[nTN
- 3], *Table
);
1740 nArrSize
= szArrSize
? atoi(szArrSize
) : 0;
1742 assert(pTokens
[nTN
- 4] == eT_br_sq_1
);
1743 //const char *szName = Parser.GetString(pTokens[nTN-5], *Table);
1744 nTokName
= pTokens
[nTN
- 5];
1748 uint32 nType
= pTokens
[nTN
- 3];
1749 assert(nType
== eT_float
|| nType
== eT_float2
|| nType
== eT_float3
|| nType
== eT_float4
|| nType
== eT_float4x4
|| nType
== eT_float3x4
|| nType
== eT_float2x4
|| nType
== eT_float3x3
||
1750 nType
== eT_half
|| nType
== eT_half2
|| nType
== eT_half3
|| nType
== eT_half4
|| nType
== eT_half4x4
|| nType
== eT_half3x4
|| nType
== eT_half2x4
|| nType
== eT_half3x3
);
1751 if (nType
== eT_float4x4
|| nType
== eT_half4x4
)
1753 else if (nType
== eT_float3x4
|| nType
== eT_float3x3
|| nType
== eT_half3x4
|| nType
== eT_half3x3
)
1755 else if (nType
== eT_float2x4
|| nType
== eT_half2x4
)
1757 nTokName
= pTokens
[nTN
- 2];
1759 assert(nArrSize
> 0 && nArrSize
< 16);
1761 EToken eT
= (pTokens
[nTN
] == eT_TEXCOORDN
) ? eT_TEXCOORD0
: eT_TEXCOORD0_centroid
;
1763 pTokens
[nTN
] = n
+ nNested
+ eT
;
1771 SData
.push_back(SD
);
1773 if (InstBindVars
.size())
1774 qsort(&InstBindVars
[0], InstBindVars
.size(), sizeof(SCGBind
), CGBindCallback
);
1775 pInst
->m_nNumInstAttributes
= nInstParam
;
1778 static int sFetchInst(uint32
& nCur
, uint32
* pTokens
, uint32 nT
, std::vector
<uint32
>& Parameter
)
1782 uint32 nTok
= pTokens
[nCur
];
1783 if (nTok
!= eT_br_rnd_1
&& nTok
!= eT_br_rnd_2
&& nTok
!= eT_comma
)
1788 Parameter
.push_back(pTokens
[nCur
]);
1790 while (pTokens
[nCur
] == eT_dot
)
1793 Parameter
.push_back(pTokens
[nCur
]);
1794 Parameter
.push_back(pTokens
[nCur
+ 1]);
1800 static void sCR(TArray
<char>& Text
, int nLevel
)
1803 for (int i
= 0; i
< nLevel
; i
++)
1810 bool CHWShader_D3D::ConvertBinScriptToASCII(CParserBin
& Parser
, SHWSInstance
* pInst
, std::vector
<SCGBind
>& InstBindVars
, FXShaderToken
* Table
, TArray
<char>& Text
)
1815 /*if (pInst->m_RTMask == 0x2000020000680104)
1817 TArray<char> TempTx;
1818 CParserBin::ConvertToAscii(&Parser.m_Tokens[0], Parser.m_Tokens.size(), *Table, TempTx);
1819 FILE *fp = gEnv->pCryPak->FOpen("inst.txt", "w");
1822 gEnv->pCryPak->FPrintf(fp, "%s", &TempTx[0]);
1823 gEnv->pCryPak->FClose (fp);
1826 uint32
* pTokens
= &Parser
.m_Tokens
[0];
1827 uint32 nT
= Parser
.m_Tokens
.size();
1828 const char* szPrev
= " ";
1830 for (i
= 0; i
< nT
; i
++)
1832 uint32 nToken
= pTokens
[i
];
1838 if (nToken
== eT_skip
)
1843 if (nToken
== eT_skip_1
)
1847 nToken
= pTokens
[i
];
1848 if (nToken
== eT_skip_2
)
1855 if (nToken
== eT_fetchinst
)
1859 std::vector
<uint32
> ParamDst
, ParamSrc
;
1860 TArray
<char> sParamDstFull
, sParamDstName
, sParamSrc
;
1861 int nDst
= sFetchInst(i
, &Parser
.m_Tokens
[0], Parser
.m_Tokens
.size(), ParamDst
);
1862 assert(Parser
.m_Tokens
[i
] == eT_eq
);
1863 if (Parser
.m_Tokens
[i
] != eT_eq
)
1865 // Should never happen
1866 int n
= CParserBin::FindToken(i
, Parser
.m_Tokens
.size() - 1, &Parser
.m_Tokens
[0], eT_semicolumn
);
1872 int nSrc
= sFetchInst(i
, &Parser
.m_Tokens
[0], Parser
.m_Tokens
.size(), ParamSrc
);
1873 CParserBin::ConvertToAscii(&ParamDst
[0], ParamDst
.size(), *Table
, sParamDstFull
);
1874 CParserBin::ConvertToAscii(&ParamDst
[nDst
], 1, *Table
, sParamDstName
);
1875 CParserBin::ConvertToAscii(&ParamSrc
[nSrc
], 1, *Table
, sParamSrc
);
1876 assert(strncmp(&sParamSrc
[0], "Inst", 4) == 0);
1880 CParserBin::ConvertToAscii(&ParamSrc
[0], ParamSrc
.size(), *Table
, sParamSrc
);
1881 cry_sprintf(str
, "%s = %s;\n", &sParamDstFull
[0], &sParamSrc
[0]);
1882 Text
.Copy(str
, strlen(str
));
1884 while (Parser
.m_Tokens
[i
] != eT_semicolumn
)
1890 const char* szStr
= CParserBin::GetString(nToken
, *Table
, false);
1892 if (!szStr
|| !szStr
[0])
1895 bRes
= CParserBin::CorrectScript(pTokens
, i
, nT
, Text
);
1899 #if defined(_DEBUG) && !CRY_PLATFORM_ORBIS
1903 char c
= szStr
[n
++];
1904 bool bASC
= isascii(c
);
1908 if (nToken
== eT_semicolumn
|| nToken
== eT_br_cv_1
)
1910 if (nToken
== eT_br_cv_1
)
1915 Text
.Copy(szStr
, strlen(szStr
));
1916 if (nToken
== eT_semicolumn
)
1918 if (i
+ 1 < nT
&& pTokens
[i
+ 1] == eT_br_cv_2
)
1919 sCR(Text
, nLevel
- 1);
1923 else if (i
+ 1 < nT
)
1925 if (pTokens
[i
+ 1] < eT_br_rnd_1
|| pTokens
[i
+ 1] >= eT_float
)
1935 char cPrev
= Text
[Text
.Num() - 1];
1936 if (!SkipChar((uint8
)cPrev
) && !SkipChar((uint8
)szStr
[0]))
1940 Text
.Copy(szStr
, strlen(szStr
));
1941 if (nToken
== eT_br_cv_2
)
1944 if (i
+ 1 < nT
&& pTokens
[i
+ 1] != eT_semicolumn
)
1955 int OrigToBase64Size(int orig_size
)
1957 return ((orig_size
+ 2) / 3) * 4;
1960 static const uint8 BASE64_TABLE
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1962 void Base64EncodeBuffer(const void* orig_buf
, int orig_buf_size
, void* b64_buf
)
1964 const uint8
* p
= (const uint8
*)orig_buf
;
1965 uint8
* q
= (uint8
*)b64_buf
;
1968 for (int i
= 0, e
= orig_buf_size
/ 3; i
< e
; ++i
, p
+= 3, q
+= 4)
1970 // assuming little endian
1971 w
= (p
[0] << 16) | (p
[1] << 8) | p
[2];
1972 q
[0] = BASE64_TABLE
[w
>> 18];
1973 q
[1] = BASE64_TABLE
[(w
>> 12) & 0x3F];
1974 q
[2] = BASE64_TABLE
[(w
>> 6) & 0x3F];
1975 q
[3] = BASE64_TABLE
[w
& 0x3F];
1978 switch (orig_buf_size
% 3)
1982 q
[0] = BASE64_TABLE
[w
>> 2];
1983 q
[1] = BASE64_TABLE
[(w
<< 4) & 0x3F];
1988 w
= (p
[0] << 8) | p
[1];
1989 q
[0] = BASE64_TABLE
[w
>> 10];
1990 q
[1] = BASE64_TABLE
[(w
>> 4) & 0x3F];
1991 q
[2] = BASE64_TABLE
[(w
<< 2) & 0x3F];
1997 bool CHWShader_D3D::AddResourceLayoutToScript(SHWSInstance
* pInst
, const char* szProfile
, const char* pFunCCryName
, TArray
<char>& Scr
)
1999 #if CRY_RENDERER_VULKAN
2000 if (auto pEncodedLayout
= GetDeviceObjectFactory().LookupResourceLayoutEncoding(pInst
->m_Ident
.m_pipelineState
.VULKAN
.resourceLayoutHash
))
2002 const int TempBufferSize
= 4096;
2003 int bin
[TempBufferSize
];
2006 bin
[pointer
++] = strlen(szProfile
);
2007 bin
[pointer
+ ((strlen(szProfile
) + 3) / 4) - 1] = 0;
2008 memcpy(&bin
[pointer
], szProfile
, strlen(szProfile
));
2009 pointer
+= (strlen(szProfile
) + 3) / 4;
2011 bin
[pointer
++] = strlen(pFunCCryName
);
2012 bin
[pointer
+ ((strlen(pFunCCryName
) + 3) / 4) - 1] = 0;
2013 memcpy(&bin
[pointer
], pFunCCryName
, strlen(pFunCCryName
));
2014 pointer
+= (strlen(pFunCCryName
) + 3) / 4;
2016 CRY_ASSERT(TempBufferSize
- pointer
- pEncodedLayout
->size() > 0);
2017 memcpy(&bin
[pointer
], pEncodedLayout
->data(), pEncodedLayout
->size());
2018 pointer
+= (pEncodedLayout
->size() + 3) / 4;
2020 // vertex input description: currently disabled.
2024 string head
= "/*\n";
2025 string tail
= "\n*/\n\n";
2027 Scr
.Insert(0, head
.length() + OrigToBase64Size(pointer
* 4) + tail
.length());
2029 memcpy(&Scr
[0], head
.c_str(), head
.length());
2030 Base64EncodeBuffer(bin
, pointer
* 4, &Scr
[head
.length()]);
2031 memcpy(&Scr
[head
.length() + OrigToBase64Size(pointer
* 4)], tail
.c_str(), tail
.length());
2040 void CHWShader_D3D::mfGetSrcFileName(char* srcName
, int nSize
)
2042 if (!srcName
|| nSize
<= 0)
2044 if (!m_NameSourceFX
.empty())
2046 cry_strcpy(srcName
, nSize
, m_NameSourceFX
.c_str());
2049 cry_strcpy(srcName
, nSize
, gRenDev
->m_cEF
.m_HWPath
);
2050 if (m_eSHClass
== eHWSC_Vertex
)
2051 cry_strcat(srcName
, nSize
, "Declarations/CGVShaders/");
2052 else if (m_eSHClass
== eHWSC_Pixel
)
2053 cry_strcat(srcName
, nSize
, "Declarations/CGPShaders/");
2055 cry_strcat(srcName
, nSize
, "Declarations/CGGShaders/");
2056 cry_strcat(srcName
, nSize
, GetName());
2057 cry_strcat(srcName
, nSize
, ".crycg");
2060 void CHWShader_D3D::mfGenName(SHWSInstance
* pInst
, char* dstname
, int nSize
, byte bType
)
2063 CHWShader::mfGenName(pInst
->m_Ident
.m_GLMask
, pInst
->m_Ident
.m_RTMask
, pInst
->m_Ident
.m_LightMask
, pInst
->m_Ident
.m_MDMask
, pInst
->m_Ident
.m_MDVMask
, pInst
->m_Ident
.m_pipelineState
.opaque
, pInst
->m_eClass
, dstname
, nSize
, bType
);
2065 CHWShader::mfGenName(0, 0, 0, 0, 0, 0, eHWSC_Num
, dstname
, nSize
, bType
);
2068 void CHWShader_D3D::mfGetDstFileName(SHWSInstance
* pInst
, CHWShader_D3D
* pSH
, char* dstname
, int nSize
, byte bType
)
2070 cry_strcpy(dstname
, nSize
, gRenDev
->m_cEF
.m_ShadersCache
);
2072 if (pSH
->m_eSHClass
== eHWSC_Vertex
)
2074 if (bType
== 1 || bType
== 4)
2075 cry_strcat(dstname
, nSize
, "CGVShaders/Debug/");
2076 else if (bType
== 0)
2077 cry_strcat(dstname
, nSize
, "CGVShaders/");
2078 else if (bType
== 2 || bType
== 3)
2079 cry_strcat(dstname
, nSize
, "CGVShaders/Pending/");
2081 else if (pSH
->m_eSHClass
== eHWSC_Pixel
)
2083 if (bType
== 1 || bType
== 4)
2084 cry_strcat(dstname
, nSize
, "CGPShaders/Debug/");
2085 else if (bType
== 0)
2086 cry_strcat(dstname
, nSize
, "CGPShaders/");
2087 else if (bType
== 2 || bType
== 3)
2088 cry_strcat(dstname
, nSize
, "CGPShaders/Pending/");
2090 else if (GEOMETRYSHADER_SUPPORT
&& pSH
->m_eSHClass
== eHWSC_Geometry
)
2092 if (bType
== 1 || bType
== 4)
2093 cry_strcat(dstname
, nSize
, "CGGShaders/Debug/");
2094 else if (bType
== 0)
2095 cry_strcat(dstname
, nSize
, "CGGShaders/");
2096 else if (bType
== 2 || bType
== 3)
2097 cry_strcat(dstname
, nSize
, "CGGShaders/Pending/");
2099 else if (GEOMETRYSHADER_SUPPORT
&& pSH
->m_eSHClass
== eHWSC_Hull
)
2101 if (bType
== 1 || bType
== 4)
2102 cry_strcat(dstname
, nSize
, "CGHShaders/Debug/");
2103 else if (bType
== 0)
2104 cry_strcat(dstname
, nSize
, "CGHShaders/");
2105 else if (bType
== 2 || bType
== 3)
2106 cry_strcat(dstname
, nSize
, "CGHShaders/Pending/");
2108 else if (GEOMETRYSHADER_SUPPORT
&& pSH
->m_eSHClass
== eHWSC_Domain
)
2110 if (bType
== 1 || bType
== 4)
2111 cry_strcat(dstname
, nSize
, "CGDShaders/Debug/");
2112 else if (bType
== 0)
2113 cry_strcat(dstname
, nSize
, "CGDShaders/");
2114 else if (bType
== 2 || bType
== 3)
2115 cry_strcat(dstname
, nSize
, "CGDShaders/Pending/");
2117 else if (GEOMETRYSHADER_SUPPORT
&& pSH
->m_eSHClass
== eHWSC_Compute
)
2119 if (bType
== 1 || bType
== 4)
2120 cry_strcat(dstname
, nSize
, "CGCShaders/Debug/");
2121 else if (bType
== 0)
2122 cry_strcat(dstname
, nSize
, "CGCShaders/");
2123 else if (bType
== 2 || bType
== 3)
2124 cry_strcat(dstname
, nSize
, "CGCShaders/Pending/");
2127 cry_strcat(dstname
, nSize
, pSH
->GetName());
2130 cry_strcat(dstname
, nSize
, "_out");
2134 char* s
= strchr(dstname
, '(');
2139 char szGenName
[256];
2140 mfGenName(pInst
, szGenName
, 256, bType
);
2142 cry_strcat(dstname
, nSize
, szGenName
);
2145 //========================================================================================================
2146 // Binary cache support
2148 SShaderCache::~SShaderCache()
2152 CResFile
* pRes
= m_pStreamInfo
->m_pRes
;
2156 assert(pRes
== m_pRes
[0] || pRes
== m_pRes
[1]);
2157 assert(!pRes
->mfIsDirStreaming());
2158 //bWarn = pRes->mfIsDirStreaming();
2160 /*if (m_pStreamInfo->m_EntriesQueue.size())
2163 Warning("Warning: SShader`Cache::~SShaderCache(): '%s' Streaming tasks is still in progress!: %d", m_Name.c_str(), m_pStreamInfo->m_EntriesQueue.size());*/
2165 m_pStreamInfo
->AbortJobs();
2168 CHWShader::m_ShaderCache
.erase(m_Name
);
2169 SAFE_DELETE(m_pRes
[CACHE_USER
]);
2170 SAFE_DELETE(m_pRes
[CACHE_READONLY
]);
2171 SAFE_RELEASE(m_pStreamInfo
);
2174 void SShaderCache::Cleanup()
2177 m_pRes
[0]->mfDeactivate(true);
2179 m_pRes
[1]->mfDeactivate(true);
2182 bool SShaderCache::isValid()
2184 return ((m_pRes
[CACHE_READONLY
] || m_pRes
[CACHE_USER
]) && CParserBin::m_nPlatform
== m_nPlatform
);
2187 int SShaderCache::Size()
2189 int nSize
= sizeof(SShaderCache
);
2192 nSize
+= m_pRes
[0]->Size();
2194 nSize
+= m_pRes
[1]->Size();
2198 int SShaderDevCache::Size()
2200 int nSize
= sizeof(SShaderDevCache
);
2202 nSize
+= m_DeviceShaders
.size() * sizeof(SD3DShader
);
2207 void SShaderCache::GetMemoryUsage(ICrySizer
* pSizer
) const
2209 pSizer
->AddObject(this, sizeof(*this));
2210 pSizer
->AddObject(m_pRes
[0]);
2211 pSizer
->AddObject(m_pRes
[1]);
2214 bool SShaderCache::ReadResource(CResFile
* rf
, int nCache
)
2216 if (CRenderer::CV_r_shadersdebug
== 3 || CRenderer::CV_r_shadersdebug
== 4)
2217 iLog
->Log("---Shader Cache: Loading into in-memory cache %s", rf
->mfGetFileName());
2219 CResFileOpenScope
rfOpenGuard(rf
);
2221 auto handle
= rfOpenGuard
.getHandle()->mfGetHandle();
2224 // Open without streaming
2225 if (!rfOpenGuard
.open(RA_READ
| (CParserBin::m_bEndians
? RA_ENDIANS
: 0),
2226 &gRenDev
->m_cEF
.m_ResLookupDataMan
[nCache
],
2229 handle
= rfOpenGuard
.getHandle()->mfGetHandle();
2234 const auto librarySize
= rfOpenGuard
.getHandle()->mfGetResourceSize();
2235 const auto name
= rfOpenGuard
.getHandle()->mfGetFileName();
2236 if (librarySize
> 0)
2238 m_pBinary
[nCache
] = std::unique_ptr
<byte
[]>(new byte
[librarySize
]);
2239 gEnv
->pCryPak
->FSeek(handle
, 0, SEEK_SET
);
2240 const auto readBytes
= gEnv
->pCryPak
->FReadRaw(m_pBinary
[nCache
].get(), librarySize
, 1, handle
);
2243 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_WARNING
, "SShaderCache: \"%s\" invalid!", name
);
2244 m_pBinary
[nCache
] = nullptr;
2255 std::pair
<std::unique_ptr
<byte
[]>, uint32
> SShaderCache::DecompressResource(int resVersion
, int i
, size_t offset
, size_t size
, bool swapEndian
)
2257 using ReturnType
= std::pair
<std::unique_ptr
<byte
[]>, size_t>;
2259 uint32 decompressedSize
= 0;
2260 std::unique_ptr
<byte
[]> pData
= nullptr;
2262 const auto buf
= m_pBinary
[i
].get() + offset
;
2266 case RESVERSION_LZSS
:
2267 decompressedSize
= *reinterpret_cast<uint32
*>(buf
);
2268 if (size
>= 10000000)
2269 return ReturnType
{};
2271 SwapEndian(decompressedSize
, eBigEndian
);
2272 pData
= std::unique_ptr
<byte
[]>(new byte
[decompressedSize
]);
2275 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_ERROR
, "FileRead - Allocation fault");
2276 return ReturnType
{};
2278 if (!Decodem(&buf
[4], pData
.get(), size
- 4, decompressedSize
))
2280 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_ERROR
, "FileRead - Decodem fault");
2281 return ReturnType
{};
2286 case RESVERSION_LZMA
:
2288 if (Lzma86_GetUnpackSize(buf
, size
, &outSize64
) != 0)
2290 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_ERROR
, "FileRead - data error");
2291 return ReturnType
{};
2293 decompressedSize
= static_cast<uint32
>(outSize64
);
2294 if (decompressedSize
!= 0)
2296 pData
= std::unique_ptr
<byte
[]>(new byte
[decompressedSize
]);
2299 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_ERROR
, "FileRead - can't allocate");
2300 return ReturnType
{};
2302 size_t sizeOut
= decompressedSize
;
2303 const auto res
= Lzma86_Decode(pData
.get(), &sizeOut
, buf
, &size
);
2304 decompressedSize
= static_cast<uint32_t>(sizeOut
);
2307 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_ERROR
, "FileRead - LzmaDecoder error");
2308 return ReturnType
{};
2314 case RESVERSION_DEBUG
:
2315 decompressedSize
= size
- 20;
2316 if (decompressedSize
< 0 || decompressedSize
> 128 * 1024 * 1024)
2318 CryWarning(EValidatorModule::VALIDATOR_MODULE_RENDERER
, EValidatorSeverity::VALIDATOR_ERROR
, "FileRead - Corrupt DirEntiy size");
2319 return ReturnType
{};
2321 pData
= std::unique_ptr
<byte
[]>(new byte
[decompressedSize
]);
2322 memcpy(pData
.get(), &buf
[10], decompressedSize
);
2327 return std::make_pair(std::move(pData
), decompressedSize
);
2330 void SShaderDevCache::GetMemoryUsage(ICrySizer
* pSizer
) const
2332 pSizer
->AddObject(this, sizeof(*this));
2333 pSizer
->AddObject(m_DeviceShaders
);
2336 SShaderDevCache
* CHWShader::mfInitDevCache(const char* name
, CHWShader
* pSH
)
2338 SShaderDevCache
* pCache
= NULL
;
2339 FXShaderDevCacheItor it
= m_ShaderDevCache
.find(CCryNameR(name
));
2340 if (it
!= m_ShaderDevCache
.end())
2342 pCache
= it
->second
;
2343 pCache
->m_nRefCount
++;
2347 pCache
= new SShaderDevCache
;
2348 pCache
->m_Name
= name
;
2353 std::unique_ptr
<byte
[]> CHWShader_D3D::mfGetCacheItem(uint32
& nFlags
, int32
& nSize
)
2355 LOADING_TIME_PROFILE_SECTION(gEnv
->pSystem
);
2356 SHWSInstance
* pInst
= m_pCurInst
;
2357 std::unique_ptr
<byte
[]> pData
;
2359 if (!m_pGlobalCache
|| !m_pGlobalCache
->isValid())
2363 mfGenName(pInst
, name
, 128, 1);
2365 CResFile
* rf
= nullptr;
2366 CDirEntry
* de
= nullptr;
2369 bool bAsync
= false;
2370 int n
= CRenderer::CV_r_shadersAllowCompilation
== 0 ? 1 : 2;
2371 for (nCache
= 0; nCache
< n
; nCache
++)
2373 rf
= m_pGlobalCache
->m_pRes
[nCache
];
2376 de
= rf
->mfGetEntry(name
, &bAsync
);
2382 pInst
->m_nCache
= nCache
;
2384 pInst
->m_bAsyncActivating
= false;
2386 // Attempt to cache the whole entry
2387 if (!m_pGlobalCache
->m_pBinary
[nCache
] && CRenderer::CV_r_shaderscacheinmemory
!= 0)
2389 m_pGlobalCache
->ReadResource(rf
, nCache
);
2390 // Needs to be re-read after (re-)opening the cache entry
2391 de
= rf
->mfGetEntry(name
, &bAsync
);
2394 if (m_pGlobalCache
->m_pBinary
[nCache
] && CRenderer::CV_r_shaderscacheinmemory
!= 0)
2398 // Decompress from library
2399 auto pair
= m_pGlobalCache
->DecompressResource(rf
->mfGetVersion(), nCache
, de
->GetOffset(), de
->GetSize(), rf
->RequiresSwapEndianOnRead());
2400 nSize
= static_cast<int32
>(pair
.second
);
2401 pData
= std::move(pair
).first
;
2403 if (CRenderer::CV_r_shadersdebug
== 3 || CRenderer::CV_r_shadersdebug
== 4)
2404 iLog
->Log("---Shader Cache: Loaded from in-memory cache %s: 0x%x", rf
->mfGetFileName(), de
->GetName().get());
2409 nSize
= rf
->mfFileRead(de
);
2410 pInst
->m_bAsyncActivating
= (nSize
== -1);
2411 byte
* pD
= (byte
*)rf
->mfFileGetBuf(de
);
2413 if (pD
&& nSize
> 0)
2415 pData
= std::unique_ptr
<byte
[]>(new byte
[nSize
]);
2416 memcpy(pData
.get(), pD
, nSize
);
2419 rf
->mfFileClose(de
->GetName(), de
->GetFlags());
2421 if (CRenderer::CV_r_shadersdebug
== 3 || CRenderer::CV_r_shadersdebug
== 4)
2422 iLog
->Log("---Shader Cache: Loaded from disk %s: 0x%x", rf
->mfGetFileName(), de
->GetName().get());
2425 if (pData
&& nSize
> 0)
2427 if (CParserBin::m_bEndians
)
2428 SwapEndian(*reinterpret_cast<SShaderCacheHeaderItem
*>(pData
.get()), eBigEndian
);
2429 pInst
->m_DeviceObjectID
= de
->GetName().get();
2431 if (nCache
== CACHE_USER
)
2432 nFlags
|= HWSG_CACHE_USER
;
2437 pInst
->m_bAsyncActivating
= bAsync
;
2442 bool CHWShader_D3D::mfAddCacheItem(SShaderCache
* pCache
, SShaderCacheHeaderItem
* pItem
, const byte
* pData
, int nLen
, bool bFlush
, CCryNameTSCRC Name
)
2446 if (!pCache
->m_pRes
[CACHE_USER
])
2449 if (CRenderer::CV_r_shadersdebug
== 3 || CRenderer::CV_r_shadersdebug
== 4)
2450 iLog
->Log("---Cache: StoredToGlobal %s': 0x%x", pCache
->m_pRes
[CACHE_USER
]->mfGetFileName(), Name
.get());
2452 pItem
->m_CRC32
= CCrc32::Compute(pData
, nLen
);
2453 //CryLog("Size: %d: CRC: %x", nLen, pItem->m_CRC32);
2455 byte
* pNew
= new byte
[sizeof(SShaderCacheHeaderItem
) + nLen
];
2456 if (CParserBin::m_bEndians
)
2458 SShaderCacheHeaderItem IT
= *pItem
;
2459 SwapEndian(IT
, eBigEndian
);
2460 memcpy(pNew
, &IT
, sizeof(SShaderCacheHeaderItem
));
2463 memcpy(pNew
, pItem
, sizeof(SShaderCacheHeaderItem
));
2464 memcpy(&pNew
[sizeof(SShaderCacheHeaderItem
)], pData
, nLen
);
2466 CDirEntry
de(Name
, nLen
+ sizeof(SShaderCacheHeaderItem
), RF_COMPRESS
| RF_TEMPDATA
);
2467 pCache
->m_pRes
[CACHE_USER
]->mfFileAdd(&de
);
2468 SDirEntryOpen
* pOE
= pCache
->m_pRes
[CACHE_USER
]->mfOpenEntry(de
.GetName());
2472 pCache
->m_pRes
[CACHE_USER
]->mfFlush();
2474 // Also evict in-memory image of user cache
2475 pCache
->m_pBinary
[CACHE_USER
] = nullptr;
2481 std::vector
<SEmptyCombination
> SEmptyCombination::s_Combinations
;
2483 bool CHWShader_D3D::mfAddEmptyCombination(CShader
* pSH
, uint64 nRT
, uint64 nGL
, uint32 nLT
, const SCacheCombination
& cmbSaved
)
2485 SEmptyCombination Comb
;
2486 Comb
.nGLNew
= m_nMaskGenShader
;
2487 Comb
.nRTNew
= cmbSaved
.Ident
.m_RTMask
& m_nMaskAnd_RT
| m_nMaskOr_RT
;
2488 Comb
.nLTNew
= cmbSaved
.Ident
.m_LightMask
;
2490 Comb
.nRTOrg
= nRT
& m_nMaskAnd_RT
| m_nMaskOr_RT
;
2492 Comb
.nMD
= cmbSaved
.Ident
.m_MDMask
;
2493 Comb
.nMDV
= cmbSaved
.Ident
.m_MDVMask
;
2494 if (m_eSHClass
== eHWSC_Pixel
)
2496 Comb
.nMD
&= ~HWMD_TEXCOORD_FLAG_MASK
;
2500 Comb
.pShader
= this;
2501 if (Comb
.nRTNew
!= Comb
.nRTOrg
|| Comb
.nGLNew
!= Comb
.nGLOrg
|| Comb
.nLTNew
!= Comb
.nLTOrg
)
2502 SEmptyCombination::s_Combinations
.push_back(Comb
);
2504 m_nMaskGenShader
= nGL
;
2509 bool CHWShader_D3D::mfStoreEmptyCombination(CShader
* pSH
, SEmptyCombination
& Comb
)
2511 if (!m_pGlobalCache
|| !m_pGlobalCache
->m_pRes
[CACHE_USER
])
2514 CResFile
* rf
= m_pGlobalCache
->m_pRes
[CACHE_USER
];
2517 SShaderCombIdent Ident
;
2518 Ident
.m_GLMask
= Comb
.nGLNew
;
2519 Ident
.m_RTMask
= Comb
.nRTNew
;
2520 Ident
.m_LightMask
= Comb
.nLTNew
;
2521 Ident
.m_MDMask
= Comb
.nMD
;
2522 Ident
.m_MDVMask
= Comb
.nMDV
;
2523 SHWSInstance
* pInstNew
= mfGetInstance(pSH
, Ident
, 0);
2524 mfGenName(pInstNew
, nameNew
, 128, 1);
2525 CDirEntry
* deNew
= rf
->mfGetEntry(nameNew
);
2530 Ident
.m_GLMask
= Comb
.nGLOrg
;
2531 Ident
.m_RTMask
= Comb
.nRTOrg
;
2532 Ident
.m_LightMask
= Comb
.nLTOrg
;
2533 Ident
.m_MDMask
= Comb
.nMD
;
2534 Ident
.m_MDVMask
= Comb
.nMDV
;
2535 SHWSInstance
* pInstOrg
= mfGetInstance(pSH
, Ident
, 0);
2536 mfGenName(pInstOrg
, nameOrg
, 128, 1);
2537 CDirEntry
* deOrg
= rf
->mfGetEntry(nameOrg
);
2540 if (deOrg
->GetOffset() != deNew
->GetOffset())
2541 deOrg
->MarkNotSaved();
2543 // Also evict in-memory image of user cache
2544 m_pGlobalCache
->m_pBinary
[CACHE_USER
] = nullptr;
2548 CDirEntry
de(nameOrg
, deNew
->GetSize(), deNew
->GetOffset(), deNew
->GetFlags());
2555 bool CHWShader_D3D::mfFlushCacheFile()
2559 for (i
= 0; i
< m_Insts
.size(); i
++)
2561 SHWSInstance
* pInst
= m_Insts
[i
];
2562 if (pInst
->m_Handle
.m_bStatus
== 2) // Fake
2564 pInst
->m_Handle
.SetShader(NULL
);
2568 // Also evict in-memory image of user cache
2570 m_pGlobalCache
->m_pBinary
[CACHE_USER
] = nullptr;
2572 return m_pGlobalCache
&& m_pGlobalCache
->m_pRes
[CACHE_USER
] && m_pGlobalCache
->m_pRes
[CACHE_USER
]->mfFlush();
2582 bool needsProcessing
;
2585 bool operator<(const SData
& o
) const
2587 return Name
< o
.Name
;
2590 #if CRY_PLATFORM_DESKTOP
2591 // Remove shader duplicates
2592 bool CHWShader::mfOptimiseCacheFile(SShaderCache
* pCache
, bool bForce
, SOptimiseStats
* pStats
)
2594 CResFile
* pRes
= pCache
->m_pRes
[CACHE_USER
];
2596 ResDir
* Dir
= pRes
->mfGetDirectory();
2600 mfValidateDirEntries(pRes
);
2601 mfValidateTokenData(pRes
);
2604 std::vector
<SData
> Data
;
2607 pStats
->nEntries
+= Dir
->size();
2609 for (i
= 0; i
< Dir
->size(); i
++)
2611 CDirEntry
* pDE
= &(*Dir
)[i
];
2612 if (!pDE
->IsValid())
2615 if (pDE
->GetFlags() & RF_RES_$
)
2617 if (pDE
->GetName() == CShaderMan::s_cNameHEAD
)
2621 d
.nSizeComp
= d
.nSizeDecomp
= 0;
2622 d
.pData
= pRes
->mfFileReadCompressed(pDE
, d
.nSizeDecomp
, d
.nSizeComp
);
2623 assert(d
.pData
&& d
.nSizeComp
&& d
.nSizeDecomp
);
2624 if (!d
.pData
|| !d
.nSizeComp
|| !d
.nSizeDecomp
)
2627 pStats
->nTokenDataSize
+= d
.nSizeDecomp
;
2629 d
.needsProcessing
= false;
2630 d
.Name
= pDE
->GetName();
2631 d
.flags
= pDE
->GetFlags();
2637 d
.flags
= pDE
->GetFlags();
2638 d
.nSizeComp
= d
.nSizeDecomp
= 0;
2639 d
.pData
= pRes
->mfFileReadCompressed(pDE
, d
.nSizeDecomp
, d
.nSizeComp
);
2640 assert(d
.pData
&& d
.nSizeComp
&& d
.nSizeDecomp
);
2641 if (!d
.pData
|| !d
.nSizeComp
|| !d
.nSizeDecomp
)
2643 d
.nOffset
= pDE
->GetOffset();
2644 d
.needsProcessing
= true;
2645 d
.Name
= pDE
->GetName();
2647 pRes
->mfCloseEntry(pDE
->GetName(), pDE
->GetFlags());
2651 int nOutFiles
= Data
.size();
2653 // detect duplicates
2654 for (i
= 0; i
< Data
.size(); i
++)
2656 if (!Data
[i
].needsProcessing
)
2659 Data
[i
].needsProcessing
= false;
2660 int nSizeComp
= Data
[i
].nSizeComp
;
2661 int nSizeDecomp
= Data
[i
].nSizeDecomp
;
2662 for (j
= i
+ 1; j
< Data
.size(); j
++)
2664 if (!Data
[j
].needsProcessing
)
2667 if (nSizeComp
!= Data
[j
].nSizeComp
|| nSizeDecomp
!= Data
[j
].nSizeDecomp
)
2670 if (!memcmp(Data
[i
].pData
, Data
[j
].pData
, nSizeComp
))
2672 Data
[j
].needsProcessing
= false;
2673 Data
[j
].nOffset
= Data
[i
].nOffset
;
2674 Data
[j
].flags
|= RF_DUPLICATE
;
2680 if (nOutFiles
!= Data
.size() || CRenderer::CV_r_shaderscachedeterministic
)
2682 if (nOutFiles
== Data
.size())
2684 iLog
->Log(" Forcing optimise for deterministic order...");
2687 iLog
->Log(" Optimising shaders resource '%s' (%" PRISIZE_T
" items)...", pCache
->m_Name
.c_str(), Data
.size() - 1);
2690 pRes
->mfOpen(RA_CREATE
| (CParserBin::m_bEndians
? RA_ENDIANS
: 0), &gRenDev
->m_cEF
.m_ResLookupDataMan
[CACHE_USER
]);
2692 float fVersion
= FX_CACHE_VER
;
2693 uint32 nMinor
= (int)(((float)fVersion
- (float)(int)fVersion
) * 10.1f
);
2694 uint32 nMajor
= (int)fVersion
;
2696 SResFileLookupData
* pLookupCache
= pCache
->m_pRes
[CACHE_USER
]->GetLookupData(false, 0, 0);
2697 CRY_ASSERT(pLookupCache
!= NULL
);
2699 if (pLookupCache
== NULL
|| pLookupCache
->m_CacheMajorVer
!= nMajor
|| pLookupCache
->m_CacheMinorVer
!= nMinor
)
2701 CRY_ASSERT_MESSAGE(pLookupCache
== NULL
, "Losing ShaderIdents by recreating lookupdata cache");
2702 pLookupCache
= pRes
->GetLookupData(true, 0, (float)FX_CACHE_VER
);
2707 if (CRenderer::CV_r_shaderscachedeterministic
)
2708 std::sort(Data
.begin(), Data
.end());
2710 for (i
= 0; i
< Data
.size(); i
++)
2712 SData
* pD
= &Data
[i
];
2715 if (pD
->flags
& RF_RES_$
)
2717 de
= CDirEntry(pD
->Name
, pD
->nSizeDecomp
, pD
->flags
);
2718 SDirEntryOpen
* pOE
= pRes
->mfOpenEntry(pD
->Name
);
2719 pOE
->pData
= pD
->pData
;
2721 else if (pD
->flags
& RF_DUPLICATE
)
2723 de
= CDirEntry(pD
->Name
, pD
->nSizeComp
+ 4, pD
->nOffset
, pD
->flags
| RF_COMPRESS
);
2724 SAFE_DELETE_ARRAY(pD
->pData
);
2730 pStats
->nSizeUncompressed
+= pD
->nSizeDecomp
;
2731 pStats
->nSizeCompressed
+= pD
->nSizeComp
;
2732 pStats
->nUniqueEntries
++;
2737 de
= CDirEntry(pD
->Name
, pD
->nSizeComp
+ 4, pD
->nOffset
, pD
->flags
| RF_TEMPDATA
| RF_COMPRESS
| RF_COMPRESSED
);
2739 SDirEntryOpen
* pOE
= pRes
->mfOpenEntry(pD
->Name
);
2740 byte
* pData
= new byte
[de
.GetSize()];
2741 uint32 nSize
= pD
->nSizeDecomp
;
2742 memcpy(pData
, &nSize
, sizeof(uint32
));
2743 memcpy(pData
+sizeof(uint32
), pD
->pData
, pD
->nSizeComp
);
2745 SAFE_DELETE_ARRAY(pD
->pData
);
2748 pRes
->mfFileAdd(&de
);
2752 if (nOutFiles
!= Data
.size())
2753 iLog
->Log(" -- Removed %" PRISIZE_T
" duplicated shaders", Data
.size() - nOutFiles
);
2756 int nSizeDir
= pRes
->mfFlush();
2757 //int nSizeCompr = pRes->mfFlush();
2760 mfValidateTokenData(pRes
);
2764 pStats
->nDirDataSize
+= nSizeDir
;
2766 for (i
= 0; i
< Data
.size(); i
++)
2768 SData
* pD
= &Data
[i
];
2769 SAFE_DELETE_ARRAY(pD
->pData
);
2773 CryLog(" -- Shader cache '%s' stats: Entries: %d, Unique Entries: %d, Size: %.3f Mb, Compressed Size: %.3f Mb, Token data size: %3f Mb, Directory Size: %.3f Mb", pCache
->m_Name
.c_str(), pStats
->nEntries
, pStats
->nUniqueEntries
, pStats
->nSizeUncompressed
/ 1024.0f
/ 1024.0f
, pStats
->nSizeCompressed
/ 1024.0f
/ 1024.0f
, pStats
->nTokenDataSize
/ 1024.0f
/ 1024.0f
, pStats
->nDirDataSize
/ 1024.0f
/ 1024.0f
);
2779 int __cdecl
sSort(const VOID
* arg1
, const VOID
* arg2
)
2781 CDirEntry
** pi1
= (CDirEntry
**)arg1
;
2782 CDirEntry
** pi2
= (CDirEntry
**)arg2
;
2783 CDirEntry
* ti1
= *pi1
;
2784 CDirEntry
* ti2
= *pi2
;
2785 if (ti1
->GetName() < ti2
->GetName())
2787 if (ti1
->GetName() == ti2
->GetName())
2792 bool CHWShader::_OpenCacheFile(float fVersion
, SShaderCache
* pCache
, CHWShader
* pSH
, bool bCheckValid
, uint32 CRC32
, int nCache
, CResFile
* pRF
, bool bReadOnly
)
2794 assert(nCache
== CACHE_USER
|| nCache
== CACHE_READONLY
);
2797 CHWShader_D3D
* pSHHW
= (CHWShader_D3D
*)pSH
;
2798 int nRes
= pRF
->mfOpen(RA_READ
| (CParserBin::m_bEndians
? RA_ENDIANS
: 0), &gRenDev
->m_cEF
.m_ResLookupDataMan
[nCache
], (nCache
== CACHE_READONLY
&& pCache
->m_pStreamInfo
) ? pCache
->m_pStreamInfo
: NULL
);
2808 SResFileLookupData
* pLookup
= pRF
->GetLookupData(false, 0, 0);
2811 else if (bCheckValid
)
2813 if (fVersion
&& (pLookup
->m_CacheMajorVer
!= (int)fVersion
|| pLookup
->m_CacheMinorVer
!= (int)(((float)fVersion
- (float)(int)fVersion
) * 10.1f
)))
2815 if (!bValid
&& (CRenderer::CV_r_shadersdebug
== 2 || nCache
== CACHE_READONLY
))
2817 LogWarningEngineOnly("WARNING: Shader cache '%s' version mismatch (Cache: %d.%d, Expected: %.1f)", pRF
->mfGetFileName(), pLookup
->m_CacheMajorVer
, pLookup
->m_CacheMinorVer
, fVersion
);
2821 if (bValid
&& pLookup
->m_CRC32
!= pSHHW
->m_CRC32
)
2824 if (CRenderer::CV_r_shadersdebug
== 2 && (CRenderer::CV_r_shadersdebug
== 2 || nCache
== CACHE_READONLY
))
2826 LogWarningEngineOnly("WARNING: Shader cache '%s' CRC mismatch", pRF
->mfGetFileName());
2833 if (nCache
== CACHE_USER
)
2838 int nAcc
= CRenderer::CV_r_shadersAllowCompilation
!= 0 ? (RA_READ
| RA_WRITE
) : RA_READ
;
2839 if (!pRF
->mfOpen(nAcc
| (CParserBin::m_bEndians
? RA_ENDIANS
: 0), &gRenDev
->m_cEF
.m_ResLookupDataMan
[nCache
]))
2847 if (!bValid
&& bCheckValid
)
2849 if (nCache
== CACHE_USER
&& !bReadOnly
)
2851 if (!pRF
->mfOpen(RA_CREATE
| (CParserBin::m_bEndians
? RA_ENDIANS
: 0), &gRenDev
->m_cEF
.m_ResLookupDataMan
[nCache
]))
2858 SResFileLookupData
* pLookup
= pRF
->GetLookupData(true, CRC32
, (float)FX_CACHE_VER
);
2861 pCache
->m_bNeedPrecache
= true;
2869 pCache
->m_pRes
[nCache
] = pRF
;
2870 pCache
->m_bReadOnly
[nCache
] = bReadOnly
;
2873 mfValidateTokenData(pRF
);
2879 bool CHWShader::mfOpenCacheFile(const char* szName
, float fVersion
, SShaderCache
* pCache
, CHWShader
* pSH
, bool bCheckValid
, uint32 CRC32
, bool bReadOnly
)
2881 bool bValidRO
= false;
2882 bool bValidUser
= true;
2883 // don't load the readonly cache, when shaderediting is true
2884 if (!CRenderer::CV_r_shadersediting
&& !pCache
->m_pRes
[CACHE_READONLY
])
2886 stack_string szEngine
= stack_string("%ENGINE%/") + stack_string(szName
);
2887 CResFile
* rfRO
= new CResFile(szEngine
);
2888 bool bRO
= bReadOnly
;
2889 if (!CRenderer::CV_r_shadersAllowCompilation
)
2891 bValidRO
= _OpenCacheFile(fVersion
, pCache
, pSH
, bCheckValid
, CRC32
, CACHE_READONLY
, rfRO
, bRO
);
2893 if (!CRenderer::CV_r_shadersAllowCompilation
)
2897 if ((!bReadOnly
|| gRenDev
->IsShaderCacheGenMode()) && !pCache
->m_pRes
[CACHE_USER
])
2899 stack_string szUser
= stack_string(gRenDev
->m_cEF
.m_szUserPath
.c_str()) + stack_string(szName
);
2900 CResFile
* rfUser
= new CResFile(szUser
.c_str());
2901 bValidUser
= _OpenCacheFile(fVersion
, pCache
, pSH
, bCheckValid
, CRC32
, CACHE_USER
, rfUser
, bReadOnly
);
2904 return (bValidRO
|| bValidUser
);
2907 SShaderCache
* CHWShader::mfInitCache(const char* name
, CHWShader
* pSH
, bool bCheckValid
, uint32 CRC32
, bool bReadOnly
, bool bAsync
)
2909 // LOADING_TIME_PROFILE_SECTION(iSystem);
2911 CHWShader_D3D
* pSHHW
= (CHWShader_D3D
*)pSH
;
2913 if (!CRenderer::CV_r_shadersAllowCompilation
)
2914 bCheckValid
= false;
2916 if (CRenderer::CV_r_shadersediting
)
2922 pSHHW
->mfGetDstFileName(pSHHW
->m_pCurInst
, pSHHW
, namedst
, 256, 0);
2923 PathUtil::ReplaceExtension(namedst
, "fxcb");
2927 SShaderCache
* pCache
= NULL
;
2928 FXShaderCacheItor it
= m_ShaderCache
.find(CCryNameR(name
));
2929 if (it
!= m_ShaderCache
.end())
2931 pCache
= it
->second
;
2937 int nCache
[2] = { -1, -1 };
2938 if (!CRenderer::CV_r_shadersAllowCompilation
)
2939 nCache
[0] = CACHE_READONLY
;
2942 nCache
[0] = CACHE_USER
;
2943 nCache
[1] = CACHE_READONLY
;
2946 for (int i
= 0; i
< 2; i
++)
2948 if (nCache
[i
] < 0 || !pCache
->m_pRes
[i
])
2950 CResFile
* pRF
= pCache
->m_pRes
[i
];
2951 SResFileLookupData
* pLookup
= pRF
->GetLookupData(false, 0, (float)FX_CACHE_VER
);
2952 bValid
= (pLookup
&& pLookup
->m_CRC32
== CRC32
);
2955 SAFE_DELETE(pCache
->m_pRes
[i
]);
2959 if (!CRenderer::CV_r_shadersAllowCompilation
&& !pCache
->m_pRes
[CACHE_READONLY
])
2963 if (bReadOnly
&& (!pCache
->m_pRes
[CACHE_READONLY
] || !pCache
->m_pRes
[CACHE_USER
]))
2965 if (!bReadOnly
&& !pCache
->m_pRes
[CACHE_USER
])
2970 mfOpenCacheFile(name
, (float)FX_CACHE_VER
, pCache
, pSH
, bCheckValid
, CRC32
, bReadOnly
);
2977 pCache
= new SShaderCache
;
2979 pCache
->m_pStreamInfo
= new SResStreamInfo(pCache
);
2980 pCache
->m_nPlatform
= CParserBin::m_nPlatform
;
2981 pCache
->m_Name
= name
;
2982 mfOpenCacheFile(name
, (float)FX_CACHE_VER
, pCache
, pSH
, bCheckValid
, CRC32
, bReadOnly
);
2983 m_ShaderCache
.insert(FXShaderCacheItor::value_type(CCryNameR(name
), pCache
));
2989 byte
* CHWShader_D3D::mfBindsToCache(SHWSInstance
* pInst
, std::vector
<SCGBind
>* Binds
, int nParams
, byte
* pP
)
2992 for (i
= 0; i
< nParams
; i
++)
2994 SCGBind
* cgb
= &(*Binds
)[i
];
2995 SShaderCacheHeaderItemVar
* pVar
= (SShaderCacheHeaderItemVar
*)pP
;
2996 pVar
->m_nCount
= cgb
->m_nParameters
;
2997 pVar
->m_Reg
= cgb
->m_dwBind
;
2998 if (CParserBin::m_bEndians
)
3000 SwapEndian(pVar
->m_nCount
, eBigEndian
);
3001 SwapEndian(pVar
->m_Reg
, eBigEndian
);
3003 int len
= strlen(cgb
->m_Name
.c_str()) + 1;
3004 memcpy(pVar
->m_Name
, cgb
->m_Name
.c_str(), len
);
3005 pP
+= offsetof(SShaderCacheHeaderItemVar
, m_Name
) + strlen(pVar
->m_Name
) + 1;
3010 byte
* CHWShader_D3D::mfBindsFromCache(std::vector
<SCGBind
>*& Binds
, int nParams
, byte
* pP
)
3013 for (i
= 0; i
< nParams
; i
++)
3016 Binds
= new std::vector
<SCGBind
>;
3018 SShaderCacheHeaderItemVar
* pVar
= (SShaderCacheHeaderItemVar
*)pP
;
3020 short nParameters
= pVar
->m_nCount
;
3021 if (CParserBin::m_bEndians
)
3022 SwapEndian(nParameters
, eBigEndian
);
3023 cgb
.m_nParameters
= nParameters
;
3025 cgb
.m_Name
= pVar
->m_Name
;
3027 int dwBind
= pVar
->m_Reg
;
3028 if (CParserBin::m_bEndians
)
3029 SwapEndian(dwBind
, eBigEndian
);
3030 cgb
.m_dwBind
= dwBind
;
3032 Binds
->push_back(cgb
);
3033 pP
+= offsetof(SShaderCacheHeaderItemVar
, m_Name
) + strlen(pVar
->m_Name
) + 1;
3038 byte
* CHWShader::mfIgnoreBindsFromCache(int nParams
, byte
* pP
)
3041 for (i
= 0; i
< nParams
; i
++)
3043 SShaderCacheHeaderItemVar
* pVar
= (SShaderCacheHeaderItemVar
*)pP
;
3044 pP
+= offsetof(SShaderCacheHeaderItemVar
, m_Name
) + strlen(pVar
->m_Name
) + 1;
3049 bool CHWShader_D3D::mfUploadHW(SHWSInstance
* pInst
, byte
* pBuf
, uint32 nSize
, CShader
* pSH
, uint32 nFlags
)
3051 PROFILE_FRAME(Shader_mfUploadHW
);
3053 const char* sHwShaderName
= _HELP("Vertex Shader");
3054 if (m_eSHClass
== eHWSC_Pixel
)
3055 sHwShaderName
= _HELP("Pixel Shader");
3056 MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_D3D
, 0, "D3D HW %s", sHwShaderName
);
3059 if (!pInst
->m_Handle
.m_pShader
)
3060 pInst
->m_Handle
.SetShader(new SD3DShader
);
3062 assert(pInst
->m_Handle
.m_pShader
!= nullptr);
3064 if ((m_eSHClass
== eHWSC_Vertex
) && (!(nFlags
& HWSF_PRECACHE
)) && !pInst
->m_bFallback
)
3065 mfUpdateFXVertexFormat(pInst
, pSH
);
3067 pInst
->m_Shader
.m_nDataSize
= nSize
;
3068 if (m_eSHClass
== eHWSC_Pixel
)
3069 s_nDevicePSDataSize
+= nSize
;
3071 s_nDeviceVSDataSize
+= nSize
;
3073 if (m_eSHClass
== eHWSC_Pixel
)
3074 hr
= (pInst
->m_Handle
.m_pShader
->m_pHandle
= GetDeviceObjectFactory().CreatePixelShader(pBuf
, nSize
)) ? S_OK
: E_FAIL
;
3075 else if (m_eSHClass
== eHWSC_Vertex
)
3076 hr
= (pInst
->m_Handle
.m_pShader
->m_pHandle
= GetDeviceObjectFactory().CreateVertexShader(pBuf
, nSize
)) ? S_OK
: E_FAIL
;
3077 else if (m_eSHClass
== eHWSC_Geometry
)
3079 #if 1 // use 0 for FastGS emulation mode
3080 if (m_Flags
& HWSG_GS_MULTIRES
)
3082 #if defined(USE_NV_API) && (CRY_RENDERER_DIRECT3D >= 110) && (CRY_RENDERER_DIRECT3D < 120)
3083 if (CVrProjectionManager::IsMultiResEnabledStatic())
3085 NvAPI_D3D11_CREATE_FASTGS_EXPLICIT_DESC FastGSArgs
= { NVAPI_D3D11_CREATEFASTGSEXPLICIT_VER
, NV_FASTGS_USE_VIEWPORT_MASK
};
3086 NvAPI_Status Status
= NvAPI_D3D11_CreateFastGeometryShaderExplicit(gcpRendD3D
->GetDevice().GetRealDevice(), alias_cast
<DWORD
*>(pBuf
), nSize
, NULL
, &FastGSArgs
, alias_cast
<ID3D11GeometryShader
**>(&pInst
->m_Handle
.m_pShader
->m_pHandle
));
3087 hr
= (Status
== NVAPI_OK
) ? S_OK
: E_FAIL
;
3092 pInst
->m_Handle
.m_pShader
->m_bDisabled
= true;
3093 pInst
->m_Handle
.m_pShader
->m_pHandle
= nullptr;
3100 hr
= (pInst
->m_Handle
.m_pShader
->m_pHandle
= GetDeviceObjectFactory().CreateGeometryShader(pBuf
, nSize
)) ? S_OK
: E_FAIL
;
3103 else if (m_eSHClass
== eHWSC_Hull
)
3104 hr
= (pInst
->m_Handle
.m_pShader
->m_pHandle
= GetDeviceObjectFactory().CreateHullShader(pBuf
, nSize
)) ? S_OK
: E_FAIL
;
3105 else if (m_eSHClass
== eHWSC_Compute
)
3106 hr
= (pInst
->m_Handle
.m_pShader
->m_pHandle
= GetDeviceObjectFactory().CreateComputeShader(pBuf
, nSize
)) ? S_OK
: E_FAIL
;
3107 else if (m_eSHClass
== eHWSC_Domain
)
3108 hr
= (pInst
->m_Handle
.m_pShader
->m_pHandle
= GetDeviceObjectFactory().CreateDomainShader(pBuf
, nSize
)) ? S_OK
: E_FAIL
;
3114 if (pInst
->m_Handle
.m_pShader
->m_pHandle
)
3116 #if defined(ORBIS_GPU_DEBUGGER_SUPPORT) && !CRY_RENDERER_GNM
3118 cry_sprintf(name
, "%s_%s(LT%x)@(RT%llx)(MD%x)(MDV%x)(GL%llx)(PSS%llx)", pSH
->GetName(), m_EntryFunc
.c_str(), pInst
->m_Ident
.m_LightMask
, pInst
->m_Ident
.m_RTMask
, pInst
->m_Ident
.m_MDMask
, pInst
->m_Ident
.m_MDVMask
, pInst
->m_Ident
.m_GLMask
, pInst
->m_Ident
.m_pipelineState
.opaque
);
3119 ((CCryDXOrbisShader
*)pInst
->m_Handle
.m_pShader
->m_pHandle
)->RegisterWithGPUDebugger(name
);
3122 // Assign name to Shader for enhanced debugging
3123 #if !defined(RELEASE) && (CRY_PLATFORM_WINDOWS || CRY_PLATFORM_ORBIS)
3125 sprintf(name
, "%s_%s(LT%x)@(RT%llx)(MD%x)(MDV%x)(GL%llx)(PSS%llx)", pSH
->GetName(), m_EntryFunc
.c_str(), pInst
->m_Ident
.m_LightMask
, pInst
->m_Ident
.m_RTMask
, pInst
->m_Ident
.m_MDMask
, pInst
->m_Ident
.m_MDVMask
, pInst
->m_Ident
.m_GLMask
, pInst
->m_Ident
.m_pipelineState
.opaque
);
3126 #if CRY_PLATFORM_WINDOWS
3127 #if CRY_RENDERER_DIRECT3D
3128 ((ID3D11DeviceChild
*)pInst
->m_Handle
.m_pShader
->m_pHandle
)->SetPrivateData(WKPDID_D3DDebugObjectName
, strlen(name
), name
);
3129 #elif CRY_RENDERER_VULKAN
3130 reinterpret_cast<NCryVulkan::CShader
*>(pInst
->m_Handle
.m_pShader
->m_pHandle
)->DebugSetName(name
);
3132 #elif CRY_PLATFORM_ORBIS && !CRY_RENDERER_GNM
3133 ((CCryDXOrbisShader
*)pInst
->m_Handle
.m_pShader
->m_pHandle
)->DebugSetName(name
);
3138 return (hr
== S_OK
);
3141 bool CHWShader_D3D::mfUploadHW(D3DBlob
* pShader
, SHWSInstance
* pInst
, CShader
* pSH
, uint32 nFlags
)
3143 bool bResult
= true;
3144 if (m_eSHClass
== eHWSC_Vertex
&& !pInst
->m_bFallback
)
3145 mfUpdateFXVertexFormat(pInst
, pSH
);
3146 if (pShader
&& !(m_Flags
& HWSG_PRECACHEPHASE
))
3148 DWORD
* pCode
= (DWORD
*)pShader
->GetBufferPointer();
3149 if (gcpRendD3D
->m_cEF
.m_nCombinationsProcess
>= 0)
3151 pInst
->m_Handle
.SetFake();
3155 bResult
= mfUploadHW(pInst
, (byte
*)pCode
, (uint32
)pShader
->GetBufferSize(), pSH
, nFlags
);
3156 if (m_eSHClass
== eHWSC_Vertex
)
3158 size_t nSize
= pShader
->GetBufferSize();
3159 pInst
->m_Shader
.m_pShaderData
= new byte
[nSize
];
3160 pInst
->m_Shader
.m_nDataSize
= nSize
;
3161 memcpy(pInst
->m_Shader
.m_pShaderData
, pCode
, nSize
);
3166 if (m_eSHClass
== eHWSC_Vertex
)
3167 Warning("CHWShader_D3D::mfUploadHW: Could not create vertex shader '%s'(0x%" PRIx64
")\n", GetName(), pInst
->m_Ident
.m_GLMask
);
3168 else if (m_eSHClass
== eHWSC_Pixel
)
3169 Warning("CHWShader_D3D::mfUploadHW: Could not create pixel shader '%s'(0x%" PRIx64
")\n", GetName(), pInst
->m_Ident
.m_GLMask
);
3170 else if (m_eSHClass
== eHWSC_Geometry
)
3171 Warning("CHWShader_D3D::mfUploadHW: Could not create geometry shader '%s'(0x%" PRIx64
")\n", GetName(), pInst
->m_Ident
.m_GLMask
);
3172 else if (m_eSHClass
== eHWSC_Domain
)
3173 Warning("CHWShader_D3D::mfUploadHW: Could not create domain shader '%s'(0x%" PRIx64
")\n", GetName(), pInst
->m_Ident
.m_GLMask
);
3174 else if (m_eSHClass
== eHWSC_Hull
)
3175 Warning("CHWShader_D3D::mfUploadHW: Could not create hull shader '%s'(0x%" PRIx64
")\n", GetName(), pInst
->m_Ident
.m_GLMask
);
3176 else if (m_eSHClass
== eHWSC_Compute
)
3177 Warning("CHWShader_D3D::mfUploadHW: Could not create compute shader '%s'(0x%" PRIx64
")\n", GetName(), pInst
->m_Ident
.m_GLMask
);
3183 bool CHWShader_D3D::mfActivateCacheItem(CShader
* pSH
, SShaderCacheHeaderItem
* pItem
, uint32 nSize
, uint32 nFlags
)
3185 SHWSInstance
* pInst
= m_pCurInst
;
3186 byte
* pData
= (byte
*)pItem
;
3187 pData
+= sizeof(SShaderCacheHeaderItem
);
3189 std::vector
<SCGBind
>* pInstBinds
= NULL
;
3190 pInst
->Release(m_pDevCache
, false);
3191 pBuf
= mfBindsFromCache(pInstBinds
, pItem
->m_nInstBinds
, pBuf
);
3192 nSize
-= (uint32
)(pBuf
- (byte
*)pItem
);
3193 pInst
->m_eClass
= (EHWShaderClass
)pItem
->m_Class
;
3194 pInst
->m_nVertexFormat
= pItem
->m_nVertexFormat
;
3195 pInst
->m_nInstructions
= pItem
->m_nInstructions
;
3196 pInst
->m_VStreamMask_Decl
= pItem
->m_StreamMask_Decl
;
3197 pInst
->m_VStreamMask_Stream
= pItem
->m_StreamMask_Stream
;
3198 bool bResult
= true;
3199 SD3DShader
* pHandle
= NULL
;
3200 SShaderDevCache
* pCache
= m_pDevCache
;
3201 if (!(nFlags
& HWSG_CACHE_USER
))
3205 FXDeviceShaderItor it
= pCache
->m_DeviceShaders
.find(pInst
->m_DeviceObjectID
);
3206 if (it
!= pCache
->m_DeviceShaders
.end())
3207 pHandle
= it
->second
;
3213 pInst
->m_Handle
.SetShader(pHandle
);
3214 pInst
->m_Handle
.AddRef();
3216 #if CRY_PLATFORM_ORBIS || CRY_PLATFORM_DURANGO || CRY_RENDERER_VULKAN
3217 if (m_eSHClass
== eHWSC_Vertex
)
3220 D3DCreateBlob(nSize
, (D3DBlob
**)&pS
);
3221 DWORD
* pBuffer
= (DWORD
*)pS
->GetBufferPointer();
3222 memcpy(pBuffer
, pBuf
, nSize
);
3223 mfVertexFormat(pInst
, this, pS
, nullptr);
3227 if ((m_eSHClass
== eHWSC_Vertex
) && (!(nFlags
& HWSF_PRECACHE
)) && !pInst
->m_bFallback
)
3228 mfUpdateFXVertexFormat(pInst
, pSH
);
3232 if (gcpRendD3D
->m_cEF
.m_nCombinationsProcess
> 0)
3234 pInst
->m_Handle
.SetFake();
3238 #if CRY_PLATFORM_ORBIS || CRY_PLATFORM_DURANGO || CRY_RENDERER_VULKAN
3239 if (m_eSHClass
== eHWSC_Vertex
)
3242 D3DCreateBlob(nSize
, (D3DBlob
**)&pS
);
3243 DWORD
* pBuffer
= (DWORD
*)pS
->GetBufferPointer();
3244 memcpy(pBuffer
, pBuf
, nSize
);
3245 mfVertexFormat(pInst
, this, pS
, nullptr);
3250 bResult
= mfUploadHW(pInst
, pBuf
, nSize
, pSH
, nFlags
);
3254 SAFE_DELETE(pInstBinds
);
3255 assert(!"Shader creation error");
3256 iLog
->Log("WARNING: cannot create shader '%s' (FX: %s)", m_EntryFunc
.c_str(), GetName());
3259 pCache
->m_DeviceShaders
.insert(FXDeviceShaderItor::value_type(pInst
->m_DeviceObjectID
, pInst
->m_Handle
.m_pShader
));
3261 void* pConstantTable
= NULL
;
3262 void* pShaderReflBuf
= NULL
;
3263 hr
= D3DReflect(pBuf
, nSize
, IID_ID3D11ShaderReflection
, &pShaderReflBuf
);
3264 ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pShaderReflBuf
;
3266 pConstantTable
= (void*)pShaderReflection
;
3267 if (m_eSHClass
== eHWSC_Vertex
|| gRenDev
->IsEditorMode())
3269 pInst
->m_Shader
.m_pShaderData
= new byte
[nSize
];
3270 pInst
->m_Shader
.m_nDataSize
= nSize
;
3271 memcpy(pInst
->m_Shader
.m_pShaderData
, pBuf
, nSize
);
3274 bResult
&= (hr
== S_OK
);
3276 mfCreateBinds(pInst
, pConstantTable
, pBuf
, nSize
);
3278 mfGatherFXParameters(pInst
, &pInst
->m_pBindVars
, pInstBinds
, this, 0, pSH
);
3279 SAFE_DELETE(pInstBinds
);
3280 SAFE_RELEASE(pShaderReflection
);
3285 /*CHWShader_D3D::SHWSInstance *g_pInst;
3286 CHWShader_D3D::SHWSInstance g_Inst;
3287 CHWShader_D3D::SHWSInstance *g_pInst0;
3288 CHWShader_D3D::SHWSInstance g_Inst0;
3289 CHWShader_D3D *g_pSH;*/
3291 bool CHWShader_D3D::mfCreateCacheItem(SHWSInstance
* pInst
, std::vector
<SCGBind
>& InstBinds
, byte
* pData
, int nLen
, CHWShader_D3D
* pSH
, bool bShaderThread
)
3293 if (!pSH
->m_pGlobalCache
|| !pSH
->m_pGlobalCache
->m_pRes
[CACHE_USER
])
3295 if (pSH
->m_pGlobalCache
)
3296 pSH
->m_pGlobalCache
->Release(false);
3297 pSH
->m_pGlobalCache
= mfInitCache(NULL
, pSH
, true, pSH
->m_CRC32
, false, false);
3299 assert(pSH
->m_pGlobalCache
);
3300 if (!pSH
->m_pGlobalCache
|| !pSH
->m_pGlobalCache
->m_pRes
[CACHE_USER
])
3303 byte
* byteData
= NULL
;
3304 DWORD
* dwordData
= NULL
;
3306 SShaderCacheHeaderItem h
;
3307 h
.m_nInstBinds
= static_cast<byte
>(InstBinds
.size());
3308 h
.m_nInstructions
= pInst
->m_nInstructions
;
3309 h
.m_nVertexFormat
= pInst
->m_nVertexFormat
;
3310 h
.m_Class
= pData
? pInst
->m_eClass
: 255;
3311 h
.m_StreamMask_Decl
= pInst
->m_VStreamMask_Decl
;
3312 h
.m_StreamMask_Stream
= (byte
)pInst
->m_VStreamMask_Stream
;
3313 int nNewSize
= (h
.m_nInstBinds
) * sizeof(SShaderCacheHeaderItemVar
) + nLen
;
3314 byte
* pNewData
= new byte
[nNewSize
];
3315 byte
* pP
= pNewData
;
3316 pP
= mfBindsToCache(pInst
, &InstBinds
, h
.m_nInstBinds
, pP
);
3317 PREFAST_ASSUME(pData
);
3318 memcpy(pP
, pData
, nLen
);
3323 mfGenName(pInst
, name
, 256, 1);
3324 CCryNameTSCRC nm
= CCryNameTSCRC(name
);
3325 bool bRes
= mfAddCacheItem(pSH
->m_pGlobalCache
, &h
, pNewData
, (int)(pP
- pNewData
), false, nm
);
3326 SAFE_DELETE_ARRAY(pNewData
);
3327 if ((!(pSH
->m_Flags
& HWSG_PRECACHEPHASE
) && gRenDev
->m_cEF
.m_nCombinationsProcess
<= 0))
3329 if (bShaderThread
&& false)
3331 if (pInst
->m_pAsync
)
3332 pInst
->m_pAsync
->m_bPendedFlush
= true;
3335 pSH
->mfFlushCacheFile();
3336 cry_strcpy(name
, pSH
->GetName());
3337 char* s
= strchr(name
, '(');
3340 if (!bShaderThread
|| true)
3343 if (pSH
->m_Flags
& HWSG_FP_EMULATION
)
3345 SShaderCombIdent Ident
= pInst
->m_Ident
;
3347 Ident
.m_GLMask
= pSH
->m_nMaskGenFX
;
3348 gRenDev
->m_cEF
.mfInsertNewCombination(Ident
, pInst
->m_eClass
, name
, 0, NULL
, bStore
);
3351 pInst
->m_nCache
= CACHE_USER
;
3356 //============================================================================
3358 void CHWShader_D3D::mfSaveCGFile(const char* scr
, const char* path
)
3360 if (CRenderer::CV_r_shadersdebug
< 1)
3363 if (path
&& path
[0])
3365 #if defined(__GNUC__)
3366 cry_sprintf(name
, "%s/%s(LT%x)@(RT%llx)(MD%x)(MDV%x)(GL%llx)(PSS%llx).cg", path
, GetName(), m_pCurInst
->m_Ident
.m_LightMask
, m_pCurInst
->m_Ident
.m_RTMask
, m_pCurInst
->m_Ident
.m_MDMask
, m_pCurInst
->m_Ident
.m_MDVMask
, m_pCurInst
->m_Ident
.m_GLMask
, m_pCurInst
->m_Ident
.m_pipelineState
.opaque
);
3368 cry_sprintf(name
, "%s/%s(LT%x)/(RT%I64x)(MD%x)(MDV%x)(GL%I64x)(PSS%llx).cg", path
, GetName(), m_pCurInst
->m_Ident
.m_LightMask
, m_pCurInst
->m_Ident
.m_RTMask
, m_pCurInst
->m_Ident
.m_MDMask
, m_pCurInst
->m_Ident
.m_MDVMask
, m_pCurInst
->m_Ident
.m_GLMask
, m_pCurInst
->m_Ident
.m_pipelineState
.opaque
);
3373 #if defined(__GNUC__)
3374 cry_sprintf(name
, "Shaders/Cache/D3D10/fxerror/%s(GL%llx)@(LT%x)(RT%llx)@(MD%x)(MDV%x)(PSS%llx).cg", GetName(), m_pCurInst
->m_Ident
.m_GLMask
, m_pCurInst
->m_Ident
.m_LightMask
, m_pCurInst
->m_Ident
.m_RTMask
, m_pCurInst
->m_Ident
.m_MDMask
, m_pCurInst
->m_Ident
.m_MDVMask
, m_pCurInst
->m_Ident
.m_pipelineState
.opaque
);
3376 cry_sprintf(name
, "FXError/%s(GL%I64x)/(LT%x)(RT%I64x)/(MD%x)(MDV%x)(PSS%llx).cg", GetName(), m_pCurInst
->m_Ident
.m_GLMask
, m_pCurInst
->m_Ident
.m_LightMask
, m_pCurInst
->m_Ident
.m_RTMask
, m_pCurInst
->m_Ident
.m_MDMask
, m_pCurInst
->m_Ident
.m_MDVMask
, m_pCurInst
->m_Ident
.m_pipelineState
.opaque
);
3382 fp
= gEnv
->pCryPak
->FOpen(name
, "w");
3386 size_t len
= strlen(scr
);
3387 gEnv
->pCryPak
->FWrite(scr
, len
, fp
);
3388 gEnv
->pCryPak
->FClose(fp
);
3392 void CHWShader_D3D::mfOutputCompilerError(string
& strErr
, const char* szSrc
)
3394 if (CRenderer::CV_r_shadersdebug
)
3396 FILE* fp
= fxopen("$$err", "w");
3404 string strE
= strErr
;
3406 size_t newlinePos
= strE
.find('\n');
3408 while (newlinePos
!= string::npos
)
3410 iLog
->LogError("%s", strE
.substr(0, newlinePos
).c_str());
3411 strE
= strE
.substr(newlinePos
+ 1);
3412 newlinePos
= strE
.find('\n');
3416 iLog
->LogError("%s", strE
.c_str());
3419 SShaderAsyncInfo::~SShaderAsyncInfo()
3422 AUTO_LOCK(g_cAILock
);
3427 assert(m_pFXShader
->GetID() >= 0 && m_pFXShader
->GetID() < MAX_REND_SHADERS
);
3429 SAFE_RELEASE(m_pFXShader
);
3430 SAFE_RELEASE(m_pShader
);
3431 SAFE_RELEASE(m_pErrors
);
3433 if (ID3D11ShaderReflection
* pShaderReflection
= static_cast<ID3D11ShaderReflection
*>(m_pConstants
))
3435 pShaderReflection
->Release();
3436 m_pConstants
= nullptr;
3440 // Flush pended or processed shaders (main thread task)
3441 void SShaderAsyncInfo::FlushPendingShaders()
3443 //assert (gRenDev->m_pRT->IsRenderThread());
3445 if (!SShaderAsyncInfo::PendingList().m_Next
)
3447 SShaderAsyncInfo::PendingList().m_Next
= &SShaderAsyncInfo::PendingList();
3448 SShaderAsyncInfo::PendingList().m_Prev
= &SShaderAsyncInfo::PendingList();
3449 SShaderAsyncInfo::PendingListT().m_Next
= &SShaderAsyncInfo::PendingListT();
3450 SShaderAsyncInfo::PendingListT().m_Prev
= &SShaderAsyncInfo::PendingListT();
3453 SShaderAsyncInfo
* pAI
, * pAINext
;
3455 AUTO_LOCK(g_cAILock
);
3456 for (pAI
= PendingListT().m_Next
; pAI
!= &PendingListT(); pAI
= pAINext
)
3458 pAINext
= pAI
->m_Next
;
3460 pAI
->Link(&PendingList());
3464 for (pAI
= PendingList().m_Next
; pAI
!= &PendingList(); pAI
= pAINext
)
3466 pAINext
= pAI
->m_Next
;
3468 CHWShader_D3D
* pSH
= pAI
->m_pShader
;
3471 SShaderCombIdent Ident
;
3472 Ident
.m_GLMask
= pSH
->m_nMaskGenShader
;
3473 Ident
.m_LightMask
= pAI
->m_LightMask
;
3474 Ident
.m_RTMask
= pAI
->m_RTMask
;
3475 Ident
.m_MDMask
= pAI
->m_MDMask
;
3476 Ident
.m_MDVMask
= pAI
->m_MDVMask
;
3477 Ident
.m_pipelineState
.opaque
= pAI
->m_pipelineState
.opaque
;
3478 CHWShader_D3D::SHWSInstance
* pInst
= pSH
->mfGetInstance(pAI
->m_pFXShader
, pAI
->m_nHashInstance
, Ident
);
3481 if (pInst
->m_pAsync
!= pAI
)
3482 CryFatalError("Shader instance async info doesn't match queued async info.");
3483 pSH
->mfAsyncCompileReady(pInst
);
3488 void CShader::mfFlushPendedShaders()
3490 SShaderAsyncInfo::FlushPendingShaders();
3493 void CHWShader::mfFlushPendedShadersWait(int nMaxAllowed
)
3495 if (nMaxAllowed
> 0 && SShaderAsyncInfo::s_nPendingAsyncShaders
< nMaxAllowed
)
3497 if (CRenderer::CV_r_shadersasynccompiling
> 0)
3499 if (!gRenDev
->IsShaderCacheGenMode())
3501 iLog
->Log("Flushing pended shaders...");
3506 if (SShaderAsyncInfo::s_nPendingAsyncShaders
<= 0)
3508 int n
= (int)iTimer
->GetAsyncCurTime();
3513 SShaderAsyncInfo::FlushPendingShaders();
3518 // Compile FXC shaders or next iteration of internal shaders
3519 SShaderAsyncInfo::FlushPendingShaders();
3521 if (SShaderAsyncInfo::s_nPendingAsyncShaders
)
3523 if (!gRenDev
->IsShaderCacheGenMode())
3525 iLog
->Log("Finished flushing pended shaders...");
3530 int CHWShader_D3D::mfAsyncCompileReady(SHWSInstance
* pInst
)
3532 //SHWSInstance *pInst = m_pCurInst;
3533 //assert(pInst->m_pAsync);
3534 if (!pInst
->m_pAsync
)
3537 gRenDev
->m_cEF
.m_ShaderCacheStats
.m_nNumShaderAsyncCompiles
= SShaderAsyncInfo::s_nPendingAsyncShaders
;
3539 SShaderAsyncInfo
* pAsync
= pInst
->m_pAsync
;
3540 int nFrame
= GetCurrentFrameID();
3541 if (pAsync
->m_nFrame
!= nFrame
)
3543 pAsync
->m_nFrame
= nFrame
;
3546 std::vector
<SCGBind
> InstBindVars
;
3547 D3DBlob
* pShader
= NULL
;
3548 D3DBlob
* pErrorMsgs
= NULL
;
3550 char nmDst
[256], nameSrc
[256];
3551 bool bResult
= true;
3554 SShaderTechnique
* pTech
= nullptr;//gRenDev->m_RP.m_pCurTechnique;
3555 CShader
* pSH
= pAsync
->m_pFXShader
;
3557 if (pAsync
->m_bPending
)
3562 if (pSH
->m_fMinVisibleDistance
< pAsync
->m_fMinDistance
)
3563 pAsync
->m_fMinDistance
= pSH
->m_fMinVisibleDistance
;
3566 mfPrintCompileInfo(pInst
);
3568 mfGetDstFileName(pInst
, this, nmDst
, 256, 3);
3569 gEnv
->pCryPak
->AdjustFileName(nmDst
, nameSrc
, 0);
3570 if (pAsync
->m_pFXShader
&& pAsync
->m_pFXShader
->m_HWTechniques
.Num())
3571 pTech
= pAsync
->m_pFXShader
->m_HWTechniques
[0];
3572 if ((pAsync
->m_pErrors
&& !pAsync
->m_Errors
.empty()) || !pAsync
->m_pDevShader
)
3574 if (CRenderer::CV_r_logShaders
)
3575 gcpRendD3D
->LogShv("Async %d: **Failed to compile 0x%x '%s' shader\n", GetCurrentFrameID(), pInst
, nameSrc
);
3576 string Errors
= pAsync
->m_Errors
;
3577 string Text
= pAsync
->m_Text
;
3578 CShader
* pFXShader
= pAsync
->m_pFXShader
;
3579 nRefCount
= pFXShader
? pFXShader
->GetRefCounter() : 0;
3580 nRefCount
= min(nRefCount
, pAsync
->m_pShader
? pAsync
->m_pShader
->GetRefCounter() : 0);
3581 if (nRefCount
<= 1) // Just exit if shader was deleted
3583 pInst
->m_pAsync
= NULL
;
3584 SAFE_DELETE(pAsync
);
3588 mfOutputCompilerError(Errors
, Text
.c_str());
3590 Warning("Couldn't compile HW shader '%s'", GetName());
3591 mfSaveCGFile(Text
.c_str(), NULL
);
3595 else if (CRenderer::CV_r_logShaders
)
3596 gcpRendD3D
->LogShv("Async %d: Finished compiling 0x%x '%s' shader\n", GetCurrentFrameID(), pInst
, nameSrc
);
3597 pShader
= pAsync
->m_pDevShader
;
3598 pErrorMsgs
= pAsync
->m_pErrors
;
3599 strErr
= pAsync
->m_Errors
;
3600 InstBindVars
= pAsync
->m_InstBindVars
;
3602 if (pAsync
->m_bPendedEnv
)
3604 bResult
&= CHWShader_D3D::mfCreateShaderEnv(pAsync
->m_nThread
, pInst
, pAsync
->m_pDevShader
, pAsync
->m_pConstants
, pAsync
->m_pErrors
, pAsync
->m_InstBindVars
, this, false, pAsync
->m_pFXShader
, pAsync
->m_nCombination
);
3605 assert(bResult
== true);
3609 if (pAsync
->m_bPendedSamplers
)
3610 mfGatherFXParameters(pInst
, &pInst
->m_pBindVars
, &InstBindVars
, this, 2, pAsync
->m_pFXShader
);
3612 if (pAsync
->m_bPendedFlush
)
3615 cry_strcpy(nmDst
, GetName());
3616 char* s
= strchr(nmDst
, '(');
3619 SShaderCombIdent Ident
= pInst
->m_Ident
;
3620 Ident
.m_GLMask
= m_nMaskGenFX
;
3621 gRenDev
->m_cEF
.mfInsertNewCombination(Ident
, pInst
->m_eClass
, nmDst
, 0);
3624 nRefCount
= pAsync
->m_pFXShader
? pAsync
->m_pFXShader
->GetRefCounter() : 0;
3625 nRefCount
= min(nRefCount
, pAsync
->m_pShader
? pAsync
->m_pShader
->GetRefCounter() : 0);
3626 if (nRefCount
<= 1) // Just exit if shader was deleted
3628 pInst
->m_pAsync
= NULL
;
3629 SAFE_DELETE(pAsync
);
3632 SAFE_DELETE(pInst
->m_pAsync
);
3635 if (pErrorMsgs
&& !strErr
.empty())
3638 bResult
&= mfUploadHW(pShader
, pInst
, pSH
, 0);
3639 SAFE_RELEASE(pShader
);
3644 mfUpdatePreprocessFlags(pTech
);
3650 bool CHWShader_D3D::mfRequestAsync(CShader
* pSH
, SHWSInstance
* pInst
, std::vector
<SCGBind
>& InstBindVars
, const char* prog_text
, const char* szProfile
, const char* szEntry
)
3652 #ifdef SHADER_ASYNC_COMPILATION
3653 char nameSrc
[256], nmDst
[256];
3654 mfGetDstFileName(pInst
, this, nmDst
, 256, 3);
3655 gEnv
->pCryPak
->AdjustFileName(nmDst
, nameSrc
, 0);
3657 if (!SShaderAsyncInfo::PendingList().m_Next
)
3659 SShaderAsyncInfo::PendingList().m_Next
= &SShaderAsyncInfo::PendingList();
3660 SShaderAsyncInfo::PendingList().m_Prev
= &SShaderAsyncInfo::PendingList();
3661 SShaderAsyncInfo::PendingListT().m_Next
= &SShaderAsyncInfo::PendingListT();
3662 SShaderAsyncInfo::PendingListT().m_Prev
= &SShaderAsyncInfo::PendingListT();
3665 if (!m_pGlobalCache
|| !m_pGlobalCache
->m_pRes
[CACHE_USER
])
3668 m_pGlobalCache
->Release(false);
3669 m_pGlobalCache
= mfInitCache(NULL
, this, true, m_CRC32
, false, false);
3672 pInst
->m_pAsync
= new SShaderAsyncInfo
;
3673 pInst
->m_pAsync
->m_nFrame
= GetCurrentFrameID();
3674 pInst
->m_pAsync
->m_InstBindVars
= InstBindVars
;
3675 pInst
->m_pAsync
->m_pShader
= this;
3676 pInst
->m_pAsync
->m_pShader
->AddRef();
3677 pInst
->m_pAsync
->m_pFXShader
= pSH
;
3678 pInst
->m_pAsync
->m_pFXShader
->AddRef();
3679 pInst
->m_pAsync
->m_nCombination
= gRenDev
->m_cEF
.m_nCombinationsProcess
;
3680 assert(!stricmp(m_NameSourceFX
.c_str(), pInst
->m_pAsync
->m_pFXShader
->m_NameFile
.c_str()));
3681 InstContainer
* pInstCont
= &m_Insts
;
3682 pInst
->m_pAsync
->m_nHashInstance
= pInst
->m_Ident
.m_nHash
;
3683 pInst
->m_pAsync
->m_RTMask
= pInst
->m_Ident
.m_RTMask
;
3684 pInst
->m_pAsync
->m_LightMask
= pInst
->m_Ident
.m_LightMask
;
3685 pInst
->m_pAsync
->m_MDMask
= pInst
->m_Ident
.m_MDMask
;
3686 pInst
->m_pAsync
->m_MDVMask
= pInst
->m_Ident
.m_MDVMask
;
3687 pInst
->m_pAsync
->m_pipelineState
.opaque
= pInst
->m_Ident
.m_pipelineState
.opaque
;
3688 pInst
->m_pAsync
->m_eClass
= pInst
->m_eClass
;
3689 pInst
->m_pAsync
->m_Text
= prog_text
;
3690 pInst
->m_pAsync
->m_Name
= szEntry
;
3691 pInst
->m_pAsync
->m_Profile
= szProfile
;
3695 pInst
->m_pAsync
->m_fMinDistance
= pSH
->m_fMinVisibleDistance
;
3698 // Generate request line text to store on the shaderlist for next shader cache gen
3700 char szShaderGenName
[512];
3701 cry_strcpy(szShaderGenName
, GetName());
3702 char* s
= strchr(szShaderGenName
, '(');
3706 SShaderCombIdent Ident
= pInst
->m_Ident
;
3707 Ident
.m_GLMask
= m_nMaskGenFX
;
3708 gRenDev
->m_cEF
.mfInsertNewCombination(Ident
, pInst
->m_eClass
, szShaderGenName
, 0, &RequestLine
, false);
3710 pInst
->m_pAsync
->m_RequestLine
= RequestLine
;
3713 CAsyncShaderTask::InsertPendingShader(pInst
->m_pAsync
);
3715 if (CRenderer::CV_r_logShaders
)
3716 gcpRendD3D
->LogShv("Async %d: Requested compiling 0x%x '%s' shader\n", GetCurrentFrameID(), pInst
, nameSrc
);
3721 void CHWShader_D3D::mfSubmitRequestLine(SHWSInstance
* pInst
, string
* pRequestLine
)
3723 // Generate request line text.
3724 char szShaderGenName
[512];
3725 cry_strcpy(szShaderGenName
, GetName());
3726 char* s
= strchr(szShaderGenName
, '(');
3730 SShaderCombIdent Ident
= pInst
->m_Ident
;
3731 Ident
.m_GLMask
= m_nMaskGenFX
;
3732 gRenDev
->m_cEF
.mfInsertNewCombination(Ident
, pInst
->m_eClass
, szShaderGenName
, 0, &RequestLine
, false);
3735 *pRequestLine
= RequestLine
;
3737 if (!CRenderer::CV_r_shaderssubmitrequestline
|| !CRenderer::CV_r_shadersremotecompiler
|| pInst
->m_bHasSendRequest
)
3740 // make sure we only send the request once
3741 pInst
->m_bHasSendRequest
= true;
3743 #ifdef SHADER_ASYNC_COMPILATION
3744 if (CRenderer::CV_r_shadersasynccompiling
&& !(m_Flags
& HWSG_SYNC
))
3746 if (!SShaderAsyncInfo::PendingList().m_Next
)
3748 SShaderAsyncInfo::PendingList().m_Next
= &SShaderAsyncInfo::PendingList();
3749 SShaderAsyncInfo::PendingList().m_Prev
= &SShaderAsyncInfo::PendingList();
3750 SShaderAsyncInfo::PendingListT().m_Next
= &SShaderAsyncInfo::PendingListT();
3751 SShaderAsyncInfo::PendingListT().m_Prev
= &SShaderAsyncInfo::PendingListT();
3754 SShaderAsyncInfo
* pAsync
= new SShaderAsyncInfo
;
3758 pAsync
->m_RequestLine
= RequestLine
;
3759 pAsync
->m_Text
= "";
3760 pAsync
->m_bDeleteAfterRequest
= true;
3762 CAsyncShaderTask::InsertPendingShader(pAsync
);
3768 NRemoteCompiler::CShaderSrv::Instance().RequestLine(
3769 #if CRY_PLATFORM_ORBIS
3770 "ShaderList_Orbis.txt",
3771 #elif CRY_PLATFORM_DURANGO
3772 "ShaderList_Durango.txt",
3773 #elif CRY_RENDERER_OPENGLES && DXGL_INPUT_GLSL
3774 "ShaderList_GLES3.txt",
3775 #elif CRY_RENDERER_OPENGL && DXGL_INPUT_GLSL
3776 "ShaderList_GL4.txt",
3778 "ShaderList_PC.txt",
3780 RequestLine
.c_str());
3784 bool CHWShader_D3D::mfCompileHLSL_Int(CShader
* pSH
, char* prog_text
, D3DBlob
** ppShader
, void** ppConstantTable
, D3DBlob
** ppErrorMsgs
, string
& strErr
, std::vector
<SCGBind
>& InstBindVars
)
3787 SHWSInstance
* pInst
= m_pCurInst
;
3788 const char* szProfile
= mfProfileString(pInst
->m_eClass
);
3789 const char* pFunCCryName
= m_EntryFunc
.c_str();
3792 if (CRenderer::CV_r_shadersdebug
== 2)
3794 mfSaveCGFile(prog_text
, "TestCG");
3797 #if CRY_RENDERER_VULKAN || CRY_RENDERER_GNM
3798 if (pInst
->m_Ident
.m_pipelineState
.opaque
== UPipelineState().opaque
)
3800 CryWarning(VALIDATOR_MODULE_RENDERER
, VALIDATOR_WARNING
,"Cannot compile %s(LT%x)/(RT%I64x)(MD%x)(MDV%x)(GL%I64x)(PSS%llx).cg. Resource layout missing!",
3801 GetName(), m_pCurInst
->m_Ident
.m_LightMask
, m_pCurInst
->m_Ident
.m_RTMask
, m_pCurInst
->m_Ident
.m_MDMask
,
3802 m_pCurInst
->m_Ident
.m_MDVMask
, m_pCurInst
->m_Ident
.m_GLMask
, m_pCurInst
->m_Ident
.m_pipelineState
.opaque
);
3808 if (CRenderer::CV_r_shadersasynccompiling
&& !(m_Flags
& HWSG_SYNC
))
3810 return mfRequestAsync(pSH
, pInst
, InstBindVars
, prog_text
, szProfile
, pFunCCryName
);
3812 else if (CRenderer::CV_r_shadersremotecompiler
)
3814 string sCompiler
= gRenDev
->m_cEF
.mfGetShaderCompileFlags(pInst
->m_eClass
, pInst
->m_Ident
.m_pipelineState
);
3817 mfSubmitRequestLine(pInst
, &RequestLine
);
3819 std::vector
<uint8
> Data
;
3820 if (NRemoteCompiler::ESOK
!= NRemoteCompiler::CShaderSrv::Instance().Compile(Data
, szProfile
, prog_text
, pFunCCryName
, sCompiler
.c_str(), RequestLine
.c_str()))
3823 sErrorText
.reserve(Data
.size());
3824 for (uint32 i
= 0; i
< Data
.size(); i
++)
3825 sErrorText
+= Unicode::ConvertSafe
<Unicode::eErrorRecovery_FallbackWin1252ThenDiscard
, string
>(Data
[i
]); // HLSLcc may return garbage data, need to sanitize.
3826 strErr
= sErrorText
;
3831 D3DCreateBlob(Data
.size(), (D3DBlob
**)ppShader
);
3832 D3DBlob
* pShader
= (D3DBlob
*) *ppShader
;
3833 DWORD
* pBuf
= (DWORD
*) pShader
->GetBufferPointer();
3834 memcpy(pBuf
, &Data
[0], Data
.size());
3836 *ppShader
= (D3DBlob
*) pShader
;
3837 pBuf
= (DWORD
*)pShader
->GetBufferPointer();
3838 size_t nSize
= pShader
->GetBufferSize();
3840 bool bReflect
= true;
3842 #if CRY_PLATFORM_DESKTOP
3843 if (CParserBin::PlatformIsConsole())
3849 void* pShaderReflBuf
;
3850 hr
= D3DReflect(pBuf
, nSize
, IID_ID3D11ShaderReflection
, &pShaderReflBuf
);
3853 ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pShaderReflBuf
;
3854 *ppConstantTable
= (void*)pShaderReflection
;
3864 #if CRY_PLATFORM_WINDOWS
3867 static bool s_logOnce_WrongPlatform
= false;
3868 #if !CRY_RENDERER_OPENGL
3869 #if !defined(_RELEASE)
3870 if (!s_logOnce_WrongPlatform
&& (CParserBin::m_nPlatform
& (SF_D3D11
| SF_DURANGO
)) == 0)
3872 s_logOnce_WrongPlatform
= true;
3873 iLog
->LogError("Trying to build non DX11 shader via internal compiler which is not supported. Please use remote compiler instead!");
3876 uint32 nFlags
= D3D10_SHADER_PACK_MATRIX_ROW_MAJOR
| D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY
;
3877 if (CRenderer::CV_r_shadersdebug
== 3 || CRenderer::CV_r_shadersdebug
== 4)
3878 nFlags
|= D3D10_SHADER_DEBUG
| D3D10_SHADER_SKIP_OPTIMIZATION
;
3880 hr
= D3DCompile(prog_text
, strlen(prog_text
), GetName(), NULL
, NULL
, pFunCCryName
, szProfile
, nFlags
, 0, (ID3DBlob
**) ppShader
, (ID3DBlob
**) ppErrorMsgs
);
3881 if (FAILED(hr
) || !*ppShader
)
3883 if (ppErrorMsgs
&& *ppErrorMsgs
)
3885 const char* err
= (const char*)ppErrorMsgs
[0]->GetBufferPointer();
3890 strErr
+= "D3DXCompileShader failed";
3896 void* pShaderReflBuf
;
3897 UINT
* pData
= (UINT
*)ppShader
[0]->GetBufferPointer();
3898 UINT nSize
= (uint32
)ppShader
[0]->GetBufferSize();
3899 hr
= D3DReflect(pData
, nSize
, IID_ID3D11ShaderReflection
, &pShaderReflBuf
);
3902 ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pShaderReflBuf
;
3903 *ppConstantTable
= (void*)pShaderReflection
;
3913 #endif // #if CRY_PLATFORM_WINDOWS || CRY_PLATFORM_DURANGO
3918 D3DBlob
* CHWShader_D3D::mfCompileHLSL(CShader
* pSH
, char* prog_text
, void** ppConstantTable
, D3DBlob
** ppErrorMsgs
, uint32 nFlags
, std::vector
<SCGBind
>& InstBindVars
)
3920 // LOADING_TIME_PROFILE_SECTION(iSystem);
3922 // Test adding source text to context
3923 SHWSInstance
* pInst
= m_pCurInst
;
3925 D3DBlob
* pCode
= NULL
;
3932 if (!CRenderer::CV_r_shadersAllowCompilation
)
3935 bool bResult
= mfCompileHLSL_Int(pSH
, prog_text
, &pCode
, ppConstantTable
, ppErrorMsgs
, strErr
, InstBindVars
);
3938 if (CRenderer::CV_r_shadersasynccompiling
)
3943 mfOutputCompilerError(strErr
, prog_text
);
3945 Warning("Couldn't compile HW shader '%s'", GetName());
3946 mfSaveCGFile(prog_text
, NULL
);
3954 void CHWShader_D3D::mfPrepareShaderDebugInfo(SHWSInstance
* pInst
, CHWShader_D3D
* pSH
, const char* szAsm
, std::vector
<SCGBind
>& InstBindVars
, void* pConstantTable
)
3958 char* szInst
= strstr((char*)szAsm
, "pproximately ");
3960 pInst
->m_nInstructions
= atoi(&szInst
[13]);
3963 if (CParserBin::m_nPlatform
& (SF_D3D11
| SF_DURANGO
| SF_GL4
| SF_GLES3
))
3965 ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pConstantTable
;
3967 if (pShaderReflection
)
3969 D3D11_SHADER_DESC Desc
;
3970 pShaderReflection
->GetDesc(&Desc
);
3972 pInst
->m_nInstructions
= Desc
.InstructionCount
;
3973 pInst
->m_nTempRegs
= Desc
.TempRegisterCount
;
3977 if (CRenderer::CV_r_shadersdebug
)
3980 mfGetDstFileName(pInst
, pSH
, nmdst
, 256, 4);
3986 szName
= gRenDev
->m_cEF
.m_szUserPath
+ string(nmdst
) + string(".fxca");
3987 statusdst
= gEnv
->pCryPak
->FOpen(szName
.c_str(), "wb");
3992 gEnv
->pCryPak
->FPrintf(statusdst
, "\n// %s %s\n\n", "%STARTSHADER", mfProfileString(pInst
->m_eClass
));
3993 if (pSH
->m_eSHClass
== eHWSC_Vertex
)
3995 for (uint32 i
= 0; i
< (uint32
)InstBindVars
.size(); i
++)
3997 SCGBind
* pBind
= &InstBindVars
[i
];
3998 gEnv
->pCryPak
->FPrintf(statusdst
, "// %s %s %d %d\n", "%%", pBind
->m_Name
.c_str(), pBind
->m_nParameters
, pBind
->m_dwBind
);
4001 gEnv
->pCryPak
->FPrintf(statusdst
, "%s", szAsm
);
4002 gEnv
->pCryPak
->FPrintf(statusdst
, "\n// %s\n", "%ENDSHADER");
4003 gEnv
->pCryPak
->FClose(statusdst
);
4005 pInst
->m_Handle
.m_pShader
= NULL
;
4009 void CHWShader_D3D::mfPrintCompileInfo(SHWSInstance
* pInst
)
4012 int nParams
= pInst
->m_pBindVars
.size();
4013 for (int i
= 0; i
< nParams
; i
++)
4015 SCGBind
* pB
= &pInst
->m_pBindVars
[i
];
4016 nConsts
+= pB
->m_nParameters
;
4019 char szGenName
[512];
4020 cry_strcpy(szGenName
, GetName());
4021 char* s
= strchr(szGenName
, '(');
4024 if (CRenderer::CV_r_shadersdebug
== 2)
4027 SShaderCombIdent
Ident(m_nMaskGenFX
, pInst
->m_Ident
);
4028 gRenDev
->m_cEF
.mfInsertNewCombination(Ident
, pInst
->m_eClass
, szGenName
, 0, &pName
, false);
4029 CryLog(" Compile (FX:0x%I64x, GL:0x%I64x) %s (%d instructions, %d tempregs, %d/%d constants) ... ", m_nMaskGenFX
, pInst
->m_Ident
.m_GLMask
, pName
.c_str(), pInst
->m_nInstructions
, pInst
->m_nTempRegs
, nParams
, nConsts
);
4030 int nSize
= strlen(szGenName
);
4031 mfGenName(pInst
, &szGenName
[nSize
], 512 - nSize
, 1);
4032 CryLog(" --- Cache entry: %s", szGenName
);
4036 int nSize
= strlen(szGenName
);
4037 mfGenName(pInst
, &szGenName
[nSize
], 512 - nSize
, 1);
4038 CryLog(" Compile %s (%d instructions, %d tempregs, %d/%d constants) ... ", szGenName
, pInst
->m_nInstructions
, pInst
->m_nTempRegs
, nParams
, nConsts
);
4041 if (gRenDev
->m_cEF
.m_bActivated
&& CRenderer::CV_r_shadersdebug
> 0)
4044 #if defined(__GNUC__)
4049 "(%x)(%x)(%x)(%llx)(%s) wasn't compiled before preactivating phase",
4050 GetName(), pInst
->m_Ident
.m_RTMask
, pInst
->m_Ident
.m_LightMask
, pInst
->m_Ident
.m_MDMask
, pInst
->m_Ident
.m_MDVMask
, pInst
->m_Ident
.m_pipelineState
.opaque
, mfProfileString(pInst
->m_eClass
));
4053 bool CHWShader_D3D::mfCreateShaderEnv(int nThread
, SHWSInstance
* pInst
, D3DBlob
* pShader
, void*& pConstantTable
, D3DBlob
*& pErrorMsgs
, std::vector
<SCGBind
>& InstBindVars
, CHWShader_D3D
* pSH
, bool bShaderThread
, CShader
* pFXShader
, int nCombination
, const char* src
)
4055 // Create asm (.fxca) cache file
4062 if (pInst
->m_pBindVars
.size())
4065 if (pShader
&& (nCombination
< 0))
4067 #if !CRY_RENDERER_OPENGL
4068 D3DBlob
* pAsm
= NULL
;
4069 D3DBlob
* pSrc
= (D3DBlob
*)pShader
;
4070 UINT
* pBuf
= (UINT
*)pSrc
->GetBufferPointer();
4071 D3DDisassemble(pBuf
, pSrc
->GetBufferSize(), 0, NULL
, &pAsm
);
4074 char* szAsm
= (char*)pAsm
->GetBufferPointer();
4075 mfPrepareShaderDebugInfo(pInst
, pSH
, szAsm
, InstBindVars
, pConstantTable
);
4080 //assert(!pInst->m_pBindVars);
4084 bool bVF
= pSH
->m_eSHClass
== eHWSC_Vertex
;
4085 #if CRY_PLATFORM_DESKTOP
4086 if (CParserBin::PlatformIsConsole())
4089 #if !CRY_RENDERER_OPENGL
4090 if (CParserBin::m_nPlatform
& (SF_GL4
| SF_GLES3
))
4094 mfVertexFormat(pInst
, pSH
, pShader
, pConstantTable
);
4096 mfCreateBinds(pInst
, pConstantTable
, (byte
*)pShader
->GetBufferPointer(), (uint32
)pShader
->GetBufferSize());
4098 if (!(pSH
->m_Flags
& HWSG_PRECACHEPHASE
))
4101 int nParams
= pInst
->m_pBindVars
.size();
4102 for (int i
= 0; i
< nParams
; i
++)
4104 SCGBind
* pB
= &pInst
->m_pBindVars
[i
];
4105 nConsts
+= pB
->m_nParameters
;
4107 if (gRenDev
->m_cEF
.m_nCombinationsProcess
>= 0)
4109 //assert(!bShaderThread);
4111 //if (!(gRenDev->m_cEF.m_nCombination & 0xff))
4112 if (!CParserBin::m_nPlatform
)
4114 CryLog("%d: Compile %s %s (%d out of %d) - (%d/%d constants) ... ", nThread
,
4115 mfProfileString(pInst
->m_eClass
), pSH
->GetName(), nCombination
, gRenDev
->m_cEF
.m_nCombinationsProcessOverall
,
4120 CryLog("%d: Compile %s %s (%d out of %d) ... ", nThread
,
4121 mfProfileString(pInst
->m_eClass
), pSH
->GetName(), nCombination
, gRenDev
->m_cEF
.m_nCombinationsProcessOverall
);
4126 mfGatherFXParameters(pInst
, &pInst
->m_pBindVars
, &InstBindVars
, pSH
, bShaderThread
? 1 : 0, pFXShader
);
4129 mfCreateCacheItem(pInst
, InstBindVars
, (byte
*)pShader
->GetBufferPointer(), (uint32
)pShader
->GetBufferSize(), pSH
, bShaderThread
);
4131 mfCreateCacheItem(pInst
, InstBindVars
, NULL
, 0, pSH
, bShaderThread
);
4133 SAFE_RELEASE(pErrorMsgs
);
4134 if (ID3D11ShaderReflection
* pShaderReflection
= (ID3D11ShaderReflection
*)pConstantTable
)
4136 pShaderReflection
->Release();
4137 pConstantTable
= nullptr;
4143 // Compile pixel/vertex shader for the current instance properties
4144 bool CHWShader_D3D::mfActivate(CShader
* pSH
, uint32 nFlags
, FXShaderToken
* Table
, TArray
<uint32
>* pSHData
)
4146 PROFILE_FRAME(Shader_HWShaderActivate
);
4148 bool bResult
= true;
4149 SHWSInstance
* pInst
= m_pCurInst
;
4151 mfLogShaderRequest(pInst
);
4153 if (mfIsValid(pInst
, true) == ED3DShError_NotCompiled
)
4155 //if (!(m_Flags & HWSG_PRECACHEPHASE) && !(nFlags & HWSF_NEXT))
4156 // mfSetHWStartProfile(nFlags);
4158 bool bCreate
= false;
4159 // We need a different source and desination for fpStripExtension
4160 // since a call to strcpy with the same src and dst results in
4161 // undefined behaviour
4162 char nameCacheUnstripped
[256];
4163 char nameCache
[256];
4164 float t0
= gEnv
->pTimer
->GetAsyncCurTime();
4166 /*if (CRenderer::CV_r_shaderspreactivate == 2 || (nFlags & HWSF_STORECOMBINATION))
4168 cry_strcpy(nameCache, GetName());
4169 char *s = strchr(nameCache, '(');
4172 gRenDev->m_cEF.mfInsertNewCombination(m_nMaskGenFX, pInst->m_RTMask, pInst->m_LightMask, pInst->m_MDMask, pInst->m_MDVMask, pInst->m_pipelineState.opaque, pInst->m_eSHClass, nameCache, 1);
4173 if (nFlags & HWSF_STORECOMBINATION)
4176 mfGetDstFileName(pInst
, this, nameCacheUnstripped
, 256, 0);
4178 cry_strcpy(nameCache
, nameCacheUnstripped
);
4179 PathUtil::ReplaceExtension(nameCache
, "fxcb");
4181 m_pDevCache
= mfInitDevCache(nameCache
, this);
4185 std::unique_ptr
<byte
[]> pCacheItemBuffer
= nullptr;
4187 // if shader compiling is enabled, make sure the user folder shader caches are also available
4188 bool bReadOnly
= CRenderer::CV_r_shadersAllowCompilation
== 0;
4189 if (!m_pGlobalCache
|| m_pGlobalCache
->m_nPlatform
!= CParserBin::m_nPlatform
||
4190 (!bReadOnly
&& !m_pGlobalCache
->m_pRes
[CACHE_USER
]))
4192 SAFE_RELEASE(m_pGlobalCache
);
4193 bool bAsync
= CRenderer::CV_r_shadersasyncactivation
!= 0;
4194 if (nFlags
& HWSF_PRECACHE
)
4196 m_pGlobalCache
= mfInitCache(nameCache
, this, true, m_CRC32
, bReadOnly
, bAsync
);
4198 if (gRenDev
->m_cEF
.m_nCombinationsProcess
>= 0)
4200 mfGetDstFileName(pInst
, this, nameCache
, 256, 0);
4201 PathUtil::ReplaceExtension(nameCache
, "fxcb");
4202 FXShaderCacheNamesItor it
= m_ShaderCacheList
.find(nameCache
);
4203 if (it
== m_ShaderCacheList
.end())
4204 m_ShaderCacheList
.insert(FXShaderCacheNamesItor::value_type(nameCache
, m_CRC32
));
4206 pCacheItemBuffer
= mfGetCacheItem(nFlags
, nSize
);
4209 auto pCacheItem
= reinterpret_cast<SShaderCacheHeaderItem
*>(pCacheItemBuffer
.get());
4210 if (pCacheItem
&& pCacheItem
->m_Class
!= 255)
4212 if (Table
&& CRenderer::CV_r_shadersAllowCompilation
)
4213 mfGetCacheTokenMap(Table
, pSHData
, m_nMaskGenShader
);
4214 if (((m_Flags
& HWSG_PRECACHEPHASE
) || gRenDev
->m_cEF
.m_nCombinationsProcess
>= 0))
4218 bool bRes
= mfActivateCacheItem(pSH
, pCacheItem
, nSize
, nFlags
);
4221 return (pInst
->m_Handle
.m_pShader
!= NULL
);
4223 else if (pCacheItem
&& pCacheItem
->m_Class
== 255 && (nFlags
& HWSF_PRECACHE
) == 0)
4229 //assert(!m_TokenData.empty());
4231 TArray
<char> newScr
;
4233 if (nFlags
& HWSF_PRECACHE
)
4234 gRenDev
->m_cEF
.m_nCombinationsCompiled
++;
4235 /*if (strstr(m_NameSourceFX.c_str(), "Cloak") && !strcmp(m_EntryFunc.c_str(), "Common_ZPassVS"))
4240 float fTime0
= iTimer
->GetAsyncCurTime();
4241 D3DBlob
* pShader
= NULL
;
4242 void* pConstantTable
= NULL
;
4243 D3DBlob
* pErrorMsgs
= NULL
;
4244 std::vector
<SCGBind
> InstBindVars
;
4245 m_Flags
|= HWSG_WASGENERATED
;
4247 bool bScriptSuccess
= false;
4249 if (CRenderer::CV_r_shadersAllowCompilation
)
4251 // MemReplay shows that 16kb should be enough memory to hold the script without having to reallocate
4252 newScr
.reserve(16 * 1024);
4253 bScriptSuccess
= mfGenerateScript(pSH
, pInst
, InstBindVars
, nFlags
, Table
, pSHData
, newScr
);
4254 ASSERT_IN_SHADER(bScriptSuccess
);
4257 if (!pInst
->m_bAsyncActivating
)
4259 // report miss in global cache to log and/or callback
4260 mfLogShaderCacheMiss(pInst
);
4262 // still sumit the request line when no compiling to be sure that the shadercompiler will
4263 // compile it in the next build
4264 if (!CRenderer::CV_r_shadersAllowCompilation
)
4265 mfSubmitRequestLine(pInst
);
4268 if (!bScriptSuccess
)
4270 if (!pInst
->m_bAsyncActivating
)
4273 Warning("Warning: Shader %s(%llx)(%x)(%x)(%x)(%llx)(%s) is not existing in the cache\n",
4275 Warning("Warning: Shader %s(%I64x)(%x)(%x)(%x)(%llx)(%s) is not existing in the cache\n",
4277 GetName(), pInst
->m_Ident
.m_RTMask
, pInst
->m_Ident
.m_LightMask
, pInst
->m_Ident
.m_MDMask
, pInst
->m_Ident
.m_MDVMask
, pInst
->m_Ident
.m_pipelineState
.opaque
, mfProfileString(pInst
->m_eClass
));
4283 PROFILE_FRAME(Shader_CompileHLSL
);
4284 pShader
= mfCompileHLSL(pSH
, newScr
.Data(), &pConstantTable
, &pErrorMsgs
, nFlags
, InstBindVars
);
4287 gRenDev
->m_cEF
.m_ShaderCacheStats
.m_nNumShaderAsyncCompiles
= SShaderAsyncInfo::s_nPendingAsyncShaders
;
4291 if (!CRenderer::CV_r_shadersAllowCompilation
|| pInst
->IsAsyncCompiling())
4294 bResult
= mfCreateShaderEnv(0, pInst
, pShader
, pConstantTable
, pErrorMsgs
, InstBindVars
, this, false, pSH
, gRenDev
->m_cEF
.m_nCombinationsProcess
, newScr
.Data());
4295 bResult
&= mfUploadHW(pShader
, pInst
, pSH
, nFlags
);
4296 SAFE_RELEASE(pShader
);
4297 SAFE_RELEASE(pErrorMsgs
);
4298 if (ID3D11ShaderReflection
* pShaderReflection
= static_cast<ID3D11ShaderReflection
*>(pConstantTable
))
4300 pShaderReflection
->Release();
4301 pConstantTable
= nullptr;
4304 fTime0
= iTimer
->GetAsyncCurTime() - fTime0
;
4305 //iLog->LogToConsole(" Time activate: %.3f", fTime0);
4308 mfGetCacheTokenMap(Table
, pSHData
, m_nMaskGenShader
);
4310 ED3DShError shResult
= mfIsValid(pInst
, true);
4311 bool bSuccess
= (shResult
== ED3DShError_Ok
) || (shResult
== ED3DShError_Fake
);
4316 //////////////////////////////////////////////////////////////////////////
4318 #ifdef SHADER_ASYNC_COMPILATION
4320 #pragma warning(disable: 4355)// warning C4355: 'this' : used in base member initializer list
4322 CAsyncShaderTask::CAsyncShaderTask()
4329 void CAsyncShaderTask::InsertPendingShader(SShaderAsyncInfo
* pAsync
)
4331 AUTO_LOCK(g_cAILock
);
4332 pAsync
->Link(&BuildList());
4333 CryInterlockedIncrement(&SShaderAsyncInfo::s_nPendingAsyncShaders
);
4336 void CAsyncShaderTask::FlushPendingShaders()
4338 SShaderAsyncInfo
* pAI
, * pAI2
, * pAINext
;
4339 assert(m_flush_list
.m_Prev
== &m_flush_list
&& m_flush_list
.m_Next
== &m_flush_list
); // the flush list must be empty - cleared by the shader compile thread
4340 if (BuildList().m_Prev
== &BuildList() && BuildList().m_Next
== &BuildList())
4341 return; // the build list is empty, might need to do some assert here
4343 AUTO_LOCK(g_cAILock
);
4345 for (pAI
= BuildList().m_Prev
; pAI
!= &BuildList(); pAI
= pAINext
)
4347 pAINext
= pAI
->m_Prev
;
4349 pAI
->Link(&m_flush_list
);
4353 // Sorting by distance
4354 if (gRenDev
->m_cEF
.m_nCombinationsProcess
< 0)
4355 for (pAI
= m_flush_list
.m_Next
; pAI
!= &m_flush_list
; pAI
= pAI
->m_Next
)
4358 PREFAST_ASSUME(pAI
);
4360 int nFrame
= pAI
->m_nFrame
;
4361 float fDist
= pAI
->m_fMinDistance
;
4362 for (pAI2
= pAI
->m_Next
; pAI2
!= &m_flush_list
; pAI2
= pAI2
->m_Next
)
4364 if (pAI2
->m_nFrame
< nFrame
)
4366 if (pAI2
->m_nFrame
> nFrame
|| pAI2
->m_fMinDistance
< fDist
)
4369 nFrame
= pAI2
->m_nFrame
;
4370 fDist
= pAI2
->m_fMinDistance
;
4375 assert(pAI
!= pAINext
);
4376 SShaderAsyncInfo
* pAIP0
= pAI
->m_Prev
;
4377 SShaderAsyncInfo
* pAIP1
= pAINext
->m_Prev
== pAI
? pAINext
: pAINext
->m_Prev
;
4379 pAI
->m_Next
->m_Prev
= pAI
->m_Prev
;
4380 pAI
->m_Prev
->m_Next
= pAI
->m_Next
;
4381 pAI
->m_Next
= pAIP1
->m_Next
;
4382 pAIP1
->m_Next
->m_Prev
= pAI
;
4383 pAIP1
->m_Next
= pAI
;
4384 pAI
->m_Prev
= pAIP1
;
4388 pAI
->m_Next
->m_Prev
= pAI
->m_Prev
;
4389 pAI
->m_Prev
->m_Next
= pAI
->m_Next
;
4390 pAI
->m_Next
= pAIP0
->m_Next
;
4391 pAIP0
->m_Next
->m_Prev
= pAI
;
4392 pAIP0
->m_Next
= pAI
;
4393 pAI
->m_Prev
= pAIP0
;
4397 for (pAI
= m_flush_list
.m_Next
; pAI
!= &m_flush_list
; pAI
= pAINext
)
4399 pAINext
= pAI
->m_Next
;
4400 assert(pAI
->m_bPending
);
4401 SubmitAsyncRequestLine(pAI
);
4402 if (pAI
->m_Text
.length() > 0)
4403 CompileAsyncShader(pAI
);
4405 CryInterlockedDecrement(&SShaderAsyncInfo::s_nPendingAsyncShaders
);
4407 AUTO_LOCK(g_cAILock
);
4410 pAI
->m_bPending
= 0;
4411 pAI
->Link(&SShaderAsyncInfo::PendingListT());
4414 if (pAI
->m_bDeleteAfterRequest
)
4421 bool CAsyncShaderTask::PostCompile(SShaderAsyncInfo
* pAsync
)
4423 bool bResult
= true;
4424 /*if (pAsync->m_nCombination < 0 && false)
4426 CHWShader_D3D *pSH = pAsync->m_pShader;
4427 CHWShader_D3D::SHWSInstance *pInst = pSH->mfGetInstance(pAsync->m_nOwner, pSH->m_nMaskGenShader);
4428 bResult = CHWShader_D3D::mfCreateShaderEnv(m_nThread, pInst, pAsync->m_pDevShader, pAsync->m_pConstants, pAsync->m_pErrors, pAsync->m_InstBindVars, pSH, true, pAsync->m_pFXShader, pAsync->m_nCombination);
4429 assert(bResult == true);
4433 pAsync
->m_nThread
= m_nThread
;
4434 pAsync
->m_bPendedEnv
= true;
4439 void CAsyncShaderTask::SubmitAsyncRequestLine(SShaderAsyncInfo
* pAsync
)
4441 if (CRenderer::CV_r_shadersremotecompiler
)
4443 if (!pAsync
->m_shaderList
.empty())
4445 NRemoteCompiler::CShaderSrv::Instance().RequestLine(pAsync
->m_shaderList
.c_str(), pAsync
->m_RequestLine
.c_str());
4449 NRemoteCompiler::CShaderSrv::Instance().RequestLine(
4450 #if CRY_PLATFORM_ORBIS
4451 "ShaderList_Orbis.txt",
4452 #elif CRY_PLATFORM_DURANGO
4453 "ShaderList_Durango.txt",
4454 #elif CRY_RENDERER_OPENGLES && DXGL_INPUT_GLSL
4455 "ShaderList_GLES3.txt",
4456 #elif CRY_RENDERER_OPENGL && DXGL_INPUT_GLSL
4457 "ShaderList_GL4.txt",
4459 "ShaderList_PC.txt",
4461 pAsync
->m_RequestLine
.c_str());
4466 bool CAsyncShaderTask::CompileAsyncShader(SShaderAsyncInfo
* pAsync
)
4468 bool bResult
= true;
4469 if (CRenderer::CV_r_shadersremotecompiler
)
4471 string sCompiler
= gRenDev
->m_cEF
.mfGetShaderCompileFlags(pAsync
->m_eClass
, pAsync
->m_pipelineState
);
4473 std::vector
<uint8
> Data
;
4474 if (NRemoteCompiler::ESOK
!= NRemoteCompiler::CShaderSrv::Instance().Compile(Data
, pAsync
->m_Profile
, pAsync
->m_Text
.c_str(), pAsync
->m_Name
.c_str(), sCompiler
.c_str(), pAsync
->m_RequestLine
.c_str()))
4477 D3DCreateBlob(sizeof("D3DXCompileShader failed"), (D3DBlob
**)&pAsync
->m_pErrors
);
4478 DWORD
* pBuf
= (DWORD
*) pAsync
->m_pErrors
->GetBufferPointer();
4479 memcpy(pBuf
, "D3DXCompileShader failed", sizeof("D3DXCompileShader failed"));
4485 sErrorText
.reserve(Data
.size());
4486 for (uint32 i
= 0; i
< Data
.size(); i
++)
4487 sErrorText
+= Data
[i
];
4491 sErrorText
.assign("Unknown Error");
4494 pAsync
->m_Errors
+= sErrorText
;
4500 D3DCreateBlob(Data
.size(), (D3DBlob
**) &pAsync
->m_pDevShader
);
4501 D3DBlob
* pShader
= (D3DBlob
*)*&pAsync
->m_pDevShader
;
4502 DWORD
* pBuf
= (DWORD
*)pShader
->GetBufferPointer();
4503 memcpy(pBuf
, &Data
[0], Data
.size());
4505 pAsync
->m_pDevShader
= (D3DBlob
*)pShader
;
4506 pBuf
= (DWORD
*)pShader
->GetBufferPointer();
4507 size_t nSize
= pShader
->GetBufferSize();
4509 bool bReflect
= true;
4511 #if CRY_PLATFORM_DESKTOP
4512 if (CParserBin::PlatformIsConsole())
4515 #if !CRY_RENDERER_OPENGL
4516 if (CParserBin::m_nPlatform
& (SF_GL4
| SF_GLES3
))
4522 ID3D11ShaderReflection
* pShaderReflection
;
4523 hr
= D3DReflect(pBuf
, nSize
, IID_ID3D11ShaderReflection
, (void**)&pShaderReflection
);
4526 pAsync
->m_pConstants
= (void*)pShaderReflection
;
4532 bResult
= PostCompile(pAsync
);
4536 pAsync
->m_pDevShader
= 0;
4540 #if CRY_PLATFORM_WINDOWS && !CRY_RENDERER_OPENGL
4543 static bool s_logOnce_WrongPlatform
= false;
4544 #if !defined(_RELEASE)
4545 if (!s_logOnce_WrongPlatform
&& (CParserBin::m_nPlatform
& (SF_D3D11
| SF_DURANGO
)) == 0)
4547 s_logOnce_WrongPlatform
= true;
4548 iLog
->LogError("Trying to build non DX11 shader via internal compiler which is not supported. Please use remote compiler instead!");
4551 uint32 nFlags
= D3D10_SHADER_PACK_MATRIX_ROW_MAJOR
| D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY
;
4552 if (CRenderer::CV_r_shadersdebug
== 3 || CRenderer::CV_r_shadersdebug
== 4)
4553 nFlags
|= D3D10_SHADER_DEBUG
| D3D10_SHADER_SKIP_OPTIMIZATION
;
4555 const char* Name
= pAsync
->m_pShader
? pAsync
->m_pShader
->GetName() : "Unknown";
4557 hr
= D3DCompile(pAsync
->m_Text
.c_str(), pAsync
->m_Text
.size(), Name
, NULL
, NULL
, pAsync
->m_Name
.c_str(), pAsync
->m_Profile
.c_str(), nFlags
, 0, (ID3DBlob
**) &pAsync
->m_pDevShader
, (ID3DBlob
**) &pAsync
->m_pErrors
);
4558 if (FAILED(hr
) || !pAsync
->m_pDevShader
)
4560 if (pAsync
->m_pErrors
)
4562 const char* err
= (const char*)pAsync
->m_pErrors
->GetBufferPointer();
4563 pAsync
->m_Errors
+= err
;
4567 pAsync
->m_Errors
+= "D3DXCompileShader failed";
4573 ID3D11ShaderReflection
* pShaderReflection
;
4574 UINT
* pData
= (UINT
*)pAsync
->m_pDevShader
->GetBufferPointer();
4575 size_t nSize
= pAsync
->m_pDevShader
->GetBufferSize();
4576 hr
= D3DReflect(pData
, nSize
, IID_ID3D11ShaderReflection
, (void**)&pShaderReflection
);
4579 pAsync
->m_pConstants
= (void*)pShaderReflection
;
4580 bResult
= PostCompile(pAsync
);
4588 #endif // #if CRY_PLATFORM_WINDOWS
4592 void CAsyncShaderTask::CShaderThread::ThreadEntry()
4596 m_task
->FlushPendingShaders();
4597 if (!CRenderer::CV_r_shadersasynccompiling
)
4606 //===============================================================================================
4609 #ifdef SHADERS_SERIALIZING
4611 bool STexSamplerFX::Export(SShaderSerializeContext
& SC
)
4617 TS
.m_nsName
= SC
.AddString(m_szName
.c_str());
4618 TS
.m_nsNameTexture
= SC
.AddString(m_szTexture
.c_str());
4619 TS
.m_eTexType
= m_eTexType
;
4620 TS
.m_nSamplerSlot
= m_nSlotId
;
4621 TS
.m_nTexFlags
= m_nTexFlags
;
4623 if (m_nTexState
!= EDefaultSamplerStates::Unspecified
)
4625 const SSamplerState
& pTS
= CDeviceObjectFactory::LookupSamplerState(m_nTexState
).first
;
4628 TS
.m_nMinFilter
= pTS
.m_nMinFilter
;
4629 TS
.m_nMagFilter
= pTS
.m_nMagFilter
;
4630 TS
.m_nMipFilter
= pTS
.m_nMipFilter
;
4631 TS
.m_nAddressU
= pTS
.m_nAddressU
;
4632 TS
.m_nAddressV
= pTS
.m_nAddressV
;
4633 TS
.m_nAddressW
= pTS
.m_nAddressW
;
4634 TS
.m_nAnisotropy
= pTS
.m_nAnisotropy
;
4635 TS
.m_dwBorderColor
= pTS
.m_dwBorderColor
;
4636 TS
.m_bActive
= pTS
.m_bActive
;
4637 TS
.m_bComparison
= pTS
.m_bComparison
;
4638 TS
.m_bSRGBLookup
= pTS
.m_bSRGBLookup
;
4643 TS
.m_nRTIdx
= SC
.FXTexRTs
.Num();
4645 SHRenderTarget
* pRT
= m_pTarget
;
4648 RT
.m_eOrder
= pRT
->m_eOrder
;
4649 RT
.m_nProcessFlags
= pRT
->m_nProcessFlags
;
4650 RT
.m_nsTargetName
= SC
.AddString(pRT
->m_TargetName
.c_str());
4651 RT
.m_nWidth
= pRT
->m_nWidth
;
4652 RT
.m_nHeight
= pRT
->m_nHeight
;
4653 RT
.m_eTF
= pRT
->m_eTF
;
4654 RT
.m_nIDInPool
= pRT
->m_nIDInPool
;
4655 RT
.m_eUpdateType
= pRT
->m_eUpdateType
;
4656 RT
.m_bTempDepth
= pRT
->m_bTempDepth
;
4657 RT
.m_ClearColor
= pRT
->m_ClearColor
;
4658 RT
.m_fClearDepth
= pRT
->m_fClearDepth
;
4659 RT
.m_nFlags
= pRT
->m_nFlags
;
4660 RT
.m_nFilterFlags
= pRT
->m_nFilterFlags
;
4662 SC
.FXTexRTs
.push_back(RT
);
4665 //crude workaround for TArray push_back() bug a=b operator. Does not init a, breaks texState dtor for a
4666 SSTexSamplerFX
* pNewSampler
= SC
.FXTexSamplers
.AddIndex(1);
4667 memcpy(pNewSampler
, &TS
, sizeof(SSTexSamplerFX
));
4671 bool STexSamplerFX::Import(SShaderSerializeContext
& SC
, SSTexSamplerFX
* pTS
)
4675 m_szName
= sString(pTS
->m_nsName
, SC
.Strings
);
4676 m_szTexture
= sString(pTS
->m_nsNameTexture
, SC
.Strings
);
4677 m_eTexType
= pTS
->m_eTexType
;
4678 m_nSlotId
= pTS
->m_nSamplerSlot
;
4679 m_nTexFlags
= pTS
->m_nTexFlags
;
4681 if (pTS
->m_bTexState
)
4685 TS
.m_nMinFilter
= pTS
->m_nMinFilter
;
4686 TS
.m_nMagFilter
= pTS
->m_nMagFilter
;
4687 TS
.m_nMipFilter
= pTS
->m_nMipFilter
;
4688 TS
.m_nAddressU
= pTS
->m_nAddressU
;
4689 TS
.m_nAddressV
= pTS
->m_nAddressV
;
4690 TS
.m_nAddressW
= pTS
->m_nAddressW
;
4691 TS
.m_nAnisotropy
= pTS
->m_nAnisotropy
;
4692 TS
.m_dwBorderColor
= pTS
->m_dwBorderColor
;
4693 TS
.m_bActive
= pTS
->m_bActive
;
4694 TS
.m_bComparison
= pTS
->m_bComparison
;
4695 TS
.m_bSRGBLookup
= pTS
->m_bSRGBLookup
;
4697 m_nTexState
= CDeviceObjectFactory::GetOrCreateSamplerStateHandle(TS
);
4700 if (pTS
->m_nRTIdx
!= -1)
4702 SSHRenderTarget
* pRT
= &SC
.FXTexRTs
[pTS
->m_nRTIdx
];
4703 SHRenderTarget
* pDst
= new SHRenderTarget
;
4705 pDst
->m_eOrder
= pRT
->m_eOrder
;
4706 pDst
->m_nProcessFlags
= pRT
->m_nProcessFlags
;
4707 pDst
->m_TargetName
= sString(pRT
->m_nsTargetName
, SC
.Strings
);
4708 pDst
->m_nWidth
= pRT
->m_nWidth
;
4709 pDst
->m_nHeight
= pRT
->m_nHeight
;
4710 pDst
->m_eTF
= pRT
->m_eTF
;
4711 pDst
->m_nIDInPool
= pRT
->m_nIDInPool
;
4712 pDst
->m_eUpdateType
= pRT
->m_eUpdateType
;
4713 pDst
->m_bTempDepth
= pRT
->m_bTempDepth
!= 0;
4714 pDst
->m_ClearColor
= pRT
->m_ClearColor
;
4715 pDst
->m_fClearDepth
= pRT
->m_fClearDepth
;
4716 pDst
->m_nFlags
= pRT
->m_nFlags
;
4717 pDst
->m_nFilterFlags
= pRT
->m_nFilterFlags
;
4727 bool SFXParam::Export(SShaderSerializeContext
& SC
)
4732 PR
.m_nsName
= SC
.AddString(m_Name
.c_str());
4733 PR
.m_nsAnnotations
= SC
.AddString(m_Annotations
.c_str());
4734 PR
.m_nsSemantic
= SC
.AddString(m_Semantic
.c_str());
4735 PR
.m_nsValues
= SC
.AddString(m_Values
.c_str());
4737 PR
.m_eType
= m_eType
;
4739 PR
.m_nComps
= m_nComps
;
4740 PR
.m_nFlags
= m_nFlags
;
4741 PR
.m_nParameters
= m_nParameters
;
4742 PR
.m_nRegister
[0] = m_nRegister
[0];
4743 PR
.m_nRegister
[1] = m_nRegister
[1];
4744 PR
.m_nRegister
[2] = m_nRegister
[2];
4746 SC
.FXParams
.push_back(PR
);
4750 bool SFXParam::Import(SShaderSerializeContext
& SC
, SSFXParam
* pPR
)
4754 m_Name
= sString(pPR
->m_nsName
, SC
.Strings
);
4755 m_Annotations
= sString(pPR
->m_nsAnnotations
, SC
.Strings
);
4756 m_Semantic
= sString(pPR
->m_nsSemantic
, SC
.Strings
);
4757 m_Values
= sString(pPR
->m_nsValues
, SC
.Strings
);
4759 m_eType
= pPR
->m_eType
;
4761 m_nComps
= pPR
->m_nComps
;
4762 m_nFlags
= pPR
->m_nFlags
;
4763 m_nParameters
= pPR
->m_nParameters
;
4764 m_nRegister
[0] = pPR
->m_nRegister
[0];
4765 m_nRegister
[1] = pPR
->m_nRegister
[1];
4766 m_nRegister
[2] = pPR
->m_nRegister
[2];
4771 bool SFXSampler::Export(SShaderSerializeContext
& SC
)
4776 PR
.m_nsName
= SC
.AddString(m_Name
.c_str());
4777 PR
.m_nsAnnotations
= SC
.AddString(m_Annotations
.c_str());
4778 PR
.m_nsSemantic
= SC
.AddString(m_Semantic
.c_str());
4779 PR
.m_nsValues
= SC
.AddString(m_Values
.c_str());
4781 PR
.m_eType
= m_eType
;
4782 PR
.m_nArray
= m_nArray
;
4783 PR
.m_nFlags
= m_nFlags
;
4784 PR
.m_nRegister
[0] = m_nRegister
[0];
4785 PR
.m_nRegister
[1] = m_nRegister
[1];
4786 PR
.m_nRegister
[2] = m_nRegister
[2];
4788 SC
.FXSamplers
.push_back(PR
);
4792 bool SFXSampler::Import(SShaderSerializeContext
& SC
, SSFXSampler
* pPR
)
4796 m_Name
= sString(pPR
->m_nsName
, SC
.Strings
);
4797 m_Annotations
= sString(pPR
->m_nsAnnotations
, SC
.Strings
);
4798 m_Semantic
= sString(pPR
->m_nsSemantic
, SC
.Strings
);
4799 m_Values
= sString(pPR
->m_nsValues
, SC
.Strings
);
4801 m_eType
= pPR
->m_eType
;
4802 m_nArray
= pPR
->m_nArray
;
4803 m_nFlags
= pPR
->m_nFlags
;
4804 m_nRegister
[0] = pPR
->m_nRegister
[0];
4805 m_nRegister
[1] = pPR
->m_nRegister
[1];
4806 m_nRegister
[2] = pPR
->m_nRegister
[2];
4811 bool SFXTexture::Export(SShaderSerializeContext
& SC
)
4816 PR
.m_nsName
= SC
.AddString(m_Name
.c_str());
4817 PR
.m_nsAnnotations
= SC
.AddString(m_Annotations
.c_str());
4818 PR
.m_nsSemantic
= SC
.AddString(m_Semantic
.c_str());
4819 PR
.m_nsValues
= SC
.AddString(m_Values
.c_str());
4821 PR
.m_nsNameTexture
= SC
.AddString(m_szTexture
.c_str());
4822 PR
.m_bSRGBLookup
= m_bSRGBLookup
;
4823 PR
.m_eType
= m_eType
;
4824 PR
.m_nArray
= m_nArray
;
4825 PR
.m_nFlags
= m_nFlags
;
4826 PR
.m_nRegister
[0] = m_nRegister
[0];
4827 PR
.m_nRegister
[1] = m_nRegister
[1];
4828 PR
.m_nRegister
[2] = m_nRegister
[2];
4830 SC
.FXTextures
.push_back(PR
);
4834 bool SFXTexture::Import(SShaderSerializeContext
& SC
, SSFXTexture
* pPR
)
4838 m_Name
= sString(pPR
->m_nsName
, SC
.Strings
);
4839 m_Annotations
= sString(pPR
->m_nsAnnotations
, SC
.Strings
);
4840 m_Semantic
= sString(pPR
->m_nsSemantic
, SC
.Strings
);
4841 m_Values
= sString(pPR
->m_nsValues
, SC
.Strings
);
4843 m_szTexture
= sString(pPR
->m_nsNameTexture
, SC
.Strings
);
4844 m_bSRGBLookup
= pPR
->m_bSRGBLookup
;
4845 m_eType
= pPR
->m_eType
;
4846 m_nArray
= pPR
->m_nArray
;
4847 m_nFlags
= pPR
->m_nFlags
;
4848 m_nRegister
[0] = pPR
->m_nRegister
[0];
4849 m_nRegister
[1] = pPR
->m_nRegister
[1];
4850 m_nRegister
[2] = pPR
->m_nRegister
[2];
4855 bool CHWShader_D3D::ExportSamplers(SCHWShader
& SHW
, SShaderSerializeContext
& SC
)
4859 //Samplers no longer stored here
4862 SHW
.m_nSamplers
= m_Samplers
.size();
4863 for (i
= 0; i
< m_Samplers
.size(); i
++)
4865 STexSampler
& TS
= m_Samplers
[i
];
4866 bRes
&= TS
.Export(SC
);
4872 bool CHWShader::ImportSamplers(SShaderSerializeContext
& SC
, SCHWShader
* pSHW
, byte
*& pData
, std::vector
<STexSamplerRT
>& Samplers
)
4876 //Samplers no longer stored here
4880 for (i
= 0; i
< pSHW
->m_nSamplers
; i
++)
4883 bRes
&= TS
.Import(SC
, pData
);
4885 Samplers
.push_back(TS
);
4891 bool CHWShader_D3D::ExportParams(SCHWShader
& SHW
, SShaderSerializeContext
& SC
)
4895 //params no longer here
4898 SHW
.m_nParams
= m_Params
.size();
4899 for (i
= 0; i
< m_Params
.size(); i
++)
4901 SFXParam
& PR
= m_Params
[i
];
4902 bRes
&= PR
.Export(SC
);
4910 bool CHWShader::ImportParams(SShaderSerializeContext
& SC
, SCHWShader
* pSHW
, byte
*& pData
, std::vector
<SFXParam
>& Params
)
4914 //params no longer here
4918 for (i
= 0; i
< pSHW
->m_nParams
; i
++)
4921 bRes
&= PR
.Import(SC
, pData
);
4923 Params
.push_back(PR
);
4929 bool CHWShader_D3D::Export(SShaderSerializeContext
& SC
)
4936 cry_strcpy(str
, GetName());
4937 char* c
= strchr(str
, '(');
4941 SHW
.m_nsName
= SC
.AddString(str
);
4942 SHW
.m_nsNameSourceFX
= SC
.AddString(m_NameSourceFX
.c_str());
4943 SHW
.m_nsEntryFunc
= SC
.AddString(m_EntryFunc
.c_str());
4945 SHW
.m_eSHClass
= m_eSHClass
;
4946 SHW
.m_dwShaderType
= m_dwShaderType
;
4947 SHW
.m_nMaskGenFX
= m_nMaskGenFX
;
4948 SHW
.m_nMaskGenShader
= m_nMaskGenShader
;
4949 SHW
.m_nMaskOr_RT
= m_nMaskOr_RT
;
4950 SHW
.m_nMaskAnd_RT
= m_nMaskAnd_RT
;
4951 SHW
.m_Flags
= m_Flags
;
4953 FXShaderToken
* pMap
= NULL
;
4954 TArray
<uint32
>* pData
= &m_TokenData
;
4955 bool bDeleteTokenData
= false;
4957 // No longer export any token data, slow and bloated!
4958 const bool bOutputTokens
= false;
4960 if (bOutputTokens
) // && !pData->size())
4965 bDeleteTokenData
= true;
4966 mfGetCacheTokenMap(pMap
, pData
, m_nMaskGenShader
/*is this correct? m_nMaskGenFX*/);
4972 if (bOutputTokens
&& !pMap
)
4978 SHW
.m_nTokens
= bOutputTokens
? pData
->size() : 0;
4979 SHW
.m_nTableEntries
= bOutputTokens
? pMap
->size() : 0;
4981 SCHWShader SHWTemp
= SHW
;
4983 SHW
.Export(SC
.Data
);
4988 sAddDataArray_POD(SC
.Data
, *pData
, nOffs
);
4990 FXShaderTokenItor itor
;
4991 for (itor
= pMap
->begin(); itor
!= pMap
->end(); itor
++)
4993 //String pool method
4994 sAddData(SC
.Data
, itor
->Token
);
4995 uint32 tokenStrIdx
= SC
.AddString(itor
->SToken
.c_str());
4996 sAddData(SC
.Data
, tokenStrIdx
);
5000 bRes
&= ExportSamplers(SHW
, SC
);
5001 bRes
&= ExportParams(SHW
, SC
);
5005 if (memcmp(&SHW
, &SHWTemp
, sizeof(SCHWShader
)))
5007 CryFatalError("Export failed");
5011 if (bDeleteTokenData
)
5020 CHWShader
* CHWShader::Import(SShaderSerializeContext
& SC
, int nOffs
, uint32 CRC32
, CShader
* pSH
)
5025 CHWShader
* pHWSH
= NULL
;
5026 SCHWShader shaderHW
;
5027 shaderHW
.Import(&SC
.Data
[nOffs
]);
5028 SCHWShader
* pSHW
= &shaderHW
;
5030 byte
* pData
= &SC
.Data
[nOffs
+ sizeof(SCHWShader
)];
5032 const char* szName
= sString(pSHW
->m_nsName
, SC
.Strings
);
5033 const char* szNameSource
= sString(pSHW
->m_nsNameSourceFX
, SC
.Strings
);
5034 const char* szNameEntry
= sString(pSHW
->m_nsEntryFunc
, SC
.Strings
);
5036 TArray
<uint32
> SHData
;
5037 SHData
.resize(pSHW
->m_nTokens
);
5038 memcpy(&SHData
[0], pData
, pSHW
->m_nTokens
* sizeof(uint32
));
5039 pData
+= pSHW
->m_nTokens
* sizeof(uint32
);
5041 FXShaderToken Table
, * pTable
= NULL
;
5042 Table
.reserve(pSHW
->m_nTableEntries
);
5046 //Copy string pool, TODO separate string pool for tokens!
5047 //TArray<char> tokenStringPool = SC.Strings;
5049 // Token data is no longer in export data
5050 if (0) //CRenderer::CV_r_shadersAllowCompilation)
5053 for (uint32 i
= 0; i
< pSHW
->m_nTableEntries
; i
++)
5055 // string pool method
5056 DWORD nToken
= *(DWORD
*)&pData
[nOffs
];
5057 nOffs
+= sizeof(DWORD
);
5058 uint32 nTokenStrIdx
= *(DWORD
*)&pData
[nOffs
];
5059 nOffs
+= sizeof(uint32
);
5061 if (CParserBin::m_bEndians
)
5063 SwapEndian(nToken
, eBigEndian
);
5064 SwapEndian(nTokenStrIdx
, eBigEndian
);
5068 TD
.SToken
= sString(nTokenStrIdx
, SC
.Strings
);
5072 Table
.push_back(TD
);
5076 std::vector
<STexSamplerRT
> Samplers
;
5077 ImportSamplers(SC
, pSHW
, pData
, Samplers
);
5079 std::vector
<SFXParam
> Params
;
5080 ImportParams(SC
, pSHW
, pData
, Params
);
5083 bool bPrecache
= (SC
.SSR
.m_Flags
& EF_PRECACHESHADER
) != 0;
5085 //static CHWShader *mfForName(const char *name, const char *nameSource, uint32 CRC32, const char *szEntryFunc, EHWShaderClass eClass, TArray<uint32>& SHData, FXShaderToken *pTable, uint32 dwType, CShader *pFX, uint64 nMaskGen=0, uint64 nMaskGenFX=0);
5086 pHWSH
= CHWShader::mfForName(szName
, szNameSource
, CRC32
, szNameEntry
, pSHW
->m_eSHClass
, SHData
, pTable
, pSHW
->m_dwShaderType
, pSH
, pSHW
->m_nMaskGenShader
, pSHW
->m_nMaskGenFX
);
5088 pHWSH
->m_eSHClass
= shaderHW
.m_eSHClass
;
5089 pHWSH
->m_dwShaderType
= shaderHW
.m_dwShaderType
;
5090 pHWSH
->m_nMaskGenFX
= shaderHW
.m_nMaskGenFX
;
5091 pHWSH
->m_nMaskGenShader
= shaderHW
.m_nMaskGenShader
;
5092 pHWSH
->m_nMaskOr_RT
= shaderHW
.m_nMaskOr_RT
;
5093 pHWSH
->m_nMaskAnd_RT
= shaderHW
.m_nMaskAnd_RT
;
5094 pHWSH
->m_Flags
= shaderHW
.m_Flags
;
5100 bool CHWShader_D3D::Export(SShaderSerializeContext
& SC
)
5106 const char* CHWShader_D3D::mfGetActivatedCombinations(bool bForLevel
)
5108 TArray
<char> Combinations
;
5112 for (i
= 0; i
< m_Insts
.size(); i
++)
5114 SHWSInstance
* pInst
= m_Insts
[i
];
5116 cry_strcpy(name
, GetName());
5117 char* s
= strchr(name
, '(');
5121 SShaderCombIdent
Ident(m_nMaskGenFX
, pInst
->m_Ident
);
5122 gRenDev
->m_cEF
.mfInsertNewCombination(Ident
, pInst
->m_eClass
, name
, 0, &str
, false);
5126 assert(str
[0] == '<' && str
[2] == '>');
5128 if (str
[0] == '<' && str
[2] == '>')
5129 s1
.Format("<%d>%s", pInst
->m_nUsed
, &str
[3]);
5132 Combinations
.Copy(s1
.c_str(), s1
.size());
5133 Combinations
.Copy("\n", 1);
5137 if (!Combinations
.Num())
5139 pPtr
= new char[Combinations
.Num() + 1];
5140 memcpy(pPtr
, &Combinations
[0], Combinations
.Num());
5141 pPtr
[Combinations
.Num()] = 0;
5145 const char* CHWShader::GetCurrentShaderCombinations(bool bForLevel
) threadsafe
5147 CryAutoReadLock
<CryRWLock
> lock(CBaseResource::s_cResLock
);
5149 TArray
<char> Combinations
;
5152 SResourceContainer
* pRL
;
5154 Name
= CHWShader::mfGetClassName(eHWSC_Vertex
);
5155 pRL
= CBaseResource::GetResourcesForClass(Name
);
5160 ResourcesMapItor itor
;
5161 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
5163 CHWShader
* vs
= (CHWShader
*)itor
->second
;
5166 const char* szCombs
= vs
->mfGetActivatedCombinations(bForLevel
);
5169 Combinations
.Copy(szCombs
, strlen(szCombs
));
5175 Name
= CHWShader::mfGetClassName(eHWSC_Pixel
);
5176 pRL
= CBaseResource::GetResourcesForClass(Name
);
5180 ResourcesMapItor itor
;
5181 for (itor
= pRL
->m_RMap
.begin(); itor
!= pRL
->m_RMap
.end(); itor
++)
5183 CHWShader
* ps
= (CHWShader
*)itor
->second
;
5186 const char* szCombs
= ps
->mfGetActivatedCombinations(bForLevel
);
5189 Combinations
.Copy(szCombs
, strlen(szCombs
));
5195 if (!Combinations
.Num())
5197 pPtr
= new char[Combinations
.Num() + 1];
5198 memcpy(pPtr
, &Combinations
[0], Combinations
.Num());
5199 pPtr
[Combinations
.Num()] = 0;