DragonNest/Common/EternityEngine/D3DDevice9/EtStateManager.h
2024-12-19 09:48:26 +08:00

358 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "Singleton.h"
//#define _CHECK_STATE_PERFORMANCE
struct SStateBlock
{
const static int MAX_SAMPLER_COUNT = 16;
struct RenderStateValue
{
D3DRENDERSTATETYPE State;
DWORD Value;
bool operator < ( RenderStateValue &rhs )
{
return State < rhs.State;
}
};
struct SamplerStateValue
{
D3DSAMPLERSTATETYPE State;
DWORD Value;
DWORD Sampler;
bool operator < ( SamplerStateValue &rhs )
{
return State < rhs.State;
}
};
RenderStateValue m_RenderStates[ MAX_SAMPLER_COUNT ];
SamplerStateValue m_SamplerStates[ MAX_SAMPLER_COUNT ];
int m_RenderCount;
int m_SamplerCount;
DWORD m_OldRenderValue[MAX_SAMPLER_COUNT];
DWORD m_OldSamplerValue[MAX_SAMPLER_COUNT];
SStateBlock()
{
Clear();
memset(m_RenderStates, 0, sizeof(m_RenderStates));
memset(m_SamplerStates, 0, sizeof(m_SamplerStates));
}
bool operator == (SStateBlock &rhs )
{
if(m_RenderCount != rhs.m_RenderCount || m_SamplerCount != rhs.m_SamplerCount ) return false;
for( int i = 0; i < m_RenderCount; i++) {
if( m_RenderStates[i].State != rhs.m_RenderStates[i].State )
return false;
if( m_RenderStates[i].Value != rhs.m_RenderStates[i].Value )
return false;
}
for( int i = 0; i < m_SamplerCount; i++) {
if( m_SamplerStates[i].State != rhs.m_SamplerStates[i].State )
return false;
if( m_SamplerStates[i].Value != rhs.m_SamplerStates[i].Value )
return false;
}
return true;
}
void Clear()
{
m_RenderCount = 0;
m_SamplerCount = 0;
for( int i = 0; i < MAX_SAMPLER_COUNT; i++) {
m_OldRenderValue[ i ] = 0;
m_OldSamplerValue[ i ] = 0;
}
}
void AddRenderState( D3DRENDERSTATETYPE State, DWORD Value)
{
int i;
for( i = 0; i < m_RenderCount; i++) {
if( m_RenderStates[ i ].State == State ) {
m_RenderStates[ i ].Value = Value;
break;
}
}
if( i == m_RenderCount ) {
assert( m_RenderCount < MAX_SAMPLER_COUNT );
if( m_RenderCount < MAX_SAMPLER_COUNT )
{
m_RenderStates[ m_RenderCount ].State = State;
m_RenderStates[ m_RenderCount ].Value = Value;
m_RenderCount++;
std::sort( m_RenderStates, m_RenderStates + m_RenderCount );
}
}
}
void AddSamplerState( D3DSAMPLERSTATETYPE State, DWORD Value, DWORD Sampler = 0 )
{
int i;
for( i = 0; i < m_SamplerCount; i++) {
if( m_SamplerStates[ i ].State == State ) {
m_SamplerStates[ i ].Value = Value;
break;
}
}
if( i == m_SamplerCount ) {
assert( m_SamplerCount < MAX_SAMPLER_COUNT );
if( m_SamplerCount < MAX_SAMPLER_COUNT )
{
m_SamplerStates[ m_SamplerCount ].State = State;
m_SamplerStates[ m_SamplerCount ].Value = Value;
m_SamplerStates[ m_SamplerCount ].Sampler = Sampler;
m_SamplerCount++;
std::sort( m_SamplerStates, m_SamplerStates + m_SamplerCount );
}
}
}
void SetState() const
{
for( int j = 0; j < m_RenderCount; j++) {
GetEtDevice()->GetRenderState( m_RenderStates[ j ].State, (DWORD*)&m_OldRenderValue[ j ] );
GetEtDevice()->SetRenderState( m_RenderStates[ j ].State, m_RenderStates[ j ].Value);
}
for( int j = 0; j < m_SamplerCount; j++) {
GetEtDevice()->GetSamplerState( m_SamplerStates[ j ].Sampler, m_SamplerStates[ j ].State, (DWORD*)&m_OldSamplerValue[ j ] );
GetEtDevice()->SetSamplerState( m_SamplerStates[ j ].Sampler, m_SamplerStates[ j ].State, m_SamplerStates[ j ].Value);
}
}
void RestoreState() const
{
for( int j = 0; j < m_RenderCount; j++) {
GetEtDevice()->SetRenderState( m_RenderStates[ j ].State, m_OldRenderValue[ j ]);
}
for( int j = 0; j < m_SamplerCount; j++) {
GetEtDevice()->SetSamplerState( m_SamplerStates[ j ].Sampler, m_SamplerStates[ j ].State, m_OldSamplerValue[ j ]);
}
}
};
struct CEtStateBlockManager : public ID3DXEffectStateManager, public CSingleton < CEtStateBlockManager >
{
public:
enum {
RS_MAX = D3DRS_BLENDOPALPHA + 1,
SS_MAX = D3DSAMP_DMAPOFFSET + 1,
TS_MAX = D3DTSS_CONSTANT + 1,
DIRTY_MAX = 32, // <20>ѹ<EFBFBD><D1B9><EFBFBD> DrawCall <20><> 32<33><32> <20>̻<EFBFBD><CCBB><EFBFBD> Setting <20><> <20>ȵɰŶ<C9B0> <20><><EFBFBD><EFBFBD><EFBFBD>ϴµ<CFB4> Ȥ<><C8A4> <20><><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD> <20><><EFBFBD>Ŀ<EFBFBD> <20>ø<EFBFBD><C3B8><EFBFBD>.
STAGE_MAX = 8,
};
private:
IDirect3DDevice9 *m_pD3DDevice;
enum {
RESET_MAGIC_NUMBER = 0xBAADCAFE // 0 <20>̳<EFBFBD> 0xFFFFFFFF <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
};
DWORD m_RenderState[ 4 ][ RS_MAX ];
DWORD m_SamplerState[ 4 ][ STAGE_MAX ][ SS_MAX ];
DWORD m_TextureStageState[ 4 ][ STAGE_MAX ][ TS_MAX ];
DWORD m_DirtyRenderState[ DIRTY_MAX ];
DWORD m_DirtySamplerState[ STAGE_MAX ][ DIRTY_MAX ];
DWORD m_DirtyTextureStageState[ STAGE_MAX ][ DIRTY_MAX ];
bool m_DirtyRenderFlag[ RS_MAX ];
bool m_DirtySamplerFlag[ STAGE_MAX ][ SS_MAX ];
bool m_DirtyTextureStageFlag[ STAGE_MAX ][ TS_MAX ];
int m_nDirtyRenderCount;
int m_DirtySamplerCount[ STAGE_MAX ];
int m_DirtyTextureStageCount[ STAGE_MAX ];
#if defined( _CHECK_STATE_PERFORMANCE )
int m_nStateTotal;
int m_nStateSkip;
#endif
LPDIRECT3DVERTEXSHADER9 m_currVertexShader;
LPDIRECT3DPIXELSHADER9 m_currPixelShader;
LPDIRECT3DBASETEXTURE9 m_currTexture[ STAGE_MAX ];
bool m_bEnable;
#if defined( _CHECK_STATE_PERFORMANCE )
int m_nShaderSkip;
int m_nShaderTotal;
int m_nTextureSkip;
int m_nTextureTotal;
#endif
std::vector< SStateBlock > m_stateBlocks;
public:
CEtStateBlockManager();
virtual ~CEtStateBlockManager();
void Initialize( CEtDevice *pDevice );
void Reset();
void SetDefaultState();
public:
void GetRenderStateDefered( D3DRENDERSTATETYPE State, DWORD *pdwValue );
void SetRenderStateDefered( D3DRENDERSTATETYPE State, DWORD dwValue );
void GetSamplerStateDefered( DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD *pdwValue );
void SetSamplerStateDefered( DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD Value );
void GetTextureStageStateDefered( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pdwValue);
void SetTextureStageStateDefered( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
void FlushDeferedStates();
void DebugDumpState();
bool IsEnable() { return m_bEnable; }
void SetEnable( bool bEnable ) { m_bEnable = bEnable; }
void Diff();
void Capture();
void Restore();
public:
STDMETHOD(QueryInterface)( REFIID iid, LPVOID *ppv) {
return S_OK;
}
STDMETHOD_(ULONG, AddRef)() {
return S_OK;
}
STDMETHOD_(ULONG, Release)() {
return S_OK;
}
STDMETHOD(SetTransform)( D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix) {
return m_pD3DDevice->SetTransform( State, pMatrix);
}
STDMETHOD(SetMaterial)( CONST D3DMATERIAL9 *pMaterial ) {
return m_pD3DDevice->SetMaterial( pMaterial );
}
STDMETHOD(SetLight)( DWORD Index, CONST D3DLIGHT9 *pLight ) {
return m_pD3DDevice->SetLight( Index, pLight);
}
STDMETHOD(LightEnable)( DWORD Index, BOOL Enable ) {
return m_pD3DDevice->LightEnable( Index, Enable);
}
// Use EtDevice
STDMETHOD(SetRenderState)( D3DRENDERSTATETYPE State, DWORD Value ) {
if( m_bEnable ) {
SetRenderStateDefered( State, Value);
return S_OK;
}
else {
return m_pD3DDevice->SetRenderState( State, Value);
}
}
STDMETHOD(SetTexture)( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture ) {
if( m_bEnable ) {
#if defined( _CHECK_STATE_PERFORMANCE )
m_nTextureTotal++;
#endif
//ASSERT( Stage < STAGE_MAX );
if( m_currTexture[ Stage ] != pTexture ) {
m_currTexture[ Stage ] = pTexture;
return m_pD3DDevice->SetTexture( Stage, pTexture );
}
else {
#if defined( _CHECK_STATE_PERFORMANCE )
m_nTextureSkip++;
#endif
return S_OK;
}
}
else {
return m_pD3DDevice->SetTexture( Stage, pTexture);
}
}
// Use EtDevice
STDMETHOD(SetTextureStageState)( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value ) {
if( m_bEnable ) {
SetTextureStageStateDefered( Stage, Type, Value);
return S_OK;
}
else {
return m_pD3DDevice->SetTextureStageState( Stage, Type, Value);
}
}
// Use EtDevice
STDMETHOD(SetSamplerState)( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value ) {
if( m_bEnable ) {
SetSamplerStateDefered( Sampler, Type, Value);
return S_OK;
}
else {
return m_pD3DDevice->SetSamplerState( Sampler, Type, Value);
}
}
STDMETHOD(SetNPatchMode)( FLOAT NumSegments ) {
return m_pD3DDevice->SetNPatchMode( NumSegments );
}
STDMETHOD(SetFVF)( DWORD FVF ) {
return m_pD3DDevice->SetFVF( FVF );
}
STDMETHOD(SetVertexShader)( LPDIRECT3DVERTEXSHADER9 pShader ) {
if( m_bEnable ) {
#if defined( _CHECK_STATE_PERFORMANCE )
m_nShaderTotal++;
#endif
if( m_currVertexShader != pShader ) {
m_currVertexShader = pShader;
return m_pD3DDevice->SetVertexShader( pShader );
}
else {
#if defined( _CHECK_STATE_PERFORMANCE )
m_nShaderSkip++;
#endif
return S_OK;
}
}
else {
return m_pD3DDevice->SetVertexShader( pShader );
}
}
STDMETHOD(SetVertexShaderConstantF)( UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount ) {
return m_pD3DDevice->SetVertexShaderConstantF( RegisterIndex, pConstantData, RegisterCount);
}
STDMETHOD(SetVertexShaderConstantI)( UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount ) {
return m_pD3DDevice->SetVertexShaderConstantI( RegisterIndex, pConstantData, RegisterCount);
}
STDMETHOD(SetVertexShaderConstantB)( UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount ) {
return m_pD3DDevice->SetVertexShaderConstantB( RegisterIndex, pConstantData, RegisterCount);
}
STDMETHOD(SetPixelShader)( LPDIRECT3DPIXELSHADER9 pShader ) {
if( m_bEnable ) {
#if defined( _CHECK_STATE_PERFORMANCE )
m_nShaderTotal++;
#endif
if( m_currPixelShader != pShader ) {
m_currPixelShader = pShader;
return m_pD3DDevice->SetPixelShader( pShader );
}
else {
#if defined( _CHECK_STATE_PERFORMANCE )
m_nShaderSkip++;
#endif
return S_OK;
}
}
else {
return m_pD3DDevice->SetPixelShader( pShader);
}
}
STDMETHOD(SetPixelShaderConstantF)( UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount ) {
return m_pD3DDevice->SetPixelShaderConstantF( RegisterIndex, pConstantData, RegisterCount);
}
STDMETHOD(SetPixelShaderConstantI)( UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount ) {
return m_pD3DDevice->SetPixelShaderConstantI( RegisterIndex, pConstantData, RegisterCount);
}
STDMETHOD(SetPixelShaderConstantB)( UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount ) {
return m_pD3DDevice->SetPixelShaderConstantB( RegisterIndex, pConstantData, RegisterCount);
}
// StateBlock
int CreateStateBlock( SStateBlock *StateBlock );
SStateBlock* GetStateBlock( int index ) { return &m_stateBlocks[index]; }
};
extern CEtStateBlockManager s_EtStateManager;
CEtStateBlockManager* GetEtStateManager();