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.
3731 lines
109 KiB
C++
3731 lines
109 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 : Script parser implementations.
|
|
|
|
|
|
#include "RenderDll_precompiled.h"
|
|
#include "CryCrc32.h"
|
|
#include "../RenderCapabilities.h"
|
|
#include <AzCore/std/string/string.h>
|
|
#include <AzCore/PlatformId/PlatformId.h>
|
|
|
|
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#undef AZ_RESTRICTED_SECTION
|
|
#define PARSERBIN_CPP_SECTION_1 1
|
|
#define PARSERBIN_CPP_SECTION_2 2
|
|
#endif
|
|
|
|
#if defined(OPENGL_ES) || defined(CRY_USE_METAL)
|
|
#include "../../XRenderD3D9/DriverD3D.h" // for gcpRendD3D
|
|
#endif
|
|
|
|
const char* g_KeyTokens[eT_max];
|
|
TArray<bool> sfxIFDef;
|
|
|
|
bool CParserBin::m_bEditable;
|
|
uint32 CParserBin::m_nPlatform;
|
|
AZ::PlatformID CParserBin::m_targetPlatform = AZ::PlatformID::PLATFORM_MAX;
|
|
bool CParserBin::m_bEndians;
|
|
bool CParserBin::m_bParseFX = true;
|
|
bool CParserBin::m_bShaderCacheGen = false;
|
|
|
|
ShaderBucketAllocator g_shaderBucketAllocator;
|
|
|
|
IGeneralMemoryHeap* g_shaderGeneralHeap = nullptr;
|
|
|
|
CParserBin::CParserBin(SShaderBin* pBin)
|
|
{
|
|
m_pCurBinShader = pBin;
|
|
m_pCurShader = NULL;
|
|
GetISystem()->GetISystemEventDispatcher()->RegisterListener(this);
|
|
}
|
|
CParserBin::CParserBin(SShaderBin* pBin, CShader* pSH)
|
|
{
|
|
m_pCurBinShader = pBin;
|
|
m_pCurShader = pSH;
|
|
GetISystem()->GetISystemEventDispatcher()->RegisterListener(this);
|
|
}
|
|
|
|
CParserBin::~CParserBin()
|
|
{
|
|
sfxIFIgnore.clear();
|
|
sfxIFDef.clear();
|
|
GetISystem()->GetISystemEventDispatcher()->RemoveListener(this);
|
|
}
|
|
|
|
void CParserBin::OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam)
|
|
{
|
|
switch (event)
|
|
{
|
|
case ESYSTEM_EVENT_FULL_SHUTDOWN:
|
|
{
|
|
sfxIFIgnore.clear();
|
|
sfxIFDef.clear();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint32 CParserBin::GetCRC32(const char* szStr)
|
|
{
|
|
uint32 nGen = CCrc32::Compute(szStr);
|
|
assert(nGen >= eT_user_first);
|
|
|
|
return nGen;
|
|
}
|
|
|
|
FXMacroBin CParserBin::m_StaticMacros;
|
|
|
|
void CParserBin::Init()
|
|
{
|
|
// Register key tokens
|
|
fxTokenKey("#include", eT_include);
|
|
fxTokenKey("#define", eT_define);
|
|
fxTokenKey("#undefine", eT_undefine);
|
|
fxTokenKey("#define", eT_define_2);
|
|
fxTokenKey("#fetchinst", eT_fetchinst);
|
|
fxTokenKey("#if", eT_if);
|
|
fxTokenKey("#ifdef", eT_ifdef);
|
|
fxTokenKey("#ifndef", eT_ifndef);
|
|
fxTokenKey("#if", eT_if_2);
|
|
fxTokenKey("#ifdef", eT_ifdef_2);
|
|
fxTokenKey("#ifndef", eT_ifndef_2);
|
|
fxTokenKey("#endif", eT_endif);
|
|
fxTokenKey("#else", eT_else);
|
|
fxTokenKey("#elif", eT_elif);
|
|
fxTokenKey("#warning", eT_warning);
|
|
fxTokenKey("#register_env", eT_register_env);
|
|
fxTokenKey("#ifcvar", eT_ifcvar);
|
|
fxTokenKey("#ifncvar", eT_ifncvar);
|
|
fxTokenKey("#elifcvar", eT_elifcvar);
|
|
fxTokenKey("#skip", eT_skip);
|
|
fxTokenKey("#skip_(", eT_skip_1);
|
|
fxTokenKey("#skip_)", eT_skip_2);
|
|
|
|
fxTokenKey("|", eT_or);
|
|
fxTokenKey("&", eT_and);
|
|
|
|
fxTokenKey("(", eT_br_rnd_1);
|
|
fxTokenKey(")", eT_br_rnd_2);
|
|
fxTokenKey("[", eT_br_sq_1);
|
|
fxTokenKey("]", eT_br_sq_2);
|
|
fxTokenKey("{", eT_br_cv_1);
|
|
fxTokenKey("}", eT_br_cv_2);
|
|
fxTokenKey("<", eT_br_tr_1);
|
|
fxTokenKey(">", eT_br_tr_2);
|
|
fxTokenKey(",", eT_comma);
|
|
fxTokenKey(".", eT_dot);
|
|
fxTokenKey(":", eT_colon);
|
|
fxTokenKey(";", eT_semicolumn);
|
|
fxTokenKey("!", eT_excl);
|
|
fxTokenKey("\"", eT_quote);
|
|
fxTokenKey("'", eT_sing_quote);
|
|
|
|
fxTokenKey("s0", eT_s0);
|
|
fxTokenKey("s1", eT_s1);
|
|
fxTokenKey("s2", eT_s2);
|
|
fxTokenKey("s3", eT_s3);
|
|
fxTokenKey("s4", eT_s4);
|
|
fxTokenKey("s5", eT_s5);
|
|
fxTokenKey("s6", eT_s6);
|
|
fxTokenKey("s7", eT_s7);
|
|
fxTokenKey("s8", eT_s8);
|
|
fxTokenKey("s9", eT_s9);
|
|
fxTokenKey("s10", eT_s10);
|
|
fxTokenKey("s11", eT_s11);
|
|
fxTokenKey("s12", eT_s12);
|
|
fxTokenKey("s13", eT_s13);
|
|
fxTokenKey("s14", eT_s14);
|
|
fxTokenKey("s15", eT_s15);
|
|
|
|
fxTokenKey("t0", eT_t0);
|
|
fxTokenKey("t1", eT_t1);
|
|
fxTokenKey("t2", eT_t2);
|
|
fxTokenKey("t3", eT_t3);
|
|
fxTokenKey("t4", eT_t4);
|
|
fxTokenKey("t5", eT_t5);
|
|
fxTokenKey("t6", eT_t6);
|
|
fxTokenKey("t7", eT_t7);
|
|
fxTokenKey("t8", eT_t8);
|
|
fxTokenKey("t9", eT_t9);
|
|
fxTokenKey("t10", eT_t10);
|
|
fxTokenKey("t11", eT_t11);
|
|
fxTokenKey("t12", eT_t12);
|
|
fxTokenKey("t13", eT_t13);
|
|
fxTokenKey("t14", eT_t14);
|
|
fxTokenKey("t15", eT_t15);
|
|
|
|
fxTokenKey("//", eT_comment);
|
|
|
|
fxTokenKey("?", eT_question);
|
|
fxTokenKey("=", eT_eq);
|
|
fxTokenKey("+", eT_plus);
|
|
fxTokenKey("-", eT_minus);
|
|
fxTokenKey("/", eT_div);
|
|
fxTokenKey("*", eT_mul);
|
|
fxTokenKey("dot", eT_dot_math);
|
|
fxTokenKey("mul", eT_mul_math);
|
|
fxTokenKey("sqrt", eT_sqrt_math);
|
|
fxTokenKey("exp", eT_exp_math);
|
|
fxTokenKey("log", eT_log_math);
|
|
fxTokenKey("log2", eT_log2_math);
|
|
fxTokenKey("sin", eT_sin_math);
|
|
fxTokenKey("cos", eT_cos_math);
|
|
fxTokenKey("sincos", eT_sincos_math);
|
|
fxTokenKey("floor", eT_floor_math);
|
|
fxTokenKey("floor", eT_ceil_math);
|
|
fxTokenKey("frac", eT_frac_math);
|
|
fxTokenKey("lerp", eT_lerp_math);
|
|
fxTokenKey("abs", eT_abs_math);
|
|
fxTokenKey("clamp", eT_clamp_math);
|
|
fxTokenKey("min", eT_min_math);
|
|
fxTokenKey("max", eT_max_math);
|
|
fxTokenKey("length", eT_length_math);
|
|
|
|
fxTokenKey("%_LT_LIGHTS", eT__LT_LIGHTS);
|
|
fxTokenKey("%_LT_NUM", eT__LT_NUM);
|
|
fxTokenKey("%_LT_HASPROJ", eT__LT_HASPROJ);
|
|
fxTokenKey("%_LT_0_TYPE", eT__LT_0_TYPE);
|
|
fxTokenKey("%_LT_1_TYPE", eT__LT_1_TYPE);
|
|
fxTokenKey("%_LT_2_TYPE", eT__LT_2_TYPE);
|
|
fxTokenKey("%_LT_3_TYPE", eT__LT_3_TYPE);
|
|
fxTokenKey("%_TT_TEXCOORD_MATRIX", eT__TT_TEXCOORD_MATRIX);
|
|
fxTokenKey("%_TT_TEXCOORD_GEN_OBJECT_LINEAR_DIFFUSE", eT__TT_TEXCOORD_GEN_OBJECT_LINEAR_DIFFUSE);
|
|
fxTokenKey("%_TT_TEXCOORD_GEN_OBJECT_LINEAR_EMITTANCE", eT__TT_TEXCOORD_GEN_OBJECT_LINEAR_EMITTANCE);
|
|
fxTokenKey("%_TT_TEXCOORD_GEN_OBJECT_LINEAR_EMITTANCE_MULT", eT__TT_TEXCOORD_GEN_OBJECT_LINEAR_EMITTANCE_MULT);
|
|
fxTokenKey("%_TT_TEXCOORD_GEN_OBJECT_LINEAR_DETAIL", eT__TT_TEXCOORD_GEN_OBJECT_LINEAR_DETAIL);
|
|
fxTokenKey("%_TT_TEXCOORD_GEN_OBJECT_LINEAR_CUSTOM", eT__TT_TEXCOORD_GEN_OBJECT_LINEAR_CUSTOM);
|
|
fxTokenKey("%_TT_TEXCOORD_PROJ", eT__TT_TEXCOORD_PROJ);
|
|
fxTokenKey("%_VT_TYPE", eT__VT_TYPE);
|
|
fxTokenKey("%_VT_TYPE_MODIF", eT__VT_TYPE_MODIF);
|
|
fxTokenKey("%_VT_BEND", eT__VT_BEND);
|
|
fxTokenKey("%_VT_DET_BEND", eT__VT_DET_BEND);
|
|
fxTokenKey("%_VT_GRASS", eT__VT_GRASS);
|
|
fxTokenKey("%_VT_WIND", eT__VT_WIND);
|
|
fxTokenKey("%_VT_DEPTH_OFFSET", eT__VT_DEPTH_OFFSET);
|
|
fxTokenKey("%_FT_TEXTURE", eT__FT_TEXTURE);
|
|
fxTokenKey("%_FT_TEXTURE1", eT__FT_TEXTURE1);
|
|
fxTokenKey("%_FT_NORMAL", eT__FT_NORMAL);
|
|
fxTokenKey("%_FT_PSIZE", eT__FT_PSIZE);
|
|
fxTokenKey("%_FT_DIFFUSE", eT__FT_DIFFUSE);
|
|
fxTokenKey("%_FT_SPECULAR", eT__FT_SPECULAR);
|
|
fxTokenKey("%_FT_TANGENT_STREAM", eT__FT_TANGENT_STREAM);
|
|
fxTokenKey("%_FT_QTANGENT_STREAM", eT__FT_QTANGENT_STREAM);
|
|
fxTokenKey("%_FT_SKIN_STREAM", eT__FT_SKIN_STREAM);
|
|
fxTokenKey("%_FT_VERTEX_VELOCITY_STREAM", eT__FT_VERTEX_VELOCITY_STREAM);
|
|
fxTokenKey("%_FT_SRGBWRITE", eT__FT_SRGBWRITE);
|
|
fxTokenKey("%_FT0_COP", eT__FT0_COP);
|
|
fxTokenKey("%_FT0_AOP", eT__FT0_AOP);
|
|
fxTokenKey("%_FT0_CARG1", eT__FT0_CARG1);
|
|
fxTokenKey("%_FT0_CARG2", eT__FT0_CARG2);
|
|
fxTokenKey("%_FT0_AARG1", eT__FT0_AARG1);
|
|
fxTokenKey("%_FT0_AARG2", eT__FT0_AARG2);
|
|
|
|
fxTokenKey("%_VS", eT__VS);
|
|
fxTokenKey("%_PS", eT__PS);
|
|
fxTokenKey("%_GS", eT__GS);
|
|
fxTokenKey("%_HS", eT__HS);
|
|
fxTokenKey("%_DS", eT__DS);
|
|
fxTokenKey("%_CS", eT__CS);
|
|
|
|
FX_REGISTER_TOKEN(_g_SkinQuat);
|
|
|
|
FX_REGISTER_TOKEN(tex2D);
|
|
FX_REGISTER_TOKEN(tex2Dproj);
|
|
FX_REGISTER_TOKEN(tex3D);
|
|
FX_REGISTER_TOKEN(texCUBE);
|
|
FX_REGISTER_TOKEN(sampler1D);
|
|
FX_REGISTER_TOKEN(sampler2D);
|
|
FX_REGISTER_TOKEN(sampler3D);
|
|
FX_REGISTER_TOKEN(samplerCUBE);
|
|
FX_REGISTER_TOKEN(SamplerState);
|
|
FX_REGISTER_TOKEN(SamplerComparisonState);
|
|
FX_REGISTER_TOKEN(sampler_state);
|
|
FX_REGISTER_TOKEN(Texture2D);
|
|
FX_REGISTER_TOKEN(Texture2DArray);
|
|
FX_REGISTER_TOKEN(Texture2DMS);
|
|
FX_REGISTER_TOKEN(RWTexture2D);
|
|
FX_REGISTER_TOKEN(RWTexture2DArray);
|
|
FX_REGISTER_TOKEN(TextureCube);
|
|
FX_REGISTER_TOKEN(TextureCubeArray);
|
|
FX_REGISTER_TOKEN(Texture3D);
|
|
FX_REGISTER_TOKEN(RWTexture3D);
|
|
|
|
FX_REGISTER_TOKEN(float);
|
|
FX_REGISTER_TOKEN(float2);
|
|
FX_REGISTER_TOKEN(float3);
|
|
FX_REGISTER_TOKEN(float4);
|
|
FX_REGISTER_TOKEN(float4x4);
|
|
FX_REGISTER_TOKEN(float3x4);
|
|
FX_REGISTER_TOKEN(float2x4);
|
|
FX_REGISTER_TOKEN(float3x3);
|
|
FX_REGISTER_TOKEN(half);
|
|
FX_REGISTER_TOKEN(half2);
|
|
FX_REGISTER_TOKEN(half3);
|
|
FX_REGISTER_TOKEN(half4);
|
|
FX_REGISTER_TOKEN(half4x4);
|
|
FX_REGISTER_TOKEN(half3x4);
|
|
FX_REGISTER_TOKEN(half2x4);
|
|
FX_REGISTER_TOKEN(half3x3);
|
|
FX_REGISTER_TOKEN(bool);
|
|
FX_REGISTER_TOKEN(int);
|
|
FX_REGISTER_TOKEN(int2);
|
|
FX_REGISTER_TOKEN(int4);
|
|
FX_REGISTER_TOKEN(uint);
|
|
FX_REGISTER_TOKEN(uint2);
|
|
FX_REGISTER_TOKEN(uint4);
|
|
|
|
FX_REGISTER_TOKEN(inout);
|
|
FX_REGISTER_TOKEN(asm);
|
|
|
|
FX_REGISTER_TOKEN(struct);
|
|
FX_REGISTER_TOKEN(sampler);
|
|
FX_REGISTER_TOKEN(const);
|
|
FX_REGISTER_TOKEN(static);
|
|
FX_REGISTER_TOKEN(groupshared);
|
|
FX_REGISTER_TOKEN(TEXCOORDN);
|
|
FX_REGISTER_TOKEN(TEXCOORD0);
|
|
FX_REGISTER_TOKEN(TEXCOORD1);
|
|
FX_REGISTER_TOKEN(TEXCOORD2);
|
|
FX_REGISTER_TOKEN(TEXCOORD3);
|
|
FX_REGISTER_TOKEN(TEXCOORD4);
|
|
FX_REGISTER_TOKEN(TEXCOORD5);
|
|
FX_REGISTER_TOKEN(TEXCOORD6);
|
|
FX_REGISTER_TOKEN(TEXCOORD7);
|
|
FX_REGISTER_TOKEN(TEXCOORD8);
|
|
FX_REGISTER_TOKEN(TEXCOORD9);
|
|
FX_REGISTER_TOKEN(TEXCOORD10);
|
|
FX_REGISTER_TOKEN(TEXCOORD11);
|
|
FX_REGISTER_TOKEN(TEXCOORD12);
|
|
FX_REGISTER_TOKEN(TEXCOORD13);
|
|
FX_REGISTER_TOKEN(TEXCOORD14);
|
|
FX_REGISTER_TOKEN(TEXCOORD15);
|
|
FX_REGISTER_TOKEN(TEXCOORD16);
|
|
FX_REGISTER_TOKEN(TEXCOORD17);
|
|
FX_REGISTER_TOKEN(TEXCOORD18);
|
|
FX_REGISTER_TOKEN(TEXCOORD19);
|
|
FX_REGISTER_TOKEN(TEXCOORD20);
|
|
FX_REGISTER_TOKEN(TEXCOORD21);
|
|
FX_REGISTER_TOKEN(TEXCOORD22);
|
|
FX_REGISTER_TOKEN(TEXCOORD23);
|
|
FX_REGISTER_TOKEN(TEXCOORD24);
|
|
FX_REGISTER_TOKEN(TEXCOORD25);
|
|
FX_REGISTER_TOKEN(TEXCOORD26);
|
|
FX_REGISTER_TOKEN(TEXCOORD27);
|
|
FX_REGISTER_TOKEN(TEXCOORD28);
|
|
FX_REGISTER_TOKEN(TEXCOORD29);
|
|
FX_REGISTER_TOKEN(TEXCOORD30);
|
|
FX_REGISTER_TOKEN(TEXCOORD31);
|
|
FX_REGISTER_TOKEN(TEXCOORDN_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD0_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD1_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD2_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD3_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD4_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD5_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD6_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD7_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD8_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD9_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD10_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD11_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD12_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD13_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD14_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD15_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD16_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD17_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD18_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD19_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD20_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD21_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD22_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD23_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD24_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD25_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD26_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD27_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD28_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD29_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD30_centroid);
|
|
FX_REGISTER_TOKEN(TEXCOORD31_centroid);
|
|
FX_REGISTER_TOKEN(COLOR0);
|
|
|
|
FX_REGISTER_TOKEN(packoffset);
|
|
FX_REGISTER_TOKEN(register);
|
|
FX_REGISTER_TOKEN(return );
|
|
FX_REGISTER_TOKEN(vsregister);
|
|
FX_REGISTER_TOKEN(psregister);
|
|
FX_REGISTER_TOKEN(gsregister);
|
|
FX_REGISTER_TOKEN(dsregister);
|
|
FX_REGISTER_TOKEN(hsregister);
|
|
FX_REGISTER_TOKEN(csregister);
|
|
FX_REGISTER_TOKEN(slot);
|
|
FX_REGISTER_TOKEN(vsslot);
|
|
FX_REGISTER_TOKEN(psslot);
|
|
FX_REGISTER_TOKEN(gsslot);
|
|
FX_REGISTER_TOKEN(dsslot);
|
|
FX_REGISTER_TOKEN(hsslot);
|
|
FX_REGISTER_TOKEN(csslot);
|
|
FX_REGISTER_TOKEN(color);
|
|
|
|
FX_REGISTER_TOKEN(Buffer);
|
|
FX_REGISTER_TOKEN(RWBuffer);
|
|
FX_REGISTER_TOKEN(StructuredBuffer);
|
|
FX_REGISTER_TOKEN(RWStructuredBuffer);
|
|
FX_REGISTER_TOKEN(ByteAddressBuffer);
|
|
FX_REGISTER_TOKEN(RWByteAddressBuffer);
|
|
FX_REGISTER_TOKEN(RasterizerOrderedBuffer);
|
|
FX_REGISTER_TOKEN(RasterizerOrderedByteAddressBuffer);
|
|
FX_REGISTER_TOKEN(RasterizerOrderedStructuredBuffer);
|
|
|
|
FX_REGISTER_TOKEN(Position);
|
|
FX_REGISTER_TOKEN(Allways);
|
|
|
|
FX_REGISTER_TOKEN(STANDARDSGLOBAL);
|
|
|
|
FX_REGISTER_TOKEN(technique);
|
|
FX_REGISTER_TOKEN(string);
|
|
FX_REGISTER_TOKEN(UIName);
|
|
FX_REGISTER_TOKEN(UIDescription);
|
|
FX_REGISTER_TOKEN(UIWidget);
|
|
FX_REGISTER_TOKEN(UIWidget0);
|
|
FX_REGISTER_TOKEN(UIWidget1);
|
|
FX_REGISTER_TOKEN(UIWidget2);
|
|
FX_REGISTER_TOKEN(UIWidget3);
|
|
|
|
FX_REGISTER_TOKEN(Texture);
|
|
FX_REGISTER_TOKEN(Filter);
|
|
FX_REGISTER_TOKEN(MinFilter);
|
|
FX_REGISTER_TOKEN(MagFilter);
|
|
FX_REGISTER_TOKEN(MipFilter);
|
|
FX_REGISTER_TOKEN(AddressU);
|
|
FX_REGISTER_TOKEN(AddressV);
|
|
FX_REGISTER_TOKEN(AddressW);
|
|
FX_REGISTER_TOKEN(BorderColor);
|
|
FX_REGISTER_TOKEN(AnisotropyLevel);
|
|
FX_REGISTER_TOKEN(sRGBLookup);
|
|
FX_REGISTER_TOKEN(Global);
|
|
|
|
FX_REGISTER_TOKEN(LINEAR);
|
|
FX_REGISTER_TOKEN(POINT);
|
|
FX_REGISTER_TOKEN(NONE);
|
|
FX_REGISTER_TOKEN(ANISOTROPIC);
|
|
FX_REGISTER_TOKEN(MIN_MAG_MIP_POINT);
|
|
FX_REGISTER_TOKEN(MIN_MAG_MIP_LINEAR);
|
|
FX_REGISTER_TOKEN(MIN_MAG_LINEAR_MIP_POINT);
|
|
FX_REGISTER_TOKEN(COMPARISON_MIN_MAG_LINEAR_MIP_POINT);
|
|
FX_REGISTER_TOKEN(MINIMUM_MIN_MAG_MIP_LINEAR);
|
|
FX_REGISTER_TOKEN(MAXIMUM_MIN_MAG_MIP_LINEAR);
|
|
|
|
FX_REGISTER_TOKEN(Clamp);
|
|
FX_REGISTER_TOKEN(Border);
|
|
FX_REGISTER_TOKEN(Wrap);
|
|
FX_REGISTER_TOKEN(Mirror);
|
|
|
|
FX_REGISTER_TOKEN(Script);
|
|
|
|
FX_REGISTER_TOKEN(RenderOrder);
|
|
FX_REGISTER_TOKEN(ProcessOrder);
|
|
FX_REGISTER_TOKEN(RenderCamera);
|
|
FX_REGISTER_TOKEN(RenderType);
|
|
FX_REGISTER_TOKEN(RenderFilter);
|
|
FX_REGISTER_TOKEN(RenderColorTarget1);
|
|
FX_REGISTER_TOKEN(RenderDepthStencilTarget);
|
|
FX_REGISTER_TOKEN(ClearSetColor);
|
|
FX_REGISTER_TOKEN(ClearSetDepth);
|
|
FX_REGISTER_TOKEN(ClearTarget);
|
|
FX_REGISTER_TOKEN(RenderTarget_IDPool);
|
|
FX_REGISTER_TOKEN(RenderTarget_UpdateType);
|
|
FX_REGISTER_TOKEN(RenderTarget_Width);
|
|
FX_REGISTER_TOKEN(RenderTarget_Height);
|
|
FX_REGISTER_TOKEN(GenerateMips);
|
|
|
|
FX_REGISTER_TOKEN(PreProcess);
|
|
FX_REGISTER_TOKEN(PostProcess);
|
|
FX_REGISTER_TOKEN(PreDraw);
|
|
|
|
FX_REGISTER_TOKEN(WaterReflection);
|
|
FX_REGISTER_TOKEN(Panorama);
|
|
|
|
FX_REGISTER_TOKEN(WaterPlaneReflected);
|
|
FX_REGISTER_TOKEN(PlaneReflected);
|
|
FX_REGISTER_TOKEN(Current);
|
|
|
|
FX_REGISTER_TOKEN(CurObject);
|
|
FX_REGISTER_TOKEN(CurScene);
|
|
FX_REGISTER_TOKEN(RecursiveScene);
|
|
FX_REGISTER_TOKEN(CopyScene);
|
|
|
|
FX_REGISTER_TOKEN(Refractive);
|
|
FX_REGISTER_TOKEN(ForceRefractionUpdate);
|
|
FX_REGISTER_TOKEN(Heat);
|
|
|
|
FX_REGISTER_TOKEN(DepthBuffer);
|
|
FX_REGISTER_TOKEN(DepthBufferTemp);
|
|
FX_REGISTER_TOKEN(DepthBufferOrig);
|
|
|
|
FX_REGISTER_TOKEN($ScreenSize);
|
|
FX_REGISTER_TOKEN(WaterReflect);
|
|
FX_REGISTER_TOKEN(FogColor);
|
|
|
|
FX_REGISTER_TOKEN(Color);
|
|
FX_REGISTER_TOKEN(Depth);
|
|
|
|
FX_REGISTER_TOKEN($RT_2D);
|
|
FX_REGISTER_TOKEN($RT_Cube);
|
|
|
|
FX_REGISTER_TOKEN(pass);
|
|
FX_REGISTER_TOKEN(CustomRE);
|
|
FX_REGISTER_TOKEN(Style);
|
|
|
|
FX_REGISTER_TOKEN(VertexShader);
|
|
FX_REGISTER_TOKEN(PixelShader);
|
|
FX_REGISTER_TOKEN(GeometryShader);
|
|
FX_REGISTER_TOKEN(DomainShader);
|
|
FX_REGISTER_TOKEN(HullShader);
|
|
FX_REGISTER_TOKEN(ComputeShader);
|
|
FX_REGISTER_TOKEN(ZEnable);
|
|
FX_REGISTER_TOKEN(ZWriteEnable);
|
|
FX_REGISTER_TOKEN(CullMode);
|
|
FX_REGISTER_TOKEN(SrcBlend);
|
|
FX_REGISTER_TOKEN(DestBlend);
|
|
FX_REGISTER_TOKEN(AlphaBlendEnable);
|
|
FX_REGISTER_TOKEN(AlphaFunc);
|
|
FX_REGISTER_TOKEN(AlphaRef);
|
|
FX_REGISTER_TOKEN(ZFunc);
|
|
FX_REGISTER_TOKEN(ColorWriteEnable);
|
|
FX_REGISTER_TOKEN(IgnoreMaterialState);
|
|
|
|
FX_REGISTER_TOKEN(None);
|
|
FX_REGISTER_TOKEN(Disable);
|
|
FX_REGISTER_TOKEN(CCW);
|
|
FX_REGISTER_TOKEN(CW);
|
|
FX_REGISTER_TOKEN(Back);
|
|
FX_REGISTER_TOKEN(Front);
|
|
|
|
FX_REGISTER_TOKEN(Never);
|
|
FX_REGISTER_TOKEN(Less);
|
|
FX_REGISTER_TOKEN(Equal);
|
|
FX_REGISTER_TOKEN(LEqual);
|
|
FX_REGISTER_TOKEN(LessEqual);
|
|
FX_REGISTER_TOKEN(NotEqual);
|
|
FX_REGISTER_TOKEN(GEqual);
|
|
FX_REGISTER_TOKEN(GreaterEqual);
|
|
FX_REGISTER_TOKEN(Greater)
|
|
FX_REGISTER_TOKEN(Always);
|
|
|
|
FX_REGISTER_TOKEN(RED);
|
|
FX_REGISTER_TOKEN(GREEN);
|
|
FX_REGISTER_TOKEN(BLUE);
|
|
FX_REGISTER_TOKEN(ALPHA);
|
|
|
|
FX_REGISTER_TOKEN(ONE);
|
|
FX_REGISTER_TOKEN(ZERO);
|
|
FX_REGISTER_TOKEN(SRC_COLOR);
|
|
FX_REGISTER_TOKEN(SrcColor);
|
|
FX_REGISTER_TOKEN(ONE_MINUS_SRC_COLOR);
|
|
FX_REGISTER_TOKEN(InvSrcColor);
|
|
FX_REGISTER_TOKEN(SRC_ALPHA);
|
|
FX_REGISTER_TOKEN(SrcAlpha);
|
|
FX_REGISTER_TOKEN(ONE_MINUS_SRC_ALPHA);
|
|
FX_REGISTER_TOKEN(InvSrcAlpha);
|
|
FX_REGISTER_TOKEN(DST_ALPHA);
|
|
FX_REGISTER_TOKEN(DestAlpha);
|
|
FX_REGISTER_TOKEN(ONE_MINUS_DST_ALPHA);
|
|
FX_REGISTER_TOKEN(InvDestAlpha);
|
|
FX_REGISTER_TOKEN(DST_COLOR);
|
|
FX_REGISTER_TOKEN(DestColor);
|
|
FX_REGISTER_TOKEN(ONE_MINUS_DST_COLOR);
|
|
FX_REGISTER_TOKEN(InvDestColor);
|
|
FX_REGISTER_TOKEN(SRC_ALPHA_SATURATE);
|
|
|
|
FX_REGISTER_TOKEN(NULL);
|
|
|
|
FX_REGISTER_TOKEN(cbuffer);
|
|
FX_REGISTER_TOKEN(PER_BATCH);
|
|
FX_REGISTER_TOKEN(PER_INSTANCE);
|
|
FX_REGISTER_TOKEN(PER_FRAME);
|
|
FX_REGISTER_TOKEN(PER_MATERIAL);
|
|
FX_REGISTER_TOKEN(PER_SHADOWGEN);
|
|
|
|
FX_REGISTER_TOKEN(ShaderType);
|
|
FX_REGISTER_TOKEN(ShaderDrawType);
|
|
FX_REGISTER_TOKEN(PreprType);
|
|
FX_REGISTER_TOKEN(Public);
|
|
FX_REGISTER_TOKEN(NoPreview);
|
|
FX_REGISTER_TOKEN(LocalConstants);
|
|
FX_REGISTER_TOKEN(Cull);
|
|
FX_REGISTER_TOKEN(SupportsAttrInstancing);
|
|
FX_REGISTER_TOKEN(SupportsConstInstancing);
|
|
FX_REGISTER_TOKEN(SupportsDeferredShading);
|
|
FX_REGISTER_TOKEN(SupportsFullDeferredShading);
|
|
FX_REGISTER_TOKEN(Decal);
|
|
FX_REGISTER_TOKEN(DecalNoDepthOffset);
|
|
FX_REGISTER_TOKEN(NoChunkMerging);
|
|
FX_REGISTER_TOKEN(ForceTransPass);
|
|
FX_REGISTER_TOKEN(AfterHDRPostProcess);
|
|
FX_REGISTER_TOKEN(AfterPostProcess);
|
|
FX_REGISTER_TOKEN(ForceZpass);
|
|
FX_REGISTER_TOKEN(ForceWaterPass);
|
|
FX_REGISTER_TOKEN(ForceDrawLast);
|
|
FX_REGISTER_TOKEN(ForceDrawFirst);
|
|
FX_REGISTER_TOKEN(ForceDrawAfterWater);
|
|
FX_REGISTER_TOKEN(DepthFixup);
|
|
FX_REGISTER_TOKEN(SingleLightPass);
|
|
FX_REGISTER_TOKEN(HWTessellation);
|
|
FX_REGISTER_TOKEN(VertexColors);
|
|
FX_REGISTER_TOKEN(WaterParticle);
|
|
FX_REGISTER_TOKEN(AlphaBlendShadows);
|
|
FX_REGISTER_TOKEN(ZPrePass);
|
|
|
|
FX_REGISTER_TOKEN(VT_DetailBendingGrass);
|
|
FX_REGISTER_TOKEN(VT_DetailBending);
|
|
FX_REGISTER_TOKEN(VT_WindBending);
|
|
|
|
FX_REGISTER_TOKEN(Light);
|
|
FX_REGISTER_TOKEN(Shadow);
|
|
FX_REGISTER_TOKEN(Fur);
|
|
FX_REGISTER_TOKEN(General);
|
|
FX_REGISTER_TOKEN(Terrain);
|
|
FX_REGISTER_TOKEN(Overlay);
|
|
FX_REGISTER_TOKEN(NoDraw);
|
|
FX_REGISTER_TOKEN(Custom);
|
|
FX_REGISTER_TOKEN(Sky);
|
|
FX_REGISTER_TOKEN(OceanShore);
|
|
FX_REGISTER_TOKEN(Hair);
|
|
FX_REGISTER_TOKEN(Compute);
|
|
FX_REGISTER_TOKEN(SkinPass);
|
|
FX_REGISTER_TOKEN(ForceGeneralPass);
|
|
FX_REGISTER_TOKEN(EyeOverlay);
|
|
|
|
FX_REGISTER_TOKEN(Metal);
|
|
FX_REGISTER_TOKEN(Ice);
|
|
FX_REGISTER_TOKEN(Water);
|
|
FX_REGISTER_TOKEN(FX);
|
|
FX_REGISTER_TOKEN(HDR);
|
|
FX_REGISTER_TOKEN(Glass);
|
|
FX_REGISTER_TOKEN(Vegetation);
|
|
FX_REGISTER_TOKEN(Particle);
|
|
FX_REGISTER_TOKEN(GenerateSprites);
|
|
FX_REGISTER_TOKEN(GenerateClouds);
|
|
FX_REGISTER_TOKEN(ScanWater);
|
|
|
|
FX_REGISTER_TOKEN(NoLights);
|
|
FX_REGISTER_TOKEN(NoMaterialState);
|
|
FX_REGISTER_TOKEN(PositionInvariant);
|
|
FX_REGISTER_TOKEN(TechniqueZ);
|
|
FX_REGISTER_TOKEN(TechniqueZPrepass);
|
|
FX_REGISTER_TOKEN(TechniqueShadowGen);
|
|
FX_REGISTER_TOKEN(TechniqueMotionBlur);
|
|
FX_REGISTER_TOKEN(TechniqueCustomRender);
|
|
FX_REGISTER_TOKEN(TechniqueEffectLayer);
|
|
FX_REGISTER_TOKEN(TechniqueDebug);
|
|
FX_REGISTER_TOKEN(TechniqueSoftAlphaTest);
|
|
FX_REGISTER_TOKEN(TechniqueWaterRefl);
|
|
FX_REGISTER_TOKEN(TechniqueWaterCaustic);
|
|
FX_REGISTER_TOKEN(TechniqueThickness);
|
|
|
|
FX_REGISTER_TOKEN(KeyFrameParams);
|
|
FX_REGISTER_TOKEN(KeyFrameRandColor);
|
|
FX_REGISTER_TOKEN(KeyFrameRandIntensity);
|
|
FX_REGISTER_TOKEN(KeyFrameRandSpecMult);
|
|
FX_REGISTER_TOKEN(KeyFrameRandPosOffset);
|
|
FX_REGISTER_TOKEN(Speed);
|
|
|
|
FX_REGISTER_TOKEN(Beam);
|
|
FX_REGISTER_TOKEN(LensOptics);
|
|
FX_REGISTER_TOKEN(Cloud);
|
|
FX_REGISTER_TOKEN(Ocean);
|
|
|
|
FX_REGISTER_TOKEN(Model);
|
|
FX_REGISTER_TOKEN(StartRadius);
|
|
FX_REGISTER_TOKEN(EndRadius);
|
|
FX_REGISTER_TOKEN(StartColor);
|
|
FX_REGISTER_TOKEN(EndColor);
|
|
FX_REGISTER_TOKEN(LightStyle);
|
|
FX_REGISTER_TOKEN(Length);
|
|
|
|
FX_REGISTER_TOKEN(RGBStyle);
|
|
FX_REGISTER_TOKEN(Scale);
|
|
FX_REGISTER_TOKEN(Blind);
|
|
FX_REGISTER_TOKEN(SizeBlindScale);
|
|
FX_REGISTER_TOKEN(SizeBlindBias);
|
|
FX_REGISTER_TOKEN(IntensBlindScale);
|
|
FX_REGISTER_TOKEN(IntensBlindBias);
|
|
FX_REGISTER_TOKEN(MinLight);
|
|
FX_REGISTER_TOKEN(DistFactor);
|
|
FX_REGISTER_TOKEN(DistIntensityFactor);
|
|
FX_REGISTER_TOKEN(FadeTime);
|
|
FX_REGISTER_TOKEN(Layer);
|
|
FX_REGISTER_TOKEN(Importance);
|
|
FX_REGISTER_TOKEN(VisAreaScale);
|
|
|
|
FX_REGISTER_TOKEN(Poly);
|
|
FX_REGISTER_TOKEN(Identity);
|
|
FX_REGISTER_TOKEN(FromObj);
|
|
FX_REGISTER_TOKEN(FromLight);
|
|
FX_REGISTER_TOKEN(Fixed);
|
|
|
|
FX_REGISTER_TOKEN(ParticlesFile);
|
|
|
|
FX_REGISTER_TOKEN(Gravity);
|
|
FX_REGISTER_TOKEN(WindDirection);
|
|
FX_REGISTER_TOKEN(WindSpeed);
|
|
FX_REGISTER_TOKEN(WaveHeight);
|
|
FX_REGISTER_TOKEN(DirectionalDependence);
|
|
FX_REGISTER_TOKEN(ChoppyWaveFactor);
|
|
FX_REGISTER_TOKEN(SuppressSmallWavesFactor);
|
|
|
|
FX_REGISTER_TOKEN(x);
|
|
FX_REGISTER_TOKEN(y);
|
|
FX_REGISTER_TOKEN(z);
|
|
FX_REGISTER_TOKEN(w);
|
|
FX_REGISTER_TOKEN(r);
|
|
FX_REGISTER_TOKEN(g);
|
|
FX_REGISTER_TOKEN(b);
|
|
FX_REGISTER_TOKEN(a);
|
|
|
|
FX_REGISTER_TOKEN(true);
|
|
FX_REGISTER_TOKEN(false);
|
|
|
|
FX_REGISTER_TOKEN(0);
|
|
FX_REGISTER_TOKEN(1);
|
|
FX_REGISTER_TOKEN(2);
|
|
FX_REGISTER_TOKEN(3);
|
|
FX_REGISTER_TOKEN(4);
|
|
FX_REGISTER_TOKEN(5);
|
|
FX_REGISTER_TOKEN(6);
|
|
FX_REGISTER_TOKEN(7);
|
|
FX_REGISTER_TOKEN(8);
|
|
FX_REGISTER_TOKEN(9);
|
|
FX_REGISTER_TOKEN(10);
|
|
FX_REGISTER_TOKEN(11);
|
|
FX_REGISTER_TOKEN(12);
|
|
FX_REGISTER_TOKEN(13);
|
|
FX_REGISTER_TOKEN(14);
|
|
FX_REGISTER_TOKEN(15);
|
|
FX_REGISTER_TOKEN(16);
|
|
FX_REGISTER_TOKEN(17);
|
|
FX_REGISTER_TOKEN(18);
|
|
FX_REGISTER_TOKEN(19);
|
|
FX_REGISTER_TOKEN(20);
|
|
FX_REGISTER_TOKEN(21);
|
|
FX_REGISTER_TOKEN(22);
|
|
FX_REGISTER_TOKEN(23);
|
|
FX_REGISTER_TOKEN(24);
|
|
|
|
FX_REGISTER_TOKEN(ORBIS);
|
|
FX_REGISTER_TOKEN(PCDX11);
|
|
FX_REGISTER_TOKEN(GL4);
|
|
FX_REGISTER_TOKEN(GLES3);
|
|
FX_REGISTER_TOKEN(METAL);
|
|
FX_REGISTER_TOKEN(OSXMETAL);
|
|
FX_REGISTER_TOKEN(IOSMETAL);
|
|
|
|
FX_REGISTER_TOKEN(STANDARDSGLOBAL);
|
|
|
|
FX_REGISTER_TOKEN(GLES3_0);
|
|
|
|
FX_REGISTER_TOKEN(Load);
|
|
FX_REGISTER_TOKEN(Sample);
|
|
FX_REGISTER_TOKEN(Gather);
|
|
FX_REGISTER_TOKEN(GatherRed);
|
|
FX_REGISTER_TOKEN(GatherGreen);
|
|
FX_REGISTER_TOKEN(GatherBlue);
|
|
FX_REGISTER_TOKEN(GatherAlpha);
|
|
|
|
FXMacroItor it;
|
|
for (it = sStaticMacros.begin(); it != sStaticMacros.end(); it++)
|
|
{
|
|
bool bKey = false;
|
|
uint32 nName = CParserBin::fxToken(it->first.c_str(), &bKey);
|
|
if (!bKey)
|
|
{
|
|
nName = GetCRC32(it->first.c_str());
|
|
}
|
|
SMacroFX* pr = &it->second;
|
|
uint32 nMacros = 0;
|
|
uint32 Macro[64];
|
|
if (pr->m_szMacro[0])
|
|
{
|
|
char* szBuf = (char*)pr->m_szMacro.c_str();
|
|
SkipCharacters (&szBuf, " ");
|
|
if (!szBuf[0])
|
|
{
|
|
break;
|
|
}
|
|
char com[1024];
|
|
bKey = false;
|
|
uint32 dwToken = CParserBin::NextToken(szBuf, com, bKey);
|
|
if (!bKey)
|
|
{
|
|
dwToken = GetCRC32(com);
|
|
}
|
|
Macro[nMacros++] = dwToken;
|
|
}
|
|
AddMacro(nName, Macro, nMacros, pr->m_nMask, m_StaticMacros);
|
|
}
|
|
sStaticMacros.clear();
|
|
|
|
if (!CParserBin::m_bShaderCacheGen)
|
|
{
|
|
#if defined(CRY_USE_METAL)
|
|
SetupForMETAL();
|
|
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#elif defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION PARSERBIN_CPP_SECTION_1
|
|
#include AZ_RESTRICTED_FILE(ParserBin_cpp)
|
|
#endif
|
|
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
|
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
|
#elif defined(OPENGL_ES) && DXGL_INPUT_GLSL
|
|
SetupForGLES3();
|
|
#elif defined(OPENGL) && DXGL_INPUT_GLSL
|
|
SetupForGL4();
|
|
#else
|
|
SetupForD3D11();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void CParserBin::SetupTargetPlatform()
|
|
{
|
|
#if !defined(CONSOLE)
|
|
if (CParserBin::m_bShaderCacheGen)
|
|
{
|
|
m_targetPlatform = static_cast<AZ::PlatformID>(CRenderer::CV_r_shadersPlatform);
|
|
}
|
|
else
|
|
#endif // !defined(CONSOLE)
|
|
{
|
|
m_targetPlatform = AZ::g_currentPlatform;
|
|
}
|
|
}
|
|
|
|
void CParserBin::SetupForD3D11()
|
|
{
|
|
CleanPlatformMacros();
|
|
SetupTargetPlatform();
|
|
|
|
uint32 nMacro[1] = {eT_1};
|
|
|
|
AddMacro(CParserBin::fxToken("PCDX11"), nMacro, 1, 0, m_StaticMacros);
|
|
|
|
m_nPlatform = SF_D3D11;
|
|
|
|
SetupShadersCacheAndFilter();
|
|
|
|
SetupFeatureDefines();
|
|
gRenDev->m_cEF.m_Bin.InvalidateCache();
|
|
gRenDev->m_cEF.mfInitLookups();
|
|
|
|
SAFE_DELETE(gRenDev->m_cEF.m_pGlobalExt);
|
|
gRenDev->m_cEF.m_pGlobalExt = gRenDev->m_cEF.mfCreateShaderGenInfo("RunTime", true);
|
|
}
|
|
|
|
void CParserBin::SetupForGL4()
|
|
{
|
|
CleanPlatformMacros();
|
|
SetupTargetPlatform();
|
|
uint32 nMacro[1] = {eT_1};
|
|
|
|
AddMacro(CParserBin::fxToken("GL4"), nMacro, 1, 0, m_StaticMacros);
|
|
|
|
if (!gRenDev->IsShaderCacheGenMode())
|
|
{
|
|
if IsCVarConstAccess(constexpr) (CRenderer::CV_r_ShadersUseLLVMDirectXCompiler)
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_LLVM_DIRECTX_SHADER_COMPILER);
|
|
}
|
|
}
|
|
|
|
m_nPlatform = SF_GL4;
|
|
|
|
SetupShadersCacheAndFilter();
|
|
|
|
SetupFeatureDefines();
|
|
gRenDev->m_cEF.m_Bin.InvalidateCache();
|
|
gRenDev->m_cEF.mfInitLookups();
|
|
|
|
SAFE_DELETE(gRenDev->m_cEF.m_pGlobalExt);
|
|
gRenDev->m_cEF.m_pGlobalExt = gRenDev->m_cEF.mfCreateShaderGenInfo("RunTime", true);
|
|
}
|
|
|
|
void CParserBin::SetupForGLES3()
|
|
{
|
|
CleanPlatformMacros();
|
|
SetupTargetPlatform();
|
|
uint32 nMacro[1] = {eT_1};
|
|
|
|
AddMacro(CParserBin::fxToken("GLES3"), nMacro, 1, 0, m_StaticMacros);
|
|
// Forcing small uniform buffers since OpenGLES only guarantees 16k of space for uniform blocks.
|
|
// We don't do it per device because that would add extra permutations.
|
|
AddMacro(CParserBin::GetCRC32("SMALL_UNIFORM_BUFFERS"), nMacro, 1, 0, m_StaticMacros);
|
|
|
|
m_nPlatform = SF_GLES3;
|
|
if (!gRenDev->IsShaderCacheGenMode())
|
|
{
|
|
if IsCVarConstAccess(constexpr) (CRenderer::CV_r_ShadersUseLLVMDirectXCompiler)
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_LLVM_DIRECTX_SHADER_COMPILER);
|
|
}
|
|
#if defined(OPENGL_ES)
|
|
AZ_Assert(gcpRendD3D, "Null CD3D9Renderer");
|
|
uint32 glVersion = RenderCapabilities::GetDeviceGLVersion();
|
|
AZ_Assert(glVersion >= DXGLES_VERSION_30, "Invalid OpenGL version %lu", static_cast<unsigned long>(glVersion));
|
|
if (glVersion == DXGLES_VERSION_30)
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_GLES3_0);
|
|
}
|
|
|
|
if (!gcpRendD3D->UseHalfFloatRenderTargets())
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_FIXED_POINT);
|
|
}
|
|
#endif // defined(OPENGL_ES)
|
|
}
|
|
|
|
SetupShadersCacheAndFilter();
|
|
SetupFeatureDefines();
|
|
SetupForGMEM(CRenderer::CV_r_EnableGMEMPath);
|
|
gRenDev->m_cEF.m_Bin.InvalidateCache();
|
|
gRenDev->m_cEF.mfInitLookups();
|
|
|
|
SAFE_DELETE(gRenDev->m_cEF.m_pGlobalExt);
|
|
gRenDev->m_cEF.m_pGlobalExt = gRenDev->m_cEF.mfCreateShaderGenInfo("RunTime", true);
|
|
}
|
|
|
|
|
|
void CParserBin::RemoveGMEMStaticFlags()
|
|
{
|
|
gRenDev->m_cEF.RemoveStaticFlag(HWSST_GMEM_256BPP);
|
|
gRenDev->m_cEF.RemoveStaticFlag(HWSST_GMEM_128BPP);
|
|
gRenDev->m_cEF.RemoveStaticFlag(HWSST_GMEM_PLS);
|
|
gRenDev->m_cEF.RemoveStaticFlag(HWSST_GMEM_VELOCITY_BUFFER);
|
|
gRenDev->m_cEF.RemoveStaticFlag(HWSST_GMEM_RT_GREATER_FOUR);
|
|
gRenDev->m_cEF.RemoveStaticFlag(HWSST_FEATURE_FETCH_DEPTHSTENCIL);
|
|
}
|
|
|
|
void CParserBin::SetupGMEMCommonStaticFlags()
|
|
{
|
|
#if defined(OPENGL_ES) || defined(CRY_USE_METAL)
|
|
if (RenderCapabilities::SupportsPLSExtension())
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_GMEM_PLS);
|
|
}
|
|
|
|
// TAA and motion blur need an extra render target to write the objects velocity.
|
|
if (CRenderer::CV_r_MotionBlur > 0 || (gRenDev->FX_GetAntialiasingType() & eAT_TEMPORAL_MASK) != 0)
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_GMEM_VELOCITY_BUFFER);
|
|
}
|
|
|
|
// Ensure that the device can support at least 5 render targets - GBUFFER A, GBUFFER B, GBUFFER C, Lin Depth/Stencil and Velocity
|
|
if (RenderCapabilities::SupportsRenderTargets(CD3D9Renderer::s_gmemLargeRTCount))
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_GMEM_RT_GREATER_FOUR);
|
|
}
|
|
|
|
RenderCapabilities::FrameBufferFetchMask fetchCapabilities = RenderCapabilities::GetFrameBufferFetchCapabilities();
|
|
if (fetchCapabilities.test(RenderCapabilities::FBF_DEPTH) && fetchCapabilities.test(RenderCapabilities::FBF_STENCIL))
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_FEATURE_FETCH_DEPTHSTENCIL);
|
|
}
|
|
#endif // defined(OPENGL_ES) || defined(CRY_USE_METAL)
|
|
}
|
|
|
|
void CParserBin::SetupForMETAL()
|
|
{
|
|
CleanPlatformMacros();
|
|
SetupTargetPlatform();
|
|
uint32 nMacro[1] = {eT_1};
|
|
|
|
AddMacro(CParserBin::fxToken("METAL"), nMacro, 1, 0, m_StaticMacros);
|
|
|
|
switch (m_targetPlatform)
|
|
{
|
|
case AZ::PlatformID::PLATFORM_APPLE_OSX:
|
|
AddMacro(CParserBin::fxToken("OSXMETAL"), nMacro, 1, 0, m_StaticMacros);
|
|
break;
|
|
case AZ::PlatformID::PLATFORM_APPLE_IOS:
|
|
AddMacro(CParserBin::fxToken("IOSMETAL"), nMacro, 1, 0, m_StaticMacros);
|
|
break;
|
|
default:
|
|
AZ_Assert(false, "Invalid platform id (%s) for Metal shader setup", AZ::GetPlatformName(m_targetPlatform));
|
|
return;
|
|
}
|
|
|
|
|
|
if (!gRenDev->IsShaderCacheGenMode())
|
|
{
|
|
if IsCVarConstAccess(constexpr) (CRenderer::CV_r_ShadersUseLLVMDirectXCompiler)
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_LLVM_DIRECTX_SHADER_COMPILER);
|
|
}
|
|
}
|
|
|
|
m_nPlatform = SF_METAL;
|
|
SetupShadersCacheAndFilter();
|
|
SetupFeatureDefines();
|
|
SetupForGMEM(CRenderer::CV_r_EnableGMEMPath);
|
|
gRenDev->m_cEF.m_Bin.InvalidateCache();
|
|
gRenDev->m_cEF.mfInitLookups();
|
|
|
|
SAFE_DELETE(gRenDev->m_cEF.m_pGlobalExt);
|
|
gRenDev->m_cEF.m_pGlobalExt = gRenDev->m_cEF.mfCreateShaderGenInfo("RunTime", true);
|
|
}
|
|
|
|
void CParserBin::SetupForGMEM([[maybe_unused]] int const gmemPath)
|
|
{
|
|
AZ_Assert(m_nPlatform == SF_METAL || m_nPlatform == SF_GLES3, "Invalid platform (%d) for setup up GMEM");
|
|
|
|
#if defined(OPENGL_ES) || defined(CRY_USE_METAL)
|
|
uint32 nMacro[1] = { eT_1 };
|
|
|
|
CD3D9Renderer::EGmemPath enabledGmemPath;
|
|
CD3D9Renderer::EGmemPathState gmemState;
|
|
assert(gcpRendD3D);
|
|
enabledGmemPath = gcpRendD3D->FX_GetEnabledGmemPath(&gmemState);
|
|
const char* strUnsupportedFeats = "CParserBin::SetupForGMEM: cannot use 256bpp GMEM path due to SSDO or SSR being used! It is recommended to disable these features on mobile platforms. Forcing 128bpp path instead.";
|
|
const char* strUnsupportedGmem256 = "CParserBin::SetupForGMEM: 256bpp GMEM path not supported on this device! Forcing 128bpp GMEM path instead.";
|
|
const char* strUnsupportedGmem128 = "CParserBin::SetupForGMEM: 128bpp GMEM path not supported on this device! Forcing regular render path instead.";
|
|
|
|
switch (gmemPath)
|
|
{
|
|
case 0:
|
|
RemoveGMEMStaticFlags();
|
|
break;
|
|
case 1:
|
|
{
|
|
// Does devices allow this path?
|
|
if (CD3D9Renderer::eGT_DEV_UNSUPPORTED == gmemState)
|
|
{
|
|
CryLogAlways(strUnsupportedGmem256);
|
|
SetupForGMEM(2);
|
|
return;
|
|
}
|
|
|
|
// Some deferred passes don't fit in the 256bpp path and must be resolved.
|
|
// We can delay these passes until after the GMEM section, however the effect will be a frame behind.
|
|
// This causes ghosting artifacts. Since the 128bpp path must resolve after the G-Buffer pass anyways,
|
|
// it can also process the data for these deferred passes in time.
|
|
// This will obviously set back performance... but the following effects are very performance heavy and
|
|
// should not be used on mobile devices in most cases.
|
|
if (CD3D9Renderer::eGT_OK != gmemState && CD3D9Renderer::eGT_128bpp_PATH == enabledGmemPath)
|
|
{
|
|
CryLogAlways(strUnsupportedFeats);
|
|
SetupForGMEM(2);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
assert(CD3D9Renderer::eGT_OK == gmemState);
|
|
}
|
|
|
|
RemoveGMEMStaticFlags();
|
|
SetupGMEMCommonStaticFlags();
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_GMEM_256BPP);
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
// Does devices allow this path?
|
|
if (CD3D9Renderer::eGT_DEV_UNSUPPORTED == gmemState && CD3D9Renderer::eGT_REGULAR_PATH == enabledGmemPath)
|
|
{
|
|
CryLogAlways(strUnsupportedGmem128);
|
|
SetupForGMEM(0);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
assert(CD3D9Renderer::eGT_128bpp_PATH == enabledGmemPath);
|
|
}
|
|
|
|
RemoveGMEMStaticFlags();
|
|
SetupGMEMCommonStaticFlags();
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_GMEM_128BPP);
|
|
break;
|
|
}
|
|
default:
|
|
CRY_ASSERT(0);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CParserBin::SetupForOrbis()
|
|
{
|
|
CleanPlatformMacros();
|
|
SetupTargetPlatform();
|
|
uint32 nMacro[1] = {eT_1};
|
|
AddMacro(CParserBin::fxToken("ORBIS"), nMacro, 1, 0, m_StaticMacros);
|
|
m_nPlatform = SF_ORBIS;
|
|
|
|
SetupShadersCacheAndFilter();
|
|
|
|
SetupFeatureDefines();
|
|
gRenDev->m_cEF.m_Bin.InvalidateCache();
|
|
gRenDev->m_cEF.mfInitLookups();
|
|
SAFE_DELETE(gRenDev->m_cEF.m_pGlobalExt);
|
|
gRenDev->m_cEF.m_pGlobalExt = gRenDev->m_cEF.mfCreateShaderGenInfo("RunTime", true);
|
|
}
|
|
|
|
void CParserBin::SetupForJasper()
|
|
{
|
|
CleanPlatformMacros();
|
|
SetupTargetPlatform();
|
|
uint32 nMacro[1] = { eT_1 };
|
|
|
|
m_nPlatform = SF_JASPER;
|
|
|
|
SetupShadersCacheAndFilter();
|
|
|
|
AddMacro(CParserBin::fxToken("JASPER"), nMacro, 1, 0, m_StaticMacros);
|
|
|
|
SetupFeatureDefines();
|
|
gRenDev->m_cEF.m_Bin.InvalidateCache();
|
|
gRenDev->m_cEF.mfInitLookups();
|
|
|
|
SAFE_DELETE(gRenDev->m_cEF.m_pGlobalExt);
|
|
gRenDev->m_cEF.m_pGlobalExt = gRenDev->m_cEF.mfCreateShaderGenInfo("RunTime", true);
|
|
}
|
|
|
|
CCryNameTSCRC CParserBin::GetPlatformSpecName(CCryNameTSCRC orgName)
|
|
{
|
|
CCryNameTSCRC nmTemp = orgName;
|
|
if (CParserBin::m_nPlatform == SF_D3D11)
|
|
{
|
|
nmTemp.add(0x200);
|
|
}
|
|
else
|
|
if (CParserBin::m_nPlatform == SF_GL4)
|
|
{
|
|
nmTemp.add(0x300);
|
|
}
|
|
else
|
|
if (CParserBin::m_nPlatform == SF_GLES3)
|
|
{
|
|
nmTemp.add(0x800);
|
|
}
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#define AZ_RESTRICTED_SECTION PARSERBIN_CPP_SECTION_2
|
|
#include AZ_RESTRICTED_FILE(ParserBin_cpp)
|
|
#endif
|
|
// Confetti Nicholas Baldwin: adding metal shader language support
|
|
else
|
|
if (CParserBin::m_nPlatform == SF_METAL)
|
|
{
|
|
nmTemp.add(0x900);
|
|
}
|
|
else
|
|
if (CParserBin::m_bEndians)
|
|
{
|
|
nmTemp.add(0x500);
|
|
}
|
|
|
|
return nmTemp;
|
|
}
|
|
|
|
uint32 CParserBin::fxTokenKey(const char* szToken, EToken eTC)
|
|
{
|
|
g_KeyTokens[eTC] = szToken;
|
|
return eTC;
|
|
}
|
|
|
|
uint32 CParserBin::fxToken(const char* szToken, bool* bKey)
|
|
{
|
|
for (int i = 0; i < eT_max; i++)
|
|
{
|
|
if (!g_KeyTokens[i])
|
|
{
|
|
continue;
|
|
}
|
|
if (!strcmp(szToken, g_KeyTokens[i]))
|
|
{
|
|
if (bKey)
|
|
{
|
|
*bKey = true;
|
|
}
|
|
return i;
|
|
}
|
|
}
|
|
if (bKey)
|
|
{
|
|
*bKey = false;
|
|
}
|
|
return eT_unknown;
|
|
}
|
|
/*uint32 CParserBin::NewUserToken(uint32 nToken, const char* psToken, bool bUseFinalTable)
|
|
{
|
|
const string tmpstr = psToken;
|
|
return NewUserToken(nToken,tmpstr,bUseFinalTable);
|
|
}*/
|
|
uint32 CParserBin::NewUserToken(uint32 nToken, const char* psToken, bool bUseFinalTable)
|
|
{
|
|
if (nToken != eT_unknown)
|
|
{
|
|
return nToken;
|
|
}
|
|
nToken = GetCRC32(psToken);
|
|
|
|
if (bUseFinalTable)
|
|
{
|
|
FXShaderTokenItor itor = std::lower_bound(m_TokenTable.begin(), m_TokenTable.end(), nToken, SortByToken());
|
|
if (itor != m_TokenTable.end() && (*itor).Token == nToken)
|
|
{
|
|
assert(!strcmp((*itor).SToken.c_str(), psToken));
|
|
return nToken;
|
|
}
|
|
STokenD TD;
|
|
TD.SToken = psToken;
|
|
TD.Token = nToken;
|
|
m_TokenTable.insert(itor, TD);
|
|
}
|
|
else
|
|
{
|
|
SShaderBin* pBin = m_pCurBinShader;
|
|
assert(pBin);
|
|
FXShaderTokenItor itor = std::lower_bound(pBin->m_TokenTable.begin(), pBin->m_TokenTable.end(), nToken, SortByToken());
|
|
if (itor != pBin->m_TokenTable.end() && (*itor).Token == nToken)
|
|
{
|
|
assert(!strcmp((*itor).SToken.c_str(), psToken));
|
|
return nToken;
|
|
}
|
|
STokenD TD;
|
|
TD.SToken = psToken;
|
|
TD.Token = nToken;
|
|
pBin->m_TokenTable.insert(itor, TD);
|
|
}
|
|
|
|
return nToken;
|
|
}
|
|
|
|
uint32 CParserBin::NextToken(char*& buf, char* com, bool& bKey)
|
|
{
|
|
char ch;
|
|
int n = 0;
|
|
while ((ch = *buf) != 0)
|
|
{
|
|
// Iterate until a special character that indicates we've reached the end of a token is found
|
|
if (SkipChar(ch))
|
|
{
|
|
break;
|
|
}
|
|
com[n++] = ch;
|
|
++buf;
|
|
if (ch == '/')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
// If the first character of buf returns true for SkipChar (or buf is zero-length)
|
|
if (!n)
|
|
{
|
|
// And that character is not a space
|
|
if (ch != ' ')
|
|
{
|
|
// The special character is the token that needs to be returned
|
|
com[n++] = ch;
|
|
++buf;
|
|
}
|
|
}
|
|
com[n] = 0;
|
|
// Check to see if com is a key token, and return the enum for that token
|
|
uint32 dwToken = fxToken(com, &bKey);
|
|
return dwToken;
|
|
}
|
|
|
|
bool CParserBin::AddMacro(uint32 dwName, const uint32* pMacro, int nMacroTokens, uint64 nMask, FXMacroBin& Macro)
|
|
{
|
|
// Use 'lower_bound' instead of 'find' to avoid double traversal of the
|
|
// underlying tree. Iterator reused as insertion hint to 'insert()'.
|
|
FXMacroBinItor it = Macro.lower_bound(dwName);
|
|
|
|
SMacroBinFX* macro;
|
|
if (it != Macro.end() && it->first == dwName)
|
|
{
|
|
macro = &it->second;
|
|
}
|
|
else
|
|
{
|
|
// Creates empty vector - no allocation.
|
|
macro = &Macro.insert(it, FXMacroBinItor::value_type(dwName, SMacroBinFX()))->second;
|
|
}
|
|
macro->m_nMask = nMask;
|
|
if (nMacroTokens)
|
|
{
|
|
macro->m_Macro.resize(nMacroTokens);
|
|
memcpy(¯o->m_Macro[0], pMacro, nMacroTokens * sizeof(uint32));
|
|
}
|
|
else
|
|
{
|
|
macro->m_Macro.clear();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CParserBin::RemoveMacro(uint32 dwName, FXMacroBin& Macro)
|
|
{
|
|
FXMacroBinItor it = Macro.find(dwName);
|
|
if (it == Macro.end())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
Macro.erase(dwName);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CParserBin::CleanPlatformMacros()
|
|
{
|
|
RemoveMacro(CParserBin::fxToken("ORBIS"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::fxToken("PCDX11"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::fxToken("GL4"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::fxToken("GLES3"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::fxToken("METAL"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::fxToken("OSXMETAL"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::fxToken("IOSMETAL"), m_StaticMacros);
|
|
}
|
|
|
|
const SMacroBinFX* CParserBin::FindMacro(uint32 dwName, FXMacroBin& Macro)
|
|
{
|
|
FXMacroBinItor it = Macro.find(dwName);
|
|
if (it != Macro.end())
|
|
{
|
|
return &it->second;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool CParserBin::GetBool(SParserFrame& Frame)
|
|
{
|
|
if (Frame.IsEmpty())
|
|
{
|
|
return true;
|
|
}
|
|
EToken eT = GetToken(Frame);
|
|
if (eT == eT_true || eT == eT_1)
|
|
{
|
|
return true;
|
|
}
|
|
if (eT == eT_false || eT == eT_0)
|
|
{
|
|
return false;
|
|
}
|
|
CRY_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
CCryNameR CParserBin::GetNameString(SParserFrame& Frame)
|
|
{
|
|
if (Frame.IsEmpty())
|
|
{
|
|
return CCryNameR("");
|
|
}
|
|
|
|
stack_string Str;
|
|
int nCur = Frame.m_nFirstToken;
|
|
int nLast = Frame.m_nLastToken;
|
|
while (nCur <= nLast)
|
|
{
|
|
int nTok = m_Tokens[nCur++];
|
|
const char* szStr = GetString(nTok);
|
|
if (Str.size() && !SkipChar(Str[Str.size() - 1]) && !SkipChar(szStr[0]))
|
|
{
|
|
Str += " ";
|
|
}
|
|
Str += szStr;
|
|
}
|
|
return CCryNameR(Str.c_str());
|
|
}
|
|
|
|
string CParserBin::GetString(SParserFrame& Frame)
|
|
{
|
|
if (Frame.IsEmpty())
|
|
{
|
|
return "";
|
|
}
|
|
|
|
stack_string Str;
|
|
int nCur = Frame.m_nFirstToken;
|
|
int nLast = Frame.m_nLastToken;
|
|
while (nCur <= nLast)
|
|
{
|
|
int nTok = m_Tokens[nCur++];
|
|
const char* szStr = GetString(nTok);
|
|
if (Str.size() && !SkipChar(Str[Str.size() - 1]) && !SkipChar(szStr[0]))
|
|
{
|
|
Str += " ";
|
|
}
|
|
Str += szStr;
|
|
}
|
|
return string(Str.c_str());
|
|
}
|
|
|
|
const char* CParserBin::GetString(uint32 nToken, FXShaderToken& Table, bool bOnlyKey)
|
|
{
|
|
FXShaderTokenItor it;
|
|
if (nToken < eT_max)
|
|
{
|
|
assert(g_KeyTokens[nToken]);
|
|
return g_KeyTokens[nToken];
|
|
}
|
|
if (!bOnlyKey)
|
|
{
|
|
it = std::lower_bound(Table.begin(), Table.end(), nToken, SortByToken());
|
|
if (it != Table.end() && (*it).Token == nToken)
|
|
{
|
|
return (*it).SToken.c_str();
|
|
}
|
|
}
|
|
|
|
CRY_ASSERT(0);
|
|
return "";
|
|
}
|
|
|
|
const char* CParserBin::GetString(uint32 nToken, bool bOnlyKey)
|
|
{
|
|
return GetString(nToken, m_TokenTable, bOnlyKey);
|
|
}
|
|
|
|
static void sCR(TArray<char>& Text, int nLevel)
|
|
{
|
|
Text.AddElem('\n');
|
|
for (int i = 0; i < nLevel; i++)
|
|
{
|
|
Text.AddElem(' ');
|
|
Text.AddElem(' ');
|
|
}
|
|
}
|
|
|
|
bool CParserBin::CorrectScript(uint32* pTokens, uint32& i, uint32 nT, TArray<char>& Text)
|
|
{
|
|
|
|
int nTex = Text.Num() - 1;
|
|
int nTT = nTex;
|
|
while (nTex > 0)
|
|
{
|
|
char c = Text[nTex];
|
|
if (c <= 32)
|
|
{
|
|
nTex++;
|
|
break;
|
|
}
|
|
nTex--;
|
|
}
|
|
if (strncmp(&Text[nTex], "float", 5))
|
|
{
|
|
CRY_ASSERT(0);
|
|
iLog->Log("Wrong script tokens...");
|
|
return false;
|
|
}
|
|
memset(&Text[nTex], 0x20202020, nTT - nTex + 1);
|
|
i++;
|
|
while (i < nT)
|
|
{
|
|
uint32 nTok = pTokens[i];
|
|
if (nTok == eT_semicolumn)
|
|
{
|
|
return true;
|
|
}
|
|
i++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CParserBin::ConvertToAscii(uint32* pTokens, uint32 nT, FXShaderToken& Table, TArray<char>& Text, bool bInclSkipTokens)
|
|
{
|
|
uint32 i;
|
|
bool bRes = true;
|
|
|
|
int nLevel = 0;
|
|
for (i = 0; i < nT; i++)
|
|
{
|
|
uint32 nToken = pTokens[i];
|
|
if (nToken == 0)
|
|
{
|
|
Text.Copy("\n", 1);
|
|
continue;
|
|
}
|
|
if (!bInclSkipTokens)
|
|
{
|
|
if (nToken == eT_skip)
|
|
{
|
|
i++;
|
|
continue;
|
|
}
|
|
if (nToken == eT_skip_1)
|
|
{
|
|
while (i < nT)
|
|
{
|
|
nToken = pTokens[i];
|
|
if (nToken == eT_skip_2)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
assert(i < nT);
|
|
continue;
|
|
}
|
|
}
|
|
const char* szStr = GetString(nToken, Table, false);
|
|
assert(szStr);
|
|
if (!szStr || !szStr[0])
|
|
{
|
|
bRes = CParserBin::CorrectScript(pTokens, i, nT, Text);
|
|
}
|
|
else
|
|
{
|
|
if (nToken == eT_semicolumn || nToken == eT_br_cv_1)
|
|
{
|
|
if (nToken == eT_br_cv_1)
|
|
{
|
|
sCR(Text, nLevel);
|
|
nLevel++;
|
|
}
|
|
Text.Copy(szStr, strlen(szStr));
|
|
if (nToken == eT_semicolumn)
|
|
{
|
|
if (i + 1 < nT && pTokens[i + 1] == eT_br_cv_2)
|
|
{
|
|
sCR(Text, nLevel - 1);
|
|
}
|
|
else
|
|
{
|
|
sCR(Text, nLevel);
|
|
}
|
|
}
|
|
else
|
|
if (i + 1 < nT)
|
|
{
|
|
if (pTokens[i + 1] < eT_br_rnd_1 || pTokens[i + 1] >= eT_float)
|
|
{
|
|
sCR(Text, nLevel);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (i + 1 < nT)
|
|
{
|
|
if (Text.Num())
|
|
{
|
|
char cPrev = Text[Text.Num() - 1];
|
|
if (!SkipChar((uint8)cPrev) && !SkipChar((uint8)szStr[0]))
|
|
{
|
|
Text.AddElem(' ');
|
|
}
|
|
}
|
|
}
|
|
Text.Copy(szStr, strlen(szStr));
|
|
if (nToken == eT_br_cv_2)
|
|
{
|
|
nLevel--;
|
|
if (i + 1 < nT && pTokens[i + 1] != eT_semicolumn)
|
|
{
|
|
sCR(Text, nLevel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Text.AddElem(0);
|
|
|
|
return bRes;
|
|
}
|
|
|
|
void CParserBin::MergeTable(SShaderBin* pBin)
|
|
{
|
|
FXShaderTokenItor it = m_TokenTable.begin();
|
|
FXShaderTokenItor end = m_TokenTable.end();
|
|
FXShaderTokenItor bit = pBin->m_TokenTable.begin();
|
|
FXShaderTokenItor bend = pBin->m_TokenTable.end();
|
|
|
|
FXShaderToken newTable;
|
|
newTable.reserve(m_TokenTable.size() + pBin->m_TokenTable.size());
|
|
while (true)
|
|
{
|
|
STokenD* last = newTable.size() ? &(*newTable.rbegin()) : NULL;
|
|
|
|
unsigned mask = 0;
|
|
mask |= (bit != bend) << 0;
|
|
mask |= (it != end) << 1;
|
|
|
|
switch (mask)
|
|
{
|
|
// No iterators valid anymore, nothing left to do
|
|
case 0x0:
|
|
goto done;
|
|
|
|
// Other iterator valid, internal iterator invalid
|
|
case 0x1:
|
|
if (!last || bit->Token != last->Token)
|
|
{
|
|
newTable.push_back(*bit);
|
|
}
|
|
++bit;
|
|
break;
|
|
|
|
// Other iterator invalid, internal iterator valid
|
|
case 0x2:
|
|
if (!last || it->Token != last->Token)
|
|
{
|
|
newTable.push_back(*it);
|
|
}
|
|
++it;
|
|
break;
|
|
|
|
// Noth iterators valid
|
|
case 0x3:
|
|
{
|
|
STokenD& iTD = (*it);
|
|
STokenD& oTD = (*bit);
|
|
if (iTD.Token < oTD.Token)
|
|
{
|
|
if (!last || it->Token != last->Token)
|
|
{
|
|
newTable.push_back(*it);
|
|
}
|
|
++it;
|
|
}
|
|
else
|
|
{
|
|
if (!last || bit->Token != last->Token)
|
|
{
|
|
newTable.push_back(*bit);
|
|
}
|
|
++bit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
;
|
|
}
|
|
|
|
// Verify that the merging results in a sorted table
|
|
# if defined _DEBUG
|
|
for (std::size_t i = 1; i < newTable.size(); ++i)
|
|
{
|
|
assert (newTable[i - 1].Token <= newTable[i].Token);
|
|
}
|
|
# endif
|
|
|
|
done:
|
|
swap(newTable, m_TokenTable);
|
|
}
|
|
|
|
bool CParserBin::IgnorePreprocessBlock(const uint32* pTokens, uint32& nT, int nMaxTokens, PodArray<uint32>& tokensBuffer, int nPass)
|
|
{
|
|
int nLevel = 0;
|
|
bool bEnded = false;
|
|
while (*pTokens != 0)
|
|
{
|
|
if ((int)nT >= nMaxTokens)
|
|
{
|
|
break;
|
|
}
|
|
uint32 nToken = NextToken(pTokens, nT, nMaxTokens - 1);
|
|
if (nToken >= eT_if && nToken <= eT_ifndef_2)
|
|
{
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, nMaxTokens, false, tokensBuffer);
|
|
}
|
|
nLevel++;
|
|
continue;
|
|
}
|
|
if (nToken == eT_endif)
|
|
{
|
|
if (!nLevel)
|
|
{
|
|
bEnded = true;
|
|
nT--;
|
|
break;
|
|
}
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, nMaxTokens, true, tokensBuffer);
|
|
}
|
|
nLevel--;
|
|
}
|
|
else
|
|
if (nToken == eT_else || nToken == eT_elif)
|
|
{
|
|
if (!nLevel)
|
|
{
|
|
nT--;
|
|
break;
|
|
}
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, nMaxTokens, nToken == eT_else, tokensBuffer);
|
|
}
|
|
}
|
|
}
|
|
if ((int)nT >= nMaxTokens)
|
|
{
|
|
CRY_ASSERT(0);
|
|
Warning("Couldn't find #endif directive for associated #ifdef");
|
|
return false;
|
|
}
|
|
|
|
return bEnded;
|
|
}
|
|
|
|
void CParserBin::InsertSkipTokens(const uint32* pTokens, uint32 nStart, [[maybe_unused]] uint32 nTokens, bool bSingle, PodArray<uint32>& tokensBuffer)
|
|
{
|
|
SParserFrame Fr;
|
|
Fr.m_nFirstToken = nStart;
|
|
Fr.m_nLastToken = nStart;
|
|
|
|
if (!bSingle)
|
|
{
|
|
uint32 nS = nStart + 1;
|
|
CheckIfExpression(pTokens, nS, 0);
|
|
Fr.m_nLastToken = nS - 1;
|
|
}
|
|
|
|
if (Fr.m_nLastToken - Fr.m_nFirstToken == 0)
|
|
{
|
|
tokensBuffer.push_back(eT_skip);
|
|
tokensBuffer.push_back(pTokens[Fr.m_nFirstToken]);
|
|
}
|
|
else
|
|
{
|
|
tokensBuffer.push_back(eT_skip_1);
|
|
while (Fr.m_nFirstToken <= Fr.m_nLastToken)
|
|
{
|
|
tokensBuffer.push_back(pTokens[Fr.m_nFirstToken]);
|
|
Fr.m_nFirstToken++;
|
|
}
|
|
tokensBuffer.push_back(eT_skip_2);
|
|
}
|
|
}
|
|
|
|
bool CParserBin::CheckIfExpression(const uint32* pTokens, uint32& nT, int nPass, uint64* nMask)
|
|
{
|
|
uint32 tmpBuf[64] = {0};
|
|
byte bRes[64] = {0};
|
|
byte bOr[64] = {0};
|
|
int nLevel = 0;
|
|
int i;
|
|
while (true)
|
|
{
|
|
uint32 nToken = pTokens[nT];
|
|
if (nToken == eT_br_rnd_1) // check for '('
|
|
{
|
|
nT++;
|
|
int n = 0;
|
|
int nD = 0;
|
|
while (true)
|
|
{
|
|
int nTok = pTokens[nT];
|
|
if (nTok == eT_br_rnd_1) // check for '('
|
|
{
|
|
n++;
|
|
}
|
|
else
|
|
if (nTok == eT_br_rnd_2) // check for ')'
|
|
{
|
|
if (!n)
|
|
{
|
|
tmpBuf[nD] = 0;
|
|
nT++;
|
|
break;
|
|
}
|
|
n--;
|
|
}
|
|
else
|
|
if (nTok == 0)
|
|
{
|
|
return false;
|
|
}
|
|
tmpBuf[nD++] = nTok;
|
|
nT++;
|
|
}
|
|
uint32 nT2 = 0;
|
|
bRes[nLevel] = CheckIfExpression(&tmpBuf[0], nT2, nPass, nMask);
|
|
nLevel++;
|
|
bOr[nLevel] = 255;
|
|
}
|
|
else
|
|
{
|
|
uint32 nTok = pTokens[nT++];
|
|
bool bNeg = false;
|
|
if (nTok == eT_excl)
|
|
{
|
|
bNeg = true;
|
|
nTok = pTokens[nT++];
|
|
}
|
|
const SMacroBinFX* pFound = FindMacro(nTok, m_Macros[nPass]);
|
|
if (!pFound)
|
|
{
|
|
pFound = FindMacro(nTok, m_StaticMacros);
|
|
}
|
|
if (!pFound && !nPass)
|
|
{
|
|
pFound = FindMacro(nTok, m_Macros[1]);
|
|
}
|
|
bRes[nLevel] = (pFound) ? true : false;
|
|
|
|
if (pFound && nMask)
|
|
{
|
|
*nMask |= pFound->m_nMask;
|
|
}
|
|
|
|
if (nTok == eT_1)
|
|
{
|
|
bRes[nLevel] = true;
|
|
}
|
|
if (bNeg)
|
|
{
|
|
bRes[nLevel] = !bRes[nLevel];
|
|
}
|
|
nLevel++;
|
|
bOr[nLevel] = 255;
|
|
}
|
|
uint32 nTok = pTokens[nT];
|
|
if (nTok == eT_or)
|
|
{
|
|
bOr[nLevel] = true;
|
|
nT++;
|
|
assert (pTokens[nT] == eT_or);
|
|
if (pTokens[nT] == eT_or)
|
|
{
|
|
nT++;
|
|
}
|
|
}
|
|
else
|
|
if (nTok == eT_and)
|
|
{
|
|
bOr[nLevel] = false;
|
|
nT++;
|
|
assert (pTokens[nT] == eT_and);
|
|
if (pTokens[nT] == eT_and)
|
|
{
|
|
nT++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
byte Res = false;
|
|
for (i = 0; i < nLevel; i++)
|
|
{
|
|
if (!i)
|
|
{
|
|
Res = bRes[i];
|
|
}
|
|
else
|
|
{
|
|
assert(bOr[i] != 255);
|
|
if (bOr[i])
|
|
{
|
|
Res = Res | bRes[i];
|
|
}
|
|
else
|
|
{
|
|
Res = Res & bRes[i];
|
|
}
|
|
}
|
|
}
|
|
return Res != 0;
|
|
}
|
|
|
|
void CParserBin::BuildSearchInfo()
|
|
{
|
|
/* int i;
|
|
for (i=0; i<m_Tokens.size(); i++)
|
|
{
|
|
uint32 nToken = m_Tokens[i];
|
|
if (nToken < eT_max)
|
|
{
|
|
if (m_KeyOffsets.size() <= nToken)
|
|
m_KeyOffsets.resize(nToken+1);
|
|
std::vector<int>& Dst = m_KeyOffsets[nToken];
|
|
Dst.push_back(i);
|
|
}
|
|
else
|
|
{
|
|
FXShaderTokenItor itor = m_Table.find(nToken);
|
|
if (itor != m_Table.end())
|
|
itor->second.Offsets.push_back(i);
|
|
else
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
m_bEmbeddedSearchInfo = true;*/
|
|
}
|
|
|
|
bool CParserBin::PreprocessTokens(ShaderTokensVec& Tokens, int nPass, PodArray<uint32>& tokensBuffer)
|
|
{
|
|
bool bRet = true;
|
|
uint32 nTokenParam;
|
|
|
|
uint32 nT = 0;
|
|
const uint32* pTokens = &Tokens[0];
|
|
const uint32 nTSize = Tokens.size();
|
|
while (nT < nTSize)
|
|
{
|
|
uint32 nToken = NextToken(pTokens, nT, nTSize - 1);
|
|
if (!nToken)
|
|
{
|
|
break;
|
|
}
|
|
bool bFirst = false;
|
|
switch (nToken)
|
|
{
|
|
case eT_include:
|
|
{
|
|
nTokenParam = pTokens[nT++];
|
|
const char* szName = GetString(nTokenParam, false);
|
|
assert(szName);
|
|
SShaderBin* pBin = gRenDev->m_cEF.m_Bin.GetBinShader(szName, true, 0);
|
|
if (!pBin)
|
|
{
|
|
AZ_Assert(false, "Fatal error: could not find required shader include file '%s'", szName);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
assert(pBin);
|
|
MergeTable(pBin);
|
|
pBin->Lock();
|
|
bool result = PreprocessTokens(pBin->m_Tokens, nPass, tokensBuffer);
|
|
pBin->Unlock();
|
|
|
|
if(!result)
|
|
{
|
|
// PreprocessTokens will output an error message, no need for one here
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case eT_define:
|
|
case eT_define_2:
|
|
{
|
|
uint32 nMacro = 0;
|
|
int n = nPass;
|
|
uint64 nMask = 0;
|
|
nTokenParam = pTokens[nT++];
|
|
/*const char *szname = GetString(nTokenParam);
|
|
if (!_stricmp(szname, "%_SHADOW_GEN"))
|
|
{
|
|
int nnn = 0;
|
|
}*/
|
|
const uint32* pMacro = &pTokens[nT];
|
|
while (pMacro[nMacro])
|
|
{
|
|
nMacro++;
|
|
}
|
|
if (nToken == eT_define_2)
|
|
{
|
|
n = 1;
|
|
if (nMacro)
|
|
{
|
|
nMask = GetInt(pMacro[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (uint32 i = 0; i < m_IfAffectMask.Num(); i++)
|
|
{
|
|
nMask |= m_IfAffectMask[i];
|
|
}
|
|
}
|
|
AddMacro(nTokenParam, pMacro, nMacro, nMask, m_Macros[n]);
|
|
|
|
if (nPass == 0)
|
|
{
|
|
if (sfxIFDef.Num())
|
|
{
|
|
AddMacro(nTokenParam, pMacro, nMacro, nMask, m_Macros[1]);
|
|
}
|
|
|
|
tokensBuffer.push_back(eT_define_2);
|
|
tokensBuffer.push_back(nTokenParam);
|
|
tokensBuffer.AddList((uint32*)pMacro, nMacro + 1);
|
|
}
|
|
nT += nMacro + 1;
|
|
}
|
|
break;
|
|
case eT_undefine:
|
|
{
|
|
nTokenParam = pTokens[nT++];
|
|
int n = nPass;
|
|
FXMacroBinItor it = m_Macros[nPass].find(nTokenParam);
|
|
if (it == m_Macros[n].end() && !nPass)
|
|
{
|
|
it = m_Macros[1].find(nTokenParam);
|
|
n = 1;
|
|
}
|
|
if (it == m_Macros[n].end())
|
|
{
|
|
Warning("Couldn't find macro '%s'", GetString(nTokenParam));
|
|
}
|
|
else
|
|
{
|
|
m_Macros[n].erase(nTokenParam);
|
|
}
|
|
}
|
|
break;
|
|
case eT_if:
|
|
case eT_ifdef:
|
|
case eT_ifndef:
|
|
bFirst = true;
|
|
case eT_if_2:
|
|
case eT_ifdef_2:
|
|
case eT_ifndef_2:
|
|
if ((nPass == 0 && !bFirst) || (nPass == 1 && bFirst))
|
|
{
|
|
if (nPass == 1)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
|
|
sfxIFIgnore.AddElem(true);
|
|
sfxIFDef.AddElem(false);
|
|
tokensBuffer.push_back(nToken);
|
|
|
|
uint64 nIfMask = 0;
|
|
uint32 nS = nT;
|
|
CheckIfExpression(pTokens, nT, 0, &nIfMask);
|
|
tokensBuffer.AddList((uint32*)pTokens + nS, nT - nS);
|
|
|
|
m_IfAffectMask.AddElem(nIfMask);
|
|
}
|
|
else
|
|
{
|
|
uint64 nIfMask = 0;
|
|
sfxIFIgnore.AddElem(false);
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, nTSize, false, tokensBuffer);
|
|
}
|
|
bool bRes = CheckIfExpression(pTokens, nT, nPass, &nIfMask);
|
|
m_IfAffectMask.AddElem(nIfMask);
|
|
if (nToken == eT_ifndef || nToken == eT_ifndef_2)
|
|
{
|
|
bRes = !bRes;
|
|
}
|
|
if (!bRes)
|
|
{
|
|
IgnorePreprocessBlock(pTokens, nT, nTSize, tokensBuffer, nPass);
|
|
sfxIFDef.AddElem(false);
|
|
}
|
|
else
|
|
{
|
|
sfxIFDef.AddElem(true);
|
|
}
|
|
}
|
|
break;
|
|
case eT_elif:
|
|
{
|
|
int nLevel = sfxIFDef.Num() - 1;
|
|
if (nLevel < 0)
|
|
{
|
|
CRY_ASSERT(0);
|
|
Warning("#elif without #ifdef");
|
|
return false;
|
|
}
|
|
if (sfxIFIgnore[nLevel] == true)
|
|
{
|
|
tokensBuffer.push_back(nToken);
|
|
}
|
|
else
|
|
{
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, Tokens.size(), false, tokensBuffer);
|
|
}
|
|
if (sfxIFDef[nLevel] == true)
|
|
{
|
|
IgnorePreprocessBlock(pTokens, nT, Tokens.size(), tokensBuffer, nPass);
|
|
}
|
|
else
|
|
{
|
|
uint64 nIfMask = 0;
|
|
bool bRes = CheckIfExpression(pTokens, nT, nPass, &nIfMask);
|
|
if (!bRes)
|
|
{
|
|
IgnorePreprocessBlock(pTokens, nT, Tokens.size(), tokensBuffer, nPass);
|
|
}
|
|
else
|
|
{
|
|
sfxIFDef[nLevel] = true;
|
|
}
|
|
|
|
m_IfAffectMask[nLevel] = nIfMask;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case eT_else:
|
|
{
|
|
int nLevel = sfxIFDef.Num() - 1;
|
|
if (nLevel < 0)
|
|
{
|
|
CRY_ASSERT(0);
|
|
Warning("#else without #ifdef");
|
|
return false;
|
|
}
|
|
if (sfxIFIgnore[nLevel] == true)
|
|
{
|
|
tokensBuffer.push_back(nToken);
|
|
}
|
|
else
|
|
{
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, Tokens.size(), true, tokensBuffer);
|
|
}
|
|
if (sfxIFDef[nLevel] == true)
|
|
{
|
|
bool bEnded = IgnorePreprocessBlock(pTokens, nT, Tokens.size(), tokensBuffer, nPass);
|
|
if (!bEnded)
|
|
{
|
|
CRY_ASSERT(0);
|
|
Warning("#else or #elif after #else");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case eT_endif:
|
|
{
|
|
int nLevel = sfxIFDef.Num() - 1;
|
|
if (nLevel < 0)
|
|
{
|
|
CRY_ASSERT(0);
|
|
Warning("#endif without #ifdef");
|
|
return false;
|
|
}
|
|
if (sfxIFIgnore[nLevel] == true)
|
|
{
|
|
tokensBuffer.push_back(nToken);
|
|
}
|
|
else
|
|
if (!nPass)
|
|
{
|
|
InsertSkipTokens(pTokens, nT - 1, Tokens.size(), true, tokensBuffer);
|
|
}
|
|
sfxIFDef.Remove(nLevel);
|
|
sfxIFIgnore.Remove(nLevel);
|
|
m_IfAffectMask.Remove(nLevel);
|
|
}
|
|
break;
|
|
case eT_warning:
|
|
{
|
|
const char* szStr = GetString(pTokens[nT++]);
|
|
Warning(szStr);
|
|
}
|
|
break;
|
|
case eT_register_env:
|
|
{
|
|
const char* szStr = GetString(pTokens[nT++]);
|
|
fxRegisterEnv(szStr);
|
|
}
|
|
break;
|
|
case eT_ifcvar:
|
|
case eT_ifncvar:
|
|
{
|
|
const char* szStr = GetString(pTokens[nT++]);
|
|
sfxIFIgnore.AddElem(false);
|
|
ICVar* pVar = iConsole->GetCVar(szStr);
|
|
int nVal = 0;
|
|
if (!pVar)
|
|
{
|
|
iLog->Log("Warning: couldn't find variable '%s'", szStr);
|
|
}
|
|
else
|
|
{
|
|
nVal = pVar->GetIVal();
|
|
}
|
|
if (nToken == eT_ifncvar)
|
|
{
|
|
nVal = !nVal;
|
|
}
|
|
if (!nVal)
|
|
{
|
|
IgnorePreprocessBlock(pTokens, nT, Tokens.size(), tokensBuffer, nPass);
|
|
sfxIFDef.AddElem(false);
|
|
}
|
|
else
|
|
{
|
|
sfxIFDef.AddElem(true);
|
|
}
|
|
}
|
|
break;
|
|
case eT_elifcvar:
|
|
{
|
|
int nLevel = sfxIFDef.Num() - 1;
|
|
if (nLevel < 0)
|
|
{
|
|
CRY_ASSERT(0);
|
|
Warning("#elifcvar without #ifcvar or #ifdef");
|
|
return false;
|
|
}
|
|
sfxIFIgnore.AddElem(false);
|
|
if (sfxIFDef[nLevel] == true)
|
|
{
|
|
IgnorePreprocessBlock(pTokens, nT, Tokens.size(), tokensBuffer, nPass);
|
|
}
|
|
else
|
|
{
|
|
const char* szStr = GetString(pTokens[nT++]);
|
|
ICVar* pVar = iConsole->GetCVar(szStr);
|
|
int nVal = 0;
|
|
if (!pVar)
|
|
{
|
|
iLog->Log("Warning: couldn't find variable '%s'", szStr);
|
|
}
|
|
else
|
|
{
|
|
nVal = pVar->GetIVal();
|
|
}
|
|
if (!nVal)
|
|
{
|
|
IgnorePreprocessBlock(pTokens, nT, Tokens.size(), tokensBuffer, nPass);
|
|
}
|
|
else
|
|
{
|
|
sfxIFDef[nLevel] = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
FXMacroBinItor it = m_Macros[nPass].find(nToken);
|
|
if (it != m_Macros[nPass].end())
|
|
{
|
|
// Found macro
|
|
SMacroBinFX* pM = &it->second;
|
|
for (uint32 i = 0; i < pM->m_Macro.size(); i++)
|
|
{
|
|
tokensBuffer.push_back(pM->m_Macro[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tokensBuffer.push_back(nToken);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
bool CParserBin::Preprocess(int nPass, ShaderTokensVec& Tokens, FXShaderToken* pSrcTable)
|
|
{
|
|
bool bRes = true;
|
|
|
|
m_IfAffectMask.Reserve(5);
|
|
m_IfAffectMask.SetUse(0);
|
|
sfxIFDef.SetUse(0);
|
|
sfxIFIgnore.SetUse(0);
|
|
|
|
m_Macros[nPass].clear();
|
|
|
|
// Use a buffer to process tokens, transfer to the
|
|
// real storage in Tokens once we know the full quantity
|
|
enum
|
|
{
|
|
TOKENS_BUFFER_SIZE = 90000
|
|
};
|
|
|
|
PodArray<uint32> tokensBuffer(TOKENS_BUFFER_SIZE);
|
|
|
|
m_TokenTable = *pSrcTable;
|
|
bRes = PreprocessTokens(Tokens, nPass, tokensBuffer);
|
|
#ifndef _RELEASE
|
|
if (tokensBuffer.Size() > TOKENS_BUFFER_SIZE)
|
|
{
|
|
CryLogAlways("CParserBin::Preprocess: tokenBuffer has been exceeded (buffer=%u, count=%u). Adjust buffer size to remove unnecessary allocs.", TOKENS_BUFFER_SIZE, tokensBuffer.Size());
|
|
}
|
|
#endif
|
|
m_Tokens.reserve(tokensBuffer.Size());
|
|
m_Tokens.SetUse(0);
|
|
m_Tokens.Copy(tokensBuffer.GetElements(), tokensBuffer.Count());
|
|
|
|
if (!nPass)
|
|
{
|
|
BuildSearchInfo();
|
|
}
|
|
|
|
assert(!sfxIFDef.Num());
|
|
assert(!sfxIFIgnore.Num());
|
|
return bRes;
|
|
}
|
|
|
|
int CParserBin::CopyTokens(SParserFrame& Fragment, std::vector<uint32>& NewTokens)
|
|
{
|
|
if (Fragment.IsEmpty())
|
|
{
|
|
return 0;
|
|
}
|
|
int nCopy = Fragment.m_nLastToken - Fragment.m_nFirstToken + 1;
|
|
int nStart = NewTokens.size();
|
|
NewTokens.resize(nStart + nCopy);
|
|
memcpy(&NewTokens[nStart], &m_Tokens[Fragment.m_nFirstToken], nCopy * sizeof(uint32));
|
|
|
|
return nCopy;
|
|
}
|
|
|
|
int CParserBin::CopyTokens(SCodeFragment* pCF, PodArray<uint32>& SHData, TArray<SCodeFragment>& Replaces, TArray<uint32>& NewTokens, uint32 nID)
|
|
{
|
|
int nRepl = -1;
|
|
uint32 i;
|
|
|
|
for (i = 0; i < Replaces.size(); i++)
|
|
{
|
|
SCodeFragment* pFR = &Replaces[i];
|
|
|
|
if (pFR->m_dwName == nID)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (i != Replaces.size())
|
|
{
|
|
assert (!(i & 1));
|
|
nRepl = i;
|
|
}
|
|
int nDst = SHData.size();
|
|
int nSrc = pCF->m_nFirstToken;
|
|
uint32* pSrc = &m_Tokens[0];
|
|
int nSize = pCF->m_nLastToken - nSrc + 1;
|
|
if (nRepl >= 0)
|
|
{
|
|
int nDstStart = nDst;
|
|
uint32* pSrc2 = &NewTokens[0];
|
|
while (nSrc <= (int)pCF->m_nLastToken)
|
|
{
|
|
if (nRepl >= (int)Replaces.size() || Replaces[nRepl].m_dwName != nID)
|
|
{
|
|
int nCopy = pCF->m_nLastToken - nSrc + 1;
|
|
SHData.resize(nDst + nCopy);
|
|
memcpy(&SHData[nDst], &pSrc[nSrc], nCopy * sizeof(uint32));
|
|
nSrc += nCopy;
|
|
nDst += nCopy;
|
|
}
|
|
else
|
|
{
|
|
int nCopy = Replaces[nRepl].m_nFirstToken - nSrc;
|
|
if (nCopy)
|
|
{
|
|
assert(nCopy > 0);
|
|
SHData.resize(nDst + nCopy);
|
|
memcpy(&SHData[nDst], &pSrc[nSrc], nCopy * sizeof(uint32));
|
|
nSrc += nCopy + (Replaces[nRepl].m_nLastToken - Replaces[nRepl].m_nFirstToken + 1);
|
|
nDst += nCopy;
|
|
}
|
|
nRepl++;
|
|
nCopy = Replaces[nRepl].m_nLastToken - Replaces[nRepl].m_nFirstToken + 1;
|
|
SHData.resize(nDst + nCopy);
|
|
memcpy(&SHData[nDst], &pSrc2[Replaces[nRepl].m_nFirstToken], nCopy * sizeof(uint32));
|
|
nDst += nCopy;
|
|
nRepl++;
|
|
}
|
|
}
|
|
return SHData.size() - nDstStart;
|
|
}
|
|
else
|
|
{
|
|
SHData.resize(nDst + nSize);
|
|
memcpy(&SHData[nDst], &pSrc[nSrc], nSize * sizeof(uint32));
|
|
return nSize;
|
|
}
|
|
}
|
|
|
|
int32 CParserBin::FindToken(uint32 nStart, uint32 nLast, const uint32* pTokens, uint32 nToken)
|
|
{
|
|
while (nStart <= nLast)
|
|
{
|
|
if (pTokens[nStart] == nToken)
|
|
{
|
|
return nStart;
|
|
}
|
|
nStart++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int32 CParserBin::FindToken(uint32 nStart, uint32 nLast, uint32 nToken)
|
|
{
|
|
if (nStart >= m_Tokens.size() || nLast >= m_Tokens.size())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//if (!m_bEmbeddedSearchInfo)
|
|
return FindToken(nStart, nLast, &m_Tokens[0], nToken);
|
|
/*std::vector<int> *pSI;
|
|
if (nToken < eT_max)
|
|
{
|
|
if (nToken >= m_KeyOffsets.size())
|
|
return -1;
|
|
pSI = &m_KeyOffsets[nToken];
|
|
}
|
|
else
|
|
{
|
|
FXShaderTokenItor itor = m_Table.find(nToken);
|
|
if (itor == m_Table.end())
|
|
return -1;
|
|
pSI = &itor->second.Offsets;
|
|
}
|
|
for (int i=0; i<pSI->size(); i++)
|
|
{
|
|
int nOffs = (*pSI)[i];
|
|
if (nOffs>=nStart && nOffs<=nLast)
|
|
return nOffs;
|
|
}
|
|
return -1;*/
|
|
}
|
|
|
|
int32 CParserBin::FindToken(uint32 nStart, uint32 nLast, const uint32* pToks)
|
|
{
|
|
uint32* pTokens = &m_Tokens[0];
|
|
while (nStart <= nLast)
|
|
{
|
|
int n = 0;
|
|
uint32 nTok = pToks[n];
|
|
while (nTok)
|
|
{
|
|
if (pTokens[nStart] == nTok)
|
|
{
|
|
return nStart;
|
|
}
|
|
n++;
|
|
nTok = pToks[n];
|
|
}
|
|
nStart++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static ETokenStorageClass sCheckForModificator(uint32 nToken)
|
|
{
|
|
switch (nToken)
|
|
{
|
|
case eT_const:
|
|
return eTS_const;
|
|
case eT_static:
|
|
return eTS_static;
|
|
case eT_shared:
|
|
return eTS_shared;
|
|
case eT_groupshared:
|
|
return eTS_groupshared;
|
|
default:
|
|
return eTS_default;
|
|
}
|
|
}
|
|
int CParserBin::GetNextToken(uint32& nStart, ETokenStorageClass& nTokenStorageClass)
|
|
{
|
|
uint32* pTokens = &m_Tokens[0];
|
|
uint32 nTokensSize = m_Tokens.size();
|
|
ETokenStorageClass nNewTokenStorageClass = eTS_default;
|
|
while (true)
|
|
{
|
|
bool bFunction = false;
|
|
|
|
if (m_CurFrame.m_nCurToken >= m_CurFrame.m_nLastToken)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
uint32 nToken;
|
|
if ((nToken = pTokens[m_CurFrame.m_nCurToken]) == eT_unknown)
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
nStart = m_CurFrame.m_nCurToken;
|
|
|
|
if (nToken == eT_quote)
|
|
{
|
|
m_CurFrame.m_nCurToken++;
|
|
continue;
|
|
}
|
|
if (nToken == eT_skip)
|
|
{
|
|
m_CurFrame.m_nCurToken += 2;
|
|
continue;
|
|
}
|
|
if (nToken == eT_skip_1)
|
|
{
|
|
while (m_CurFrame.m_nCurToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nToken = pTokens[m_CurFrame.m_nCurToken++];
|
|
if (nToken == eT_skip_2)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Check for storage class- if existing, add all tokens in line (its global constant - should not go to any constant buffer)
|
|
nNewTokenStorageClass = sCheckForModificator(nToken);
|
|
if (nNewTokenStorageClass != eTS_default)
|
|
{
|
|
nTokenStorageClass = nNewTokenStorageClass;
|
|
|
|
SCodeFragment Fr;
|
|
Fr.m_eType = eFT_StorageClass; // Set code fragment type
|
|
Fr.m_nFirstToken = m_CurFrame.m_nCurToken; // Set first token offset for code fragment
|
|
while (pTokens[m_CurFrame.m_nCurToken] != eT_semicolumn)
|
|
{
|
|
if (m_CurFrame.m_nCurToken + 1 == nTokensSize)
|
|
{
|
|
break;
|
|
}
|
|
//const char *pszToken0 = GetString( pTokens[m_CurFrame.m_nCurToken] ); // handy for debugging - do not remove for now plz
|
|
m_CurFrame.m_nCurToken++;
|
|
}
|
|
|
|
Fr.m_nLastToken = m_CurFrame.m_nCurToken++; // Set last token offset to code fragment
|
|
Fr.m_dwName = pTokens[Fr.m_nLastToken - 1]; // Set fragment name (this is used for parser to search and discard fragments of code if not used in functions or structures)
|
|
m_CodeFragments.push_back(Fr); // Finally add to list
|
|
|
|
//const char *pszToken0 = GetString( Fr.m_dwName ); // handy for debugging - do not remove for now plz
|
|
|
|
continue;
|
|
}
|
|
|
|
// if preprocessor
|
|
if (nToken >= eT_include && nToken <= eT_elifcvar)
|
|
{
|
|
SCodeFragment Fr;
|
|
Fr.m_nFirstToken = m_CurFrame.m_nCurToken;
|
|
if (nToken >= eT_if && nToken <= eT_elif || nToken == eT_define || nToken == eT_define_2)
|
|
{
|
|
while (pTokens[m_CurFrame.m_nCurToken])
|
|
{
|
|
if (m_CurFrame.m_nCurToken + 1 == nTokensSize)
|
|
{
|
|
break;
|
|
}
|
|
m_CurFrame.m_nCurToken++;
|
|
}
|
|
}
|
|
Fr.m_nLastToken = m_CurFrame.m_nCurToken++;
|
|
m_CodeFragments.push_back(Fr);
|
|
}
|
|
else
|
|
{
|
|
m_CurFrame.m_nCurToken = nStart;
|
|
// Check for function
|
|
uint32 nLastTok = nStart;
|
|
uint32 nFnName;
|
|
int nBrIndex = -1;
|
|
if (m_CurFrame.m_nCurToken + 4 < m_CurFrame.m_nLastToken)
|
|
{
|
|
uint32 nFnRet = pTokens[m_CurFrame.m_nCurToken];
|
|
// DX11 stuff
|
|
uint32 nCur = m_CurFrame.m_nCurToken + 1;
|
|
uint32 nCount = 0;
|
|
while (nFnRet == eT_br_sq_1)
|
|
{
|
|
nCount++;
|
|
nLastTok = FindToken(nCur, m_CurFrame.m_nLastToken, eT_br_sq_2);
|
|
if (nLastTok > 0)
|
|
{
|
|
nLastTok++;
|
|
nFnRet = pTokens[nLastTok];
|
|
if (nFnRet == eT_skip)
|
|
{
|
|
pTokens[nLastTok + 1] = eT_skip;
|
|
nLastTok += 2;
|
|
nFnRet = pTokens[nLastTok];
|
|
}
|
|
nCur = nLastTok + 1;
|
|
}
|
|
}
|
|
nFnName = pTokens[nLastTok + 1];
|
|
//const char *szFn = GetString(nFnName);
|
|
if (pTokens[nLastTok + 2] == eT_br_rnd_1)
|
|
{
|
|
nBrIndex = nLastTok + 3;
|
|
nLastTok = FindToken(nLastTok + 3, m_CurFrame.m_nLastToken, eT_br_cv_1);
|
|
int nRecurse = 0;
|
|
while (nLastTok <= m_CurFrame.m_nLastToken)
|
|
{
|
|
uint32 nT = pTokens[nLastTok];
|
|
if (nT == eT_br_cv_1)
|
|
{
|
|
nRecurse++;
|
|
}
|
|
else
|
|
if (nT == eT_br_cv_2)
|
|
{
|
|
nRecurse--;
|
|
if (nRecurse == 0)
|
|
{
|
|
bFunction = true;
|
|
break;
|
|
}
|
|
}
|
|
nLastTok++;
|
|
}
|
|
}
|
|
}
|
|
if (bFunction)
|
|
{
|
|
// check for function if expressions
|
|
assert (nBrIndex > 0);
|
|
uint32 nIdTok = FindToken(nBrIndex, m_CurFrame.m_nLastToken, eT_br_rnd_2);
|
|
assert(nIdTok > 0);
|
|
if (nIdTok > 0 && pTokens[nIdTok + 1] != eT_br_cv_1)
|
|
{
|
|
nIdTok++;
|
|
while (pTokens[nIdTok] != eT_br_cv_1)
|
|
{
|
|
if (pTokens[nIdTok] == eT_skip)
|
|
{
|
|
pTokens[nIdTok + 1] = eT_skip;
|
|
nIdTok += 2;
|
|
}
|
|
else
|
|
if (pTokens[nIdTok] == eT_skip_1)
|
|
{
|
|
while (pTokens[nIdTok] != eT_skip_2)
|
|
{
|
|
pTokens[nIdTok++] = eT_skip;
|
|
}
|
|
pTokens[nIdTok++] = eT_skip;
|
|
}
|
|
else
|
|
{
|
|
nIdTok++;
|
|
}
|
|
}
|
|
}
|
|
|
|
SCodeFragment Fr;
|
|
Fr.m_nFirstToken = m_CurFrame.m_nCurToken;
|
|
Fr.m_nLastToken = nLastTok;
|
|
Fr.m_dwName = nFnName;
|
|
#ifdef _DEBUG
|
|
//Fr.m_Name = GetString(nFnName);
|
|
#endif
|
|
Fr.m_eType = eFT_Function;
|
|
m_CodeFragments.push_back(Fr);
|
|
m_CurFrame.m_nCurToken = nLastTok + 1;
|
|
}
|
|
else
|
|
{
|
|
m_eToken = (EToken)nToken;
|
|
assert(m_eToken < eT_user_first);
|
|
m_CurFrame.m_nCurToken++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
bool CParserBin::FXGetAssignmentData(SParserFrame& Frame)
|
|
{
|
|
bool bRes = true;
|
|
|
|
Frame.m_nFirstToken = m_CurFrame.m_nCurToken;
|
|
uint32 nLastToken = m_CurFrame.m_nCurToken;
|
|
while (nLastToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
uint32 nTok = m_Tokens[nLastToken++];
|
|
if (nTok == eT_quote)
|
|
{
|
|
while (nLastToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nTok = m_Tokens[nLastToken++];
|
|
if (nTok == eT_quote)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (nTok == eT_semicolumn)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
Frame.m_nLastToken = nLastToken - 2;
|
|
if (m_Tokens[nLastToken] == eT_semicolumn)
|
|
{
|
|
m_CurFrame.m_nCurToken = nLastToken + 1;
|
|
}
|
|
else
|
|
{
|
|
m_CurFrame.m_nCurToken = nLastToken;
|
|
}
|
|
|
|
return bRes;
|
|
}
|
|
|
|
bool CParserBin::FXGetAssignmentData2(SParserFrame& Frame)
|
|
{
|
|
bool bRes = true;
|
|
|
|
Frame.m_nFirstToken = m_CurFrame.m_nCurToken;
|
|
uint32 nLastToken = m_CurFrame.m_nCurToken;
|
|
uint32 nTok = m_Tokens[nLastToken];
|
|
if (nTok == eT_br_cv_1)
|
|
{
|
|
nLastToken++;
|
|
while (nLastToken + 1 <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nTok = m_Tokens[nLastToken];
|
|
if (nTok == eT_semicolumn)
|
|
{
|
|
break;
|
|
}
|
|
nLastToken++;
|
|
}
|
|
}
|
|
else
|
|
if (nTok == eT_br_rnd_1)
|
|
{
|
|
nLastToken++;
|
|
int n = 1;
|
|
while (nLastToken + 1 <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nTok = m_Tokens[nLastToken];
|
|
if (nTok == eT_semicolumn || nTok == eT_br_tr_1 || nTok == eT_eq)
|
|
{
|
|
assert(!n);
|
|
break;
|
|
}
|
|
if (nTok == eT_br_rnd_1)
|
|
{
|
|
n++;
|
|
}
|
|
else
|
|
if (nTok == eT_br_rnd_2)
|
|
{
|
|
n--;
|
|
}
|
|
nLastToken++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (nLastToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nTok = m_Tokens[nLastToken];
|
|
if (nTok == eT_semicolumn || nTok == eT_br_rnd_1 || nTok == eT_br_cv_1 || nTok == eT_br_tr_1)
|
|
{
|
|
break;
|
|
}
|
|
nLastToken++;
|
|
}
|
|
}
|
|
|
|
Frame.m_nLastToken = nLastToken - 1;
|
|
if (m_Tokens[nLastToken] == eT_semicolumn)
|
|
{
|
|
m_CurFrame.m_nCurToken = nLastToken + 1;
|
|
}
|
|
else
|
|
{
|
|
m_CurFrame.m_nCurToken = nLastToken;
|
|
}
|
|
|
|
return bRes;
|
|
}
|
|
|
|
|
|
bool CParserBin::GetAssignmentData(SParserFrame& Frame)
|
|
{
|
|
bool bRes = true;
|
|
|
|
Frame.m_nFirstToken = m_CurFrame.m_nCurToken;
|
|
uint32 nLastToken = m_CurFrame.m_nCurToken;
|
|
uint32* pTokens = &m_Tokens[0];
|
|
uint32 nTok = pTokens[nLastToken + 1];
|
|
if (nTok == eT_br_sq_1 || nTok == eT_br_rnd_1)
|
|
{
|
|
EToken eTClose = nTok == eT_br_sq_1 ? eT_br_sq_2 : eT_br_rnd_2;
|
|
nLastToken += 2;
|
|
while (nLastToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nTok = pTokens[nLastToken];
|
|
if (nTok == eTClose || nTok == eT_semicolumn)
|
|
{
|
|
if (nTok == eT_semicolumn)
|
|
{
|
|
nLastToken--;
|
|
}
|
|
break;
|
|
}
|
|
nLastToken++;
|
|
}
|
|
}
|
|
Frame.m_nLastToken = nLastToken;
|
|
|
|
nLastToken++;
|
|
|
|
if (pTokens[nLastToken] == eT_semicolumn)
|
|
{
|
|
m_CurFrame.m_nCurToken = nLastToken + 1;
|
|
}
|
|
else
|
|
{
|
|
m_CurFrame.m_nCurToken = nLastToken;
|
|
}
|
|
|
|
return bRes;
|
|
}
|
|
|
|
bool CParserBin::GetSubData(SParserFrame& Frame, EToken eT1, EToken eT2)
|
|
{
|
|
|
|
Frame.m_nFirstToken = 0;
|
|
Frame.m_nLastToken = 0;
|
|
uint32 nTok = m_Tokens[m_CurFrame.m_nCurToken];
|
|
if (nTok != eT1)
|
|
{
|
|
return false;
|
|
}
|
|
m_CurFrame.m_nCurToken++;
|
|
Frame.m_nFirstToken = m_CurFrame.m_nCurToken;
|
|
uint32 nCurToken = m_CurFrame.m_nCurToken;
|
|
int skip = 1;
|
|
while (nCurToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
nTok = m_Tokens[nCurToken];
|
|
if (nTok == eT1)
|
|
{
|
|
skip++;
|
|
}
|
|
else
|
|
if (nTok == eT2)
|
|
{
|
|
if (--skip == 0)
|
|
{
|
|
Frame.m_nLastToken = nCurToken - 1;
|
|
nCurToken++;
|
|
break;
|
|
}
|
|
}
|
|
nCurToken++;
|
|
}
|
|
if (Frame.IsEmpty())
|
|
{
|
|
Frame.Reset();
|
|
}
|
|
if (nCurToken <= m_CurFrame.m_nLastToken && m_Tokens[nCurToken] == eT_semicolumn)
|
|
{
|
|
m_CurFrame.m_nCurToken = nCurToken + 1;
|
|
}
|
|
else
|
|
{
|
|
m_CurFrame.m_nCurToken = nCurToken;
|
|
}
|
|
|
|
return (Frame.m_nFirstToken <= Frame.m_nLastToken);
|
|
}
|
|
|
|
|
|
ETokenStorageClass CParserBin::ParseObject(SFXTokenBin* pTokens)
|
|
{
|
|
assert(m_CurFrame.m_nFirstToken <= m_CurFrame.m_nLastToken);
|
|
|
|
if (m_CurFrame.m_nCurToken + 1 >= m_CurFrame.m_nLastToken)
|
|
{
|
|
return eTS_invalid;
|
|
}
|
|
if (m_Tokens.size() <= m_CurFrame.m_nCurToken)
|
|
{
|
|
CryWarning(VALIDATOR_MODULE_RENDERER, VALIDATOR_ERROR, "Attempted out-of-bounds access in CParserBin::ParseObject");
|
|
return eTS_invalid;
|
|
}
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_unknown)
|
|
{
|
|
return eTS_invalid;
|
|
}
|
|
|
|
ETokenStorageClass nTokenStorageClass = eTS_default;
|
|
int nRes = GetNextToken(m_nFirstToken, nTokenStorageClass);
|
|
if (nRes < 0)
|
|
{
|
|
return eTS_invalid;
|
|
}
|
|
|
|
m_Name.Reset();
|
|
m_Assign.Reset();
|
|
m_Value.Reset();
|
|
m_Data.Reset();
|
|
m_Annotations.Reset();
|
|
|
|
SFXTokenBin* pT = pTokens;
|
|
while (pTokens->id != 0)
|
|
{
|
|
if (pTokens->id == m_eToken)
|
|
{
|
|
break;
|
|
}
|
|
pTokens++;
|
|
}
|
|
if (pTokens->id == 0)
|
|
{
|
|
pTokens = pT;
|
|
const char* tokenName = GetString(m_eToken);
|
|
Warning ("FXBin parser found token '%s' which was not one of the list (Skipping).\n", tokenName);
|
|
while (pTokens->id != 0)
|
|
{
|
|
Warning(" %s\n", GetString(pTokens->id));
|
|
pTokens++;
|
|
}
|
|
AZ_Assert(false, "FXBin parser found token '%s' which was not one of the list (Skipping).\n", tokenName);
|
|
#ifdef _DEBUG
|
|
TArray<char> Text;
|
|
SParserFrame Fr;
|
|
Fr.m_nFirstToken = max(m_CurFrame.m_nFirstToken, m_CurFrame.m_nCurToken - 5);
|
|
Fr.m_nLastToken = m_CurFrame.m_nLastToken;
|
|
ConvertToAscii(&m_Tokens[Fr.m_nFirstToken], Fr.m_nLastToken - Fr.m_nFirstToken + 1, m_TokenTable, Text);
|
|
#endif
|
|
return eTS_invalid;
|
|
}
|
|
|
|
bool bAnnot = false;
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_br_tr_1)
|
|
{
|
|
GetSubData(m_Annotations, eT_br_tr_1, eT_br_tr_2);
|
|
bAnnot = true;
|
|
}
|
|
|
|
GetAssignmentData(m_Name);
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_colon)
|
|
{
|
|
m_CurFrame.m_nCurToken++; // skip the ':'
|
|
GetAssignmentData(m_Assign);
|
|
}
|
|
|
|
if (!bAnnot)
|
|
{
|
|
GetSubData(m_Annotations, eT_br_tr_1, eT_br_tr_2);
|
|
}
|
|
if (m_CurFrame.m_nCurToken <= m_CurFrame.m_nLastToken)
|
|
{
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_eq)
|
|
{
|
|
m_CurFrame.m_nCurToken++; // skip the '='
|
|
FXGetAssignmentData2(m_Value);
|
|
}
|
|
|
|
GetSubData(m_Data, eT_br_cv_1, eT_br_cv_2);
|
|
}
|
|
|
|
if (m_CurFrame.m_nCurToken <= m_CurFrame.m_nLastToken && m_Tokens[m_CurFrame.m_nCurToken] == eT_semicolumn)
|
|
{
|
|
m_CurFrame.m_nCurToken++;
|
|
}
|
|
|
|
return nTokenStorageClass;
|
|
}
|
|
|
|
ETokenStorageClass CParserBin::ParseObject(SFXTokenBin* pTokens, int& nIndex)
|
|
{
|
|
assert(m_CurFrame.m_nFirstToken <= m_CurFrame.m_nLastToken);
|
|
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_unknown)
|
|
{
|
|
return eTS_invalid;
|
|
}
|
|
if (m_CurFrame.m_nCurToken + 1 >= m_CurFrame.m_nLastToken)
|
|
{
|
|
return eTS_invalid;
|
|
}
|
|
|
|
ETokenStorageClass nTokenStorageClass = eTS_default;
|
|
int nRes = GetNextToken(m_nFirstToken, nTokenStorageClass);
|
|
if (nRes < 0)
|
|
{
|
|
return eTS_invalid;
|
|
}
|
|
|
|
m_Name.Reset();
|
|
m_Assign.Reset();
|
|
m_Value.Reset();
|
|
m_Data.Reset();
|
|
m_Annotations.Reset();
|
|
|
|
SFXTokenBin* pT = pTokens;
|
|
while (pTokens->id != 0)
|
|
{
|
|
if (pTokens->id == m_eToken)
|
|
{
|
|
break;
|
|
}
|
|
pTokens++;
|
|
}
|
|
if (pTokens->id == 0)
|
|
{
|
|
pTokens = pT;
|
|
Warning ("Warning: FXBin parser found token '%s' which was not one of the list (Skipping).\n", GetString(m_eToken));
|
|
while (pTokens->id != 0)
|
|
{
|
|
Warning(" %s\n", GetString(pTokens->id));
|
|
pTokens++;
|
|
}
|
|
CRY_ASSERT(0);
|
|
#ifdef _DEBUG
|
|
TArray<char> Text;
|
|
SParserFrame Fr;
|
|
Fr.m_nFirstToken = max(m_CurFrame.m_nFirstToken, m_CurFrame.m_nCurToken - 5);
|
|
Fr.m_nLastToken = m_CurFrame.m_nLastToken;
|
|
ConvertToAscii(&m_Tokens[Fr.m_nFirstToken], Fr.m_nLastToken - Fr.m_nFirstToken + 1, m_TokenTable, Text);
|
|
#endif
|
|
return eTS_invalid;
|
|
}
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_br_sq_1)
|
|
{
|
|
m_CurFrame.m_nCurToken++;
|
|
nIndex = GetInt(m_Tokens[m_CurFrame.m_nCurToken++]);
|
|
}
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_sing_quote)
|
|
{
|
|
GetSubData(m_Name, eT_sing_quote, eT_sing_quote);
|
|
}
|
|
else
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] != eT_eq)
|
|
{
|
|
m_Name.m_nFirstToken = m_Name.m_nLastToken = m_CurFrame.m_nCurToken++;
|
|
}
|
|
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_eq)
|
|
{
|
|
m_CurFrame.m_nCurToken++;
|
|
FXGetAssignmentData(m_Data);
|
|
}
|
|
else
|
|
{
|
|
GetSubData(m_Data, eT_br_cv_1, eT_br_cv_2);
|
|
}
|
|
|
|
if (m_Tokens[m_CurFrame.m_nCurToken] == eT_semicolumn || m_Tokens[m_CurFrame.m_nCurToken] == eT_quote)
|
|
{
|
|
m_CurFrame.m_nCurToken++;
|
|
}
|
|
|
|
return nTokenStorageClass;
|
|
}
|
|
|
|
bool CParserBin::JumpSemicolumn(uint32& nStart, uint32 nEnd)
|
|
{
|
|
while (nStart <= nEnd)
|
|
{
|
|
uint32 nTok = m_Tokens[nStart++];
|
|
if (nTok == eT_semicolumn)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
SParserFrame CParserBin::BeginFrame(SParserFrame& Frame)
|
|
{
|
|
SParserFrame RetFrame = m_CurFrame;
|
|
m_CurFrame = Frame;
|
|
m_eToken = eT_unknown;
|
|
m_CurFrame.m_nCurToken = Frame.m_nFirstToken;
|
|
|
|
return RetFrame;
|
|
}
|
|
|
|
void CParserBin::EndFrame(SParserFrame& Frame)
|
|
{
|
|
m_CurFrame = Frame;
|
|
}
|
|
|
|
void SFXParam::PostLoad(CParserBin& Parser, SParserFrame& Name, SParserFrame& Annotations, SParserFrame& Values, SParserFrame& Assign)
|
|
{
|
|
m_Annotations = Parser.GetNameString(Annotations);
|
|
if (!Values.IsEmpty())
|
|
{
|
|
if (Parser.GetToken(Values) == eT_br_cv_1)
|
|
{
|
|
Values.m_nFirstToken++;
|
|
int32 nFind = Parser.FindToken(Values.m_nFirstToken, Values.m_nLastToken, eT_br_cv_2);
|
|
assert(nFind > 0 && Values.m_nLastToken == nFind);
|
|
if (nFind > 0)
|
|
{
|
|
Values.m_nLastToken--;
|
|
}
|
|
}
|
|
m_Values = Parser.GetString(Values);
|
|
}
|
|
m_Semantic = Parser.GetNameString(Assign);
|
|
m_Name = Parser.GetString(Name);
|
|
|
|
m_nFlags = 0;
|
|
if (m_ComponentCount == 1 && m_RegisterCount <= 1)
|
|
{
|
|
m_nFlags |= PF_SCALAR;
|
|
}
|
|
if (m_eType == eType_INT)
|
|
{
|
|
m_nFlags |= PF_INTEGER;
|
|
}
|
|
else
|
|
if (m_eType == eType_BOOL)
|
|
{
|
|
m_nFlags |= PF_BOOL;
|
|
}
|
|
else
|
|
if (m_eType != eType_FLOAT && m_eType != eType_HALF)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
|
|
if (Annotations.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool bIsUniformRegisterOffset = false;
|
|
|
|
uint32 nCur = Annotations.m_nFirstToken;
|
|
uint32 nLast = Annotations.m_nLastToken;
|
|
uint32* pTokens = &Parser.m_Tokens[0];
|
|
while (nCur <= nLast)
|
|
{
|
|
uint32 nTok = pTokens[nCur++];
|
|
if (nTok == eT_register || nTok == eT_psregister || nTok == eT_vsregister || nTok == eT_gsregister || nTok == eT_dsregister || nTok == eT_hsregister || nTok == eT_csregister)
|
|
{
|
|
m_nFlags |= PF_CUSTOM_BINDED;
|
|
{
|
|
uint32 nTok2 = pTokens[nCur++];
|
|
if (nTok2 != eT_eq)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
else
|
|
{
|
|
nTok2 = pTokens[nCur++];
|
|
const char* szReg = Parser.GetString(nTok2);
|
|
assert(szReg[0] == 'c');
|
|
|
|
int registerOffset = atoi(&szReg[1]);
|
|
|
|
if (nTok == eT_register)
|
|
{
|
|
m_Register[eHWSC_Vertex] = registerOffset;
|
|
m_Register[eHWSC_Pixel] = m_Register[eHWSC_Vertex];
|
|
if (CParserBin::PlatformSupportsGeometryShaders())
|
|
{
|
|
m_Register[eHWSC_Geometry] = m_Register[eHWSC_Vertex];
|
|
}
|
|
if (CParserBin::PlatformSupportsDomainShaders())
|
|
{
|
|
m_Register[eHWSC_Domain] = m_Register[eHWSC_Vertex];
|
|
}
|
|
if (CParserBin::PlatformSupportsHullShaders())
|
|
{
|
|
m_Register[eHWSC_Hull] = m_Register[eHWSC_Vertex];
|
|
}
|
|
if (CParserBin::PlatformSupportsComputeShaders())
|
|
{
|
|
m_Register[eHWSC_Compute] = m_Register[eHWSC_Vertex];
|
|
}
|
|
bIsUniformRegisterOffset = true;
|
|
}
|
|
else
|
|
if (nTok == eT_vsregister)
|
|
{
|
|
m_Register[eHWSC_Vertex] = registerOffset;
|
|
}
|
|
else
|
|
if (nTok == eT_psregister)
|
|
{
|
|
m_Register[eHWSC_Pixel] = registerOffset;
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsGeometryShaders() && nTok == eT_gsregister)
|
|
{
|
|
m_Register[eHWSC_Geometry] = registerOffset;
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsDomainShaders() && nTok == eT_dsregister)
|
|
{
|
|
m_Register[eHWSC_Domain] = registerOffset;
|
|
m_Register[eHWSC_Vertex] = m_Register[eHWSC_Domain];
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsHullShaders() && nTok == eT_hsregister)
|
|
{
|
|
m_Register[eHWSC_Hull] = registerOffset;
|
|
m_Register[eHWSC_Vertex] = m_Register[eHWSC_Hull];
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsComputeShaders() && nTok == eT_csregister)
|
|
{
|
|
m_Register[eHWSC_Compute] = registerOffset;
|
|
m_Register[eHWSC_Vertex] = m_Register[eHWSC_Compute];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (nTok == eT_Position)
|
|
{
|
|
m_nFlags |= PF_POSITION;
|
|
}
|
|
else
|
|
{
|
|
if (nTok == eT_string)
|
|
{
|
|
uint32 nTokName = pTokens[nCur++];
|
|
if (nTokName == eT_UIWidget || nTokName == eT_UIWidget0)
|
|
{
|
|
uint32 nTok0 = pTokens[nCur++];
|
|
uint32 nTok1 = pTokens[nCur++];
|
|
if (nTok0 == eT_eq && nTok1 == eT_quote)
|
|
{
|
|
nTok = pTokens[nCur++];
|
|
if (nTok == eT_color)
|
|
{
|
|
m_nFlags |= PF_TWEAKABLE_MASK;
|
|
}
|
|
else
|
|
{
|
|
m_nFlags |= PF_TWEAKABLE_0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (nTokName == eT_UIWidget1)
|
|
{
|
|
m_nFlags |= PF_TWEAKABLE_1;
|
|
}
|
|
else
|
|
if (nTokName == eT_UIWidget2)
|
|
{
|
|
m_nFlags |= PF_TWEAKABLE_2;
|
|
}
|
|
else
|
|
if (nTokName == eT_UIWidget3)
|
|
{
|
|
m_nFlags |= PF_TWEAKABLE_3;
|
|
}
|
|
}
|
|
}
|
|
if (!Parser.JumpSemicolumn(nCur, nLast))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ((m_nFlags & PF_TWEAKABLE_MASK) && !bIsUniformRegisterOffset)
|
|
{
|
|
AZ_Assert(false, "Tweakables must use 'register'. They cannot have different register offsets per stage.");
|
|
}
|
|
}
|
|
|
|
void SFXSampler::PostLoad(CParserBin& Parser, SParserFrame& Name, SParserFrame& Annotations, SParserFrame& Values, SParserFrame& Assign)
|
|
{
|
|
m_Annotations = Parser.GetNameString(Annotations);
|
|
if (!Values.IsEmpty())
|
|
{
|
|
if (Parser.GetToken(Values) == eT_br_cv_1)
|
|
{
|
|
Values.m_nFirstToken++;
|
|
int32 nFind = Parser.FindToken(Values.m_nFirstToken, Values.m_nLastToken, eT_br_cv_2);
|
|
assert(nFind > 0 && Values.m_nLastToken == nFind);
|
|
if (nFind > 0)
|
|
{
|
|
Values.m_nLastToken--;
|
|
}
|
|
}
|
|
m_Values = Parser.GetString(Values);
|
|
}
|
|
m_Semantic = Parser.GetNameString(Assign);
|
|
m_Name = Parser.GetString(Name);
|
|
m_nFlags = 0;
|
|
|
|
if (!Assign.IsEmpty())
|
|
{
|
|
uint32 nCur = Assign.m_nFirstToken;
|
|
uint32 nLast = Assign.m_nLastToken;
|
|
uint32* pTokens = &Parser.m_Tokens[0];
|
|
while (nCur <= nLast)
|
|
{
|
|
uint32 nTok = pTokens[nCur++];
|
|
if (nTok == eT_register)
|
|
{
|
|
m_nFlags |= PF_CUSTOM_BINDED;
|
|
{
|
|
uint32 nTok2 = pTokens[nCur++];
|
|
if (nTok2 != eT_br_rnd_1)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
else
|
|
{
|
|
nTok2 = pTokens[nCur++];
|
|
const char* szReg = Parser.GetString(nTok2);
|
|
while (szReg[0] == 's' || szReg[0] == 't')
|
|
{
|
|
++szReg;
|
|
}
|
|
assert(isdigit(szReg[0]));
|
|
m_Register[eHWSC_Vertex] =
|
|
m_Register[eHWSC_Pixel] =
|
|
m_Register[eHWSC_Geometry] =
|
|
m_Register[eHWSC_Domain] =
|
|
m_Register[eHWSC_Hull] =
|
|
m_Register[eHWSC_Compute] = atoi(&szReg[0]);
|
|
|
|
uint32 tok2 = pTokens[nCur++];
|
|
if (tok2 != eT_br_rnd_2)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Annotations.IsEmpty())
|
|
{
|
|
uint32 nCur = Annotations.m_nFirstToken;
|
|
uint32 nLast = Annotations.m_nLastToken;
|
|
uint32* pTokens = &Parser.m_Tokens[0];
|
|
while (nCur <= nLast)
|
|
{
|
|
uint32 nTok = pTokens[nCur++];
|
|
if (nTok == eT_psslot || nTok == eT_vsslot || nTok == eT_gsslot || nTok == eT_dsslot || nTok == eT_hsslot || nTok == eT_csslot || nTok == eT_slot)
|
|
{
|
|
m_nFlags |= PF_CUSTOM_BINDED;
|
|
{
|
|
uint32 nTok2 = pTokens[nCur++];
|
|
if (nTok2 != eT_eq)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
else
|
|
{
|
|
nTok2 = pTokens[nCur++];
|
|
const char* szReg = Parser.GetString(nTok2);
|
|
assert(isdigit(szReg[0]));
|
|
if (nTok == eT_vsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Vertex] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (nTok == eT_psslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Pixel] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsGeometryShaders() && nTok == eT_gsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Geometry] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsDomainShaders() && nTok == eT_dsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Domain] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsHullShaders() && nTok == eT_hsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Hull] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsComputeShaders() && nTok == eT_csslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Compute] = atoi(&szReg[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!Parser.JumpSemicolumn(nCur, nLast))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SFXTexture::PostLoad(CParserBin& Parser, SParserFrame& Name, SParserFrame& Annotations, SParserFrame& Values, SParserFrame& Assign)
|
|
{
|
|
m_Annotations = Parser.GetNameString(Annotations);
|
|
if (!Values.IsEmpty())
|
|
{
|
|
if (Parser.GetToken(Values) == eT_br_cv_1)
|
|
{
|
|
Values.m_nFirstToken++;
|
|
int32 nFind = Parser.FindToken(Values.m_nFirstToken, Values.m_nLastToken, eT_br_cv_2);
|
|
|
|
assert(nFind > 0 && Values.m_nLastToken == nFind);
|
|
if (nFind > 0)
|
|
Values.m_nLastToken--;
|
|
}
|
|
if (Parser.GetToken(Values) == eT_quote)
|
|
{
|
|
Values.m_nFirstToken++;
|
|
int32 nFind = Parser.FindToken(Values.m_nFirstToken, Values.m_nLastToken, eT_quote);
|
|
assert(nFind > 0 && Values.m_nLastToken == nFind);
|
|
if (nFind > 0)
|
|
{
|
|
Values.m_nLastToken--;
|
|
}
|
|
}
|
|
m_Values = Parser.GetString(Values);
|
|
}
|
|
m_Semantic = Parser.GetNameString(Assign);
|
|
m_Name = Parser.GetString(Name);
|
|
m_nFlags = 0;
|
|
|
|
if (!Assign.IsEmpty())
|
|
{
|
|
uint32 nCur = Assign.m_nFirstToken;
|
|
uint32 nLast = Assign.m_nLastToken;
|
|
uint32* pTokens = &Parser.m_Tokens[0];
|
|
while (nCur <= nLast)
|
|
{
|
|
uint32 nTok = pTokens[nCur++];
|
|
if (nTok == eT_register)
|
|
{
|
|
m_nFlags |= PF_CUSTOM_BINDED;
|
|
{
|
|
uint32 nTok2 = pTokens[nCur++];
|
|
if (nTok2 != eT_br_rnd_1)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
else
|
|
{
|
|
nTok2 = pTokens[nCur++];
|
|
const char* szReg = Parser.GetString(nTok2);
|
|
while (szReg[0] == 's' || szReg[0] == 't')
|
|
{
|
|
++szReg;
|
|
}
|
|
assert(isdigit(szReg[0]));
|
|
m_Register[eHWSC_Vertex] =
|
|
m_Register[eHWSC_Pixel] =
|
|
m_Register[eHWSC_Geometry] =
|
|
m_Register[eHWSC_Domain] =
|
|
m_Register[eHWSC_Hull] =
|
|
m_Register[eHWSC_Compute] = atoi(&szReg[0]);
|
|
|
|
uint32 tok2 = pTokens[nCur++];
|
|
if (tok2 != eT_br_rnd_2)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Annotations.IsEmpty())
|
|
{
|
|
uint32 nCur = Annotations.m_nFirstToken;
|
|
uint32 nLast = Annotations.m_nLastToken;
|
|
uint32* pTokens = &Parser.m_Tokens[0];
|
|
while (nCur <= nLast)
|
|
{
|
|
uint32 nTok = pTokens[nCur++];
|
|
if (nTok == eT_psslot || nTok == eT_vsslot || nTok == eT_gsslot || nTok == eT_dsslot || nTok == eT_hsslot || nTok == eT_csslot || nTok == eT_slot)
|
|
{
|
|
m_nFlags |= PF_CUSTOM_BINDED;
|
|
{
|
|
uint32 nTok2 = pTokens[nCur++];
|
|
if (nTok2 != eT_eq)
|
|
{
|
|
CRY_ASSERT(0);
|
|
}
|
|
else
|
|
{
|
|
nTok2 = pTokens[nCur++];
|
|
const char* szReg = Parser.GetString(nTok2);
|
|
assert(isdigit(szReg[0]));
|
|
if (nTok == eT_vsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Vertex] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (nTok == eT_psslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Pixel] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsGeometryShaders() && nTok == eT_gsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Geometry] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsDomainShaders() && nTok == eT_dsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Domain] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsHullShaders() && nTok == eT_hsslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Hull] = atoi(&szReg[0]);
|
|
}
|
|
else
|
|
if (CParserBin::PlatformSupportsComputeShaders() && nTok == eT_csslot || nTok == eT_slot)
|
|
{
|
|
m_Register[eHWSC_Compute] = atoi(&szReg[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (nTok)
|
|
{
|
|
case eT_float:
|
|
case eT_float2:
|
|
case eT_float3:
|
|
case eT_float4:
|
|
case eT_uint:
|
|
case eT_uint2:
|
|
case eT_uint4:
|
|
case eT_int:
|
|
case eT_int2:
|
|
case eT_int4:
|
|
m_Type = nTok;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!Parser.JumpSemicolumn(nCur, nLast))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
byte CParserBin::GetCompareFunc(EToken eT)
|
|
{
|
|
switch (eT)
|
|
{
|
|
case eT_None:
|
|
case eT_Disable:
|
|
return eCF_Disable;
|
|
case eT_Never:
|
|
return eCF_Never;
|
|
case eT_Less:
|
|
return eCF_Less;
|
|
case eT_Equal:
|
|
return eCF_Equal;
|
|
case eT_LEqual:
|
|
case eT_LessEqual:
|
|
return eCF_LEqual;
|
|
case eT_Greater:
|
|
return eCF_Greater;
|
|
case eT_NotEqual:
|
|
return eCF_NotEqual;
|
|
case eT_GEqual:
|
|
case eT_GreaterEqual:
|
|
return eCF_NotEqual;
|
|
case eT_Always:
|
|
return eCF_Always;
|
|
default:
|
|
Warning("unknown CompareFunc parameter '%s' (Skipping)\n", GetString(eT));
|
|
}
|
|
return eCF_Less;
|
|
}
|
|
|
|
int CParserBin::GetSrcBlend(EToken eT)
|
|
{
|
|
switch (eT)
|
|
{
|
|
case eT_ONE:
|
|
return GS_BLSRC_ONE;
|
|
case eT_ZERO:
|
|
return GS_BLSRC_ZERO;
|
|
case eT_DST_COLOR:
|
|
case eT_DestColor:
|
|
return GS_BLSRC_DSTCOL;
|
|
case eT_ONE_MINUS_DST_COLOR:
|
|
case eT_InvDestColor:
|
|
return GS_BLSRC_ONEMINUSDSTCOL;
|
|
case eT_SRC_ALPHA:
|
|
case eT_SrcAlpha:
|
|
return GS_BLSRC_SRCALPHA;
|
|
case eT_ONE_MINUS_SRC_ALPHA:
|
|
case eT_InvSrcAlpha:
|
|
return GS_BLSRC_ONEMINUSSRCALPHA;
|
|
case eT_DST_ALPHA:
|
|
case eT_DestAlpha:
|
|
return GS_BLSRC_DSTALPHA;
|
|
case eT_ONE_MINUS_DST_ALPHA:
|
|
case eT_InvDestAlpha:
|
|
return GS_BLSRC_ONEMINUSDSTALPHA;
|
|
case eT_SRC_ALPHA_SATURATE:
|
|
return GS_BLSRC_ALPHASATURATE;
|
|
|
|
default:
|
|
{
|
|
Warning("unknown SrcBlend parameter '%s' (Skipping)\n", GetString(eT));
|
|
CRY_ASSERT(0);
|
|
}
|
|
}
|
|
return GS_BLSRC_ONE;
|
|
}
|
|
|
|
int CParserBin::GetDstBlend(EToken eT)
|
|
{
|
|
switch (eT)
|
|
{
|
|
case eT_ONE:
|
|
return GS_BLDST_ONE;
|
|
case eT_ZERO:
|
|
return GS_BLDST_ZERO;
|
|
case eT_SRC_COLOR:
|
|
case eT_SrcColor:
|
|
return GS_BLDST_SRCCOL;
|
|
case eT_ONE_MINUS_SRC_COLOR:
|
|
case eT_InvSrcColor:
|
|
return GS_BLDST_ONEMINUSSRCCOL;
|
|
case eT_SRC_ALPHA:
|
|
case eT_SrcAlpha:
|
|
return GS_BLDST_SRCALPHA;
|
|
case eT_ONE_MINUS_SRC_ALPHA:
|
|
case eT_InvSrcAlpha:
|
|
return GS_BLDST_ONEMINUSSRCALPHA;
|
|
case eT_DST_ALPHA:
|
|
case eT_DestAlpha:
|
|
return GS_BLDST_DSTALPHA;
|
|
case eT_ONE_MINUS_DST_ALPHA:
|
|
case eT_InvDestAlpha:
|
|
return GS_BLDST_ONEMINUSDSTALPHA;
|
|
|
|
default:
|
|
{
|
|
Warning("unknown DstBlend parameter '%s' (Skipping)\n", GetString(eT));
|
|
CRY_ASSERT(0);
|
|
}
|
|
}
|
|
return GS_BLDST_ONE;
|
|
}
|
|
|
|
void CParserBin::SetupFeatureDefines()
|
|
{
|
|
// globally remove all features here and selectively re-enable them based on project defines and platform validation
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_MESH_TESSELLATION"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_SELF_SHADOWS"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_PARTICLES_TESSELLATION"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_SPI_CONSTANT_BUFFERS"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_SPI_INDEXED_CB"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_GEOMETRY_SHADERS"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_SVO_GI"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_8_BONE_SKINNING"), m_StaticMacros);
|
|
RemoveMacro(CParserBin::GetCRC32("FEATURE_DUAL_SOURCE_BLENDING"), m_StaticMacros);
|
|
|
|
uint32 nEnable[1] = { eT_1 };
|
|
#if defined(MESH_TESSELLATION)
|
|
if (m_nPlatform == SF_D3D11 || m_nPlatform == SF_GL4)
|
|
{
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_MESH_TESSELLATION"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
#endif
|
|
|
|
#if defined(FEATURE_DEFERRED_SHADING_SELF_SHADOWS)
|
|
// Confetti Nicholas Baldwin: adding metal shader language support
|
|
if (m_nPlatform == SF_D3D11 || m_nPlatform == SF_GL4 || m_nPlatform == SF_GLES3 || m_nPlatform == SF_METAL)
|
|
{
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_SELF_SHADOWS"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
#endif
|
|
#if defined(PARTICLES_TESSELLATION)
|
|
if (m_nPlatform == SF_D3D11 || m_nPlatform == SF_JASPER || m_nPlatform == SF_ORBIS || m_nPlatform == SF_GL4)
|
|
{
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_PARTICLES_TESSELLATION"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
#endif
|
|
|
|
if (m_nPlatform == SF_JASPER || m_nPlatform == SF_ORBIS || m_nPlatform == SF_D3D11 || m_nPlatform == SF_GL4 || m_nPlatform == SF_GLES3 || m_nPlatform == SF_METAL)
|
|
{
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_SPI_CONSTANT_BUFFERS"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
|
|
if (m_nPlatform == SF_D3D11 || m_nPlatform == SF_GL4 || m_nPlatform == SF_GLES3 || m_nPlatform == SF_METAL)
|
|
{
|
|
#if defined(FEATURE_SPI_INDEXED_CB)
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_SPI_INDEXED_CB"), nEnable, 1, 0, m_StaticMacros);
|
|
#endif
|
|
}
|
|
|
|
if (m_nPlatform & (SF_D3D11 | SF_ORBIS | SF_JASPER | SF_GL4))
|
|
{
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_GEOMETRY_SHADERS"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
|
|
#if defined(FEATURE_SVO_GI)
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_SVO_GI"), nEnable, 1, 0, m_StaticMacros);
|
|
#endif
|
|
|
|
if (m_nPlatform & (SF_D3D11 | SF_ORBIS | SF_JASPER | SF_GL4))
|
|
{
|
|
AddMacro(CParserBin::GetCRC32("FEATURE_DUAL_SOURCE_BLENDING"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
|
|
#if defined(AZ_PLATFORM_MAC)
|
|
const bool isMacOpenGl = true;
|
|
#else
|
|
const bool isMacOpenGl = false;
|
|
#endif
|
|
|
|
if ((m_nPlatform & (SF_D3D11 | SF_ORBIS | SF_JASPER)) || (isMacOpenGl == false && m_nPlatform & (SF_GL4)))
|
|
{
|
|
// Disable FEATURE_8_BONE_SKINNING because structurebuffer sb_SkinExtraBlendWeights is not handled in the code currently.
|
|
// AddMacro(CParserBin::GetCRC32("FEATURE_8_BONE_SKINNING"), nEnable, 1, 0, m_StaticMacros);
|
|
}
|
|
|
|
#if !defined(NULL_RENDERER)
|
|
if (!gRenDev->IsShaderCacheGenMode())
|
|
{
|
|
if (!RenderCapabilities::SupportsDepthClipping())
|
|
{
|
|
gRenDev->m_cEF.AddStaticFlag(HWSST_NO_DEPTH_CLIPPING);
|
|
}
|
|
}
|
|
#endif // !defined(NULL_RENDERER)
|
|
}
|
|
|
|
void CParserBin::SetupShadersCacheAndFilter()
|
|
{
|
|
const char* shaderLanguageName = GetShaderLanguageName();
|
|
|
|
gRenDev->m_cEF.m_ShadersCache = AZStd::string::format("%s%s/", g_shaderCache, shaderLanguageName);
|
|
gRenDev->m_cEF.m_ShadersFilter = shaderLanguageName;
|
|
}
|