Files
Leviathan/Client/Game/engine/Renderer/KStateManager.h
T
2026-06-01 12:46:52 +02:00

1704 lines
59 KiB
C++

/*! \brief
Bitset based Render State Manager
\author
Sung-jin Park [Orcinus]
\remark
예 - KStateManager::GetInstance<4>(); // 4는 Texture Stage 갯수
순서 - SetPass( # ); => m_pEffect->BeginPass( # ); => PushCurrentStateToDevice();
*/
#pragma once
#include <d3d9.h>
#include <d3dx9.h>
//#include <vector>
#include <map>
#include <algorithm>
#include <toolkit/c_bits.h>
//#define STATEMANAGER_TEST // Test Mode Enable
//#ifdef STATEMANAGER_TEST
#include <dump/XException.h>
//#endif
namespace StateManager
{
enum STATE_DEF { RS_MAX = 210 //< Render State Key 값의 Max 수치
,RS_CNT = 96 //< Render State Count. Tessellation 관련 State는 포함하지 않음. 포함한다면 103개
,SS_MAX = 14 //< Sampler State Key 값의 Max 수치
,SS_CNT = 13 //< Sampler State Count.
,TS_MAX = 33 //< Texture Stage State Key 값의 Max 수치
,TS_CNT = 18 //< Texture Stage State Count.
,MAX_TEXTURESTAGE = D3DDP_MAXTEXCOORD //< Max Texture Stage 개수
};
#ifdef STATEMANAGER_TEST
static bool g_OuputPushString = true;
#endif
struct ST_RenderState{};
struct ST_SamplerState{};
struct ST_TextureState{};
//--------------------------------------------------------------------------------------
// Render State Holder : RenderState, SamplerState, TextureStageState 별로 고유 데이터
//--------------------------------------------------------------------------------------
template< typename RsType >
struct _RsHolder;
template<>
struct _RsHolder< ST_RenderState >
{
static void init(); // 필수 호출 필요
static DWORD DefaultState[1][RS_MAX];
static DWORD StateIndexTable[RS_MAX];
static DWORD IndexStateTable[RS_CNT];
//! 변화된 RenderState를 Setting 하는 함수 객체
struct SetStateFN
{
SetStateFN() { m_pDevice = NULL; m_pData = NULL; m_page = 0; }
SetStateFN( IDirect3DDevice9* pDevice, DWORD* pData, bool page, DWORD stage )
{ m_pDevice = pDevice; m_pData = pData; m_page = page; }
void operator() ( int index )
{
// 이전 State 와 현재 State가 다를때만 세팅함
if( *(m_pData+(m_page*RS_MAX)+IndexStateTable[index]) != *(m_pData+((!m_page)*RS_MAX)+IndexStateTable[index]) )
{
#ifdef STATEMANAGER_TEST
if( g_OuputPushString )
{
_oprint( "SetRenderState - state_type:%u, value:%u, curpage:%u \n"
, IndexStateTable[index], *(m_pData+(m_page*RS_MAX)+IndexStateTable[index]), (DWORD)m_page );
}
#else
m_pDevice->SetRenderState( (D3DRENDERSTATETYPE)IndexStateTable[index], *(m_pData+(m_page*RS_MAX)+IndexStateTable[index]) );
#endif
}
}
IDirect3DDevice9* m_pDevice;
DWORD* m_pData;
bool m_page;
};
//! 두번째 이후 Pass에 대한 함수 객체. 이전 State Data에 변화된 값을 저장한다.
struct SetStateMultiPassFN
{
SetStateMultiPassFN() { m_pDevice = NULL; m_pData = NULL; m_page = 0; }
SetStateMultiPassFN( IDirect3DDevice9* pDevice, DWORD* pData, bool page, DWORD stage )
{ m_pDevice = pDevice; m_pData = pData; m_page = page; }
void operator() ( int index )
{
// 이전 State 와 현재 State가 다를때만 세팅함
if( *(m_pData+(m_page*RS_MAX)+IndexStateTable[index]) != *(m_pData+((!m_page)*RS_MAX)+IndexStateTable[index]) )
{
#ifdef STATEMANAGER_TEST
if( g_OuputPushString )
{
_oprint( "SetRenderState - state_type:%u, value:%u, curpage:%u \n"
, IndexStateTable[index], *(m_pData+(m_page*RS_MAX)+IndexStateTable[index]), (DWORD)m_page );
}
#else
m_pDevice->SetRenderState( (D3DRENDERSTATETYPE)IndexStateTable[index], *(m_pData+(m_page*RS_MAX)+IndexStateTable[index]) );
#endif
// Prev State Data에 바뀐 State를 세팅한다.
*(m_pData+((!m_page)*RS_MAX)+IndexStateTable[index]) = (*(m_pData+(m_page*RS_MAX)+IndexStateTable[index]));
}
}
IDirect3DDevice9* m_pDevice;
DWORD* m_pData;
bool m_page;
};
};
template<>
struct _RsHolder< ST_SamplerState >
{
static void init();
static DWORD DefaultState[MAX_TEXTURESTAGE][SS_MAX]; // Sampler State 는 Stage와 상관없어 항상 Default가 같지만, 통일성을위해
static DWORD StateIndexTable[SS_MAX];
static DWORD IndexStateTable[SS_CNT];
//! 변화된 RenderState를 Setting 하는 함수 객체
struct SetStateFN
{
SetStateFN() { m_pDevice = NULL; m_pData = NULL; m_page = 0; }
SetStateFN( IDirect3DDevice9* pDevice, DWORD* pData, bool page, DWORD stage )
{ m_pDevice = pDevice; m_pData = pData; m_page = page; m_stage = stage;}
void operator() ( int index )
{
// 이전 State 와 현재 State가 다를때만 세팅함
if( *(m_pData+(m_page*SS_MAX)+IndexStateTable[index]) != *(m_pData+((!m_page)*SS_MAX)+IndexStateTable[index]) )
{
#ifdef STATEMANAGER_TEST
if( g_OuputPushString )
{
_oprint( "SetSamplerState - stage:%u, state_type:%u, value:%u, curpage:%u \n"
, m_stage, IndexStateTable[index], *(m_pData+(m_page*SS_MAX)+IndexStateTable[index]), (DWORD)m_page );
}
#else
m_pDevice->SetSamplerState( m_stage, (D3DSAMPLERSTATETYPE)IndexStateTable[index], *(m_pData+(m_page*SS_MAX)+IndexStateTable[index]) );
#endif
}
}
IDirect3DDevice9* m_pDevice;
DWORD* m_pData;
bool m_page;
DWORD m_stage;
};
struct SetStateMultiPassFN
{
SetStateMultiPassFN() { m_pDevice = NULL; m_pData = NULL; m_page = 0; }
SetStateMultiPassFN( IDirect3DDevice9* pDevice, DWORD* pData, bool page, DWORD stage )
{ m_pDevice = pDevice; m_pData = pData; m_page = page; m_stage = stage;}
void operator() ( int index )
{
// 이전 State 와 현재 State가 다를때만 세팅함
if( *(m_pData+(m_page*SS_MAX)+IndexStateTable[index]) != *(m_pData+((!m_page)*SS_MAX)+IndexStateTable[index]) )
{
#ifdef STATEMANAGER_TEST
if( g_OuputPushString )
{
_oprint( "SetSamplerState - stage:%u, state_type:%u, value:%u, curpage:%u \n"
, m_stage, IndexStateTable[index], *(m_pData+(m_page*SS_MAX)+IndexStateTable[index]), (DWORD)m_page );
}
#else
m_pDevice->SetSamplerState( m_stage, (D3DSAMPLERSTATETYPE)IndexStateTable[index], *(m_pData+(m_page*SS_MAX)+IndexStateTable[index]) );
#endif
// Prev State Data에 바뀐 State를 세팅한다.
*(m_pData+((!m_page)*SS_MAX)+IndexStateTable[index]) = (*(m_pData+(m_page*SS_MAX)+IndexStateTable[index]));
}
}
IDirect3DDevice9* m_pDevice;
DWORD* m_pData;
bool m_page;
DWORD m_stage;
};
};
template<>
struct _RsHolder< ST_TextureState >
{
static void init();
static DWORD DefaultState[MAX_TEXTURESTAGE][TS_MAX]; // Texture State는 Stage에 따라 다른 State가 있기 때문에 이중 배열
static DWORD StateIndexTable[TS_MAX];
static DWORD IndexStateTable[TS_CNT];
//! 변화된 RenderState를 Setting 하는 함수 객체
struct SetStateFN
{
SetStateFN() { m_pDevice = NULL; m_pData = NULL; m_page = 0; }
SetStateFN( IDirect3DDevice9* pDevice, DWORD* pData, bool page, DWORD stage )
{ m_pDevice = pDevice; m_pData = pData; m_page = page; m_stage = stage;}
void operator() ( int index )
{
// 이전 State 와 현재 State가 다를때만 세팅함
if( *(m_pData+(m_page*TS_MAX)+IndexStateTable[index]) != *(m_pData+((!m_page)*TS_MAX)+IndexStateTable[index]) )
{
#ifdef STATEMANAGER_TEST
if( g_OuputPushString )
{
_oprint( "SetTextureStageState - stage:%u, state_type:%u, value:%u, curpage:%u \n"
, m_stage, IndexStateTable[index], *(m_pData+(m_page*TS_MAX)+IndexStateTable[index]), (DWORD)m_page );
}
#else
m_pDevice->SetTextureStageState( m_stage, (D3DTEXTURESTAGESTATETYPE)IndexStateTable[index], *(m_pData+(m_page*TS_MAX)+IndexStateTable[index]) );
#endif
}
}
IDirect3DDevice9* m_pDevice;
DWORD* m_pData;
bool m_page;
DWORD m_stage;
};
struct SetStateMultiPassFN
{
SetStateMultiPassFN() { m_pDevice = NULL; m_pData = NULL; m_page = 0; }
SetStateMultiPassFN( IDirect3DDevice9* pDevice, DWORD* pData, bool page, DWORD stage )
{ m_pDevice = pDevice; m_pData = pData; m_page = page; m_stage = stage;}
void operator() ( int index )
{
// 이전 State 와 현재 State가 다를때만 세팅함
if( *(m_pData+(m_page*TS_MAX)+IndexStateTable[index]) != *(m_pData+((!m_page)*TS_MAX)+IndexStateTable[index]) )
{
#ifdef STATEMANAGER_TEST
if( g_OuputPushString )
{
_oprint( "SetTextureStageState - stage:%u, state_type:%u, value:%u, curpage:%u \n"
, m_stage, IndexStateTable[index], *(m_pData+(m_page*TS_MAX)+IndexStateTable[index]), (DWORD)m_page );
}
#else
m_pDevice->SetTextureStageState( m_stage, (D3DTEXTURESTAGESTATETYPE)IndexStateTable[index], *(m_pData+(m_page*TS_MAX)+IndexStateTable[index]) );
#endif
// Prev State Data에 바뀐 State를 세팅한다.
*(m_pData+((!m_page)*TS_MAX)+IndexStateTable[index]) = (*(m_pData+(m_page*TS_MAX)+IndexStateTable[index]));
}
}
IDirect3DDevice9* m_pDevice;
DWORD* m_pData;
bool m_page;
DWORD m_stage;
};
};
//--------------------------------------------------------------------------------------
// cache D3DRENDERSTATE
//--------------------------------------------------------------------------------------
template < typename _Kty, typename _RsHolder, int _State_Max = RS_MAX, int _State_Cnt = RS_CNT >
class KRenderStateCache
{
public:
typedef _RsHolder StateTable;
typedef typename StateTable::SetStateFN SetStateFN;
typedef typename StateTable::SetStateMultiPassFN SetStateMultiPassFN;
public:
// 2개의 Page를 Swap 하며, State 기록을 한다.
c_bits<_State_Cnt> changeidx[2];
DWORD data[2][_State_Max];
bool current_page;
DWORD current_stage;
public:
inline void init( DWORD stage = 0 )
{
current_page = 0;
current_stage = stage;
memcpy( data[0], StateTable::DefaultState[stage], sizeof(data[0]) );
memcpy( data[1], StateTable::DefaultState[stage], sizeof(data[1]) );
changeidx[0].reset();
changeidx[1].reset();
}
// compare_prev -> 이전 설정값과 비교한다.
inline void set_val( _Kty key, DWORD value, bool compare_prev = false )
{
if( compare_prev && data[!current_page][key] != value ) // 이전 설정값과 비교
changeidx[current_page].set( StateTable::StateIndexTable[key] );
else if( StateTable::DefaultState[current_stage][key] != value ) // Default 와 비교
changeidx[current_page].set( StateTable::StateIndexTable[key] );
else
changeidx[current_page].reset( StateTable::StateIndexTable[key] );
data[current_page][key] = value;
}
inline DWORD get_val( _Kty key )
{
// 값이 변화된경우 Data에서, 아닐경우 Default에서
if( changeidx[current_page].test( StateTable::StateIndexTable[key] ) )
return data[current_page][key];
else
return StateTable::DefaultState[current_stage][key];
}
inline void commit( IDirect3DDevice9* pDevice, DWORD pass = 0 )
{
if( pass == 0 )
{
c_bits<_State_Cnt> ch_set( changeidx[0], changeidx[1] ); // OR is Default Constructor
// Set RenderStates
if( ch_set.any() )
ch_set.for_each_on( SetStateFN( pDevice, *data, current_page, current_stage ) );
}
else
{
// for multi pass
if( changeidx[current_page].any() )
{
changeidx[current_page].for_each_on( SetStateMultiPassFN( pDevice, *data, current_page, current_stage ) );
}
// SetStateMultiPassFN에 의해 이전 Data에 현제 세팅이 저장되어 이것을 Current에 복구시킨다.
memcpy( data[current_page], data[!current_page], sizeof(data[current_page]) );
// 이전 State Change Set을 포함하여 현제 세팅에 저장한다.
changeidx[current_page] |= changeidx[!current_page];
}
// Swap
current_page = (!current_page);
// clear index set
changeidx[current_page].reset();
// clear data
memcpy( data[current_page], StateTable::DefaultState[current_stage], sizeof(data[current_page]) );
}
};
//-------------------------------------------------------------------------------------------------------------
// State Block
//-------------------------------------------------------------------------------------------------------------
struct KRenderStateElement
{
KRenderStateElement( DWORD _type, DWORD _value ) : statetype( _type ), value( _value ) {}
DWORD statetype;
DWORD value;
};
struct KStageStateElement
{
KStageStateElement( DWORD _stage, DWORD _type, DWORD _value ) : stage( _stage ),statetype( _type ), value( _value ) {}
DWORD stage;
DWORD statetype;
DWORD value;
};
struct KStateBlock
{
std::vector<KRenderStateElement> vRenderStateBlock;
std::vector<KStageStateElement> vSamplerStateBlock;
std::vector<KStageStateElement> vTextureStateBlock;
};
struct _RenderStateCompareFN
{
_RenderStateCompareFN( DWORD _state ) { state = _state; }
bool operator() ( const KRenderStateElement& p1 )
{
if( p1.statetype == state )
return true;
else
return false;
}
DWORD state;
};
struct _StageStateCompareFN
{
_StageStateCompareFN( DWORD _stage, DWORD _state ) { stage = _stage; state = _state; }
bool operator() ( const KStageStateElement& p1 )
{
if( (p1.stage == stage) && (p1.statetype == state) )
return true;
else
return false;
}
DWORD stage;
DWORD state;
};
//-------------------------------------------------------------------------------------------------------------
// StateManager Interface
//-------------------------------------------------------------------------------------------------------------
template< int > class KStateManagerImpl;
class KStateManager : public ID3DXEffectStateManager
{
public:
KStateManager( LPDIRECT3DDEVICE9 pDevice ) : m_lRef(1L), m_pDevice(pDevice)
{
// Increment the reference count on the device, because a pointer to it has been copied for later use
#ifndef STATEMANAGER_TEST
m_pDevice->AddRef();
#endif
}
virtual ~KStateManager()
{
#ifndef STATEMANAGER_TEST
m_pDevice->Release();
#endif
}
template< int NSTAGE >
static KStateManager* Create( LPDIRECT3DDEVICE9 pDevice )
{
KStateManager* pStateManager = NULL;
pStateManager = new KStateManagerImpl<NSTAGE>( pDevice );
if( NULL == pStateManager )
{
assert( pStateManager );
return NULL;
}
return pStateManager;
}
virtual void ManagedSetRenderState( D3DRENDERSTATETYPE state, DWORD value ) = 0;
virtual void ManagedSetTextureStageState( DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value ) = 0;
virtual void ManagedSetSamplerState( DWORD stage, D3DSAMPLERSTATETYPE, DWORD value ) = 0;
virtual void ManagedSetStateBlock( DWORD key ) = 0;
virtual void PushCurrentStateToDevice() = 0;
virtual void RestoreDefault() = 0;
//! StateBlock Create. State Value가 Default 와 다를 경우만 세팅 합니다.
virtual void BeginStateBlock() = 0;
virtual void EndStateBlock( DWORD key ) = 0;
virtual bool BeginPass( LPD3DXEFFECT effect, DWORD pass ) = 0;
virtual bool EndPass( LPD3DXEFFECT effect ) = 0;
virtual void PresentCurrentRenderState( bool bShow ) = 0;
virtual void PresentCurrentSamplerState( bool bShow ) = 0;
virtual void PresentCurrentTextureState( bool bShow ) = 0;
#ifdef STATEMANAGER_TEST
virtual void TestRenderState() = 0;
virtual void TestSamplerState() = 0;
virtual void TestTextureState() = 0;
virtual void TestStateBlock() = 0;
virtual void TestMultiPass() = 0;
virtual void TestRestoreDefault() = 0;
virtual void TestPresent() = 0;
virtual void TestPerformance( DWORD count ) = 0;
virtual void TestForClearStateBlock() = 0;
#endif
protected:
LONG m_lRef;
LPDIRECT3DDEVICE9 m_pDevice;
public:
// methods inherited from ID3DXEffectStateManager
STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv)
{
if (iid == IID_IUnknown || iid == IID_ID3DXEffectStateManager)
{
*ppv = static_cast<ID3DXEffectStateManager*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(this)->AddRef();
return S_OK;
}
STDMETHOD_(ULONG, AddRef)(THIS)
{
return (ULONG)InterlockedIncrement( &m_lRef );
}
STDMETHOD_(ULONG, Release)(THIS)
{
if( 0L == InterlockedDecrement( &m_lRef ) )
{
delete this;
return 0L;
}
return m_lRef;
}
STDMETHOD(SetTexture)(THIS_ DWORD dwStage, LPDIRECT3DBASETEXTURE9 pTexture )
{
return m_pDevice->SetTexture( dwStage, pTexture );
}
STDMETHOD(SetVertexShader)(THIS_ LPDIRECT3DVERTEXSHADER9 pShader )
{
return m_pDevice->SetVertexShader( pShader );
}
STDMETHOD(SetPixelShader)(THIS_ LPDIRECT3DPIXELSHADER9 pShader )
{
return m_pDevice->SetPixelShader( pShader );
}
STDMETHOD(SetFVF)(THIS_ DWORD dwFVF )
{
return m_pDevice->SetFVF( dwFVF );
}
STDMETHOD(SetTransform)(THIS_ D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix )
{
return m_pDevice->SetTransform( State, pMatrix );
}
STDMETHOD(SetMaterial)(THIS_ CONST D3DMATERIAL9 *pMaterial )
{
return m_pDevice->SetMaterial( pMaterial );
}
STDMETHOD(SetLight)(THIS_ DWORD Index, CONST D3DLIGHT9 *pLight )
{
return m_pDevice->SetLight( Index, pLight );
}
STDMETHOD(LightEnable)(THIS_ DWORD Index, BOOL Enable )
{
return m_pDevice->LightEnable( Index, Enable );
}
STDMETHOD(SetNPatchMode)(THIS_ FLOAT NumSegments )
{
return m_pDevice->SetNPatchMode( NumSegments );
}
STDMETHOD(SetVertexShaderConstantF)(THIS_ UINT RegisterIndex,
CONST FLOAT *pConstantData,
UINT RegisterCount )
{
return m_pDevice->SetVertexShaderConstantF( RegisterIndex,
pConstantData,
RegisterCount );
}
STDMETHOD(SetVertexShaderConstantI)(THIS_ UINT RegisterIndex,
CONST INT *pConstantData,
UINT RegisterCount )
{
return m_pDevice->SetVertexShaderConstantI( RegisterIndex,
pConstantData,
RegisterCount );
}
STDMETHOD(SetVertexShaderConstantB)(THIS_ UINT RegisterIndex,
CONST BOOL *pConstantData,
UINT RegisterCount )
{
return m_pDevice->SetVertexShaderConstantB( RegisterIndex,
pConstantData,
RegisterCount );
}
STDMETHOD(SetPixelShaderConstantF)(THIS_ UINT RegisterIndex,
CONST FLOAT *pConstantData,
UINT RegisterCount )
{
return m_pDevice->SetPixelShaderConstantF( RegisterIndex,
pConstantData,
RegisterCount );
}
STDMETHOD(SetPixelShaderConstantI)(THIS_ UINT RegisterIndex,
CONST INT *pConstantData,
UINT RegisterCount )
{
return m_pDevice->SetPixelShaderConstantI( RegisterIndex,
pConstantData,
RegisterCount );
}
STDMETHOD(SetPixelShaderConstantB)(THIS_ UINT RegisterIndex,
CONST BOOL *pConstantData,
UINT RegisterCount )
{
return m_pDevice->SetPixelShaderConstantB( RegisterIndex,
pConstantData,
RegisterCount );
}
};
//-------------------------------------------------------------------------------------------------------------
// StateManager Implement
//-------------------------------------------------------------------------------------------------------------
template< int NSTAGE >
class KStateManagerImpl : public KStateManager
{
public:
KStateManagerImpl( LPDIRECT3DDEVICE9 pDevice );
virtual ~KStateManagerImpl();
protected:
void ClearStateBlock();
public:
virtual void ManagedSetRenderState( D3DRENDERSTATETYPE state, DWORD value );
virtual void ManagedSetTextureStageState( DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value );
virtual void ManagedSetSamplerState( DWORD stage, D3DSAMPLERSTATETYPE, DWORD value );
virtual void ManagedSetStateBlock( DWORD key );
virtual void PushCurrentStateToDevice();
virtual void RestoreDefault();
virtual void BeginStateBlock();
virtual void EndStateBlock( DWORD key );
virtual bool BeginPass( LPD3DXEFFECT effect, DWORD pass );
virtual bool EndPass( LPD3DXEFFECT effect );
virtual void PresentCurrentRenderState( bool bShow );
virtual void PresentCurrentSamplerState( bool bShow );
virtual void PresentCurrentTextureState( bool bShow );
#ifdef STATEMANAGER_TEST
virtual void TestRenderState();
virtual void TestSamplerState();
virtual void TestTextureState();
virtual void TestStateBlock();
virtual void TestMultiPass();
virtual void TestRestoreDefault();
virtual void TestPresent();
virtual void TestPerformance( DWORD count );
virtual void TestForClearStateBlock() { ClearStateBlock(); }
virtual void TestForSetPass( DWORD pass ) { m_dwCurrentPass = pass; }
#endif
public:
// methods inherited from ID3DXEffectStateManager
STDMETHOD(SetRenderState)(THIS_ D3DRENDERSTATETYPE d3dRenderState, DWORD dwValue )
{
ManagedSetRenderState( d3dRenderState, dwValue );
return D3D_OK;
}
STDMETHOD(SetSamplerState)(THIS_ DWORD dwStage, D3DSAMPLERSTATETYPE d3dSamplerState, DWORD dwValue )
{
ManagedSetSamplerState( dwStage, d3dSamplerState, dwValue );
return D3D_OK;
}
STDMETHOD(SetTextureStageState)(THIS_ DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTextureStageState, DWORD dwValue )
{
ManagedSetTextureStageState( dwStage, d3dTextureStageState, dwValue );
return D3D_OK;
}
protected:
KRenderStateCache<D3DRENDERSTATETYPE, _RsHolder<ST_RenderState>, RS_MAX, RS_CNT> m_RenderStateCache;
KRenderStateCache<D3DSAMPLERSTATETYPE, _RsHolder<ST_SamplerState>, SS_MAX, SS_CNT> m_SamplerStateCacheArry[NSTAGE];
KRenderStateCache<D3DTEXTURESTAGESTATETYPE, _RsHolder<ST_TextureState>, TS_MAX, TS_CNT> m_TextureStageStateCacheArray[NSTAGE];
std::map< DWORD, KStateBlock* > m_StateBlocks;
KStateBlock* m_pBlockBuffer;
DWORD m_dwCurrentPass;
};
template<int NSTAGE>
KStateManagerImpl<NSTAGE>::KStateManagerImpl( LPDIRECT3DDEVICE9 pDevice )
: KStateManager(pDevice), m_pBlockBuffer(0)
{
// 순서에 주의. RsHolder 먼저 초기화.
_RsHolder<ST_RenderState>::init();
_RsHolder<ST_SamplerState>::init();
_RsHolder<ST_TextureState>::init();
m_RenderStateCache.init();
for( int i = 0; i < NSTAGE; i++ )
{
m_TextureStageStateCacheArray[i].init( i );
m_SamplerStateCacheArry[i].init( i );
}
m_dwCurrentPass = 0;
}
template<int NSTAGE>
KStateManagerImpl<NSTAGE>::~KStateManagerImpl()
{
ClearStateBlock();
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::ClearStateBlock()
{
assert( !m_pBlockBuffer );
if( m_pBlockBuffer )
{
delete m_pBlockBuffer;
m_pBlockBuffer = NULL;
}
for( std::map<DWORD, KStateBlock*>::iterator it = m_StateBlocks.begin(); it != m_StateBlocks.end(); it++ )
{
KStateBlock* pBlock = (*it).second;
delete pBlock;
}
m_StateBlocks.clear();
m_dwCurrentPass = 0;
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::ManagedSetRenderState( D3DRENDERSTATETYPE state, DWORD value )
{
if( NULL != m_pBlockBuffer )
{
// Stroy : Default State가 들어오면, 스테이트 블럭에 포함시키지 않는다.
// 동일한 스테이트는 하나만 존재해야 하며, 중복해서 세팅된다면 마지막에 세팅된 값이 삽입된다. 디폴트면 제거 된다.
std::vector<KRenderStateElement>::iterator it = std::find_if( m_pBlockBuffer->vRenderStateBlock.begin(), m_pBlockBuffer->vRenderStateBlock.end(), _RenderStateCompareFN(state) );
if( it != m_pBlockBuffer->vRenderStateBlock.end() )
{
if( _RsHolder<ST_RenderState>::DefaultState[0][state] != value )
(*it ) = KRenderStateElement( state, value );
else
m_pBlockBuffer->vRenderStateBlock.erase( it );
}
else
{
if( _RsHolder<ST_RenderState>::DefaultState[0][state] != value )
m_pBlockBuffer->vRenderStateBlock.push_back( KRenderStateElement( state, value ) );
}
}
else
{
// 첫번째 패스가 아닐때, Prev State와 비교하여 세팅을 해준다.
m_RenderStateCache.set_val( state, value, m_dwCurrentPass > 0 );
}
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::ManagedSetSamplerState( DWORD stage, D3DSAMPLERSTATETYPE state, DWORD value )
{
assert( NSTAGE > stage );
if( NULL != m_pBlockBuffer )
{
// Stroy : Default State가 들어오면, 스테이트 블럭에 포함시키지 않는다.
// 동일한 스테이트는 하나만 존재해야 하며, 중복해서 세팅된다면 마지막에 세팅된 값이 삽입된다. 디폴트면 제거 된다.
std::vector<KStageStateElement>::iterator it = std::find_if( m_pBlockBuffer->vSamplerStateBlock.begin(), m_pBlockBuffer->vSamplerStateBlock.end(), _StageStateCompareFN(stage, state) );
if( it != m_pBlockBuffer->vSamplerStateBlock.end() )
{
if( _RsHolder<ST_SamplerState>::DefaultState[stage][state] != value )
(*it ) = KStageStateElement( stage, state, value );
else
m_pBlockBuffer->vSamplerStateBlock.erase( it );
}
else
{
if( _RsHolder<ST_SamplerState>::DefaultState[stage][state] != value )
m_pBlockBuffer->vSamplerStateBlock.push_back( KStageStateElement( stage, state, value ) );
}
}
else
m_SamplerStateCacheArry[stage].set_val( state, value, m_dwCurrentPass > 0 );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::ManagedSetTextureStageState( DWORD stage, D3DTEXTURESTAGESTATETYPE state, DWORD value )
{
assert( NSTAGE > stage );
if( NULL != m_pBlockBuffer )
{
// Stroy : Default State가 들어오면, 스테이트 블럭에 포함시키지 않는다.
// 동일한 스테이트는 하나만 존재해야 하며, 중복해서 세팅된다면 마지막에 세팅된 값이 삽입된다. 디폴트면 제거 된다.
std::vector<KStageStateElement>::iterator it = std::find_if( m_pBlockBuffer->vTextureStateBlock.begin(), m_pBlockBuffer->vTextureStateBlock.end(), _StageStateCompareFN(stage, state) );
if( it != m_pBlockBuffer->vTextureStateBlock.end() )
{
if( _RsHolder<ST_TextureState>::DefaultState[stage][state] != value )
(*it ) = KStageStateElement( stage, state, value );
else
m_pBlockBuffer->vTextureStateBlock.erase( it );
}
else
{
if( _RsHolder<ST_TextureState>::DefaultState[stage][state] != value )
m_pBlockBuffer->vTextureStateBlock.push_back( KStageStateElement( stage, state, value ) );
}
}
else
m_TextureStageStateCacheArray[stage].set_val( state, value, m_dwCurrentPass > 0 );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::ManagedSetStateBlock( DWORD key )
{
assert( !m_pBlockBuffer );
std::map<DWORD, KStateBlock*>::iterator it = m_StateBlocks.find( key );
if( it != m_StateBlocks.end() )
{
KStateBlock* pBlock = (*it).second;
std::vector<KRenderStateElement>::iterator it_re = pBlock->vRenderStateBlock.begin();
for( ; it_re != pBlock->vRenderStateBlock.end(); it_re++ )
{
ManagedSetRenderState( (D3DRENDERSTATETYPE)(*it_re).statetype, (*it_re).value );
}
std::vector<KStageStateElement>::iterator it_se = pBlock->vSamplerStateBlock.begin();
for( ; it_se != pBlock->vSamplerStateBlock.end(); it_se++ )
{
ManagedSetSamplerState( (*it_se).stage, (D3DSAMPLERSTATETYPE)(*it_se).statetype, (*it_se).value );
}
it_se = pBlock->vTextureStateBlock.begin();
for( ; it_se != pBlock->vTextureStateBlock.end(); it_se++ )
{
ManagedSetTextureStageState( (*it_se).stage, (D3DTEXTURESTAGESTATETYPE)(*it_se).statetype, (*it_se).value );
}
}
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::RestoreDefault()
{
// Set All State to Default
PushCurrentStateToDevice();
PushCurrentStateToDevice();
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::PushCurrentStateToDevice()
{
m_RenderStateCache.commit( m_pDevice, m_dwCurrentPass );
for( int i = 0; i < NSTAGE; i++ )
{
m_TextureStageStateCacheArray[i].commit( m_pDevice, m_dwCurrentPass );
m_SamplerStateCacheArry[i].commit( m_pDevice, m_dwCurrentPass );
}
// Current Pass Reset - BeginPass 에서 다시 세팅해줌
m_dwCurrentPass = 0;
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::BeginStateBlock()
{
assert( !m_pBlockBuffer );
if( NULL != m_pBlockBuffer )
delete m_pBlockBuffer;
m_pBlockBuffer = new KStateBlock;
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::EndStateBlock( DWORD key )
{
assert( m_pBlockBuffer );
if( NULL == m_pBlockBuffer )
return;
std::map< DWORD, KStateBlock* >::iterator it = m_StateBlocks.find( key );
if( it != m_StateBlocks.end() )
{
delete (*it).second;
(*it).second = NULL;
}
m_StateBlocks.insert( std::map< DWORD, KStateBlock* >::value_type(key, m_pBlockBuffer) );
m_pBlockBuffer = NULL;
}
template<int NSTAGE>
bool KStateManagerImpl<NSTAGE>::BeginPass( LPD3DXEFFECT effect, DWORD pass )
{
m_dwCurrentPass = pass;
#ifdef STATEMANAGER_TEST
HRESULT hr = D3D_OK;
#else STATEMANAGER_TEST
HRESULT hr = effect->BeginPass( pass );
#endif
PushCurrentStateToDevice();
assert( hr == D3D_OK );
return hr == D3D_OK;
}
template<int NSTAGE>
bool KStateManagerImpl<NSTAGE>::EndPass( LPD3DXEFFECT effect )
{
m_dwCurrentPass = 0;
#ifdef STATEMANAGER_TEST
HRESULT hr = D3D_OK;
#else
HRESULT hr = effect->EndPass();
#endif
assert( hr == D3D_OK );
return hr == D3D_OK;
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::PresentCurrentRenderState( bool bShow )
{
if( !bShow ) return;
_oprint( "=============== Start Present Changed Current [RenderState] =================\n" );
for( int i = 0; i < RS_CNT; i++ )
{
if( m_RenderStateCache.data[m_RenderStateCache.current_page][ _RsHolder<ST_RenderState>::IndexStateTable[i] ]
!= _RsHolder<ST_RenderState>::DefaultState[0][ _RsHolder<ST_RenderState>::IndexStateTable[i] ] )
{
_oprint( "RenderStateType : %u, Value : %u\n", _RsHolder<ST_RenderState>::IndexStateTable[i]
, m_RenderStateCache.data[m_RenderStateCache.current_page][ _RsHolder<ST_RenderState>::IndexStateTable[i] ] );
}
}
_oprint( "=============== End Present Changed Current [RenderState] =================\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::PresentCurrentSamplerState( bool bShow )
{
if( !bShow ) return;
_oprint( "=============== Start Present Changed Current [SamplerState] =================\n" );
for( int stage = 0; stage < NSTAGE; stage++ )
{
for( int i = 0; i < SS_CNT; i++ )
{
if( m_SamplerStateCacheArry[stage].data[m_SamplerStateCacheArry[stage].current_page][ _RsHolder<ST_SamplerState>::IndexStateTable[i] ]
!= _RsHolder<ST_SamplerState>::DefaultState[stage][ _RsHolder<ST_SamplerState>::IndexStateTable[i] ] )
{
_oprint( "Stage : %d, SamplerStateType : %u, Value : %u\n", stage, _RsHolder<ST_SamplerState>::IndexStateTable[i]
, m_SamplerStateCacheArry[stage].data[m_SamplerStateCacheArry[stage].current_page][ _RsHolder<ST_SamplerState>::IndexStateTable[i] ] );
}
}
}
_oprint( "=============== End Present Changed Current [SamplerState] =================\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::PresentCurrentTextureState( bool bShow )
{
if( !bShow ) return;
_oprint( "=============== Start Present Changed Current [TextureState] =================\n" );
for( int stage = 0; stage < NSTAGE; stage++ )
{
for( int i = 0; i < TS_CNT; i++ )
{
if( m_TextureStageStateCacheArray[stage].data[m_TextureStageStateCacheArray[stage].current_page][ _RsHolder<ST_TextureState>::IndexStateTable[i] ]
!= _RsHolder<ST_TextureState>::DefaultState[stage][ _RsHolder<ST_TextureState>::IndexStateTable[i] ] )
{
_oprint( "Stage : %d, TextureStateType : %u, Value : %u\n", stage, _RsHolder<ST_TextureState>::IndexStateTable[i]
, m_TextureStageStateCacheArray[stage].data[m_TextureStageStateCacheArray[stage].current_page][ _RsHolder<ST_TextureState>::IndexStateTable[i] ] );
}
}
}
_oprint( "=============== End Present Changed Current [TextureState] =================\n" );
}
static void PresentDeviceRenderState( LPDIRECT3DDEVICE9 pDevice, bool bShow )
{
if( !bShow ) return;
_oprint( "=============== Start Present Changed Device [RenderState] =================\n" );
if( pDevice )
{
DWORD dwValue;
for( int i = 0; i < RS_CNT; i++ )
{
pDevice->GetRenderState( (D3DRENDERSTATETYPE)_RsHolder<ST_RenderState>::IndexStateTable[i], &dwValue );
if( dwValue != _RsHolder<ST_RenderState>::DefaultState[0][ _RsHolder<ST_RenderState>::IndexStateTable[i] ] )
{
_oprint( "RenderStateType : %u, Value : %u\n", _RsHolder<ST_RenderState>::IndexStateTable[i], dwValue );
}
}
}
_oprint( "=============== End Present Changed Device [RenderState] =================\n" );
}
static void PresentDeviceSamplerState( LPDIRECT3DDEVICE9 pDevice, DWORD max_stage, bool bShow )
{
if( !bShow ) return;
_oprint( "=============== Start Present Changed Device [SamplerState] =================\n" );
if( pDevice )
{
DWORD dwValue;
for( DWORD stage = 0; stage < max_stage; stage++ )
{
for( int i = 0; i < SS_CNT; i++ )
{
pDevice->GetSamplerState( stage, (D3DSAMPLERSTATETYPE)_RsHolder<ST_SamplerState>::IndexStateTable[i], &dwValue );
if( dwValue != _RsHolder<ST_SamplerState>::DefaultState[stage][ _RsHolder<ST_SamplerState>::IndexStateTable[i] ] )
{
_oprint( "Stage : %u, SamplerStateType : %u, Value : %u\n", stage, _RsHolder<ST_SamplerState>::IndexStateTable[i], dwValue );
}
}
}
}
_oprint( "=============== End Present Changed Device [SamplerState] =================\n" );
}
static void PresentDeviceTextureState( LPDIRECT3DDEVICE9 pDevice, DWORD max_stage, bool bShow )
{
if( !bShow ) return;
_oprint( "=============== Start Present Changed Device [TextureState] =================\n" );
if( pDevice )
{
DWORD dwValue;
for( DWORD stage = 0; stage < max_stage; stage++ )
{
for( int i = 0; i < TS_CNT; i++ )
{
pDevice->GetTextureStageState( stage, (D3DTEXTURESTAGESTATETYPE)_RsHolder<ST_TextureState>::IndexStateTable[i], &dwValue );
if( dwValue != _RsHolder<ST_TextureState>::DefaultState[stage][ _RsHolder<ST_TextureState>::IndexStateTable[i] ] )
{
_oprint( "Stage : %u, TextureStateType : %u, Value : %u\n", stage, _RsHolder<ST_TextureState>::IndexStateTable[i], dwValue );
}
}
}
}
_oprint( "=============== End Present Changed Device [TextureState] =================\n" );
}
//--------------------------------------------------------------------------------------
// Test Code
//--------------------------------------------------------------------------------------
#ifdef STATEMANAGER_TEST
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestRenderState()
{
_oprint( "--------------------TestRenderState [Start]----------------------\n" );
// 초기화 테스트
if( memcmp( m_RenderStateCache.data[ m_RenderStateCache.current_page ], _RsHolder<ST_RenderState>::DefaultState[m_RenderStateCache.current_stage], sizeof(DWORD)*RS_MAX ) != 0 )
{
_oprint( "StateManager Default State Initialize Failed - memcmp is nonzero \n" );
}
if( m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ZENABLE ] != TRUE )
{
_oprint( "StateManager Initialize Failed - D3DRS_ZENABLE = %u \n", m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ZENABLE ] );
}
if( m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ALPHABLENDENABLE ] != FALSE )
{
_oprint( "StateManager Initialize Failed - D3DRS_ALPHABLENDENABLE = %u \n", m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ALPHABLENDENABLE ] );
}
// ManagedSetRenderState Function Test
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
if( m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ZENABLE ] != FALSE )
{
_oprint( "1. ManagedSetRenderState( D3DRS_ZENABLE, FALSE ) - Failed\n" );
}
if( m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ALPHABLENDENABLE ] != TRUE )
{
_oprint( "1. ManagedSetRenderState( D3DRS_ZENABLE, FALSE ) - Failed\n" );
}
// Commit Test
_oprint( "1. Commit Test : D3DRS_ZENABLE - %d(FALSE), D3DRS_ALPHABLENDENABLE - %d(TRUE) \n", D3DRS_ZENABLE, D3DRS_ALPHABLENDENABLE );
bool prev_page = m_RenderStateCache.current_page;
PushCurrentStateToDevice();
if( prev_page == m_RenderStateCache.current_page )
{
_oprint( "Commit : Swap Failed - current_page is not changed \n" );
}
if( memcmp( m_RenderStateCache.data[ m_RenderStateCache.current_page ], _RsHolder<ST_RenderState>::DefaultState[m_RenderStateCache.current_stage], sizeof(DWORD)*RS_MAX ) != 0 )
{
_oprint( "Commit : Data Clear & Reset Failed - memcmp is nonzero \n" );
}
// 같은 스테이트 한번 더 세팅
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
if( m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ZENABLE ] != FALSE )
{
_oprint( "2. ManagedSetRenderState( D3DRS_ZENABLE, FALSE ) - Failed\n" );
}
if( m_RenderStateCache.data[ m_RenderStateCache.current_page ][ D3DRS_ALPHABLENDENABLE ] != TRUE )
{
_oprint( "2. ManagedSetRenderState( D3DRS_ZENABLE, FALSE ) - Failed\n" );
}
// Commit Test
_oprint( "2. Commit Test : D3DRS_ZENABLE - %d(FALSE), D3DRS_ALPHABLENDENABLE - %d(TRUE) \n", D3DRS_ZENABLE, D3DRS_ALPHABLENDENABLE );
prev_page = m_RenderStateCache.current_page;
PushCurrentStateToDevice();
// 아무것도 세팅하지 않고 Commit 해본다.
// Commit Test
_oprint( "3. Commit Test(To Default) : D3DRS_ZENABLE - %d(TRUE), D3DRS_ALPHABLENDENABLE - %d(FALSE) \n", D3DRS_ZENABLE, D3DRS_ALPHABLENDENABLE );
prev_page = m_RenderStateCache.current_page;
PushCurrentStateToDevice();
_oprint( "--------------------TestRenderState [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestSamplerState()
{
_oprint( "--------------------TestSamplerState [Start]----------------------\n" );
// 초기화 테스트
for( int i = 0; i < NSTAGE; i++ )
{
if( memcmp( m_SamplerStateCacheArry[i].data[ m_SamplerStateCacheArry[i].current_page ], _RsHolder<ST_SamplerState>::DefaultState[i], sizeof(DWORD)*SS_MAX ) != 0 )
{
_oprint( "SamplerState Default State Initialize Failed - memcmp is nonzero \n" );
}
if( m_SamplerStateCacheArry[i].data[ m_SamplerStateCacheArry[i].current_page ][ D3DSAMP_ADDRESSU ] != D3DTADDRESS_WRAP )
{
_oprint( "SamplerState Initialize Failed - D3DSAMP_ADDRESSU[%d] is Not D3DTADDRESS_WRAP(%u). is %u\n"
, i, D3DTADDRESS_WRAP, m_SamplerStateCacheArry[i].data[ m_SamplerStateCacheArry[i].current_page ][ D3DSAMP_ADDRESSU ] );
}
if( m_SamplerStateCacheArry[i].data[ m_SamplerStateCacheArry[i].current_page ][ D3DSAMP_MINFILTER ] != D3DTEXF_POINT )
{
_oprint( "SamplerState Initialize Failed - D3DSAMP_MINFILTER[%d] is Not D3DTEXF_POINT(%u). is %u\n"
, i, D3DTEXF_POINT, m_SamplerStateCacheArry[i].data[ m_SamplerStateCacheArry[i].current_page ][ D3DSAMP_MINFILTER ] );
}
}
// ManagedSetRenderState Function Test
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
if( m_SamplerStateCacheArry[1].data[ m_SamplerStateCacheArry[1].current_page ][ D3DSAMP_ADDRESSU ] != D3DTADDRESS_MIRROR )
{
_oprint( "1. ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR ) - Failed\n" );
}
if( m_SamplerStateCacheArry[3].data[ m_SamplerStateCacheArry[3].current_page ][ D3DSAMP_MINFILTER ] != D3DTEXF_ANISOTROPIC )
{
_oprint( "1. ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC ) - Failed\n" );
}
// Commit Test
_oprint( "1. Commit Test : D3DSAMP_ADDRESSU(1) - %u = %u, D3DSAMP_MINFILTER(3) - %u = %u \n"
, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
bool prev_page = m_SamplerStateCacheArry[1].current_page;
PushCurrentStateToDevice();
if( prev_page == m_SamplerStateCacheArry[1].current_page )
{
_oprint( "Commit : Swap Failed - current_page is not changed \n" );
}
if( memcmp( m_SamplerStateCacheArry[2].data[ m_SamplerStateCacheArry[2].current_page ], _RsHolder<ST_SamplerState>::DefaultState[2], sizeof(DWORD)*SS_MAX ) != 0 )
{
_oprint( "Commit : Data Clear & Reset Failed - memcmp is nonzero \n" );
}
// 같은 스테이트 한번 더 세팅
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
if( m_SamplerStateCacheArry[1].data[ m_SamplerStateCacheArry[1].current_page ][ D3DSAMP_ADDRESSU ] != D3DTADDRESS_MIRROR )
{
_oprint( "2. ManagedSetRenderState( D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR ) - Failed\n" );
}
if( m_SamplerStateCacheArry[3].data[ m_SamplerStateCacheArry[3].current_page ][ D3DSAMP_MINFILTER ] != D3DTEXF_ANISOTROPIC )
{
_oprint( "2. ManagedSetRenderState( D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC ) - Failed\n" );
}
// Commit Test
_oprint( "2. Commit Test : D3DSAMP_ADDRESSU(1) - %u = %u, D3DSAMP_MINFILTER(3) - %u = %u \n"
, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
PushCurrentStateToDevice();
// 아무것도 세팅하지 않고 Commit 해본다.
// Commit Test
_oprint( "3. Commit Test(To Default) : D3DSAMP_ADDRESSU(1) - %u = %u, D3DSAMP_MINFILTER(3) - %u = %u \n"
, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP, D3DSAMP_MINFILTER, D3DTEXF_POINT );
PushCurrentStateToDevice();
_oprint( "--------------------TestSamplerState [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestTextureState()
{
_oprint( "--------------------TestTextureState [Start]----------------------\n" );
// 초기화 테스트
for( int i = 0; i < NSTAGE; i++ )
{
if( memcmp( m_TextureStageStateCacheArray[i].data[ m_TextureStageStateCacheArray[i].current_page ], _RsHolder<ST_TextureState>::DefaultState[i], sizeof(DWORD)*TS_MAX ) != 0 )
{
_oprint( "TextureState Default State Initialize Failed - memcmp is nonzero \n" );
}
if( m_TextureStageStateCacheArray[i].data[ m_TextureStageStateCacheArray[i].current_page ][ D3DTSS_COLOROP ] != D3DTOP_DISABLE )
{
_oprint( "TextureState Initialize Failed - D3DTSS_COLOROP[%d] is Not D3DTOP_DISABLE(%u). is %u\n"
, i, D3DTOP_DISABLE, m_TextureStageStateCacheArray[i].data[ m_TextureStageStateCacheArray[i].current_page ][ D3DTSS_COLOROP ] );
}
if( m_TextureStageStateCacheArray[i].data[ m_TextureStageStateCacheArray[i].current_page ][ D3DTSS_TEXCOORDINDEX ] != i )
{
_oprint( "TextureState Initialize Failed - D3DTSS_TEXCOORDINDEX[%d] is Not %d. is %u\n"
, i, i, m_TextureStageStateCacheArray[i].data[ m_TextureStageStateCacheArray[i].current_page ][ D3DTSS_TEXCOORDINDEX ] );
}
}
// ManagedSetRenderState Function Test
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
if( m_TextureStageStateCacheArray[1].data[ m_TextureStageStateCacheArray[1].current_page ][ D3DTSS_COLOROP ] != D3DTOP_SUBTRACT )
{
_oprint( "1. ManagedSetTextureState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT ) - Failed\n" );
}
if( m_TextureStageStateCacheArray[3].data[ m_TextureStageStateCacheArray[3].current_page ][ D3DTSS_TEXCOORDINDEX ] != 1 )
{
_oprint( "1. ManagedSetTextureState( 3, D3DTSS_TEXCOORDINDEX, 1 ) - Failed\n" );
}
// Commit Test
_oprint( "1. Commit Test : D3DTSS_COLOROP(1) - %u = %u, D3DTSS_TEXCOORDINDEX(3) - %u = %u \n"
, D3DTSS_COLOROP, D3DTOP_SUBTRACT, D3DTSS_TEXCOORDINDEX, 1 );
bool prev_page = m_TextureStageStateCacheArray[1].current_page;
PushCurrentStateToDevice();
if( prev_page == m_TextureStageStateCacheArray[1].current_page )
{
_oprint( "Commit : Swap Failed - current_page is not changed \n" );
}
if( memcmp( m_TextureStageStateCacheArray[2].data[ m_TextureStageStateCacheArray[2].current_page ], _RsHolder<ST_TextureState>::DefaultState[2], sizeof(DWORD)*TS_MAX ) != 0 )
{
_oprint( "Commit : Data Clear & Reset Failed - memcmp is nonzero \n" );
}
// 같은 스테이트 한번 더 세팅
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
if( m_TextureStageStateCacheArray[1].data[ m_TextureStageStateCacheArray[1].current_page ][ D3DTSS_COLOROP ] != D3DTOP_SUBTRACT )
{
_oprint( "2. ManagedSetRenderState( D3DTSS_COLOROP, D3DTOP_SUBTRACT ) - Failed\n" );
}
if( m_TextureStageStateCacheArray[3].data[ m_TextureStageStateCacheArray[3].current_page ][ D3DTSS_TEXCOORDINDEX ] != 1 )
{
_oprint( "2. ManagedSetRenderState( D3DTSS_TEXCOORDINDEX, 1 ) - Failed\n" );
}
// Commit Test
_oprint( "2. Commit Test : D3DTSS_COLOROP(1) - %u = %u, D3DTSS_TEXCOORDINDEX(3) - %u = %u \n"
, D3DTSS_COLOROP, D3DTOP_SUBTRACT, D3DTSS_TEXCOORDINDEX, 1 );
PushCurrentStateToDevice();
// 아무것도 세팅하지 않고 Commit 해본다.
// Commit Test
_oprint( "3. Commit Test(To Default) : D3DTSS_COLOROP(1) - %u = %u, D3DTSS_TEXCOORDINDEX(3) - %u = %u \n"
, D3DTSS_COLOROP, D3DTOP_DISABLE, D3DTSS_TEXCOORDINDEX, 3 );
PushCurrentStateToDevice();
_oprint( "--------------------TestTextureState [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestStateBlock()
{
_oprint( "--------------------TestStateBlock [Start]----------------------\n" );
// Block Create Test.
BeginStateBlock();
if( m_pBlockBuffer == NULL )
_oprint( "BeginStateBlock Failed - m_pBlockBuffer is NULL\n" );
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); // is default
if( m_pBlockBuffer->vRenderStateBlock.back().statetype == D3DRS_FILLMODE )
_oprint( "ManagedSetRenderState Failed - Setted Default State\n" );
ManagedSetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_POINT );
ManagedSetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
EndStateBlock( 1 );
if( m_pBlockBuffer != NULL )
_oprint( "EndStateBlock Failed - m_pBlockBuffer is not NULL\n" );
if( m_StateBlocks.empty() )
_oprint( "EndStateBlock Failed - m_StateBlocks is Empty\n" );
// SetStateBlock Test.
ManagedSetStateBlock( 1 );
_oprint( "ManagedSetStateBlock Performed. D3DRS_ZENABLE(%u) - FALSE, D3DSAMP_MINFILTER[2](%u) - %u, D3DTSS_TEXCOORDINDEX[3](%u) - 1\n"
, D3DRS_ZENABLE, D3DSAMP_MINFILTER, D3DTEXF_LINEAR, D3DTSS_TEXCOORDINDEX );
PushCurrentStateToDevice();
// Clear & Delete Test
TestForClearStateBlock();
if( m_pBlockBuffer != NULL )
_oprint( "ClearStateBlock Failed - m_pBlockBuffer is not NULL\n" );
if( !m_StateBlocks.empty() )
_oprint( "ClearStateBlock Failed - m_StateBlocks is not Empty\n" );
_oprint( "--------------------TestStateBlock [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestMultiPass()
{
_oprint( "--------------------TestMultiPass [Start]----------------------\n" );
// 일단 클리어
PushCurrentStateToDevice();
// 0 번째 패스
_oprint( "0. 0번째 패스 PushCurrentStateToDevice()\n" );
TestForSetPass( 0 );
// Set Render State From EffectInterface.
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
BeginPass( NULL, 0 );
EndPass( NULL );
// 검증
if( m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ZENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ALPHABLENDENABLE] != TRUE ||
m_SamplerStateCacheArry[1].data[!m_SamplerStateCacheArry[1].current_page][D3DSAMP_ADDRESSU] != D3DTADDRESS_MIRROR ||
m_SamplerStateCacheArry[3].data[!m_SamplerStateCacheArry[3].current_page][D3DSAMP_MINFILTER] != D3DTEXF_ANISOTROPIC ||
m_TextureStageStateCacheArray[1].data[!m_TextureStageStateCacheArray[1].current_page][D3DTSS_COLOROP] != D3DTOP_SUBTRACT ||
m_TextureStageStateCacheArray[3].data[!m_TextureStageStateCacheArray[3].current_page][D3DTSS_TEXCOORDINDEX] != 1 )
{
_oprint( "FAILED - 0 번째 패스 세팅 잘못됨\n" );
}
// 1 번째 패스
_oprint( "1. 1번째 패스 PushCurrentStateToDevice()\n" );
TestForSetPass( 1 );
// 1번째 패스에서 변경된 스테이트 세팅 (이펙트 내부에서 세팅된것)
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); // To Default
ManagedSetRenderState( D3DRS_FOGENABLE, TRUE ); // Default -> 변경
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE ); // To Default
BeginPass( NULL, 1 );
EndPass( NULL );
// 검증
if( m_RenderStateCache.changeidx[m_RenderStateCache.current_page].any() )
{
_oprint( "FAILED - 1번째 패서 Push 이후에 changeidx bitset 이 Clear가 안됨\n" );
}
// 검증
if( m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ZENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ALPHABLENDENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_FOGENABLE] != TRUE ||
m_SamplerStateCacheArry[1].data[!m_SamplerStateCacheArry[1].current_page][D3DSAMP_ADDRESSU] != D3DTADDRESS_MIRROR ||
m_SamplerStateCacheArry[3].data[!m_SamplerStateCacheArry[3].current_page][D3DSAMP_MINFILTER] != D3DTEXF_ANISOTROPIC ||
m_TextureStageStateCacheArray[1].data[!m_TextureStageStateCacheArray[1].current_page][D3DTSS_COLOROP] != D3DTOP_DISABLE ||
m_TextureStageStateCacheArray[3].data[!m_TextureStageStateCacheArray[3].current_page][D3DTSS_TEXCOORDINDEX] != 1 )
{
_oprint( "FAILED - 1 번째 패스 세팅 잘못됨\n" );
}
// 2 번째 패스
_oprint( "2. 2번째 패스 PushCurrentStateToDevice()\n" );
TestForSetPass( 2 );
// 2번째 패스에서 변경된 스테이트 세팅
ManagedSetRenderState( D3DRS_FOGENABLE, FALSE ); // To Default
BeginPass( NULL, 2 );
EndPass( NULL );
// 검증
if( m_RenderStateCache.changeidx[m_RenderStateCache.current_page].any() )
{
_oprint( "FAILED - 2번째 패서 Push 이후에 changeidx bitset 이 Clear가 안됨\n" );
}
// 검증
if( m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ZENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ALPHABLENDENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_FOGENABLE] != FALSE ||
m_SamplerStateCacheArry[1].data[!m_SamplerStateCacheArry[1].current_page][D3DSAMP_ADDRESSU] != D3DTADDRESS_MIRROR ||
m_SamplerStateCacheArry[3].data[!m_SamplerStateCacheArry[3].current_page][D3DSAMP_MINFILTER] != D3DTEXF_ANISOTROPIC ||
m_TextureStageStateCacheArray[1].data[!m_TextureStageStateCacheArray[1].current_page][D3DTSS_COLOROP] != D3DTOP_DISABLE ||
m_TextureStageStateCacheArray[3].data[!m_TextureStageStateCacheArray[3].current_page][D3DTSS_TEXCOORDINDEX] != 1 )
{
_oprint( "FAILED - 2 번째 패스 세팅 잘못됨\n" );
}
// 1 번째 패스
_oprint( "3. 3번째 패스 PushCurrentStateToDevice()\n" );
TestForSetPass( 3 );
// 3번째 패스에서 변경된 스테이트 세팅
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 0 ); // 변경
BeginPass( NULL, 3 );
EndPass( NULL );
// 검증
if( m_RenderStateCache.changeidx[m_RenderStateCache.current_page].any() )
{
_oprint( "FAILED - 3번째 패서 Push 이후에 changeidx bitset 이 Clear가 안됨\n" );
}
// 검증
if( m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ZENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_ALPHABLENDENABLE] != FALSE ||
m_RenderStateCache.data[!m_RenderStateCache.current_page][D3DRS_FOGENABLE] != FALSE ||
m_SamplerStateCacheArry[1].data[!m_SamplerStateCacheArry[1].current_page][D3DSAMP_ADDRESSU] != D3DTADDRESS_MIRROR ||
m_SamplerStateCacheArry[3].data[!m_SamplerStateCacheArry[3].current_page][D3DSAMP_MINFILTER] != D3DTEXF_ANISOTROPIC ||
m_TextureStageStateCacheArray[1].data[!m_TextureStageStateCacheArray[1].current_page][D3DTSS_COLOROP] != D3DTOP_DISABLE ||
m_TextureStageStateCacheArray[3].data[!m_TextureStageStateCacheArray[3].current_page][D3DTSS_TEXCOORDINDEX] != 0 )
{
_oprint( "FAILED - 3 번째 패스 세팅 잘못됨\n" );
}
_oprint( "--------------------TestMultiPass [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestRestoreDefault()
{
_oprint( "--------------------TestRestoreDefault [Start]----------------------\n" );
// State 변경
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
// Restore
RestoreDefault();
// 검증
if( memcmp( m_RenderStateCache.data[0], _RsHolder<ST_RenderState>::DefaultState[0], sizeof(DWORD)*RS_MAX ) != 0 ||
memcmp( m_RenderStateCache.data[1], _RsHolder<ST_RenderState>::DefaultState[0], sizeof(DWORD)*RS_MAX ) != 0 )
{
_oprint( "FAILED - Render State is Not Default \n" );
}
if( memcmp( m_SamplerStateCacheArry[0].data[0], _RsHolder<ST_SamplerState>::DefaultState[0], sizeof(DWORD)*SS_MAX ) != 0 ||
memcmp( m_SamplerStateCacheArry[0].data[1], _RsHolder<ST_SamplerState>::DefaultState[0], sizeof(DWORD)*SS_MAX ) != 0 )
{
_oprint( "FAILED - Sampler State is Not Default \n" );
}
if( memcmp( m_TextureStageStateCacheArray[2].data[0], _RsHolder<ST_TextureState>::DefaultState[2], sizeof(DWORD)*SS_MAX ) != 0 ||
memcmp( m_TextureStageStateCacheArray[2].data[1], _RsHolder<ST_TextureState>::DefaultState[2], sizeof(DWORD)*SS_MAX ) != 0 )
{
_oprint( "FAILED - Texture State is Not Default \n" );
}
_oprint( "--------------------TestRestoreDefault [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestPresent()
{
_oprint( "--------------------TestPresent [Start]----------------------\n" );
RestoreDefault();
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
_oprint( "SetRenderState - RenderStateType : %u, value : %u\n", D3DRS_ZENABLE, FALSE );
_oprint( "SetRenderState - RenderStateType : %u, value : %u\n", D3DRS_ALPHABLENDENABLE, TRUE );
_oprint( "SetSamplerState - Stage : %u, SamplerStateType : %u, value : %u\n", 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
_oprint( "SetSamplerState - Stage : %u, SamplerStateType : %u, value : %u\n", 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
_oprint( "SetTextureState - Stage : %u, TextureStateType : %u, value : %u\n", 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
_oprint( "SetTextureState - Stage : %u, TextureStateType : %u, value : %u\n", 3, D3DTSS_TEXCOORDINDEX, 1 );
PresentCurrentRenderState( true );
PresentCurrentSamplerState( true );
PresentCurrentTextureState( true );
_oprint( "--------------------TestPresent [End]----------------------\n" );
}
template<int NSTAGE>
void KStateManagerImpl<NSTAGE>::TestPerformance( DWORD count )
{
RestoreDefault();
_oprint( "--------------------TestPerformance [Start]----------------------\n" );
// 라펠즈에서 많이 쓰이는 스테이트 블록 세팅
{
BeginStateBlock();
ManagedSetRenderState( D3DRS_LIGHTING, FALSE );
// alpha blend
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
ManagedSetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
ManagedSetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
ManagedSetRenderState( D3DRS_ZENABLE, TRUE );
ManagedSetRenderState( D3DRS_STENCILENABLE, FALSE );
// alpha test
ManagedSetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
ManagedSetRenderState( D3DRS_ALPHAREF, 0 );
ManagedSetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATER );
// vertex material source
ManagedSetRenderState( D3DRS_COLORVERTEX, FALSE );
ManagedSetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );
ManagedSetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2 );
ManagedSetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL );
ManagedSetRenderState( D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL );
// set to default
for(int i = 0; i < NSTAGE ; ++i)
{
ManagedSetTextureStageState( i, D3DTSS_COLOROP, D3DTOP_DISABLE );
ManagedSetTextureStageState( i, D3DTSS_RESULTARG, D3DTA_CURRENT );
ManagedSetTextureStageState( i, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
ManagedSetSamplerState( i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
ManagedSetSamplerState( i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
ManagedSetSamplerState( i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
}
// texture state
ManagedSetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
ManagedSetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
ManagedSetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
ManagedSetTextureStageState( 0, D3DTSS_RESULTARG, D3DTA_CURRENT );
ManagedSetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
ManagedSetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
ManagedSetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
ManagedSetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
ManagedSetSamplerState( 2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
ManagedSetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
ManagedSetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_LERP );
ManagedSetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
ManagedSetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
ManagedSetTextureStageState( 1, D3DTSS_COLORARG0, D3DTA_DIFFUSE );
ManagedSetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA );
ManagedSetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
ManagedSetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT );
ManagedSetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
ManagedSetTextureStageState( 3, D3DTSS_COLORARG1, D3DTA_SPECULAR );
ManagedSetTextureStageState( 3, D3DTSS_COLORARG2, D3DTA_CURRENT );
ManagedSetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
ManagedSetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
EndStateBlock( 11 );
}
DWORD dwSetTime = 0;
DWORD dwPushTime = 0;
DWORD dwTime = ::GetSafeTickCount();
DWORD dwTemp = 0;
g_OuputPushString = false;
for( DWORD i = 0; i < count; i++ )
{
dwTemp = GetSafeTickCount();
// ManagedSetStateBlock( 11 );
if( (i % 2) == 0 )
{
ManagedSetRenderState( D3DRS_ZENABLE, FALSE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 1 );
}
else
{
ManagedSetRenderState( D3DRS_ZENABLE, TRUE );
ManagedSetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
ManagedSetSamplerState( 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
ManagedSetSamplerState( 3, D3DSAMP_MINFILTER, D3DTEXF_NONE );
ManagedSetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADD );
ManagedSetTextureStageState( 3, D3DTSS_TEXCOORDINDEX, 2 );
}
dwSetTime += GetSafeTickCount() - dwTemp;
dwTemp = GetSafeTickCount();
PushCurrentStateToDevice();
dwPushTime += GetSafeTickCount() - dwTemp;
}
DWORD dwAfterTime = GetSafeTickCount();
g_OuputPushString = true;
_oprint( " Test Count : [%u], TotalTime : [%u], SetTime : [%u], PushTime : [%u] \n", count, dwAfterTime - dwTime, dwSetTime, dwPushTime );
// Memcpy Time Test
// DWORD test_rs[RS_MAX];
// DWORD test_ss[NSTAGE][SS_MAX];
// DWORD test_ts[NSTAGE][TS_MAX];
dwTime = GetSafeTickCount();
for( DWORD i = 0; i < count; i++ )
{
memcpy( m_RenderStateCache.data[i%2], _RsHolder<ST_RenderState>::DefaultState[0], sizeof(DWORD) * RS_MAX );
for( DWORD ss = 0; ss < NSTAGE; ss++ )
{
memcpy( m_SamplerStateCacheArry[ss].data[i%2], _RsHolder<ST_SamplerState>::DefaultState[ss], sizeof(DWORD) * SS_MAX );
memcpy( m_TextureStageStateCacheArray[ss].data[i%2], _RsHolder<ST_TextureState>::DefaultState[ss], sizeof(DWORD) * TS_MAX );
}
}
dwAfterTime = GetSafeTickCount();
_oprint( " [memcpy] Test Count : [%u], Time : [%u] \n", count, dwAfterTime - dwTime );
_oprint( "--------------------TestPerformance [End]----------------------\n" );
}
#endif
} // end namespace StateManager