You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/Common/Shaders/Shader.h

1517 lines
44 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : Shaders declarations.
#ifndef CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_SHADERS_SHADER_H
#define CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_SHADERS_SHADER_H
#pragma once
#include "../Defs.h"
#include "Vertex.h"
#include <CryName.h>
#include <IShader.h>
#include "ShaderResources.h"
// bump this value up if you want to invalidate shader cache (e.g. changed some code or .ext file)
// #### VIP NOTE ####: DON'T USE MORE THAN ONE DECIMAL PLACE!!!! else it doesn't work...
#define FX_CACHE_VER 10.5f
#define FX_SER_CACHE_VER 1.4f // Shader serialization version (FX_CACHE_VER + FX_SER_CACHE_VER)
// Maximum 1 digit here
// The version determines the parse logic in the shader cache gen, these values cannot overlap
#define SHADER_LIST_VER 4
#define SHADER_SERIALISE_VER (SHADER_LIST_VER + 1)
//#define SHADER_NO_SOURCES 1 // If this defined all binary shaders (.fxb) should be located in Game folder (not user)
#if !defined(NULL_RENDERER)
#define SHADERS_SERIALIZING 1 // Enables shaders serializing (Export/Import) to/from .fxb files
#endif
struct SShaderPass;
class CShader;
class CRendElementBase;
class CResFile;
struct SEnvTexture;
struct SParserFrame;
struct SPreprocessTree;
struct SEmptyCombination;
struct SShaderCombination;
struct SShaderCache;
struct SShaderDevCache;
struct SCGParam;
struct SSFXParam;
struct SSFXSampler;
struct SSFXTexture;
enum eCompareFunc
{
eCF_Disable,
eCF_Never,
eCF_Less,
eCF_Equal,
eCF_LEqual,
eCF_Greater,
eCF_NotEqual,
eCF_GEqual,
eCF_Always
};
struct SPair
{
string m_szMacroName;
string m_szMacro;
uint32 m_nMask;
};
#if defined(MOBILE)
#define GEOMETRYSHADER_SUPPORT false
#else
#define GEOMETRYSHADER_SUPPORT true
#endif
//------------------------------------------------------------------------------
// SFX structures are the structures gathered from the shader during shader parsing
// and associated later on to a binding slot / buffer.
// They represent constants, textures and samplers.
//------------------------------------------------------------------------------
struct SFXBaseParam
{
CCryNameR m_Name; // Parameter name
std::vector <uint32> m_dwName;
uint32 m_nFlags;
short m_nArray; // Number of parameters
CCryNameR m_Annotations; // Additional parameters (between <>)
CCryNameR m_Semantic; // Parameter semantic type (after ':')
CCryNameR m_Values; // Parameter values (after '=')
byte m_eType; // Type per usage
// [Shader System] register offset per shader stage (class) - VS, PS, GS...
// This needs to be unified for all stages (and renamed as m_RegisterOffset)
short m_Register[eHWSC_Num];
SFXBaseParam()
{
m_nArray = 0;
m_nFlags = 0;
for (int i = 0; i < eHWSC_Num; i++)
{
m_Register[i] = 10000;
}
}
uint32 GetFlags() { return m_nFlags; }
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(m_dwName);
}
};
//------------------------------------------------------------------------------
// An SFXParam is the constant data gathered from the shader parsing.
// Example of usage - In Matrix 3x4: m_nParams = 3, m_nComps = 4
// Needs some more refactor to fully use SFXBaseParam.
//------------------------------------------------------------------------------
struct SFXParam : SFXBaseParam
{
short m_RegisterCount;
short m_ComponentCount;
int8 m_BindingSlot; // the CB slot
// [Shaders System] - the following needs to be removed as part of the unified offset.
// The next two parameters are only valid after the gather stage for final parameters
AZ::u8 m_OffsetStageSetter; // which stage set the offset
AZ::u8 m_StagesUsage; // Adding visibility to who's using the param
SFXParam()
{
m_RegisterCount = 0;
m_ComponentCount = 0;
m_BindingSlot = -1;
m_OffsetStageSetter = eHWSC_Vertex;
m_StagesUsage = (1 << eHWSC_Vertex);
}
~SFXParam() {}
void GetParamComp(uint32 nOffset, CryFixedStringT<128>& param);
void GetCompName(uint32 nId, CryFixedStringT<128>& name);
string GetValueForName(const char* szName, EParamType& eType);
void PostLoad(class CParserBin& Parser, SParserFrame& Name, SParserFrame& Annotations, SParserFrame& Values, SParserFrame& Assign);
void PostLoad();
bool Export(SShaderSerializeContext& SC);
bool Import(SShaderSerializeContext& SC, SSFXParam* pPR);
uint32 Size()
{
uint32 nSize = sizeof(SFXParam);
nSize += sizeofVector(m_dwName);
return nSize;
}
inline bool operator == (const SFXParam& m) const
{
if (m_Name == m.m_Name && m_Annotations == m.m_Annotations && m_Semantic == m.m_Semantic && m_Values == m.m_Values &&
m_RegisterCount == m.m_RegisterCount && m_ComponentCount == m.m_ComponentCount && m_nFlags == m.m_nFlags && m_Register[0] == m.m_Register[0] && m_Register[1] == m.m_Register[1] &&
m_eType == m.m_eType)
{
return true;
}
return false;
}
};
//------------------------------------------------------------------------------
// An SFX structure is the structure gathered from the shader during
// parsing and associated later on.
//------------------------------------------------------------------------------
struct SFXSampler : SFXBaseParam
{
int m_nTexState;
SFXSampler()
{
m_nTexState = -1;
}
~SFXSampler() {}
void PostLoad(class CParserBin& Parser, SParserFrame& Name, SParserFrame& Annotations, SParserFrame& Values, SParserFrame& Assign);
void PostLoad();
bool Export(SShaderSerializeContext& SC);
bool Import(SShaderSerializeContext& SC, SSFXSampler* pPR);
uint32 Size()
{
uint32 nSize = sizeof(SFXSampler);
nSize += sizeofVector(m_dwName);
return nSize;
}
inline bool operator == (const SFXSampler& m) const
{
if (m_Name == m.m_Name && m_Annotations == m.m_Annotations && m_Semantic == m.m_Semantic && m_Values == m.m_Values &&
m_nArray == m.m_nArray && m_nFlags == m.m_nFlags && m_Register[0] == m.m_Register[0] && m_Register[1] == m.m_Register[1] &&
m_eType == m.m_eType && m_nTexState == m.m_nTexState)
{
return true;
}
return false;
}
};
//------------------------------------------------------------------------------
// An SFX structure is the structure gathered from the shader during
// parsing and associated later on.
// SFXTexture - This structure contains a meta data gathered during shader parsing.
// It doesn't contain the actual texture data and doesn't apply to the binding directly
// but used as the data associated with the SCGTexture binding structure.
//------------------------------------------------------------------------------
struct SFXTexture : SFXBaseParam
{
uint32 m_nTexFlags;
string m_szTexture; // Texture source name
string m_szUIName; // UI name
string m_szUIDesc; // UI description
bool m_bSRGBLookup; // Lookup
byte m_Type; // Data type (float, float4, etc)
SFXTexture()
{
m_bSRGBLookup = false;
m_Type = 0;
m_nTexFlags = 0;
}
~SFXTexture() {}
uint32 GetTexFlags() { return m_nTexFlags; }
void PostLoad(class CParserBin& Parser, SParserFrame& Name, SParserFrame& Annotations, SParserFrame& Values, SParserFrame& Assign);
void PostLoad();
bool Export(SShaderSerializeContext& SC);
bool Import(SShaderSerializeContext& SC, SSFXTexture* pPR);
uint32 Size()
{
uint32 nSize = sizeof(SFXTexture);
//nSize += m_Name.capacity();
nSize += sizeofVector(m_dwName);
//nSize += m_Values.capacity();
return nSize;
}
inline bool operator == (const SFXTexture& m) const
{
if (m_Name == m.m_Name && m_Annotations == m.m_Annotations && m_Semantic == m.m_Semantic && m_Values == m.m_Values &&
m_nArray == m.m_nArray && m_nFlags == m.m_nFlags && m_Register[0] == m.m_Register[0] && m_Register[1] == m.m_Register[1] &&
m_eType == m.m_eType && m_bSRGBLookup == m.m_bSRGBLookup && m_szTexture == m.m_szTexture)
{
return true;
}
return false;
}
};
//------------------------------------------------------------------------------
struct STokenD
{
//std::vector<int> Offsets;
uint32 Token;
string SToken;
unsigned Size() { return sizeof(STokenD) /*+ sizeofVector(Offsets)*/ + SToken.capacity(); }
void GetMemoryUsage(ICrySizer* pSizer) const { pSizer->AddObject(SToken); }
};
typedef AZStd::vector<STokenD, AZ::StdLegacyAllocator> FXShaderToken;
typedef FXShaderToken::iterator FXShaderTokenItor;
struct SFXStruct
{
string m_Name;
string m_Struct;
SFXStruct()
{
}
};
enum ETexFilter
{
eTEXF_None,
eTEXF_Point,
eTEXF_Linear,
eTEXF_Anisotropic,
};
//=============================================================================
// Vertex programms / Vertex shaders (VP/VS)
static _inline float* sfparam(Vec3 param)
{
static float sparam[4];
sparam[0] = param.x;
sparam[1] = param.y;
sparam[2] = param.z;
sparam[3] = 1.0f;
return &sparam[0];
}
static _inline float* sfparam(float param)
{
static float sparam[4];
sparam[0] = param;
sparam[1] = 0;
sparam[2] = 0;
sparam[3] = 1.0f;
return &sparam[0];
}
static _inline float* sfparam(float param0, float param1, float param2, float param3)
{
static float sparam[4];
sparam[0] = param0;
sparam[1] = param1;
sparam[2] = param2;
sparam[3] = param3;
return &sparam[0];
}
_inline char* sGetFuncName(const char* pFunc)
{
static char func[128];
const char* b = pFunc;
if (*b == '[')
{
const char* s = strchr(b, ']');
if (s)
{
b = s + 1;
}
while (*b <= 0x20)
{
b++;
}
}
while (*b > 0x20)
{
b++;
}
while (*b <= 0x20)
{
b++;
}
int n = 0;
while (*b > 0x20 && *b != '(')
{
func[n++] = *b++;
}
func[n] = 0;
return func;
}
enum ERenderOrder
{
eRO_PreProcess,
eRO_PostProcess,
eRO_PreDraw
};
enum ERTUpdate
{
eRTUpdate_Unknown,
eRTUpdate_Always,
eRTUpdate_WaterReflect
};
struct SHRenderTarget
: public IRenderTarget
{
int m_nRefCount;
ERenderOrder m_eOrder;
int m_nProcessFlags; // FSPR_ flags
string m_TargetName;
int m_nWidth;
int m_nHeight;
ETEX_Format m_eTF;
int m_nIDInPool;
ERTUpdate m_eUpdateType;
CTexture* m_pTarget[2];
bool m_bTempDepth;
ColorF m_ClearColor;
float m_fClearDepth;
uint32 m_nFlags;
uint32 m_nFilterFlags;
int m_refSamplerID;
SHRenderTarget()
{
m_nRefCount = 1;
m_eOrder = eRO_PreProcess;
m_pTarget[0] = NULL;
m_pTarget[1] = NULL;
m_bTempDepth = true;
m_ClearColor = Col_Black;
m_fClearDepth = 1.f;
m_nFlags = 0;
m_nFilterFlags = 0xffffffff;
m_nProcessFlags = 0;
m_nIDInPool = -1;
m_nWidth = 256;
m_nHeight = 256;
m_eTF = eTF_R8G8B8A8;
m_eUpdateType = eRTUpdate_Unknown;
m_refSamplerID = -1;
}
virtual void Release()
{
m_nRefCount--;
if (m_nRefCount)
{
return;
}
delete this;
}
virtual void AddRef()
{
m_nRefCount++;
}
SEnvTexture* GetEnv2D();
SEnvTexture* GetEnvCM();
void GetMemoryUsage(ICrySizer* pSizer) const;
};
//=============================================================================
// Hardware shaders
#define SHADER_BIND_TEXTURE 0x2000
#define SHADER_BIND_SAMPLER 0x4000
//=============================================================================
struct SShaderCacheHeaderItem
{
AZ::u32 m_nVertexFormat;
byte m_Class;
byte m_nInstBinds;
byte m_StreamMask_Stream;
uint32 m_CRC32;
uint16 m_StreamMask_Decl;
int16 m_nInstructions;
SShaderCacheHeaderItem()
{
memset(this, 0, sizeof(SShaderCacheHeaderItem));
}
AUTO_STRUCT_INFO
};
#define MAX_VAR_NAME 512
struct SShaderCacheHeaderItemVar
{
int m_Reg;
short m_nCount;
char m_Name[MAX_VAR_NAME];
SShaderCacheHeaderItemVar()
{
memset(this, 0, sizeof(SShaderCacheHeaderItemVar));
}
};
struct SCompressedData
{
byte* m_pCompressedShader;
uint32 m_nSizeCompressedShader;
uint32 m_nSizeDecompressedShader;
SCompressedData()
{
m_pCompressedShader = NULL;
m_nSizeCompressedShader = 0;
m_nSizeDecompressedShader = 0;
}
int Size()
{
int nSize = sizeof(SCompressedData);
if (m_pCompressedShader)
{
nSize += m_nSizeCompressedShader;
}
return nSize;
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
//pSizer->AddObject(this, sizeof(SCompressedData));
if (m_pCompressedShader)
{
pSizer->AddObject(m_pCompressedShader, m_nSizeCompressedShader);
}
}
};
typedef AZStd::unordered_map<int, struct SD3DShader*, AZStd::hash<int>, AZStd::equal_to<int>, AZ::StdLegacyAllocator> FXDeviceShader;
typedef FXDeviceShader::iterator FXDeviceShaderItor;
typedef AZStd::unordered_map<int, SCompressedData, AZStd::hash<int>, AZStd::equal_to<int>, AZ::StdLegacyAllocator> FXCompressedShader;
typedef FXCompressedShader::iterator FXCompressedShaderItor;
typedef AZStd::unordered_map<CCryNameTSCRC, int, AZStd::hash<CCryNameTSCRC>, AZStd::equal_to<CCryNameTSCRC>, AZ::StdLegacyAllocator> FXCompressedShaderRemap;
typedef FXCompressedShaderRemap::iterator FXCompressedShaderRemapItor;
struct SHWActivatedShader
{
bool m_bPersistent;
FXCompressedShader m_CompressedShaders;
FXCompressedShaderRemap m_Remap;
~SHWActivatedShader();
int Size();
void GetMemoryUsage(ICrySizer* pSizer) const;
};
typedef AZStd::unordered_map<CCryNameTSCRC, SHWActivatedShader*, AZStd::hash<CCryNameTSCRC>, AZStd::equal_to<CCryNameTSCRC>, AZ::StdLegacyAllocator> FXCompressedShaders;
typedef FXCompressedShaders::iterator FXCompressedShadersItor;
#define CACHE_READONLY 0
#define CACHE_USER 1
struct SOptimiseStats
{
int nEntries;
int nUniqueEntries;
int nSizeUncompressed;
int nSizeCompressed;
int nTokenDataSize;
int nDirDataSize;
SOptimiseStats()
{
nEntries = 0;
nUniqueEntries = 0;
nSizeUncompressed = 0;
nSizeCompressed = 0;
nTokenDataSize = 0;
nDirDataSize = 0;
}
};
typedef AZStd::unordered_map<CCryNameR, SShaderCache*, AZStd::hash<CCryNameR>, AZStd::equal_to<CCryNameR>, AZ::StdLegacyAllocator> FXShaderCache;
typedef FXShaderCache::iterator FXShaderCacheItor;
typedef AZStd::unordered_map<CCryNameR, SShaderDevCache*, AZStd::hash<CCryNameR>, AZStd::equal_to<CCryNameR>, AZ::StdLegacyAllocator> FXShaderDevCache;
typedef FXShaderDevCache::iterator FXShaderDevCacheItor;
typedef AZStd::unordered_map<string, uint32, AZStd::hash<string>, AZStd::equal_to<string>, AZ::StdLegacyAllocator> FXShaderCacheNames;
typedef FXShaderCacheNames::iterator FXShaderCacheNamesItor;
//====================================================================
// HWShader run-time flags
enum EHWSRMaskBit
{
HWSR_FOG = 0,
HWSR_AMBIENT,
HWSR_ALPHATEST,
HWSR_ALPHABLEND,
HWSR_HDR_MODE, // deprecated: this flag is redundant and can be dropped, since rendering always HDR since CE3
HWSR_HDR_ENCODE,
HWSR_INSTANCING_ATTR,
HWSR_VERTEX_VELOCITY,
HWSR_SKINNING_DUAL_QUAT,
HWSR_SKINNING_DQ_LINEAR,
HWSR_SKINNING_MATRIX,
HWSR_OBJ_IDENTITY,
HWSR_DETAIL_OVERLAY,
HWSR_NEAREST,
HWSR_NOZPASS,
HWSR_DISSOLVE,
HWSR_APPLY_TOON_SHADING,
HWSR_NO_TESSELLATION,
HWSR_PER_INSTANCE_CB_TEMP,
HWSR_QUALITY,
HWSR_QUALITY1,
HWSR_SAMPLE0,
HWSR_SAMPLE1,
HWSR_SAMPLE2,
HWSR_SAMPLE3,
HWSR_SAMPLE4,
HWSR_SAMPLE5,
HWSR_DEBUG0,
HWSR_DEBUG1,
HWSR_DEBUG2,
HWSR_DEBUG3,
HWSR_CUBEMAP0,
HWSR_DECAL_TEXGEN_2D,
HWSR_SHADOW_MIXED_MAP_G16R16,
HWSR_HW_PCF_COMPARE,
HWSR_SHADOW_JITTERING,
HWSR_POINT_LIGHT,
HWSR_LIGHT_TEX_PROJ,
HWSR_PARTICLE_SHADOW,
HWSR_SOFT_PARTICLE,
HWSR_OCEAN_PARTICLE,
HWSR_GLOBAL_ILLUMINATION,
HWSR_ANIM_BLEND,
HWSR_ENVIRONMENT_CUBEMAP,
HWSR_MOTION_BLUR,
HWSR_SPRITE,
HWSR_LIGHTVOLUME0,
HWSR_LIGHTVOLUME1,
HWSR_TILED_SHADING,
HWSR_VOLUMETRIC_FOG,
HWSR_REVERSE_DEPTH,
HWSR_GPU_PARTICLE_SHADOW_PASS,
HWSR_GPU_PARTICLE_DEPTH_COLLISION,
HWSR_GPU_PARTICLE_TURBULENCE,
HWSR_GPU_PARTICLE_UV_ANIMATION,
HWSR_GPU_PARTICLE_NORMAL_MAP,
HWSR_GPU_PARTICLE_GLOW_MAP,
HWSR_GPU_PARTICLE_CUBEMAP_DEPTH_COLLISION,
HWSR_GPU_PARTICLE_WRITEBACK_DEATH_LOCATIONS,
HWSR_GPU_PARTICLE_TARGET_ATTRACTION,
HWSR_GPU_PARTICLE_SHAPE_ANGLE,
HWSR_GPU_PARTICLE_SHAPE_BOX,
HWSR_GPU_PARTICLE_SHAPE_POINT,
HWSR_GPU_PARTICLE_SHAPE_CIRCLE,
HWSR_GPU_PARTICLE_SHAPE_SPHERE,
HWSR_GPU_PARTICLE_WIND,
HWSR_MULTI_LAYER_ALPHA_BLEND,
HWSR_ADDITIVE_BLENDING,
HWSR_APPLY_SSDO,
HWSR_FOG_VOLUME_HIGH_QUALITY_SHADER,
HWSR_SRGB0,
HWSR_SRGB1,
HWSR_SRGB2,
HWSR_DEPTHFIXUP,
HWSR_DEFERRED_RENDER_TARGET_OPTIMIZATION,
HWSR_SLIM_GBUFFER,
HWSR_MAX
};
extern uint64 g_HWSR_MaskBit[HWSR_MAX];
// HWShader global flags (m_Flags)
#define HWSG_SUPPORTS_LIGHTING 0x20
#define HWSG_SUPPORTS_MULTILIGHTS 0x40
#define HWSG_SUPPORTS_MODIF 0x80
#define HWSG_SUPPORTS_VMODIF 0x100
#define HWSG_WASGENERATED 0x200
#define HWSG_NOSPECULAR 0x400
#define HWSG_SYNC 0x800
#define HWSG_CACHE_USER 0x1000
//#define HWSG_AUTOENUMTC 0x1000
#define HWSG_UNIFIEDPOS 0x2000
#define HWSG_DEFAULTPOS 0x4000
#define HWSG_PROJECTED 0x8000
#define HWSG_NOISE 0x10000
#define HWSG_PRECACHEPHASE 0x20000
#define HWSG_FP_EMULATION 0x40000
// HWShader per-instance Modificator flags (SHWSInstance::m_MDMask)
// Vertex shader specific
// Texture projected flags
#define HWMD_TEXCOORD_PROJ 0x1
// Texture transform flag
#define HWMD_TEXCOORD_MATRIX 0x100
// Object linear texgen flag
#define HWMD_TEXCOORD_GEN_OBJECT_LINEAR_DIFFUSE 0x1000
#define HWMD_TEXCOORD_GEN_OBJECT_LINEAR_EMITTANCE 0x2000
#define HWMD_TEXCOORD_GEN_OBJECT_LINEAR_EMITTANCE_MULT 0x4000
#define HWMD_TEXCOORD_GEN_OBJECT_LINEAR_DETAIL 0x8000
#define HWMD_TEXCOORD_GEN_OBJECT_LINEAR_CUSTOM 0x10000
#define HWMD_TEXCOORD_FLAG_MASK (0xfffff000 | 0xf00)
// HWShader per-instance vertex modificator flags (SHWSInstance::m_MDVMask)
// Texture projected flags (4 bits)
#define HWMDV_TYPE 0
// HWShader input flags (passed via mfSet function)
#define HWSF_SETPOINTERSFORSHADER 1
#define HWSF_SETPOINTERSFORPASS 2
#define HWSF_PRECACHE 4
#define HWSF_SETTEXTURES 8
#define HWSF_FAKE 0x10
#define HWSF_INSTANCED 0x20
#define HWSF_NEXT 0x100
#define HWSF_PRECACHE_INST 0x200
#define HWSF_STORECOMBINATION 0x400
#define HWSF_STOREDATA 0x800
// Static flags
enum EHWSSTFlag
{
HWSST_Invalid = -1,
#undef FX_STATIC_FLAG
#define FX_STATIC_FLAG(flag) HWSST_##flag,
#include "ShaderStaticFlags.inl"
HWSST_MAX
};
class CHWShader
: public CBaseResource
{
static CCryNameTSCRC s_sClassNameVS;
static CCryNameTSCRC s_sClassNamePS;
public:
EHWShaderClass m_eSHClass;
//EHWSProfile m_eHWProfile;
SShaderCache* m_pGlobalCache;
static struct SD3DShader* s_pCurPS;
static struct SD3DShader* s_pCurVS;
static struct SD3DShader* s_pCurGS;
static struct SD3DShader* s_pCurDS;
static struct SD3DShader* s_pCurHS;
static struct SD3DShader* s_pCurCS;
string m_Name;
string m_NameSourceFX;
string m_EntryFunc;
uint64 m_nMaskAnd_RT;
uint64 m_nMaskOr_RT;
uint64 m_nMaskGenShader; // Masked/Optimised m_nMaskGenFX for this specific HW shader
uint64 m_nMaskGenFX; // FX Shader should be parsed with this flags
uint64 m_nMaskSetFX; // AffectMask GL for parser tree
uint64 m_maskGenStatic; // Mask for global static flags used for generating the shader.
uint32 m_nPreprocessFlags;
int m_nFrame;
int m_nFrameLoad;
int m_Flags;
uint32 m_CRC32;
uint32 m_dwShaderType;
public:
CHWShader()
{
m_nFrame = 0;
m_nFrameLoad = 0;
m_Flags = 0;
m_nMaskGenShader = 0;
m_nMaskAnd_RT = -1;
m_nMaskOr_RT = 0;
m_CRC32 = 0;
m_nMaskGenFX = 0;
m_nMaskSetFX = 0;
m_eSHClass = eHWSC_Vertex;
m_pGlobalCache = NULL;
}
virtual ~CHWShader() {}
//EHWSProfile mfGetHWProfile(uint32 nFlags);
#if !defined (NULL_RENDERER)
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);
#endif
static void mfReloadScript(const char* szPath, const char* szName, int nFlags, uint64 nMaskGen);
static void mfFlushPendedShadersWait(int nMaxAllowed);
inline const char* GetName()
{
return m_Name.c_str();
}
virtual int Size() = 0;
virtual void GetMemoryUsage(ICrySizer* Sizer) const = 0;
virtual void mfReset([[maybe_unused]] uint32 CRC32) {}
virtual bool mfSetV(int nFlags = 0) = 0;
virtual bool mfAddEmptyCombination(CShader* pSH, uint64 nRT, uint64 nGL, uint32 nLT) = 0;
virtual bool mfStoreEmptyCombination(SEmptyCombination& Comb) = 0;
virtual const char* mfGetCurScript() {return NULL; }
virtual const char* mfGetEntryName() = 0;
virtual void mfUpdatePreprocessFlags(SShaderTechnique* pTech) = 0;
virtual bool mfFlushCacheFile() = 0;
virtual bool mfPrecache(SShaderCombination& cmb, bool bForce, bool bFallback, bool bCompressedOnly, CShader* pSH, CShaderResources* pRes) = 0;
virtual bool Export(SShaderSerializeContext& SC) = 0;
static CHWShader* Import(SShaderSerializeContext& SC, int nOffs, uint32 CRC32, CShader* pSH);
// Vertex shader specific functions
virtual AZ::Vertex::Format mfVertexFormat(bool& bUseTangents, bool& bUseLM, bool& bUseHWSkin, bool& bUseVertexVelocity) = 0;
virtual const char* mfGetActivatedCombinations(bool bForLevel) = 0;
static const char* mfProfileString(EHWShaderClass eClass);
static const char* mfClassString(EHWShaderClass eClass);
static EHWShaderClass mfStringProfile(const char* profile);
static EHWShaderClass mfStringClass(const char* szClass);
static void mfGenName(uint64 GLMask, uint64 RTMask, uint32 LightMask, uint32 MDMask, uint32 MDVMask, uint64 PSS, uint64 STMask, EHWShaderClass eClass, char* dstname, int nSize, byte bType);
static void mfCleanupCache();
static CCryNameTSCRC mfGetClassName(EHWShaderClass eClass)
{
if (eClass == eHWSC_Vertex)
{
return s_sClassNameVS;
}
else
{
return s_sClassNamePS;
}
}
static const char* GetCurrentShaderCombinations(bool bForLevel);
static bool PreactivateShaders();
static void RT_PreactivateShaders();
static byte* mfIgnoreRemapsFromCache(int nRemaps, byte* pP);
static byte* mfIgnoreBindsFromCache(int nParams, byte* pP);
#if !defined(CONSOLE)
static bool mfOptimiseCacheFile(SShaderCache* pCache, bool bForce, SOptimiseStats* Stats);
#endif
static SShaderDevCache* mfInitDevCache(const char* name, CHWShader* pSH);
static SShaderCache* mfInitCache(const char* name, CHWShader* pSH, bool bCheckValid, uint32 CRC32, bool bReadOnly, bool bAsync = false);
static bool _OpenCacheFile(float fVersion, SShaderCache* pCache, CHWShader* pSH, bool bCheckValid, uint32 CRC32, int nCache, CResFile* pRF, bool bReadOnly);
static bool mfOpenCacheFile(const char* szName, float fVersion, SShaderCache* pCache, CHWShader* pSH, bool bCheckValid, uint32 CRC32, bool bReadOnly);
static void mfValidateTokenData(CResFile* pRF);
static FXShaderCacheNames m_ShaderCacheList;
static FXShaderCache m_ShaderCache;
// Import/Export
static bool ImportSamplers(SShaderSerializeContext& SC, struct SCHWShader* pSHW, byte*& pData, std::vector<STexSamplerRT>& Samplers);
static bool ImportParams(SShaderSerializeContext& SC, SCHWShader* pSHW, byte*& pData, std::vector<SFXParam>& Params);
static FXCompressedShaders m_CompressedShaders;
};
_inline void SortLightTypes(int Types[4], int nCount)
{
switch (nCount)
{
case 2:
if (Types[0] > Types[1])
{
Exchange(Types[0], Types[1]);
}
break;
case 3:
if (Types[0] > Types[1])
{
Exchange(Types[0], Types[1]);
}
if (Types[0] > Types[2])
{
Exchange(Types[0], Types[2]);
}
if (Types[1] > Types[2])
{
Exchange(Types[1], Types[2]);
}
break;
case 4:
{
for (int i = 0; i < 4; i++)
{
for (int j = i; j < 4; j++)
{
if (Types[i] > Types[j])
{
Exchange(Types[i], Types[j]);
}
}
}
}
break;
}
}
//=========================================================================
// Dynamic lights evaluating via shaders
enum ELightStyle
{
eLS_Intensity,
eLS_RGB,
};
enum ELightMoveType
{
eLMT_Wave,
eLMT_Patch,
};
struct SLightMove
{
ELightMoveType m_eLMType;
SWaveForm m_Wave;
Vec3 m_Dir;
float m_fSpeed;
int Size()
{
int nSize = sizeof(SLightMove);
return nSize;
}
};
struct SLightStyleKeyFrame
{
ColorF cColor; // xyz: color, w: spec mult
Vec3 vPosOffset; // position offset
SLightStyleKeyFrame()
{
cColor = ColorF(Col_Black);
vPosOffset = Vec3(ZERO);
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
};
class CLightStyle
{
public:
CLightStyle()
: m_Color(Col_White)
, m_vPosOffset(ZERO)
, m_LastTime(0.0f)
, m_TimeIncr(60.0f)
, m_bRandColor(0)
, m_bRandIntensity(0)
, m_bRandPosOffset(0)
, m_bRandSpecMult(0)
{
}
static TArray <CLightStyle*> s_LStyles;
TArray<SLightStyleKeyFrame> m_Map;
ColorF m_Color; // xyz: color, w: spec mult
Vec3 m_vPosOffset; // position offset
float m_TimeIncr;
float m_LastTime;
uint8 m_bRandColor : 1;
uint8 m_bRandIntensity : 1;
uint8 m_bRandPosOffset : 1;
uint8 m_bRandSpecMult : 1;
int Size()
{
int nSize = sizeof(CLightStyle);
nSize += m_Map.GetMemoryUsage();
return nSize;
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->Add(*this);
pSizer->AddObject(m_Map);
}
static _inline CLightStyle* mfGetStyle(uint32 nStyle, float fTime)
{
if (nStyle >= s_LStyles.Num() || !s_LStyles[nStyle])
{
return NULL;
}
s_LStyles[nStyle]->mfUpdate(fTime);
return s_LStyles[nStyle];
}
void mfUpdate(float fTime);
};
//=========================================================================
// HW Shader Layer
#define SHPF_AMBIENT 0x100
#define SHPF_HASLM 0x200
#define SHPF_SHADOW 0x400
#define SHPF_RADIOSITY 0x800
#define SHPF_ALLOW_SPECANTIALIAS 0x1000
#define SHPF_BUMP 0x2000
#define SHPF_NOMATSTATE 0x4000
#define SHPF_FORCEZFUNC 0x8000
// Shader pass definition for HW shaders
struct SShaderPass
{
uint32 m_RenderState; // Render state flags
signed char m_eCull;
uint8 m_AlphaRef;
uint16 m_PassFlags; // Different usefull Pass flags (SHPF_)
CHWShader* m_VShader; // Pointer to the vertex shader for the current pass
CHWShader* m_PShader; // Pointer to fragment shader
CHWShader* m_GShader; // Pointer to the geometry shader for the current pass
CHWShader* m_HShader; // Pointer to the hull shader for the current pass
CHWShader* m_DShader; // Pointer to the domain shader for the current pass
CHWShader* m_CShader; // Pointer to the compute shader for the current pass
SShaderPass();
int Size()
{
int nSize = sizeof(SShaderPass);
return nSize;
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(m_VShader);
pSizer->AddObject(m_PShader);
pSizer->AddObject(m_GShader);
pSizer->AddObject(m_HShader);
pSizer->AddObject(m_DShader);
pSizer->AddObject(m_CShader);
}
void mfFree()
{
SAFE_RELEASE(m_VShader);
SAFE_RELEASE(m_PShader);
SAFE_RELEASE(m_GShader);
SAFE_RELEASE(m_HShader);
SAFE_RELEASE(m_DShader);
SAFE_RELEASE(m_CShader);
}
void AddRefsToShaders()
{
if (m_VShader)
{
m_VShader->AddRef();
}
if (m_PShader)
{
m_PShader->AddRef();
}
if (m_GShader)
{
m_GShader->AddRef();
}
if (m_DShader)
{
m_DShader->AddRef();
}
if (m_HShader)
{
m_HShader->AddRef();
}
if (m_CShader)
{
m_CShader->AddRef();
}
}
private:
SShaderPass& operator = (const SShaderPass& sl);
};
//===================================================================================
// Hardware Stage for HW only Shaders
#define FHF_FIRSTLIGHT 8
#define FHF_FORANIM 0x10
#define FHF_TERRAIN 0x20
#define FHF_NOMERGE 0x40
#define FHF_DETAILPASS 0x80
#define FHF_LIGHTPASS 0x100
#define FHF_FOGPASS 0x200
#define FHF_PUBLIC 0x400
#define FHF_NOLIGHTS 0x800
#define FHF_POSITION_INVARIANT 0x1000
#define FHF_RE_CLOUD 0x20000
#define FHF_TRANSPARENT 0x40000
#define FHF_WASZWRITE 0x80000
#define FHF_USE_GEOMETRY_SHADER 0x100000
#define FHF_USE_HULL_SHADER 0x200000
#define FHF_USE_DOMAIN_SHADER 0x400000
#define FHF_RE_LENSOPTICS 0x1000000
struct SShaderTechnique
{
CShader* m_shader;
CCryNameR m_NameStr;
CCryNameTSCRC m_NameCRC;
TArray <SShaderPass> m_Passes; // General passes
int m_Flags; // Different flags (FHF_)
uint32 m_nPreprocessFlags;
int8 m_nTechnique[TTYPE_MAX]; // Next technique in sequence
TArray<CRendElementBase*> m_REs; // List of all render elements registered in the shader
TArray<SHRenderTarget*> m_RTargets;
float m_fProfileTime;
int Size()
{
uint32 i;
int nSize = sizeof(SShaderTechnique);
for (i = 0; i < m_Passes.Num(); i++)
{
nSize += m_Passes[i].Size();
}
nSize += m_RTargets.GetMemoryUsage();
return nSize;
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->Add(*this);
pSizer->AddObject(m_Passes);
pSizer->AddObject(m_REs);
pSizer->AddObject(m_RTargets);
}
SShaderTechnique(CShader* shader)
{
m_shader = shader;
uint32 i;
for (i = 0; i < TTYPE_MAX; i++)
{
m_nTechnique[i] = -1;
}
for (i = 0; i < m_REs.Num(); i++)
{
SAFE_DELETE(m_REs[i]);
}
m_REs.Free();
m_Flags = 0;
m_nPreprocessFlags = 0;
m_fProfileTime = 0;
}
SShaderTechnique& operator = (const SShaderTechnique& sl)
{
memcpy(this, &sl, sizeof(SShaderTechnique));
if (sl.m_Passes.Num())
{
m_Passes.Copy(sl.m_Passes);
for (uint32 i = 0; i < sl.m_Passes.Num(); i++)
{
SShaderPass* d = &m_Passes[i];
d->AddRefsToShaders();
}
}
if (sl.m_REs.Num())
{
m_REs.Create(sl.m_REs.Num());
for (uint32 i = 0; i < sl.m_REs.Num(); i++)
{
if (sl.m_REs[i])
{
m_REs[i] = sl.m_REs[i]->mfCopyConstruct();
}
}
}
return *this;
}
~SShaderTechnique()
{
for (uint32 i = 0; i < m_Passes.Num(); i++)
{
SShaderPass* sl = &m_Passes[i];
sl->mfFree();
}
for (uint32 i = 0; i < m_REs.Num(); i++)
{
CRendElementBase* pRE = m_REs[i];
pRE->Release(false);
}
m_REs.Free();
m_Passes.Free();
}
void UpdatePreprocessFlags(CShader* pSH);
void* operator new(size_t Size) { void* ptr = CryModuleMalloc(Size); memset(ptr, 0, Size); return ptr; }
void* operator new(size_t Size, [[maybe_unused]] const std::nothrow_t& nothrow)
{
void* ptr = CryModuleMalloc(Size);
if (ptr)
{
memset(ptr, 0, Size);
}
return ptr;
}
void operator delete(void* Ptr) { CryModuleFree(Ptr); }
};
//===============================================================================
// General Shader structure
class CShader
: public IShader
, public CBaseResource
{
static CCryNameTSCRC s_sClassName;
public:
string m_NameFile; // } FIXME: This fields order is very important
string m_NameShader;
EShaderDrawType m_eSHDType; // } Check CShader::operator = in ShaderCore.cpp for more info
uint32 m_Flags; // Different flags EF_ (see IShader.h)
uint32 m_Flags2; // Different flags EF2_ (see IShader.h)
uint32 m_nMDV; // Vertex modificator flags
uint32 m_NameShaderICRC;
AZ::Vertex::Format m_vertexFormat; // Base vertex format for the shader (see VertexFormats.h)
ECull m_eCull; // Global culling type
TArray <SShaderTechnique*> m_HWTechniques; // Hardware techniques
int m_nMaskCB;
EShaderType m_eShaderType; // [Shader System TO DO] - possibly change to be data driven
uint64 m_nMaskGenFX;
uint64 m_maskGenStatic; // Static global flags used for generating the shader.
SShaderGen* m_ShaderGenParams; // BitMask params used in automatic script generation
SShaderGen* m_ShaderGenStaticParams;
SShaderTexSlots* m_ShaderTexSlots[TTYPE_MAX]; // filled out with data of the used texture slots for a given technique
// (might be NULL if this data isn't gathered)
std::vector<CShader*>* m_DerivedShaders;
CShader* m_pGenShader;
int m_nRefreshFrame; // Current frame for shader reloading (to avoid multiple reloading)
uint32 m_SourceCRC32;
uint32 m_CRC32;
//============================================================================
inline int mfGetID() { return CBaseResource::GetID(); }
void mfFree();
CShader()
: m_eSHDType(eSHDT_General)
, m_Flags(0)
, m_Flags2(0)
, m_nMDV(0)
, m_NameShaderICRC(0)
, m_vertexFormat(eVF_P3F_C4B_T2F)
, m_eCull((ECull) - 1)
, m_nMaskCB(0)
, m_eShaderType(eST_General)
, m_nMaskGenFX(0)
, m_ShaderGenParams(nullptr)
, m_DerivedShaders(nullptr)
, m_pGenShader(nullptr)
, m_nRefreshFrame(0)
, m_SourceCRC32(0)
, m_CRC32(0)
, m_ShaderGenStaticParams(nullptr)
, m_maskGenStatic(0)
{
memset(m_ShaderTexSlots, 0, sizeof(m_ShaderTexSlots));
}
virtual ~CShader();
//===================================================================================
// IShader interface
virtual int AddRef() { return CBaseResource::AddRef(); }
virtual int Release()
{
if (m_Flags & EF_SYSTEM)
{
return -1;
}
return CBaseResource::Release();
}
virtual int ReleaseForce()
{
m_Flags &= ~EF_SYSTEM;
int nRef = 0;
while (true)
{
nRef = Release();
if (nRef <= 0)
{
break;
}
}
return nRef;
}
virtual int GetID() { return CBaseResource::GetID(); }
virtual int GetRefCounter() const { return CBaseResource::GetRefCounter(); }
virtual const char* GetName() { return m_NameShader.c_str(); }
virtual const char* GetName() const { return m_NameShader.c_str(); }
// D3D Effects interface
virtual bool FXSetTechnique(const CCryNameTSCRC& Name);
virtual bool FXSetPSFloat(const CCryNameR& NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetCSFloat(const CCryNameR& NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetVSFloat(const CCryNameR& NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetGSFloat(const CCryNameR& NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetPSFloat(const char* NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetCSFloat(const char* NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetVSFloat(const char* NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXSetGSFloat(const char* NameParam, const Vec4 fParams[], int nParams) override;
virtual bool FXBegin(uint32* uiPassCount, uint32 nFlags) override;
virtual bool FXBeginPass(uint32 uiPass) override;
virtual bool FXCommit(const uint32 nFlags) override;
virtual bool FXEndPass() override;
virtual bool FXEnd() override;
virtual int GetFlags() const { return m_Flags; }
virtual int GetFlags2() const { return m_Flags2; }
virtual void SetFlags2(int Flags) { m_Flags2 |= Flags; }
virtual void ClearFlags2(int Flags) { m_Flags2 &= ~Flags; }
virtual bool Reload(int nFlags, const char* szShaderName);
#if !defined(CONSOLE) && !defined(NULL_RENDERER)
virtual void mfFlushCache();
#endif
void mfFlushPendedShaders();
virtual int GetTechniqueID(int nTechnique, int nRegisteredTechnique)
{
if (nTechnique < 0)
{
nTechnique = 0;
}
if ((int)m_HWTechniques.Num() <= nTechnique)
{
return -1;
}
SShaderTechnique* pTech = m_HWTechniques[nTechnique];
return pTech->m_nTechnique[nRegisteredTechnique];
}
virtual TArray<CRendElementBase*>* GetREs (int nTech)
{
if (nTech < 0)
{
nTech = 0;
}
if (nTech < (int)m_HWTechniques.Num())
{
SShaderTechnique* pTech = m_HWTechniques[nTech];
return &pTech->m_REs;
}
return NULL;
}
virtual int GetTexId ();
virtual unsigned int GetUsedTextureTypes (void);
virtual AZ::Vertex::Format GetVertexFormat(void) { return m_vertexFormat; }
virtual uint64 GetGenerationMask() { return m_nMaskGenFX; }
virtual ECull GetCull(void)
{
if (m_HWTechniques.Num())
{
SShaderTechnique* pTech = m_HWTechniques[0];
if (pTech->m_Passes.Num())
{
return (ECull)pTech->m_Passes[0].m_eCull;
}
}
return eCULL_None;
}
virtual SShaderGen* GetGenerationParams()
{
if (m_ShaderGenParams)
{
return m_ShaderGenParams;
}
if (m_pGenShader)
{
return m_pGenShader->m_ShaderGenParams;
}
return NULL;
}
size_t GetNumberOfUVSets() override
{
SShaderGen* shaderGenParams = GetGenerationParams();
if (shaderGenParams)
{
for (int i = 0; i < shaderGenParams->m_BitMask.Num(); i++)
{
// A material with any of the following shader gen params is using 2 uv sets
if (shaderGenParams->m_BitMask[i]->m_ParamName == "%BLENDLAYER_UV_SET_2" ||
shaderGenParams->m_BitMask[i]->m_ParamName == "%EMITTANCE_MAP_UV_SET_2" ||
shaderGenParams->m_BitMask[i]->m_ParamName == "%DETAIL_MAPPING_UV_SET_2")
{
if (shaderGenParams->m_BitMask[i]->m_Mask & m_nMaskGenFX)
{
return 2;
}
}
}
}
return 1;
}
virtual SShaderTexSlots* GetUsedTextureSlots(int nTechnique);
virtual AZStd::vector<SShaderParam>& GetPublicParams();
virtual EShaderType GetShaderType() { return m_eShaderType; }
virtual EShaderDrawType GetShaderDrawType() const { return m_eSHDType; }
virtual uint32 GetVertexModificator() { return m_nMDV; }
//=======================================================================================
bool mfPrecache(SShaderCombination& cmb, bool bForce, bool bCompressedOnly, CShaderResources* pRes);
SShaderTechnique* mfFindTechnique(const CCryNameTSCRC& name)
{
uint32 i;
for (i = 0; i < m_HWTechniques.Num(); i++)
{
SShaderTechnique* pTech = m_HWTechniques[i];
if (pTech->m_NameCRC == name)
{
return pTech;
}
}
return NULL;
}
SShaderTechnique* mfGetStartTechnique(int nTechnique);
// CRY DX12
SShaderTechnique* GetTechnique(int nStartTechnique, int nRequestedTechnique);
virtual ITexture* GetBaseTexture(int* nPass, int* nTU);
CShader& operator = (const CShader& src);
CTexture* mfFindBaseTexture(TArray<SShaderPass>& Passes, int* nPass, int* nTU);
int mfSize();
// All loaded shaders resources list
static TArray<CShaderResources*> s_ShaderResources_known;
virtual int Size([[maybe_unused]] int Flags)
{
return mfSize();
}
virtual void GetMemoryUsage(ICrySizer* Sizer) const;
void* operator new(size_t Size) { void* ptr = CryModuleMalloc(Size); memset(ptr, 0, Size); return ptr; }
void* operator new(size_t Size, [[maybe_unused]] const std::nothrow_t& nothrow)
{
void* ptr = CryModuleMalloc(Size);
if (ptr)
{
memset(ptr, 0, Size);
}
return ptr;
}
void operator delete(void* Ptr) { CryModuleFree(Ptr); }
static CCryNameTSCRC mfGetClassName()
{
return s_sClassName;
}
};
inline SShaderTechnique* SShaderItem::GetTechnique() const
{
SShaderTechnique* pTech = NULL;
int nTech = m_nTechnique;
if (nTech < 0)
{
nTech = 0;
}
CShader* pSH = (CShader*)m_pShader;
if (pSH && !pSH->m_HWTechniques.empty())
{
CryPrefetch(&pSH->m_HWTechniques[0]);
assert(m_nTechnique < 0 || pSH->m_HWTechniques.Num() == 0 || nTech < (int)pSH->m_HWTechniques.Num());
if (nTech < (int)pSH->m_HWTechniques.Num())
{
return pSH->m_HWTechniques[nTech];
}
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
#endif // CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_SHADERS_SHADER_H