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.
1268 lines
36 KiB
C++
1268 lines
36 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.
|
|
|
|
#pragma once
|
|
|
|
#include <CryThreadSafeRendererContainer.h>
|
|
#include <CryThreadSafeWorkerContainer.h>
|
|
#include "Shadow_Renderer.h"
|
|
#include "../Common/PerInstanceConstantBufferPool.h"
|
|
#include <AzCore/std/containers/unordered_map.h>
|
|
#include <AzCore/std/containers/vector.h>
|
|
//====================================================================
|
|
|
|
#define MAX_HWINST_PARAMS 32768
|
|
|
|
#define MAX_REND_OBJECTS 16384
|
|
#define TEMP_REND_OBJECTS_POOL 2048
|
|
#define MAX_REND_GEOMS_IN_BATCH 16
|
|
|
|
|
|
#define MAX_REND_SHADERS 4096
|
|
#define MAX_REND_SHADER_RES 16384
|
|
#define MAX_REND_LIGHTS 32
|
|
#define MAX_DEFERRED_LIGHTS 256
|
|
#define SG_SORT_GROUP 0
|
|
#define MAX_SHADOWMAP_LOD 20
|
|
#define MAX_SHADOWMAP_FRUSTUMS 1024
|
|
#define MAX_SORT_GROUPS 64
|
|
#define MAX_INSTANCES_THRESHOLD_HW 8
|
|
#define MAX_LIST_ORDER 2 // 0 = before water, 1 = after water
|
|
#define MAX_PREDICTION_ZONES MAX_STREAM_PREDICTION_ZONES
|
|
|
|
#define CULLER_MAX_CAMS 4
|
|
|
|
#define HW_INSTANCING_ENABLED
|
|
|
|
class CRenderView;
|
|
|
|
struct SViewport
|
|
{
|
|
int nX, nY, nWidth, nHeight;
|
|
float fMinZ, fMaxZ;
|
|
SViewport()
|
|
: nX(0)
|
|
, nY(0)
|
|
, nWidth(0)
|
|
, nHeight(0)
|
|
, fMinZ(0.0f)
|
|
, fMaxZ(0.0f)
|
|
{}
|
|
|
|
SViewport(int nNewX, int nNewY, int nNewWidth, int nNewHeight)
|
|
: nX(nNewX)
|
|
, nY(nNewY)
|
|
, nWidth(nNewWidth)
|
|
, nHeight(nNewHeight)
|
|
, fMinZ(0.0f)
|
|
, fMaxZ(0.0f)
|
|
{
|
|
}
|
|
_inline friend bool operator != (const SViewport& m1, const SViewport& m2)
|
|
{
|
|
if (m1.nX != m2.nX || m1.nY != m2.nY || m1.nWidth != m2.nWidth || m1.nHeight != m2.nHeight || m1.fMinZ != m2.fMinZ || m1.fMaxZ != m2.fMaxZ)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
_inline friend bool operator == (const SViewport& m1, const SViewport& m2)
|
|
{
|
|
return !(m1 != m2);
|
|
}
|
|
};
|
|
|
|
struct SRenderListDesc
|
|
{
|
|
int m_nStartRI[MAX_LIST_ORDER][EFSLIST_NUM];
|
|
int m_nEndRI[MAX_LIST_ORDER][EFSLIST_NUM];
|
|
int m_nBatchFlags[MAX_LIST_ORDER][EFSLIST_NUM];
|
|
};
|
|
|
|
typedef union UnINT64
|
|
{
|
|
uint64 SortVal;
|
|
struct
|
|
{
|
|
uint32 Low;
|
|
uint32 High;
|
|
}i;
|
|
} UnINT64;
|
|
|
|
#define FB_IGNORE_SG_MASK 0x100000
|
|
|
|
// FIXME: probably better to sort by shaders (Currently sorted by resources)
|
|
#if defined(AZ_RESTRICTED_PLATFORM)
|
|
#include AZ_RESTRICTED_FILE(RenderPipeline_h)
|
|
#endif
|
|
struct SRendItem
|
|
{
|
|
uint32 SortVal;
|
|
IRenderElement* pElem;
|
|
union
|
|
{
|
|
uint32 ObjSort;
|
|
float fDist;
|
|
};
|
|
CRenderObject* pObj;
|
|
uint32 nBatchFlags;
|
|
uint32 nOcclQuery : 16;
|
|
enum
|
|
{
|
|
kOcclQueryInvalid = 0xFFFFU
|
|
};
|
|
uint32 nStencRef : 8;
|
|
uint8 nTextureID;
|
|
SRendItemSorter rendItemSorter;
|
|
|
|
union QuickCopy
|
|
{
|
|
uint64 data[4];
|
|
char bytes[32];
|
|
};
|
|
|
|
//==================================================
|
|
static void* mfGetPointerCommon(ESrcPointer ePT, int* Stride, EParamType Type, ESrcPointer Dst, int Flags);
|
|
|
|
static _inline void mfGet(uint32 nVal, int& nTechnique, CShader*& Shader, CShaderResources*& Res)
|
|
{
|
|
Shader = (CShader*)CShaderMan::s_pContainer->m_RList[CBaseResource::RListIndexFromId((nVal >> 6) & (MAX_REND_SHADERS - 1))];
|
|
//Shader = (CShader *)CShaderMan::m_pContainer->m_RList[(nVal>>20) & (MAX_REND_SHADERS-1)];
|
|
nTechnique = (nVal & 0x3f);
|
|
if (nTechnique == 0x3f)
|
|
{
|
|
nTechnique = -1;
|
|
}
|
|
int nRes = (nVal >> 18) & (MAX_REND_SHADER_RES - 1);
|
|
//int nRes = (nVal>>6) & (MAX_REND_SHADER_RES-1);
|
|
Res = (nRes) ? CShader::s_ShaderResources_known[nRes] : NULL;
|
|
}
|
|
static _inline CShader* mfGetShader(uint32 flag)
|
|
{
|
|
return (CShader*)CShaderMan::s_pContainer->m_RList[CBaseResource::RListIndexFromId((flag >> 6) & (MAX_REND_SHADERS - 1))];
|
|
//return (CShader *)CShaderMan::m_pContainer->m_RList[(flag>>20) & (MAX_REND_SHADERS-1)];
|
|
}
|
|
static _inline CShaderResources* mfGetRes(uint32 nVal)
|
|
{
|
|
int nRes = (nVal >> 18) & (MAX_REND_SHADER_RES - 1);
|
|
return ((nRes) ? CShader::s_ShaderResources_known[nRes] : NULL);
|
|
}
|
|
static bool IsListEmpty(int nList, [[maybe_unused]] int nProcessID, SRenderListDesc* pRLD)
|
|
{
|
|
int nREs = pRLD->m_nEndRI[0][nList] - pRLD->m_nStartRI[0][nList];
|
|
nREs += pRLD->m_nEndRI[1][nList] - pRLD->m_nStartRI[1][nList];
|
|
|
|
if (!nREs)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool IsListEmpty(int nList, [[maybe_unused]] int nProcessID, SRenderListDesc* pRLD, int nAW)
|
|
{
|
|
int nREs = pRLD->m_nEndRI[nAW][nList] - pRLD->m_nStartRI[nAW][nList];
|
|
|
|
if (!nREs)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static uint32 BatchFlags(int nList, SRenderListDesc* pRLD)
|
|
{
|
|
uint32 nBatchFlags = 0;
|
|
int nREs = pRLD->m_nEndRI[0][nList] - pRLD->m_nStartRI[0][nList];
|
|
if (nREs)
|
|
{
|
|
nBatchFlags |= pRLD->m_nBatchFlags[0][nList];
|
|
}
|
|
nREs = pRLD->m_nEndRI[1][nList] - pRLD->m_nStartRI[1][nList];
|
|
if (nREs)
|
|
{
|
|
nBatchFlags |= pRLD->m_nBatchFlags[1][nList];
|
|
}
|
|
return nBatchFlags;
|
|
}
|
|
|
|
// Sort by SortVal member of RI
|
|
static void mfSortPreprocess(SRendItem* First, int Num);
|
|
// Sort by distance
|
|
static void mfSortByDist(SRendItem* First, int Num, bool bDecals, bool InvertedOrder = false);
|
|
// Sort by light
|
|
static void mfSortByLight(SRendItem* First, int Num, bool bSort, const bool bIgnoreRePtr, bool bSortDecals);
|
|
// Special sorting for ZPass (compromise between depth and batching)
|
|
static void mfSortForZPass(SRendItem* First, int Num);
|
|
|
|
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
|
|
|
|
// Free all renditem lists. Renderer must be flushed.
|
|
static CThreadSafeWorkerContainer<SRendItem>& RendItems(int threadIndex, int listOrder, int listNum);
|
|
|
|
static int m_RecurseLevel[RT_COMMAND_BUF_COUNT];
|
|
static int m_StartFrust[RT_COMMAND_BUF_COUNT][MAX_REND_LIGHTS + MAX_DEFERRED_LIGHTS];
|
|
static int m_EndFrust[RT_COMMAND_BUF_COUNT][MAX_REND_LIGHTS + MAX_DEFERRED_LIGHTS];
|
|
static int m_ShadowsStartRI[RT_COMMAND_BUF_COUNT][MAX_SHADOWMAP_FRUSTUMS];
|
|
static int m_ShadowsEndRI[RT_COMMAND_BUF_COUNT][MAX_SHADOWMAP_FRUSTUMS];
|
|
};
|
|
|
|
//==================================================================
|
|
|
|
struct SShaderPass;
|
|
|
|
union UVertStreamPtr
|
|
{
|
|
void* Ptr;
|
|
byte* PtrB;
|
|
SVF_P3F_C4B_T4B_N3F2* PtrVF_P3F_C4B_T4B_N3F2;
|
|
};
|
|
|
|
//==================================================================
|
|
|
|
#define MAX_DYNVBS 4
|
|
|
|
//==================================================================
|
|
|
|
#define GS_HIZENABLE 0x00010000
|
|
//==================================================================
|
|
|
|
#if defined(NULL_RENDERER)
|
|
struct SOnDemandD3DStreamProperties
|
|
{
|
|
};
|
|
|
|
struct SOnDemandD3DVertexDeclaration
|
|
{
|
|
};
|
|
|
|
struct SOnDemandD3DVertexDeclarationCache
|
|
{
|
|
};
|
|
#else
|
|
struct SOnDemandD3DStreamProperties
|
|
{
|
|
D3D11_INPUT_ELEMENT_DESC* m_pElements;
|
|
uint32 m_nNumElements;
|
|
};
|
|
|
|
struct SOnDemandD3DVertexDeclaration
|
|
{
|
|
AZStd::vector<D3D11_INPUT_ELEMENT_DESC> m_Declaration;
|
|
};
|
|
|
|
struct SOnDemandD3DVertexDeclarationCache
|
|
{
|
|
ID3D11InputLayout* m_pDeclaration;
|
|
};
|
|
|
|
template <class IndexType>
|
|
class FencedIB;
|
|
template <class VertexType>
|
|
class FencedVB;
|
|
|
|
struct SVertexDeclaration
|
|
{
|
|
int StreamMask;
|
|
AZ::Vertex::Format VertexFormat;
|
|
int InstAttrMask;
|
|
AZStd::vector<D3D11_INPUT_ELEMENT_DESC> m_Declaration;
|
|
ID3D11InputLayout* m_pDeclaration = nullptr;
|
|
|
|
// This caching structure is only used for auto-generated vertex formats for instanced renders.
|
|
// The caching format was previously invalid because it cached ID3D11InputLayout based only on the
|
|
// vertex format declaration, rather than based on the vertex format declaration with the vertex shader input
|
|
// table since a different IA layout will be generated whether a vertex shader uses different inputs or not
|
|
void* m_vertexShader = nullptr;
|
|
|
|
~SVertexDeclaration()
|
|
{
|
|
SAFE_RELEASE(m_pDeclaration);
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
struct SMSAA
|
|
{
|
|
SMSAA()
|
|
: Type(0)
|
|
, Quality(0)
|
|
, m_pDepthTex(0)
|
|
, m_pZBuffer(0)
|
|
{
|
|
}
|
|
|
|
UINT Type;
|
|
DWORD Quality;
|
|
#if defined(NULL_RENDERER)
|
|
void* m_pDepthTex;
|
|
void* m_pZBuffer;
|
|
#else
|
|
D3DTexture* m_pDepthTex;
|
|
ID3D11DepthStencilView* m_pZBuffer;
|
|
#endif
|
|
};
|
|
|
|
struct SProfInfo
|
|
{
|
|
int NumPolys;
|
|
int NumDips;
|
|
CShader* pShader;
|
|
SShaderTechnique* pTechnique;
|
|
double Time;
|
|
int m_nItems;
|
|
SProfInfo()
|
|
{
|
|
NumPolys = 0;
|
|
NumDips = 0;
|
|
pShader = NULL;
|
|
pTechnique = NULL;
|
|
m_nItems = 0;
|
|
}
|
|
void GetMemoryUsage(ICrySizer* pSizer) const
|
|
{
|
|
pSizer->AddObject(pShader);
|
|
pSizer->AddObject(pTechnique);
|
|
}
|
|
};
|
|
|
|
struct SRTargetStat
|
|
{
|
|
string m_Name;
|
|
uint32 m_nSize;
|
|
uint32 m_nWidth;
|
|
uint32 m_nHeight;
|
|
ETEX_Format m_eTF;
|
|
|
|
void GetMemoryUsage(ICrySizer* pSizer) const
|
|
{
|
|
pSizer->AddObject(m_Name);
|
|
}
|
|
};
|
|
|
|
|
|
struct SPipeStat
|
|
{
|
|
#if !defined(_RELEASE)
|
|
int m_NumRendHWInstances;
|
|
int m_RendHWInstancesPolysAll;
|
|
int m_RendHWInstancesPolysOne;
|
|
int m_RendHWInstancesDIPs;
|
|
int m_NumTextChanges;
|
|
int m_NumRTChanges;
|
|
int m_NumStateChanges;
|
|
int m_NumRendSkinnedObjects;
|
|
int m_NumVShadChanges;
|
|
int m_NumPShadChanges;
|
|
int m_NumGShadChanges;
|
|
int m_NumDShadChanges;
|
|
int m_NumHShadChanges;
|
|
int m_NumCShadChanges;
|
|
int m_NumVShaders;
|
|
int m_NumPShaders;
|
|
int m_NumGShaders;
|
|
int m_NumDShaders;
|
|
int m_NumHShaders;
|
|
int m_NumRTs;
|
|
int m_NumSprites;
|
|
int m_NumSpriteDIPS;
|
|
int m_NumSpritePolys;
|
|
int m_NumSpriteUpdates;
|
|
int m_NumSpriteAltasesUsed;
|
|
int m_NumSpriteCellsUsed;
|
|
int m_NumQIssued;
|
|
int m_NumQOccluded;
|
|
int m_NumQNotReady;
|
|
int m_NumQStallTime;
|
|
int m_NumImpostersUpdates;
|
|
int m_NumCloudImpostersUpdates;
|
|
int m_NumImpostersDraw;
|
|
int m_NumCloudImpostersDraw;
|
|
int m_NumTextures;
|
|
uint32 m_NumShadowPoolFrustums;
|
|
uint32 m_NumShadowPoolAllocsThisFrame;
|
|
uint32 m_NumShadowMaskChannels;
|
|
uint32 m_NumTiledShadingSkippedLights;
|
|
#endif
|
|
int m_NumPSInstructions;
|
|
int m_NumVSInstructions;
|
|
int m_RTCleared;
|
|
int m_RTClearedSize;
|
|
int m_RTCopied;
|
|
int m_RTCopiedSize;
|
|
int m_RTSize;
|
|
|
|
CHWShader* m_pMaxPShader;
|
|
CHWShader* m_pMaxVShader;
|
|
void* m_pMaxPSInstance;
|
|
void* m_pMaxVSInstance;
|
|
|
|
size_t m_ManagedTexturesStreamSysSize;
|
|
size_t m_ManagedTexturesStreamVidSize;
|
|
size_t m_ManagedTexturesSysMemSize;
|
|
size_t m_ManagedTexturesVidMemSize;
|
|
size_t m_DynTexturesSize;
|
|
size_t m_MeshUpdateBytes;
|
|
size_t m_DynMeshUpdateBytes;
|
|
float m_fOverdraw;
|
|
float m_fSkinningTime;
|
|
float m_fPreprocessTime;
|
|
float m_fSceneTimeMT;
|
|
float m_fTexUploadTime;
|
|
float m_fTexRestoreTime;
|
|
float m_fOcclusionTime;
|
|
float m_fRenderTime;
|
|
float m_fEnvCMapUpdateTime;
|
|
float m_fEnvTextUpdateTime;
|
|
|
|
int m_ImpostersSizeUpdate;
|
|
int m_CloudImpostersSizeUpdate;
|
|
|
|
#if REFRACTION_PARTIAL_RESOLVE_STATS
|
|
float m_fRefractionPartialResolveEstimatedCost;
|
|
int m_refractionPartialResolveCount;
|
|
int m_refractionPartialResolvePixelCount;
|
|
#endif
|
|
|
|
#if defined(ENABLE_PROFILING_CODE)
|
|
int m_NumRendMaterialBatches;
|
|
int m_NumRendGeomBatches;
|
|
int m_NumRendInstances;
|
|
|
|
int m_nDIPs[EFSLIST_NUM];
|
|
int m_nInsts;
|
|
int m_nInstCalls;
|
|
int m_nPolygons[EFSLIST_NUM];
|
|
int m_nPolygonsByTypes[EFSLIST_NUM][EVCT_NUM][2];
|
|
#endif
|
|
|
|
#if defined(ENABLE_ART_RT_TIME_ESTIMATE)
|
|
float m_actualRenderTimeMinusPost;
|
|
#endif
|
|
|
|
float m_fTimeDIPs[EFSLIST_NUM];
|
|
float m_fTimeDIPsZ;
|
|
float m_fTimeDIPsAO;
|
|
float m_fTimeDIPsRAIN;
|
|
float m_fTimeDIPsDeferredLayers;
|
|
float m_fTimeDIPsSprites;
|
|
} _ALIGN(128);
|
|
|
|
|
|
//Batch flags.
|
|
// - When adding/removing batch flags, please, update sBatchList static list in D3DRendPipeline.cpp
|
|
enum EBatchFlags
|
|
{
|
|
FB_GENERAL = 0x1,
|
|
FB_TRANSPARENT = 0x2,
|
|
FB_SKIN = 0x4,
|
|
FB_Z = 0x8,
|
|
FB_FUR = 0x10,
|
|
FB_ZPREPASS = 0x20,
|
|
FB_PREPROCESS = 0x40,
|
|
FB_MOTIONBLUR = 0x80,
|
|
FB_POST_3D_RENDER = 0x100,
|
|
FB_MULTILAYERS = 0x200,
|
|
FB_COMPILED_OBJECT = 0x400,
|
|
FB_CUSTOM_RENDER = 0x800,
|
|
FB_SOFTALPHATEST = 0x1000,
|
|
FB_LAYER_EFFECT = 0x2000,
|
|
FB_WATER_REFL = 0x4000,
|
|
FB_WATER_CAUSTIC = 0x8000,
|
|
FB_DEBUG = 0x10000,
|
|
FB_PARTICLES_THICKNESS = 0x20000,
|
|
FB_TRANSPARENT_AFTER_DOF = 0x40000, // for transparent render element skip Depth of field effect
|
|
FB_EYE_OVERLAY = 0x80000,
|
|
|
|
FB_MASK = 0xfffff //! FB flags cannot exceed 0xfffff
|
|
};
|
|
|
|
|
|
// Commit flags
|
|
#define FC_TARGETS 1
|
|
#define FC_GLOBAL_PARAMS 2
|
|
#define FC_PER_INSTANCE_PARAMS 4
|
|
#define FC_MATERIAL_PARAMS 0x10
|
|
#define FC_ALL 0x1f
|
|
|
|
|
|
// m_RP.m_Flags
|
|
#define RBF_NEAREST 0x10000
|
|
|
|
// m_RP.m_TI.m_PersFlags
|
|
#define RBPF_DRAWTOTEXTURE (1 << 16) // 0x10000
|
|
#define RBPF_MIRRORCAMERA (1 << 17) // 0x20000
|
|
#define RBPF_MIRRORCULL (1 << 18) // 0x40000
|
|
|
|
#define RBPF_ZPASS (1 << 19) // 0x80000
|
|
#define RBPF_SHADOWGEN (1 << 20) // 0x100000
|
|
|
|
#define RBPF_FP_DIRTY (1 << 21) // 0x200000
|
|
|
|
#define RBPF_NO_SHADOWGEN (1 << 22)
|
|
|
|
#define RBPF_IMPOSTERGEN (1 << 23)
|
|
#define RBPF_MAKESPRITE (1 << 24) // 0x1000000
|
|
// CRY DX12
|
|
#define RBPF_FP_MATRIXDIRTY (1 << 25)
|
|
|
|
#define RBPF_HDR (1 << 26)
|
|
#define RBPF_REVERSE_DEPTH (1 << 27)
|
|
#define RBPF_ENCODE_HDR (1 << 29)
|
|
#define RBPF_OBLIQUE_FRUSTUM_CLIPPING (1 << 30)
|
|
|
|
|
|
// m_RP.m_PersFlags1
|
|
#define RBPF1_USESTREAM (1 << 0)
|
|
#define RBPF1_USESTREAM_MASK ((1 << VSF_NUM) - 1)
|
|
|
|
#define RBPF1_IN_CLEAR (1 << 17)
|
|
|
|
#define RBPF1_SKIP_AFTER_POST_PROCESS (1 << 18)
|
|
|
|
// m_RP.m_PersFlags2
|
|
#define RBPF2_NOSHADERFOG (1 << 0)
|
|
#define RBPF2_RAINRIPPLES (1 << 1)
|
|
#define RBPF2_NOALPHABLEND (1 << 2)
|
|
#define RBPF2_SINGLE_FORWARD_LIGHT_PASS (1 << 3)
|
|
#define RBPF2_MSAA_RESTORE_SAMPLE_MASK (1 << 4)
|
|
#define RBPF2_READMASK_RESERVED_STENCIL_BIT (1 << 5)
|
|
#define RBPF2_POST_3D_RENDERER_PASS (1 << 6)
|
|
#define RBPF2_LENS_OPTICS_COMPOSITE (1 << 7)
|
|
#define RBPF2_HDR_FP16 (1 << 9)
|
|
#define RBPF2_CUSTOM_SHADOW_PASS (1 << 10)
|
|
#define RBPF2_CUSTOM_RENDER_PASS (1 << 11)
|
|
// UNUSED: (1<<12)
|
|
|
|
#define RBPF2_COMMIT_CM (1 << 13)
|
|
#define RBPF2_ZPREPASS (1 << 14)
|
|
|
|
#define RBPF2_FORWARD_SHADING_PASS (1 << 15)
|
|
|
|
#define RBPF2_MSAA_STENCILCULL (1 << 16)
|
|
|
|
#define RBPF2_THERMAL_RENDERMODE_TRANSPARENT_PASS (1 << 17)
|
|
#define RBPF2_NOALPHATEST (1 << 18)
|
|
#define RBPF2_WATERRIPPLES (1 << 19)
|
|
#define RBPF2_ALLOW_DEFERREDSHADING (1 << 20)
|
|
|
|
#define RBPF2_COMMIT_PF (1 << 21)
|
|
#define RBPF2_MSAA_SAMPLEFREQ_PASS (1 << 22)
|
|
#define RBPF2_DRAWTOCUBE (1 << 23)
|
|
|
|
#define RBPF2_MOTIONBLURPASS (1 << 24)
|
|
#define RBPF2_MATERIALLAYERPASS (1 << 25)
|
|
#define RBPF2_DISABLECOLORWRITES (1 << 26)
|
|
|
|
#define RBPF2_NOPOSTAA (1 << 27)
|
|
#define RBPF2_SKIN (1 << 28)
|
|
|
|
#define RBPF2_LIGHTSHAFTS (1 << 29)
|
|
#define RBPF2_WRITEMASK_RESERVED_STENCIL_BIT (1 << 30) // 0x010
|
|
#define RBPF2_HALFRES_PARTICLES (1 << 31)
|
|
|
|
// m_RP.m_FlagsPerFlush
|
|
#define RBSI_LOCKCULL 0x2
|
|
#define RBSI_EXTERN_VMEM_BUFFERS 0x800000
|
|
#define RBSI_INSTANCED 0x10000000
|
|
#define RBSI_CUSTOM_PREVMATRIX 0x20000000
|
|
|
|
// m_RP.m_ShaderLightMask
|
|
#define SLMF_DIRECT 0
|
|
#define SLMF_POINT 1
|
|
#define SLMF_PROJECTED 2
|
|
#define SLMF_TYPE_MASK (SLMF_POINT | SLMF_PROJECTED)
|
|
|
|
#define SLMF_LTYPE_SHIFT 8
|
|
#define SLMF_LTYPE_BITS 4
|
|
|
|
struct SLightPass
|
|
{
|
|
SRenderLight* pLights[4];
|
|
uint32 nStencLTMask;
|
|
uint32 nLights;
|
|
uint32 nLTMask;
|
|
bool bRect;
|
|
RectI rc;
|
|
};
|
|
|
|
#define MAX_STREAMS 16
|
|
|
|
struct SStreamInfo
|
|
{
|
|
const void* pStream;
|
|
int nOffset;
|
|
int nStride;
|
|
|
|
SStreamInfo() {}
|
|
SStreamInfo(const void* stream, int offset, int stride)
|
|
: pStream(stream)
|
|
, nOffset(offset)
|
|
, nStride(stride) {}
|
|
|
|
SStreamInfo& operator=(const CRendElementBase::SGeometryStreamInfo& stream)
|
|
{
|
|
pStream = stream.pStream;
|
|
nOffset = stream.nOffset;
|
|
nStride = stream.nStride;
|
|
return *this;
|
|
}
|
|
|
|
inline bool operator==(const SStreamInfo& other) const
|
|
{
|
|
return pStream == other.pStream && nOffset == other.nOffset && nStride == other.nStride;
|
|
}
|
|
};
|
|
|
|
struct SFogState
|
|
{
|
|
bool m_bEnable;
|
|
ColorF m_FogColor;
|
|
ColorF m_CurColor;
|
|
|
|
bool operator != (const SFogState& fs) const
|
|
{
|
|
return m_FogColor != fs.m_FogColor;
|
|
}
|
|
};
|
|
|
|
enum EShapeMeshType
|
|
{
|
|
SHAPE_PROJECTOR = 0,
|
|
SHAPE_PROJECTOR1,
|
|
SHAPE_PROJECTOR2,
|
|
SHAPE_CLIP_PROJECTOR,
|
|
SHAPE_CLIP_PROJECTOR1,
|
|
SHAPE_CLIP_PROJECTOR2,
|
|
SHAPE_SIMPLE_PROJECTOR,
|
|
SHAPE_SPHERE,
|
|
SHAPE_BOX,
|
|
SHAPE_MAX,
|
|
};
|
|
|
|
struct SThreadInfo
|
|
{
|
|
uint32 m_PersFlags; // Never reset
|
|
float m_RealTime;
|
|
|
|
Matrix44A m_matView = Matrix44A(IDENTITY);
|
|
Matrix44A m_matProj = Matrix44A(IDENTITY);
|
|
|
|
CCamera m_cam; // current camera
|
|
int m_nFrameID; // with recursive calls, access through GetFrameID(true)
|
|
uint32 m_nFrameUpdateID; // without recursive calls, access through GetFrameID(false)
|
|
int m_arrZonesRoundId[MAX_PREDICTION_ZONES]; // rounds ID from 3D engine, useful for texture streaming
|
|
SFogState m_FS;
|
|
CRenderObject* m_pIgnoreObject;
|
|
|
|
Plane m_pObliqueClipPlane;
|
|
bool m_bObliqueClipPlane;
|
|
|
|
byte m_eCurColorOp;
|
|
byte m_eCurAlphaOp;
|
|
byte m_eCurColorArg;
|
|
byte m_eCurAlphaArg;
|
|
bool m_sRGBWrite {
|
|
false
|
|
};
|
|
|
|
PerFrameParameters m_perFrameParameters;
|
|
|
|
~SThreadInfo() {}
|
|
SThreadInfo& operator = (const SThreadInfo& ti)
|
|
{
|
|
if (&ti == this)
|
|
{
|
|
return *this;
|
|
}
|
|
m_PersFlags = ti.m_PersFlags;
|
|
m_RealTime = ti.m_RealTime;
|
|
m_matView = ti.m_matView;
|
|
m_matProj = ti.m_matProj;
|
|
m_cam = ti.m_cam;
|
|
m_nFrameID = ti.m_nFrameID;
|
|
m_nFrameUpdateID = ti.m_nFrameUpdateID;
|
|
for (int z = 0; z < MAX_PREDICTION_ZONES; z++)
|
|
{
|
|
m_arrZonesRoundId[z] = ti.m_arrZonesRoundId[z];
|
|
}
|
|
m_FS = ti.m_FS;
|
|
m_perFrameParameters = ti.m_perFrameParameters;
|
|
m_pIgnoreObject = ti.m_pIgnoreObject;
|
|
memcpy(&m_pObliqueClipPlane, &ti.m_pObliqueClipPlane, sizeof(m_pObliqueClipPlane));
|
|
m_bObliqueClipPlane = ti.m_bObliqueClipPlane;
|
|
m_eCurColorOp = ti.m_eCurColorOp;
|
|
m_eCurAlphaOp = ti.m_eCurAlphaOp;
|
|
m_eCurColorArg = ti.m_eCurColorArg;
|
|
m_eCurAlphaArg = ti.m_eCurAlphaArg;
|
|
m_sRGBWrite = ti.m_sRGBWrite;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
|
|
#ifdef STRIP_RENDER_THREAD
|
|
struct SSingleThreadInfo
|
|
: public SThreadInfo
|
|
{
|
|
SThreadInfo& operator[] (const int) {return *this; }
|
|
const SThreadInfo& operator[] (const int) const {return *this; }
|
|
};
|
|
#endif
|
|
|
|
|
|
// Render pipeline structure
|
|
struct SRenderPipeline
|
|
{
|
|
CShader* m_pShader;
|
|
CShader* m_pReplacementShader;
|
|
CRenderObject* m_pCurObject;
|
|
CRenderObject* m_pIdendityRenderObject;
|
|
IRenderElement* m_pRE;
|
|
CRendElementBase* m_pEventRE;
|
|
int m_RendNumVerts;
|
|
uint32 m_nBatchFilter; // Batch flags ( FB_ )
|
|
SShaderTechnique* m_pRootTechnique;
|
|
SShaderTechnique* m_pCurTechnique;
|
|
SShaderPass* m_pCurPass;
|
|
uint32 m_CurPassBitMask;
|
|
int m_nShaderTechnique;
|
|
int m_nShaderTechniqueType;
|
|
CShaderResources* m_pShaderResources;
|
|
CRenderObject* m_pPrevObject;
|
|
int m_nLastRE;
|
|
TArray<SRendItem*> m_RIs[MAX_REND_GEOMS_IN_BATCH];
|
|
|
|
ColorF m_CurGlobalColor;
|
|
|
|
float m_fMinDistance; // min distance to texture
|
|
uint64 m_ObjFlags; // Instances flag for batch (merged)
|
|
int m_Flags; // Reset on start pipeline
|
|
|
|
EShapeMeshType m_nDeferredPrimitiveID;
|
|
int m_nZOcclusionBufferID;
|
|
|
|
threadID m_nFillThreadID;
|
|
threadID m_nProcessThreadID;
|
|
SThreadInfo m_TI[RT_COMMAND_BUF_COUNT];
|
|
SThreadInfo m_OldTI[MAX_RECURSION_LEVELS];
|
|
// SFogVolumeData container will be used to accumulate the fog volume influences.
|
|
CThreadSafeRendererContainer<SFogVolumeData> m_fogVolumeContibutionsData[RT_COMMAND_BUF_COUNT];
|
|
|
|
uint32 m_PersFlags1; // Persistent flags - never reset
|
|
uint32 m_PersFlags2; // Persistent flags - never reset
|
|
int m_FlagsPerFlush; // Flags which resets for each shader flush
|
|
uint32 m_nCommitFlags;
|
|
uint32 m_FlagsStreams_Decl;
|
|
uint32 m_FlagsStreams_Stream;
|
|
AZ::Vertex::Format m_CurVFormat;
|
|
uint32 m_FlagsShader_LT; // Shader light mask
|
|
uint64 m_FlagsShader_RT; // Shader runtime mask
|
|
uint32 m_FlagsShader_MD; // Shader texture modificator mask
|
|
uint32 m_FlagsShader_MDV; // Shader vertex modificator mask
|
|
uint32 m_nShaderQuality;
|
|
|
|
void (* m_pRenderFunc)();
|
|
|
|
uint32 m_CurGPRAllocStateCommit;
|
|
uint32 m_CurGPRAllocState;
|
|
int m_CurHiZState;
|
|
|
|
uint32 m_CurState;
|
|
uint32 m_StateOr;
|
|
uint32 m_StateAnd;
|
|
int m_CurAlphaRef;
|
|
uint32 m_MaterialStateOr;
|
|
uint32 m_MaterialStateAnd;
|
|
int m_MaterialAlphaRef;
|
|
uint32 m_ForceStateOr;
|
|
uint32 m_ForceStateAnd;
|
|
bool m_bIgnoreObjectAlpha;
|
|
ECull m_eCull;
|
|
uint32 m_previousPersFlags = 0;
|
|
|
|
int m_CurStencilState;
|
|
uint32 m_CurStencMask;
|
|
uint32 m_CurStencWriteMask;
|
|
uint32 m_CurStencRef;
|
|
int m_CurStencilRefAndMask;
|
|
int m_CurStencilCullFunc;
|
|
|
|
SStreamInfo m_VertexStreams[MAX_STREAMS];
|
|
void* m_pIndexStream;
|
|
|
|
uint32 m_IndexStreamOffset;
|
|
RenderIndexType m_IndexStreamType;
|
|
|
|
bool m_bFirstPass;
|
|
uint32 m_nNumRendPasses;
|
|
int m_NumShaderInstructions;
|
|
|
|
string m_sExcludeShader;
|
|
|
|
TArray<SProfInfo> m_Profile;
|
|
|
|
CCamera m_PrevCamera;
|
|
|
|
SRenderListDesc* m_pRLD;
|
|
|
|
uint32 m_nRendFlags;
|
|
bool m_bUseHDR;
|
|
int m_nPassGroupID; // EFSLIST_ pass type
|
|
int m_nPassGroupDIP; // EFSLIST_ pass type
|
|
int m_nSortGroupID;
|
|
uint32 m_nFlagsShaderBegin;
|
|
uint8 m_nCurrResolveBounds[4];
|
|
|
|
Vec2 m_CurDownscaleFactor;
|
|
|
|
ERenderQuality m_eQuality;
|
|
|
|
TArray<ShadowMapFrustum> m_SMFrustums[RT_COMMAND_BUF_COUNT][MAX_REND_RECURSION_LEVELS];
|
|
TArray<int> m_SMCustomFrustumIDs[RT_COMMAND_BUF_COUNT][MAX_REND_RECURSION_LEVELS];
|
|
CThreadSafeWorkerContainer<CustomShadowMapFrustumData> m_arrCustomShadowMapFrustumData[RT_COMMAND_BUF_COUNT];
|
|
|
|
struct SShadowFrustumToRender
|
|
{
|
|
ShadowMapFrustum* pFrustum;
|
|
int nRecursiveLevel;
|
|
int nLightID;
|
|
SRenderLight* pLight;
|
|
} _ALIGN(16);
|
|
TArray<SShadowFrustumToRender> SShadowFrustumToRenderList[RT_COMMAND_BUF_COUNT];
|
|
TArray<SRenderLight> m_DLights[RT_COMMAND_BUF_COUNT][MAX_REND_RECURSION_LEVELS];
|
|
SLightPass m_LPasses[MAX_REND_LIGHTS];
|
|
float m_fProfileTime;
|
|
|
|
struct ShadowInfo
|
|
{
|
|
ShadowMapFrustum* m_pCurShadowFrustum;
|
|
Vec3 vViewerPos;
|
|
int m_nOmniLightSide;
|
|
} m_ShadowInfo;
|
|
|
|
DynArray<SDeferredDecal> m_DeferredDecals[RT_COMMAND_BUF_COUNT][MAX_REND_RECURSION_LEVELS];
|
|
bool m_isDeferrredNormalDecals[RT_COMMAND_BUF_COUNT][MAX_REND_RECURSION_LEVELS];
|
|
|
|
UVertStreamPtr m_StreamPtrTang;
|
|
UVertStreamPtr m_NextStreamPtrTang;
|
|
|
|
UVertStreamPtr m_StreamPtr;
|
|
UVertStreamPtr m_NextStreamPtr;
|
|
int m_StreamStride;
|
|
uint m_StreamOffsetTC;
|
|
uint m_StreamOffsetColor;
|
|
|
|
float m_fLastWaterFOVUpdate;
|
|
Vec3 m_LastWaterViewdirUpdate;
|
|
Vec3 m_LastWaterUpdirUpdate;
|
|
Vec3 m_LastWaterPosUpdate;
|
|
float m_fLastWaterUpdate;
|
|
int m_nLastWaterFrameID;
|
|
|
|
bool m_depthWriteStateUsed;
|
|
|
|
#if !defined(NULL_RENDERER)
|
|
SMSAA m_MSAAData;
|
|
bool IsMSAAEnabled() const { return m_MSAAData.Type > 0; }
|
|
|
|
enum
|
|
{
|
|
nNumParticleVertexIndexBuffer = 3
|
|
};
|
|
|
|
// particle date for writing directly to VMEM
|
|
FencedVB<byte>* m_pParticleVertexBuffer[nNumParticleVertexIndexBuffer];
|
|
FencedIB <uint16>* m_pParticleIndexBuffer[nNumParticleVertexIndexBuffer];
|
|
|
|
// During writing, we only expose the base Video Memory pointer
|
|
// and the offsets to the next free memory in this buffer
|
|
byte* m_pParticleVertexVideoMemoryBase[nNumParticleVertexIndexBuffer];
|
|
byte* m_pParticleindexVideoMemoryBase[nNumParticleVertexIndexBuffer];
|
|
|
|
uint32 m_nParticleVertexOffset[nNumParticleVertexIndexBuffer];
|
|
uint32 m_nParticleIndexOffset[nNumParticleVertexIndexBuffer];
|
|
|
|
// total amount of allocated memory for particle vertex/index buffers
|
|
uint32 m_nParticleVertexBufferAvailableMemory;
|
|
uint32 m_nParticleIndexBufferAvailableMemory;
|
|
|
|
|
|
int m_nStreamOffset[3]; // deprecated!
|
|
|
|
AZ::Vertex::Format m_vertexFormats[eVF_Max];
|
|
SOnDemandD3DVertexDeclaration m_D3DVertexDeclarations[eVF_Max];
|
|
AZStd::unordered_map<AZ::u32, SOnDemandD3DVertexDeclarationCache> m_D3DVertexDeclarationCache[1 << VSF_NUM][2]; // [StreamMask][Morph][VertexFormatCRC]
|
|
SOnDemandD3DStreamProperties m_D3DStreamProperties[VSF_NUM];
|
|
|
|
TArray<SVertexDeclaration*> m_CustomVD;
|
|
#else
|
|
bool IsMSAAEnabled() const { return false; }
|
|
#endif
|
|
|
|
uint16* m_RendIndices;
|
|
uint16* m_SysRendIndices;
|
|
byte* m_SysArray;
|
|
int m_SizeSysArray;
|
|
|
|
TArray<byte> m_SysVertexPool[RT_COMMAND_BUF_COUNT];
|
|
TArray<uint16> m_SysIndexPool[RT_COMMAND_BUF_COUNT];
|
|
|
|
int m_RendNumGroup;
|
|
int m_RendNumIndices;
|
|
int m_FirstIndex;
|
|
int m_FirstVertex;
|
|
|
|
// members for external vertex/index buffers
|
|
#if !defined(NULL_RENDERER)
|
|
FencedVB<byte>* m_pExternalVertexBuffer;
|
|
FencedIB<uint16>* m_pExternalIndexBuffer;
|
|
int m_nExternalVertexBufferFirstIndex;
|
|
int m_nExternalVertexBufferFirstVertex;
|
|
#endif
|
|
|
|
// [Shader System TO DO] - change this so that we don't deal with static slots assignments
|
|
// The following structure is practically used only once to set Instance texture coord matrix.
|
|
SEfResTexture* m_ShaderTexResources[MAX_TMU];
|
|
|
|
int m_Frame;
|
|
int m_FrameMerge;
|
|
|
|
float m_fCurOpacity;
|
|
|
|
SPipeStat m_PS[RT_COMMAND_BUF_COUNT];
|
|
DynArray<SRTargetStat> m_RTStats;
|
|
|
|
int m_MaxVerts;
|
|
int m_MaxTris;
|
|
|
|
int m_RECustomTexBind[8];
|
|
int m_ShadowCustomTexBind[8];
|
|
bool m_ShadowCustomComparisonSampling[8];
|
|
|
|
CRenderView* m_pCurrentFillView;
|
|
CRenderView* m_pCurrentRenderView;
|
|
std::shared_ptr<CRenderView> m_pRenderViews[RT_COMMAND_BUF_COUNT];
|
|
//===================================================================
|
|
// Input render data
|
|
SRenderLight* m_pSunLight;
|
|
CThreadSafeWorkerContainer <CRenderObject*> m_TempObjects[RT_COMMAND_BUF_COUNT];
|
|
CRenderObject* m_ObjectsPool;
|
|
uint32 m_nNumObjectsInPool;
|
|
|
|
#if !defined(_RELEASE)
|
|
//===================================================================
|
|
// Drawcall count debug view - per Node - r_stats 6
|
|
IRenderer::RNDrawcallsMapNode m_pRNDrawCallsInfoPerNode[RT_COMMAND_BUF_COUNT];
|
|
|
|
// Functionality for retrieving previous frames stats to use this frame
|
|
IRenderer::RNDrawcallsMapNode m_pRNDrawCallsInfoPerNodePreviousFrame[RT_COMMAND_BUF_COUNT];
|
|
|
|
//===================================================================
|
|
// Drawcall count debug view - per mesh - perf hud renderBatchStats
|
|
IRenderer::RNDrawcallsMapMesh m_pRNDrawCallsInfoPerMesh[RT_COMMAND_BUF_COUNT];
|
|
|
|
// Functionality for retrieving previous frames stats to use this frame
|
|
IRenderer::RNDrawcallsMapMesh m_pRNDrawCallsInfoPerMeshPreviousFrame[RT_COMMAND_BUF_COUNT];
|
|
#endif
|
|
|
|
//================================================================
|
|
// Render elements..
|
|
|
|
class CREHDRProcess* m_pREHDR;
|
|
class CREDeferredShading* m_pREDeferredShading;
|
|
class CREPostProcess* m_pREPostProcess;
|
|
|
|
//=================================================================
|
|
// WaveForm tables
|
|
static const uint32 sSinTableCount = 1024;
|
|
float m_tSinTable[sSinTableCount];
|
|
|
|
// For explicit geometry cache motion blur
|
|
Matrix44A* m_pPrevMatrix;
|
|
|
|
public:
|
|
SRenderPipeline()
|
|
: m_pShader(0)
|
|
, m_nShaderTechnique(-1)
|
|
, m_pCurTechnique(NULL)
|
|
, m_pREPostProcess(NULL)
|
|
, m_CurDownscaleFactor(Vec2(1.0f, 1.0f))
|
|
, m_IndexStreamOffset(~0)
|
|
, m_IndexStreamType(Index16)
|
|
, m_ObjectsPool(NULL)
|
|
{}
|
|
|
|
~SRenderPipeline()
|
|
{
|
|
#if !defined(NULL_RENDERER)
|
|
for (unsigned int i = 0, n = m_CustomVD.Num(); i < n; i++)
|
|
{
|
|
delete m_CustomVD[i];
|
|
}
|
|
#endif
|
|
}
|
|
|
|
_inline SShaderTechnique* GetStartTechnique() const
|
|
{
|
|
if (m_pShader)
|
|
{
|
|
return m_pShader->mfGetStartTechnique(m_nShaderTechnique);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static const uint32 sNumObjectsInPool = 1024;
|
|
|
|
void GetMemoryUsage(ICrySizer* pSizer) const
|
|
{
|
|
// don't add the following as these are intermediate members (might be NULL) and already accounted for
|
|
//pSizer->AddObject( m_pCurPass );
|
|
//pSizer->AddObject( m_pCurTechnique );
|
|
//pSizer->AddObject( m_pRootTechnique );
|
|
|
|
pSizer->AddObject(m_pSunLight);
|
|
pSizer->AddObject(m_sExcludeShader);
|
|
pSizer->AddObject(m_Profile);
|
|
|
|
pSizer->AddObject(m_SysArray, m_SizeSysArray);
|
|
for (uint32 i = 0; i < RT_COMMAND_BUF_COUNT; ++i)
|
|
{
|
|
pSizer->AddObject(m_TempObjects[i]);
|
|
for (uint32 j = 0; j < MAX_RECURSION_LEVELS; ++j)
|
|
{
|
|
pSizer->AddObject(m_DLights[i][j]);
|
|
}
|
|
pSizer->AddObject(m_SysVertexPool[i]);
|
|
pSizer->AddObject(m_SysIndexPool[i]);
|
|
pSizer->AddObject(m_fogVolumeContibutionsData[i]);
|
|
}
|
|
pSizer->AddObject(m_RIs);
|
|
pSizer->AddObject(m_RTStats);
|
|
}
|
|
|
|
void SetRenderElement(IRenderElement* renderElement)
|
|
{
|
|
m_pRE = renderElement;
|
|
}
|
|
};
|
|
|
|
extern CryCriticalSection m_sREResLock;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// sort opeartors for render items
|
|
struct SCompareItemPreprocess
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
if (a.nBatchFlags != b.nBatchFlags)
|
|
{
|
|
return a.nBatchFlags < b.nBatchFlags;
|
|
}
|
|
|
|
return a.SortVal < b.SortVal;
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareRendItem
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
/// Nearest objects should be rendered first
|
|
int nNearA = (a.ObjSort & FOB_HAS_PREVMATRIX);
|
|
int nNearB = (b.ObjSort & FOB_HAS_PREVMATRIX);
|
|
if (nNearA != nNearB) // Sort by nearest flag
|
|
{
|
|
return nNearA > nNearB;
|
|
}
|
|
|
|
if (a.SortVal != b.SortVal) // Sort by shaders
|
|
{
|
|
return a.SortVal < b.SortVal;
|
|
}
|
|
|
|
if (a.nTextureID != b.nTextureID)
|
|
{
|
|
return a.nTextureID < b.nTextureID; // Sort by object custom texture (usually terrain sector texture)
|
|
}
|
|
|
|
if (a.pElem != b.pElem) // Sort by geometry
|
|
{
|
|
return a.pElem < b.pElem;
|
|
}
|
|
|
|
return (a.ObjSort & 0xFFFF) < (b.ObjSort & 0xFFFF); // Sort by distance
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareRendItemZPass
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
const int layerSize = 50; // Note: ObjSort contains round(entityDist * 2) for meshes
|
|
|
|
// Sort by nearest flag
|
|
int nNearA = (a.ObjSort & FOB_HAS_PREVMATRIX);
|
|
int nNearB = (b.ObjSort & FOB_HAS_PREVMATRIX);
|
|
if (nNearA != nNearB)
|
|
{
|
|
return nNearA > nNearB;
|
|
}
|
|
|
|
if (a.SortVal != b.SortVal) // Sort by shaders
|
|
{
|
|
return a.SortVal < b.SortVal;
|
|
}
|
|
|
|
// Sort by depth/distance layers
|
|
int depthLayerA = (a.ObjSort & 0xFFFF) / layerSize;
|
|
int depthLayerB = (b.ObjSort & 0xFFFF) / layerSize;
|
|
if (depthLayerA != depthLayerB)
|
|
{
|
|
return depthLayerA < depthLayerB;
|
|
}
|
|
|
|
if (a.nStencRef != b.nStencRef)
|
|
{
|
|
return a.nStencRef < b.nStencRef;
|
|
}
|
|
if (a.nTextureID != b.nTextureID)
|
|
{
|
|
return a.nTextureID < b.nTextureID; // Sort by object custom texture (usually terrain sector texture)
|
|
}
|
|
|
|
// Sorting by geometry less important than sorting by shaders
|
|
//if (a.Item != b.Item) // Sort by geometry
|
|
// return a.Item < b.Item;
|
|
|
|
return (a.ObjSort & 0xFFFF) < (b.ObjSort & 0xFFFF); // Sort by distance
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareItem_Decal
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
uint32 objSortA_Low(a.ObjSort & 0xFFFF);
|
|
uint32 objSortA_High(a.ObjSort & ~0xFFFF);
|
|
uint32 objSortB_Low(b.ObjSort & 0xFFFF);
|
|
uint32 objSortB_High(b.ObjSort & ~0xFFFF);
|
|
|
|
if (objSortA_Low != objSortB_Low)
|
|
{
|
|
return objSortA_Low < objSortB_Low;
|
|
}
|
|
|
|
if (a.SortVal != b.SortVal)
|
|
{
|
|
return a.SortVal < b.SortVal;
|
|
}
|
|
|
|
return objSortA_High < objSortB_High;
|
|
}
|
|
};
|
|
|
|
struct SCompareItem_Terrain
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
IRenderElement* pREa = a.pElem;
|
|
IRenderElement* pREb = b.pElem;
|
|
|
|
if (pREa->GetCustomTexBind(0) != pREb->GetCustomTexBind(0))
|
|
{
|
|
return pREa->GetCustomTexBind(0) < pREb->GetCustomTexBind(0);
|
|
}
|
|
|
|
return a.ObjSort < b.ObjSort;
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareItem_TerrainLayers
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
//if (a.ObjSort != b.ObjSort)
|
|
// return a.ObjSort < b.ObjSort;
|
|
|
|
float pSurfTypeA = ((float*)a.pElem->GetCustomData())[8];
|
|
float pSurfTypeB = ((float*)b.pElem->GetCustomData())[8];
|
|
if (pSurfTypeA != pSurfTypeB)
|
|
{
|
|
return (pSurfTypeA < pSurfTypeB);
|
|
}
|
|
|
|
pSurfTypeA = ((float*)a.pElem->GetCustomData())[9];
|
|
pSurfTypeB = ((float*)b.pElem->GetCustomData())[9];
|
|
if (pSurfTypeA != pSurfTypeB)
|
|
{
|
|
return (pSurfTypeA < pSurfTypeB);
|
|
}
|
|
|
|
pSurfTypeA = ((float*)a.pElem->GetCustomData())[11];
|
|
pSurfTypeB = ((float*)b.pElem->GetCustomData())[11];
|
|
return (pSurfTypeA < pSurfTypeB);
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareDist
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
if (fcmp(a.fDist, b.fDist))
|
|
{
|
|
return a.rendItemSorter.ParticleCounter() < b.rendItemSorter.ParticleCounter();
|
|
}
|
|
|
|
return (a.fDist > b.fDist);
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareDistInverted
|
|
{
|
|
bool operator()(const SRendItem& a, const SRendItem& b) const
|
|
{
|
|
if (fcmp(a.fDist, b.fDist))
|
|
{
|
|
return a.rendItemSorter.ParticleCounter() > b.rendItemSorter.ParticleCounter();
|
|
}
|
|
|
|
return (a.fDist < b.fDist);
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareByRenderingPass
|
|
{
|
|
bool operator()(const SRendItem& rA, const SRendItem& rB) const
|
|
{
|
|
return rA.rendItemSorter.IsRecursivePass() < rB.rendItemSorter.IsRecursivePass();
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct SCompareByOnlyStableFlagsOctreeID
|
|
{
|
|
bool operator()(const SRendItem& rA, const SRendItem& rB) const
|
|
{
|
|
return rA.rendItemSorter < rB.rendItemSorter;
|
|
}
|
|
};
|