1704 lines
59 KiB
C++
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
|