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.
1117 lines
30 KiB
C++
1117 lines
30 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.
|
|
|
|
#ifndef __SHADERSERIALIZE_H__
|
|
#define __SHADERSERIALIZE_H__
|
|
|
|
#if defined(SHADERS_SERIALIZING)
|
|
|
|
#include "../ResFile.h"
|
|
|
|
// Enable this for verbose messages related to r_shadersExport and r_shadersImport
|
|
//#define SHADER_SERIALIZE_VERBOSE
|
|
|
|
//
|
|
// console enums taken from d3d9types.h
|
|
//
|
|
|
|
enum X360AddressModes
|
|
{
|
|
X360TADDRESS_WRAP = 0,
|
|
X360TADDRESS_MIRROR = 1,
|
|
X360TADDRESS_CLAMP = 2,
|
|
X360TADDRESS_MIRRORONCE = 3,
|
|
X360TADDRESS_BORDER_HALF = 4,
|
|
X360TADDRESS_MIRRORONCE_BORDER_HALF = 5,
|
|
X360TADDRESS_BORDER = 6,
|
|
X360TADDRESS_MIRRORONCE_BORDER = 7,
|
|
};
|
|
|
|
enum X360FilterType
|
|
{
|
|
X360TEXF_NONE = 2,
|
|
X360TEXF_POINT = 0,
|
|
X360TEXF_LINEAR = 1,
|
|
X360TEXF_ANISOTROPIC = 4,
|
|
};
|
|
|
|
inline void sAlignData(TArray<byte>& Dst, uint32 align)
|
|
{
|
|
if (align > 0 && (Dst.Num() & (align - 1)))
|
|
{
|
|
const byte PAD = 0;
|
|
int pad = align - (Dst.Num() & (align - 1));
|
|
|
|
for (int i = 0; i < pad; i++)
|
|
{
|
|
Dst.push_back(PAD);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void sAddData(TArray<byte>& Dst, T Src, uint32 align = 0)
|
|
{
|
|
int nSize = sizeof(T);
|
|
byte* pDst = Dst.Grow(nSize);
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
T data = Src;
|
|
SwapEndian(data, eBigEndian);
|
|
memcpy(pDst, &data, nSize);
|
|
}
|
|
else
|
|
{
|
|
memcpy(pDst, &Src, nSize);
|
|
}
|
|
|
|
if (align > 0)
|
|
{
|
|
sAlignData(Dst, align);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void sAddDataArray_POD(TArray<byte>& Dst, TArray<T>& Src, uint32& nOffs, uint32 align = 0)
|
|
{
|
|
nOffs = Dst.Num();
|
|
int nSize = sizeof(T) * Src.Num();
|
|
if (!nSize)
|
|
{
|
|
return;
|
|
}
|
|
T* pDst = (T*)Dst.Grow(nSize);
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
for (uint32 i = 0; i < Src.size(); i++)
|
|
{
|
|
T d = Src[i];
|
|
SwapEndian(d, eBigEndian);
|
|
memcpy(pDst, &d, sizeof(T));
|
|
pDst++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy(pDst, &Src[0], nSize);
|
|
}
|
|
|
|
if (align > 0)
|
|
{
|
|
sAlignData(Dst, align);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void sExport(TArray<byte>& dst, T& data)
|
|
{
|
|
int startNum = dst.Num();
|
|
|
|
data.Export(dst);
|
|
|
|
// DEBUG: Check we wrote the data we expected
|
|
// Only works on native export since structures are different sizes on console :(
|
|
if (!CParserBin::m_bEndians)
|
|
{
|
|
AZ_Assert(dst.Num() - startNum == sizeof(T), "ShaderSerialize export size mismatch");
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void sAddDataArray(TArray<byte>& Dst, TArray<T>& Src, uint32& nOffs, uint32 align = 0)
|
|
{
|
|
nOffs = Dst.Num();
|
|
int nSize = sizeof(T) * Src.Num();
|
|
if (!nSize)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
int startNum = Dst.Num();
|
|
|
|
for (uint32 i = 0; i < Src.size(); i++)
|
|
{
|
|
sExport(Dst, Src[i]);
|
|
}
|
|
|
|
// DEBUG - compare src and dest, check export was successful
|
|
if (!CParserBin::m_bEndians)
|
|
{
|
|
if (memcmp(&Src[0], &Dst[startNum], nSize) != 0)
|
|
{
|
|
CryFatalError("Copy failed");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte* pDst = Dst.Grow(nSize);
|
|
memcpy(pDst, &Src[0], nSize);
|
|
}
|
|
|
|
if (align > 0)
|
|
{
|
|
sAlignData(Dst, align);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void SwapEndianEnum(T& e, bool bSwapEndian)
|
|
{
|
|
uint32 enumConv = e;
|
|
SwapEndian(enumConv, bSwapEndian);
|
|
e = (T)enumConv;
|
|
}
|
|
|
|
struct SSShaderCacheHeader
|
|
{
|
|
int m_SizeOf;
|
|
char m_szVer[16];
|
|
int m_MajorVer;
|
|
int m_MinorVer;
|
|
uint32 m_CRC32;
|
|
uint32 m_SourceCRC32;
|
|
SSShaderCacheHeader()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
AUTO_STRUCT_INFO
|
|
};
|
|
|
|
|
|
struct SSShaderRes
|
|
{
|
|
int m_nRefCount;
|
|
CResFile* m_pRes[2];
|
|
SSShaderCacheHeader m_Header[2];
|
|
bool m_bReadOnly[2];
|
|
SSShaderRes()
|
|
{
|
|
m_nRefCount = 1;
|
|
m_pRes[0] = NULL;
|
|
m_pRes[1] = NULL;
|
|
m_bReadOnly[0] = true;
|
|
m_bReadOnly[1] = true;
|
|
}
|
|
~SSShaderRes()
|
|
{
|
|
SAFE_DELETE(m_pRes[0]);
|
|
SAFE_DELETE(m_pRes[1]);
|
|
}
|
|
};
|
|
typedef std::map<CCryNameTSCRC, SSShaderRes*> FXSShaderRes;
|
|
typedef FXSShaderRes::iterator FXSShaderResItor;
|
|
|
|
struct SSShader
|
|
{
|
|
uint64 m_nMaskGenFX;
|
|
|
|
EShaderDrawType m_eSHDType;
|
|
|
|
uint32 m_Flags;
|
|
uint32 m_Flags2;
|
|
uint32 m_nMDV;
|
|
|
|
uint32 m_vertexFormatEnum; // Base vertex format for the shader (see VertexFormats.h)
|
|
ECull m_eCull; // Global culling type
|
|
|
|
EShaderType m_eShaderType;
|
|
|
|
uint32 m_nTechniques;
|
|
uint32 m_nPasses;
|
|
uint32 m_nPublicParams;
|
|
uint32 m_nFXParams;
|
|
uint32 m_nFXSamplers;
|
|
uint32 m_nFXTextures;
|
|
uint32 m_nFXTexSamplers;
|
|
uint32 m_nFXTexRTs;
|
|
uint32 m_nDataSize;
|
|
uint32 m_nStringsSize;
|
|
|
|
uint32 m_nPublicParamsOffset;
|
|
uint32 m_nFXParamsOffset;
|
|
uint32 m_nFXSamplersOffset;
|
|
uint32 m_nFXTexturesOffset;
|
|
uint32 m_nFXTexSamplersOffset;
|
|
uint32 m_nFXTexRTsOffset;
|
|
uint32 m_nTechOffset;
|
|
uint32 m_nPassOffset;
|
|
uint32 m_nStringsOffset;
|
|
uint32 m_nDataOffset;
|
|
|
|
SSShader()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nMaskGenFX);
|
|
sAddData(dst, (uint32)m_eSHDType);
|
|
sAddData(dst, m_Flags);
|
|
sAddData(dst, m_Flags2);
|
|
sAddData(dst, m_nMDV);
|
|
sAddData(dst, m_vertexFormatEnum);
|
|
sAddData(dst, (uint32)m_eCull);
|
|
sAddData(dst, (uint32)m_eShaderType);
|
|
sAddData(dst, m_nTechniques);
|
|
sAddData(dst, m_nPasses);
|
|
sAddData(dst, m_nPublicParams);
|
|
sAddData(dst, m_nFXParams);
|
|
sAddData(dst, m_nFXSamplers);
|
|
sAddData(dst, m_nFXTextures);
|
|
sAddData(dst, m_nFXTexSamplers);
|
|
sAddData(dst, m_nFXTexRTs);
|
|
sAddData(dst, m_nDataSize);
|
|
sAddData(dst, m_nStringsSize);
|
|
|
|
sAddData(dst, m_nPublicParamsOffset);
|
|
sAddData(dst, m_nFXParamsOffset);
|
|
sAddData(dst, m_nFXSamplersOffset);
|
|
sAddData(dst, m_nFXTexturesOffset);
|
|
sAddData(dst, m_nFXTexSamplersOffset);
|
|
sAddData(dst, m_nFXTexRTsOffset);
|
|
sAddData(dst, m_nTechOffset);
|
|
sAddData(dst, m_nPassOffset);
|
|
sAddData(dst, m_nStringsOffset);
|
|
sAddData(dst, m_nDataOffset);
|
|
|
|
uint32 PAD = 0;
|
|
sAddData(dst, PAD); //pad to 64bit
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nMaskGenFX, eBigEndian);
|
|
SwapEndianEnum(m_eSHDType, eBigEndian);
|
|
;
|
|
SwapEndian(m_Flags, eBigEndian);
|
|
;
|
|
SwapEndian(m_Flags2, eBigEndian);
|
|
SwapEndian(m_nMDV, eBigEndian);
|
|
SwapEndianEnum(m_vertexFormatEnum, eBigEndian);
|
|
SwapEndianEnum(m_eCull, eBigEndian);
|
|
SwapEndianEnum(m_eShaderType, eBigEndian);
|
|
SwapEndian(m_nTechniques, eBigEndian);
|
|
SwapEndian(m_nPasses, eBigEndian);
|
|
SwapEndian(m_nPublicParams, eBigEndian);
|
|
SwapEndian(m_nFXParams, eBigEndian);
|
|
SwapEndian(m_nFXSamplers, eBigEndian);
|
|
SwapEndian(m_nFXTextures, eBigEndian);
|
|
SwapEndian(m_nFXTexSamplers, eBigEndian);
|
|
SwapEndian(m_nFXTexRTs, eBigEndian);
|
|
SwapEndian(m_nDataSize, eBigEndian);
|
|
SwapEndian(m_nStringsSize, eBigEndian);
|
|
SwapEndian(m_nPublicParamsOffset, eBigEndian);
|
|
SwapEndian(m_nFXParamsOffset, eBigEndian);
|
|
SwapEndian(m_nFXSamplersOffset, eBigEndian);
|
|
SwapEndian(m_nFXTexturesOffset, eBigEndian);
|
|
SwapEndian(m_nFXTexSamplersOffset, eBigEndian);
|
|
SwapEndian(m_nFXTexRTsOffset, eBigEndian);
|
|
SwapEndian(m_nTechOffset, eBigEndian);
|
|
SwapEndian(m_nPassOffset, eBigEndian);
|
|
SwapEndian(m_nStringsOffset, eBigEndian);
|
|
SwapEndian(m_nDataOffset, eBigEndian);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSShaderParam
|
|
{
|
|
uint32 m_nameIdx;
|
|
EParamType m_Type;
|
|
UParamVal m_Value;
|
|
int m_nScriptOffs;
|
|
uint8 m_eSemantic;
|
|
|
|
SSShaderParam()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nameIdx);
|
|
sAddData(dst, (uint32)m_Type);
|
|
|
|
int sizeWritten = 0;
|
|
|
|
switch (m_Type)
|
|
{
|
|
case eType_BYTE:
|
|
sAddData(dst, m_Value.m_Byte);
|
|
sizeWritten = sizeof(m_Value.m_Byte);
|
|
break;
|
|
case eType_BOOL:
|
|
sAddData(dst, m_Value.m_Bool);
|
|
sizeWritten = sizeof(m_Value.m_Bool);
|
|
break;
|
|
case eType_SHORT:
|
|
sAddData(dst, m_Value.m_Short);
|
|
sizeWritten = sizeof(m_Value.m_Short);
|
|
break;
|
|
case eType_INT:
|
|
sAddData(dst, m_Value.m_Int);
|
|
sizeWritten = sizeof(m_Value.m_Int);
|
|
break;
|
|
case eType_HALF:
|
|
//half behaves like float?
|
|
sAddData(dst, m_Value.m_Float);
|
|
sizeWritten = sizeof(m_Value.m_Float);
|
|
break;
|
|
case eType_FLOAT:
|
|
sAddData(dst, m_Value.m_Float);
|
|
sizeWritten = sizeof(m_Value.m_Float);
|
|
break;
|
|
case eType_FCOLOR:
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
sAddData(dst, m_Value.m_Color[i]);
|
|
}
|
|
sizeWritten = sizeof(m_Value.m_Color);
|
|
}
|
|
break;
|
|
case eType_VECTOR:
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
sAddData(dst, m_Value.m_Vector[i]);
|
|
}
|
|
sizeWritten = sizeof(m_Value.m_Vector);
|
|
}
|
|
break;
|
|
|
|
//case eType_STRING,
|
|
//case eType_TEXTURE_HANDLE:
|
|
//case eType_CAMERA:
|
|
//case eType_UNKNOWN:
|
|
default:
|
|
CryFatalError("Shader param type not valid for export\n");
|
|
break;
|
|
}
|
|
|
|
//Pad to union size
|
|
byte PAD = 0;
|
|
uint32 nPadding = sizeof(UParamVal) - sizeWritten;
|
|
|
|
for (uint32 i = 0; i < nPadding; i++)
|
|
{
|
|
sAddData(dst, PAD);
|
|
}
|
|
|
|
sAddData(dst, m_nScriptOffs);
|
|
sAddData(dst, m_eSemantic);
|
|
|
|
// Align for struct padding
|
|
sAlignData(dst, 8);
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nameIdx, eBigEndian);
|
|
SwapEndianEnum(m_Type, eBigEndian);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
SwapEndian(m_Value.m_Color[i], eBigEndian);
|
|
}
|
|
SwapEndian(m_nScriptOffs, eBigEndian);
|
|
SwapEndian(m_eSemantic, eBigEndian);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSShaderTechnique
|
|
{
|
|
int m_nNameOffs;
|
|
int m_nPassesOffs;
|
|
int m_nPasses;
|
|
int m_Flags;
|
|
int8 m_nTechnique[TTYPE_MAX]; //use CONSOLE_MAX for now, PC not supported
|
|
int m_nREsOffs;
|
|
int m_nREs;
|
|
uint32 m_nPreprocessFlags;
|
|
|
|
SSShaderTechnique()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
sAddData(dst, m_nNameOffs);
|
|
sAddData(dst, m_nPassesOffs);
|
|
sAddData(dst, m_nPasses);
|
|
sAddData(dst, m_Flags);
|
|
|
|
// TTYPE_MAX is different on console!
|
|
int TECH_MAX = TTYPE_MAX;
|
|
|
|
for (int i = 0; i < TECH_MAX; i++)
|
|
{
|
|
sAddData(dst, m_nTechnique[i]);
|
|
}
|
|
|
|
sAlignData(dst, 4);
|
|
|
|
sAddData(dst, m_nREsOffs);
|
|
sAddData(dst, m_nREs);
|
|
sAddData(dst, m_nPreprocessFlags);
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
//Cannot import non native data due to TTYPE_MAX being different on different platforms
|
|
CryFatalError("SSShaderTechnique non-native import not supported");
|
|
|
|
SwapEndian(m_nNameOffs, eBigEndian);
|
|
SwapEndian(m_nPassesOffs, eBigEndian);
|
|
SwapEndian(m_nPasses, eBigEndian);
|
|
SwapEndian(m_Flags, eBigEndian);
|
|
|
|
for (int i = 0; i < TTYPE_MAX; i++)
|
|
{
|
|
SwapEndian(m_nTechnique[i], eBigEndian);
|
|
}
|
|
|
|
SwapEndian(m_nREsOffs, eBigEndian);
|
|
SwapEndian(m_nREs, eBigEndian);
|
|
SwapEndian(m_nPreprocessFlags, eBigEndian);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSShaderPass
|
|
{
|
|
uint32 m_RenderState;
|
|
int8 m_eCull;
|
|
uint8 m_AlphaRef;
|
|
uint16 m_PassFlags;
|
|
|
|
uint32 m_nVShaderOffs;
|
|
uint32 m_nPShaderOffs;
|
|
uint32 m_nGShaderOffs;
|
|
uint32 m_nDShaderOffs;
|
|
uint32 m_nCShaderOffs;
|
|
uint32 m_nHShaderOffs;
|
|
|
|
uint32 m_nRenderElemOffset;
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
sAddData(dst, m_RenderState);
|
|
sAddData(dst, m_eCull);
|
|
sAddData(dst, m_AlphaRef);
|
|
sAddData(dst, m_PassFlags);
|
|
|
|
sAddData(dst, m_nVShaderOffs);
|
|
sAddData(dst, m_nPShaderOffs);
|
|
|
|
#if 1
|
|
//if (CParserBin::PlatformSupportsGeometryShaders() &&
|
|
// CParserBin::PlatformSupportsHullShaders() &&
|
|
// CParserBin::PlatformSupportsDomainShaders() &&
|
|
// CParserBin::PlatformSupportsComputeShaders())
|
|
{
|
|
sAddData(dst, m_nGShaderOffs);
|
|
sAddData(dst, m_nDShaderOffs);
|
|
sAddData(dst, m_nCShaderOffs);
|
|
sAddData(dst, m_nHShaderOffs);
|
|
}
|
|
#endif
|
|
|
|
sAddData(dst, m_nRenderElemOffset);
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_RenderState, eBigEndian);
|
|
SwapEndian(m_eCull, eBigEndian);
|
|
SwapEndian(m_AlphaRef, eBigEndian);
|
|
SwapEndian(m_PassFlags, eBigEndian);
|
|
|
|
SwapEndian(m_nVShaderOffs, eBigEndian);
|
|
SwapEndian(m_nPShaderOffs, eBigEndian);
|
|
SwapEndian(m_nGShaderOffs, eBigEndian);
|
|
SwapEndian(m_nDShaderOffs, eBigEndian);
|
|
SwapEndian(m_nCShaderOffs, eBigEndian);
|
|
SwapEndian(m_nHShaderOffs, eBigEndian);
|
|
|
|
SwapEndian(m_nRenderElemOffset, eBigEndian);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSLightEval
|
|
{};
|
|
|
|
struct SCHWShader
|
|
{
|
|
uint64 m_nMaskGenShader;
|
|
uint64 m_nMaskGenFX;
|
|
uint64 m_nMaskAnd_RT;
|
|
uint64 m_nMaskOr_RT;
|
|
|
|
int m_Flags;
|
|
uint32 m_nsNameSourceFX;
|
|
uint32 m_nsName;
|
|
uint32 m_nsEntryFunc;
|
|
EHWShaderClass m_eSHClass;
|
|
uint32 m_nTokens;
|
|
uint32 m_nTableEntries;
|
|
uint32 m_nSamplers;
|
|
uint32 m_nParams;
|
|
uint32 m_dwShaderType;
|
|
|
|
SCHWShader()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nMaskGenShader);
|
|
sAddData(dst, m_nMaskGenFX);
|
|
sAddData(dst, m_nMaskAnd_RT);
|
|
sAddData(dst, m_nMaskOr_RT);
|
|
sAddData(dst, m_Flags);
|
|
sAddData(dst, m_nsNameSourceFX);
|
|
sAddData(dst, m_nsName);
|
|
sAddData(dst, m_nsEntryFunc);
|
|
sAddData(dst, (uint32)m_eSHClass);
|
|
sAddData(dst, m_nTokens);
|
|
sAddData(dst, m_nTableEntries);
|
|
sAddData(dst, m_nSamplers);
|
|
sAddData(dst, m_nParams);
|
|
sAddData(dst, m_dwShaderType);
|
|
|
|
//uint32 PAD=0;
|
|
//sAddData(dst, PAD); //pad up to 64bit align due to uint64
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nMaskGenShader, eBigEndian);
|
|
SwapEndian(m_nMaskGenFX, eBigEndian);
|
|
SwapEndian(m_nsNameSourceFX, eBigEndian);
|
|
SwapEndian(m_nsName, eBigEndian);
|
|
SwapEndian(m_nsEntryFunc, eBigEndian);
|
|
SwapEndianEnum(m_eSHClass, eBigEndian);
|
|
SwapEndian(m_nTokens, eBigEndian);
|
|
SwapEndian(m_nTableEntries, eBigEndian);
|
|
SwapEndian(m_nSamplers, eBigEndian);
|
|
SwapEndian(m_nParams, eBigEndian);
|
|
SwapEndian(m_dwShaderType, eBigEndian);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSTexSamplerFX
|
|
{
|
|
int m_nsName;
|
|
int m_nsNameTexture;
|
|
|
|
int m_eTexType;
|
|
int m_nSamplerSlot;
|
|
uint32 m_nFlags;
|
|
uint32 m_nTexFlags;
|
|
int m_nRTIdx;
|
|
uint32 m_bTexState;
|
|
STexState ST;
|
|
|
|
SSTexSamplerFX()
|
|
{
|
|
// if any of these assert fails it means the platform headers have changed
|
|
// we must update the cached equivalents (see top of file)
|
|
|
|
memset(this, 0, sizeof(SSTexSamplerFX));
|
|
}
|
|
|
|
SSTexSamplerFX(const SSTexSamplerFX& rhs)
|
|
{
|
|
memcpy(this, &rhs, sizeof(SSTexSamplerFX));
|
|
}
|
|
|
|
SSTexSamplerFX& operator = (const SSTexSamplerFX& rhs)
|
|
{
|
|
memcpy(this, &rhs, sizeof(SSTexSamplerFX));
|
|
return *this;
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nsName);
|
|
sAddData(dst, m_nsNameTexture);
|
|
sAddData(dst, m_eTexType);
|
|
sAddData(dst, m_nSamplerSlot);
|
|
sAddData(dst, m_nFlags);
|
|
sAddData(dst, m_nTexFlags);
|
|
sAddData(dst, m_nRTIdx);
|
|
sAddData(dst, m_bTexState);
|
|
|
|
sAddData(dst, ST.m_nMinFilter);
|
|
sAddData(dst, ST.m_nMagFilter);
|
|
sAddData(dst, ST.m_nMipFilter);
|
|
sAddData(dst, ST.m_nAddressU);
|
|
sAddData(dst, ST.m_nAddressV);
|
|
sAddData(dst, ST.m_nAddressW);
|
|
sAddData(dst, ST.m_nAnisotropy);
|
|
sAddData(dst, ST.padding);
|
|
sAddData(dst, ST.m_dwBorderColor);
|
|
|
|
sAddData(dst, ST.m_MipBias);
|
|
|
|
uint64 iPad = 0;
|
|
sAddData(dst, iPad); //m_pDeviceState
|
|
sAddData(dst, ST.m_bActive);
|
|
sAddData(dst, ST.m_bComparison);
|
|
sAddData(dst, ST.m_bSRGBLookup);
|
|
byte bPad = 0;
|
|
sAddData(dst, bPad);
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nsName, eBigEndian);
|
|
SwapEndian(m_nsNameTexture, eBigEndian);
|
|
SwapEndian(m_eTexType, eBigEndian);
|
|
SwapEndian(m_nSamplerSlot, eBigEndian);
|
|
SwapEndian(m_nFlags, eBigEndian);
|
|
SwapEndian(m_nTexFlags, eBigEndian);
|
|
SwapEndian(m_nRTIdx, eBigEndian);
|
|
SwapEndian(m_bTexState, eBigEndian);
|
|
SwapEndian(ST.m_dwBorderColor, eBigEndian);
|
|
SwapEndian(ST.m_bActive, eBigEndian);
|
|
SwapEndian(ST.m_bComparison, eBigEndian);
|
|
SwapEndian(ST.m_bSRGBLookup, eBigEndian);
|
|
}
|
|
|
|
ST.PostCreate();
|
|
}
|
|
};
|
|
|
|
struct SSHRenderTarget
|
|
{
|
|
ERenderOrder m_eOrder;
|
|
int m_nProcessFlags; // FSPR_ flags
|
|
uint32 m_nsTargetName;
|
|
int m_nWidth;
|
|
int m_nHeight;
|
|
ETEX_Format m_eTF;
|
|
int m_nIDInPool;
|
|
ERTUpdate m_eUpdateType;
|
|
uint32 m_bTempDepth;
|
|
ColorF m_ClearColor;
|
|
float m_fClearDepth;
|
|
uint32 m_nFlags;
|
|
uint32 m_nFilterFlags;
|
|
|
|
SSHRenderTarget()
|
|
{
|
|
memset(this, 0, sizeof(SSHRenderTarget));
|
|
}
|
|
|
|
// = operator to ensure padding is copied
|
|
SSHRenderTarget& operator = (const SSHRenderTarget& rhs)
|
|
{
|
|
memcpy(this, &rhs, sizeof(SSHRenderTarget));
|
|
return *this;
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
sAddData(dst, (uint32)m_eOrder);
|
|
sAddData(dst, m_nProcessFlags);
|
|
sAddData(dst, m_nsTargetName);
|
|
sAddData(dst, m_nWidth);
|
|
sAddData(dst, m_nHeight);
|
|
|
|
sAddData(dst, (uint8)m_eTF);
|
|
byte PAD = 0;
|
|
sAddData(dst, PAD);
|
|
sAddData(dst, PAD);
|
|
sAddData(dst, PAD);
|
|
|
|
sAddData(dst, m_nIDInPool);
|
|
sAddData(dst, (uint32)m_eUpdateType);
|
|
sAddData(dst, m_bTempDepth);
|
|
sAddData(dst, m_ClearColor.r);
|
|
sAddData(dst, m_ClearColor.g);
|
|
sAddData(dst, m_ClearColor.b);
|
|
sAddData(dst, m_ClearColor.a);
|
|
sAddData(dst, m_fClearDepth);
|
|
sAddData(dst, m_nFlags);
|
|
sAddData(dst, m_nFilterFlags);
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndianEnum(m_eOrder, eBigEndian);
|
|
SwapEndian(m_nProcessFlags, eBigEndian);
|
|
SwapEndian(m_nsTargetName, eBigEndian);
|
|
SwapEndian(m_nWidth, eBigEndian);
|
|
SwapEndian(m_nHeight, eBigEndian);
|
|
SwapEndianEnum(m_eTF, eBigEndian);
|
|
SwapEndian(m_nIDInPool, eBigEndian);
|
|
SwapEndianEnum(m_eUpdateType, eBigEndian);
|
|
SwapEndian(m_bTempDepth, eBigEndian);
|
|
SwapEndian(m_ClearColor.r, eBigEndian);
|
|
SwapEndian(m_ClearColor.g, eBigEndian);
|
|
SwapEndian(m_ClearColor.b, eBigEndian);
|
|
SwapEndian(m_ClearColor.a, eBigEndian);
|
|
SwapEndian(m_fClearDepth, eBigEndian);
|
|
SwapEndian(m_nFlags, eBigEndian);
|
|
SwapEndian(m_nFilterFlags, eBigEndian);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSFXParam
|
|
{
|
|
int m_nsName; // Parameter name
|
|
uint32 m_nFlags;
|
|
short m_nParameters; // Number of paramters
|
|
short m_nComps; // Number of components in single parameter
|
|
uint32 m_nsAnnotations; // Additional parameters (between <>)
|
|
uint32 m_nsSemantic; // Parameter app handling type (after ':')
|
|
uint32 m_nsValues; // Parameter values (after '=')
|
|
byte m_eType; // EParamType
|
|
int8 m_nCB;
|
|
|
|
short m_nRegister[eHWSC_Num];
|
|
|
|
SSFXParam()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nsName);
|
|
sAddData(dst, m_nFlags);
|
|
sAddData(dst, m_nParameters);
|
|
sAddData(dst, m_nComps);
|
|
sAddData(dst, m_nsAnnotations);
|
|
sAddData(dst, m_nsSemantic);
|
|
sAddData(dst, m_nsValues);
|
|
sAddData(dst, m_eType);
|
|
sAddData(dst, m_nCB);
|
|
|
|
for (int i = 0; i < eHWSC_Num; i++)
|
|
{
|
|
sAddData(dst, m_nRegister[i]);
|
|
}
|
|
|
|
// Align for struct padding
|
|
sAlignData(dst, 8);
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nsName, eBigEndian);
|
|
SwapEndian(m_nFlags, eBigEndian);
|
|
SwapEndian(m_nParameters, eBigEndian);
|
|
SwapEndian(m_nComps, eBigEndian);
|
|
SwapEndian(m_nsAnnotations, eBigEndian);
|
|
SwapEndian(m_nsSemantic, eBigEndian);
|
|
SwapEndian(m_nsValues, eBigEndian);
|
|
SwapEndian(m_eType, eBigEndian);
|
|
SwapEndian(m_nCB, eBigEndian);
|
|
|
|
for (int i = 0; i < eHWSC_Num; i++)
|
|
{
|
|
SwapEndian(m_nRegister[i], eBigEndian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SSFXSampler
|
|
{
|
|
int m_nsName; // Parameter name
|
|
uint32 m_nFlags;
|
|
short m_nArray; // Number of paramters
|
|
uint32 m_nsAnnotations; // Additional parameters (between <>)
|
|
uint32 m_nsSemantic; // Parameter app handling type (after ':')
|
|
uint32 m_nsValues; // Parameter values (after '=')
|
|
byte m_eType; // EParamType
|
|
|
|
short m_nRegister[eHWSC_Num];
|
|
|
|
SSFXSampler()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nsName);
|
|
sAddData(dst, m_nFlags);
|
|
sAddData(dst, m_nArray);
|
|
sAddData(dst, m_nsAnnotations);
|
|
sAddData(dst, m_nsSemantic);
|
|
sAddData(dst, m_nsValues);
|
|
sAddData(dst, m_eType);
|
|
|
|
for (int i = 0; i < eHWSC_Num; i++)
|
|
{
|
|
sAddData(dst, m_nRegister[i]);
|
|
}
|
|
|
|
// Align for struct padding
|
|
sAlignData(dst, 8);
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nsName, eBigEndian);
|
|
SwapEndian(m_nFlags, eBigEndian);
|
|
SwapEndian(m_nArray, eBigEndian);
|
|
SwapEndian(m_nsAnnotations, eBigEndian);
|
|
SwapEndian(m_nsSemantic, eBigEndian);
|
|
SwapEndian(m_nsValues, eBigEndian);
|
|
SwapEndian(m_eType, eBigEndian);
|
|
|
|
for (int i = 0; i < eHWSC_Num; i++)
|
|
{
|
|
SwapEndian(m_nRegister[i], eBigEndian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
struct SSFXTexture
|
|
{
|
|
int m_nsName; // Parameter name
|
|
int m_nsNameTexture;
|
|
uint32 m_nFlags;
|
|
short m_nArray; // Number of paramters
|
|
uint32 m_nsAnnotations; // Additional parameters (between <>)
|
|
uint32 m_nsSemantic; // Parameter app handling type (after ':')
|
|
uint32 m_nsValues; // Parameter values (after '=')
|
|
bool m_bSRGBLookup;
|
|
byte m_eType; // EParamType
|
|
|
|
short m_nRegister[eHWSC_Num];
|
|
|
|
SSFXTexture()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void Export(TArray<byte>& dst)
|
|
{
|
|
uint32 startOffset = dst.Num();
|
|
|
|
sAddData(dst, m_nsName);
|
|
sAddData(dst, m_nsNameTexture);
|
|
sAddData(dst, m_nFlags);
|
|
sAddData(dst, m_nArray);
|
|
sAddData(dst, m_nsAnnotations);
|
|
sAddData(dst, m_nsSemantic);
|
|
sAddData(dst, m_nsValues);
|
|
sAddData(dst, m_eType);
|
|
sAddData(dst, m_bSRGBLookup);
|
|
|
|
for (int i = 0; i < eHWSC_Num; i++)
|
|
{
|
|
sAddData(dst, m_nRegister[i]);
|
|
}
|
|
|
|
// Align for struct padding
|
|
sAlignData(dst, 8);
|
|
|
|
AZ_Assert(dst.Num() - startOffset == sizeof(*this), "ShaderSerialize export size mismatch");
|
|
}
|
|
|
|
void Import(const byte* pData)
|
|
{
|
|
memcpy(this, pData, sizeof(*this));
|
|
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
SwapEndian(m_nsName, eBigEndian);
|
|
SwapEndian(m_nsNameTexture, eBigEndian);
|
|
SwapEndian(m_nFlags, eBigEndian);
|
|
SwapEndian(m_nArray, eBigEndian);
|
|
SwapEndian(m_nsAnnotations, eBigEndian);
|
|
SwapEndian(m_nsSemantic, eBigEndian);
|
|
SwapEndian(m_nsValues, eBigEndian);
|
|
SwapEndian(m_eType, eBigEndian);
|
|
SwapEndian(m_bSRGBLookup, eBigEndian);
|
|
|
|
for (int i = 0; i < eHWSC_Num; i++)
|
|
{
|
|
SwapEndian(m_nRegister[i], eBigEndian);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
struct SShaderSerializeContext
|
|
{
|
|
SSShader SSR;
|
|
TArray<SSShaderParam> Params;
|
|
TArray<SSFXParam> FXParams;
|
|
TArray<SSFXSampler> FXSamplers;
|
|
TArray<SSFXTexture> FXTextures;
|
|
TArray<SSTexSamplerFX> FXTexSamplers;
|
|
TArray<SSHRenderTarget> FXTexRTs;
|
|
TArray<SSShaderTechnique> Techniques;
|
|
TArray<SSShaderPass> Passes;
|
|
TArray<char> Strings;
|
|
TArray<byte> Data;
|
|
|
|
std::map<uint32, uint32> m_strTable;
|
|
|
|
uint32 AddString(const char* pStr)
|
|
{
|
|
uint32 crc = CCrc32::Compute(pStr);
|
|
|
|
std::map<uint32, uint32>::iterator strIt = m_strTable.find(crc);
|
|
|
|
if (strIt != m_strTable.end())
|
|
{
|
|
uint32 offset = strIt->second;
|
|
|
|
// Debug, check strings are correct
|
|
#if 0
|
|
if (strcmp(&Strings[offset], pStr))
|
|
{
|
|
CryLogAlways("Error: %s is not %s\n", pStr, &Strings[offset]);
|
|
}
|
|
#endif
|
|
|
|
return offset;
|
|
}
|
|
|
|
uint32 nChars = Strings.Num();
|
|
m_strTable[crc] = nChars;
|
|
Strings.AddString(pStr);
|
|
return nChars;
|
|
}
|
|
};
|
|
|
|
class CShaderSerialize
|
|
{
|
|
friend class CShaderMan;
|
|
friend class CShaderManBin;
|
|
|
|
public:
|
|
enum ShaderImportResults
|
|
{
|
|
SHADER_IMPORT_SUCCESS, // Shader mask exists in the fxb lookup table
|
|
SHADER_IMPORT_MISSING_ENTRY, // We have a valid fxb lookup table, but the current permutation is missing
|
|
SHADER_IMPORT_FAILURE, // No fxb table exists for this entire shader
|
|
};
|
|
|
|
void ClearSResourceCache();
|
|
|
|
private:
|
|
bool _OpenSResource(float fVersion, SSShaderRes* pSR, CShader* pSH, int nCache, CResFile* pRF, bool bReadOnly);
|
|
bool OpenSResource(const char* szName, SSShaderRes* pSR, CShader* pSH, bool bDontUseUserFolder, bool bReadOnly);
|
|
bool CreateSResource(CShader* pSH, SSShaderRes* pSR, CCryNameTSCRC& SName, bool bDontUseUserFolder, bool bReadOnly);
|
|
SSShaderRes* InitSResource(CShader* pSH, bool bDontUseUserFolder, bool bReadOnly);
|
|
|
|
// Simple query to see if the SResource exists in the hash table
|
|
bool DoesSResourceExist(CShader* pSH);
|
|
|
|
// Helper function to abstract calling ExportHWShader per shader stage
|
|
void ExportHWShaderStage(SShaderSerializeContext& SC, CHWShader* shader, uint32& outShaderOffset);
|
|
|
|
bool ExportHWShader(CHWShader* pShader, struct SShaderSerializeContext& SC);
|
|
|
|
CHWShader* ImportHWShader(SShaderSerializeContext& SC, int nOffs, uint32 CRC32, CShader* pSH);
|
|
|
|
bool ExportShader(CShader* pSH, CShaderManBin& binShaderMgr);
|
|
ShaderImportResults ImportShader(CShader* pSH, CShaderManBin& binShaderMgr);
|
|
bool CheckFXBExists(CShader* pSH);
|
|
|
|
FXSShaderRes m_SShaderResources;
|
|
string m_customSerialisePath;
|
|
};
|
|
|
|
_inline const char* sString(int nOffs, TArray<char>& Strings)
|
|
{
|
|
return &Strings[nOffs];
|
|
}
|
|
|
|
#endif // SHADERS_SERIALIZING
|
|
|
|
#endif
|
|
|