Jump to content
  • Advertisement
Sign in to follow this  
cozzie

State manager, code review/ suggestions?

This topic is 1909 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

To prevent/ minimize redundant state setting in my engine, I've added my own 'state machine'.

It all seems to be working fine, even with d3d debug on highest warning level, there's nothing redundant left tongue.png

 

I've pasted the code below, with the question if you have any remarks or suggestions (things I've overlooked or so).

Any input appreciated as always.

// DEFINITIONS, from my header file

/**************************************************************************************/
/***								D3D_STATES structs								***/
/*** keeps track of a D3D state and it's value										***/
/*** values based on the d3dtypes.h enums, i.e. D3DRS_ZENABLE = 7, D3DZB_TRUE = 1	***/
/**************************************************************************************/

typedef struct D3D_RENDERSTATE
{
	D3DRENDERSTATETYPE	state;
	DWORD				value;
} D3D_RENDERSTATE;

typedef struct D3D_TEXSTAGE
{
	DWORD						stage;
	D3DTEXTURESTAGESTATETYPE	state;
	DWORD						value;
} D3D_TEXSTAGE;

typedef struct D3D_SAMPLER
{
	DWORD						sampler;
	D3DSAMPLERSTATETYPE			type;
	DWORD						value;
} D3D_SAMPLER;

/**************************************************************************************/
/***								CD3DSTATEMACH class								***/
/*** stores a (single) direct3d9 state machine with it's members and functions		***/
/**************************************************************************************/

class CD3dstateMach
{
public:
	bool Setup(IDirect3DDevice9 *pD3ddev);

	bool SetRenderState(const D3DRENDERSTATETYPE pState, const DWORD pValue);
	bool SetTextureStageState(const DWORD pStage, const D3DTEXTURESTAGESTATETYPE pState, const DWORD pValue);
	bool SetSamplerState(const DWORD pSampler, const D3DSAMPLERSTATETYPE pType, const DWORD pValue);

	CD3dstateMach();
	~CD3dstateMach();

private:
	CComPtr<IDirect3DDevice9>	mD3ddev;		// smart pointer

	std::vector<D3D_RENDERSTATE>	mRender;
	std::vector<D3D_TEXSTAGE>		mTexStage;
	std::vector<D3D_SAMPLER>		mSampler;
};

// IMPLEMENTATION

#define DEF_RENDER		9
#define DEF_TEXSTAGE	2
#define DEF_SAMPLER		6

D3D_RENDERSTATE defRenderState[] = 		{	{D3DRS_LIGHTING,			FALSE					},
											{D3DRS_SRCBLEND,			D3DBLEND_SRCALPHA		},
											{D3DRS_DESTBLEND,			D3DBLEND_INVSRCALPHA	},
											{D3DRS_ZENABLE,				D3DZB_TRUE				},
											{D3DRS_ZWRITEENABLE,		TRUE					},
											{D3DRS_CULLMODE,			D3DCULL_CCW				},
											{D3DRS_STENCILENABLE,		FALSE					},
											{D3DRS_FILLMODE,			D3DFILL_SOLID			},
											{D3DRS_ALPHABLENDENABLE,	FALSE					}};

D3D_TEXSTAGE defTexStageState[] = {			{0,	D3DTSS_ALPHAOP,			D3DTOP_SELECTARG1		},
											{0,	D3DTSS_ALPHAARG1,		D3DTA_TEXTURE			}};

D3D_SAMPLER defSamplerState[] = {			{0, D3DSAMP_MAGFILTER,		D3DTEXF_LINEAR			},
											{0, D3DSAMP_MIPFILTER,		D3DTEXF_LINEAR			},
											{0, D3DSAMP_MINFILTER,		D3DTEXF_ANISOTROPIC		},
											{0, D3DSAMP_MAXANISOTROPY,	4						},
											{0, D3DSAMP_ADDRESSU,		D3DTADDRESS_WRAP		},
											{0, D3DSAMP_ADDRESSV,		D3DTADDRESS_WRAP		}};

/**************************************************************************************/
/***								CONSTRUCTOR										***/
/*** ==> usage: when creating a CD3dstatemach object								***/
/*** ==> sets all variables to initial values										***/
/**************************************************************************************/

CD3dstateMach::CD3dstateMach()
{
	mD3ddev = NULL;		// smart pointer

	// renderstates
	mRender.reserve(10);
	mRender.resize(0);

	// texturestage states
	mTexStage.reserve(10);
	mTexStage.resize(0);

	// sampler states
	mSampler.reserve(10);
	mSampler.resize(0);
}

/**************************************************************************************/
/***								DESTRUCTOR										***/
/*** ==> usage: when CD3dstateMach object is not needed anymore						***/
/*** ==> resets values and cleans up if necessary									***/
/**************************************************************************************/

CD3dstateMach::~CD3dstateMach()
{
	mD3ddev = NULL;		// smart pointer
}

/**************************************************************************************/
/***									SETUP								  CONST	***/
/*** ==> usage: initial setup of d3d state machine					  				***/
/*** ==> sets the default d3d states applicable for the engine						***/
/**************************************************************************************/

bool CD3dstateMach::Setup(IDirect3DDevice9 *pD3ddev)
{
	// save pointer (smart) of the d3d device
	if((mD3ddev = pD3ddev) == NULL) return false;

	// renderstates
	D3D_RENDERSTATE newRenderState;
	for(int rs=0;rs<DEF_RENDER;++rs)
	{
		newRenderState.state	= defRenderState[rs].state;
		newRenderState.value	= defRenderState[rs].value;
		mRender.push_back(newRenderState);
	}

	// texturestage states
	D3D_TEXSTAGE newTexStage;
	for(int ts=0;ts<DEF_TEXSTAGE;++ts)
	{
		newTexStage.stage	= defTexStageState[ts].stage;
		newTexStage.state	= defTexStageState[ts].state;
		newTexStage.value	= defTexStageState[ts].value;
		mTexStage.push_back(newTexStage);
	}

	// sampler states	
	D3D_SAMPLER newSampler;
	for(int ss=0;ss<DEF_SAMPLER;++ss)
	{
		newSampler.sampler	= defSamplerState[ss].sampler;
		newSampler.type		= defSamplerState[ss].type;
		newSampler.value	= defSamplerState[ss].value;
		mSampler.push_back(newSampler);
	}

	/** set renderstates directly to D3D API						**\
	\** ONLY when engine default is other then API default state	**/

	for(int rs=0;rs<3;++rs) mD3ddev->SetRenderState(mRender[rs].state, mRender[rs].value);
	for(int ss=0;ss<4;++ss) mD3ddev->SetSamplerState(mSampler[ss].sampler, mSampler[ss].type, mSampler[ss].value);

	return true;
}

/**************************************************************************************/
/***								SET RENDERSTATE									***/
/*** ==> usage: sets a renderstate to the d3d device if needed 		  				***/
/*** ==> checks current value/states and only updates when needed					***/
/**************************************************************************************/

bool CD3dstateMach::SetRenderState(const D3DRENDERSTATETYPE pState, const DWORD pValue)
{
	for(size_t rs=0;rs<mRender.size();++rs)
	{
		if(mRender[rs].state == pState)
		{
			if(mRender[rs].value != pValue)
			{
				mRender[rs].value = pValue;
				mD3ddev->SetRenderState(mRender[rs].state, mRender[rs].value);
				return true;
			}
			else return false;
		}
	}

	// NEW STATE
	D3D_RENDERSTATE newState = { pState, pValue };
	mRender.push_back(newState);
	mD3ddev->SetRenderState(mRender.back().state, mRender.back().value);
	return true;
}

/**************************************************************************************/
/***							SET TEXTURESTAGE STATE								***/
/*** ==> usage: sets a texturestage state to the d3d device if needed 				***/
/*** ==> checks current value/states and only updates when needed					***/
/**************************************************************************************/

bool CD3dstateMach::SetTextureStageState(const DWORD pStage, const D3DTEXTURESTAGESTATETYPE pState, const DWORD pValue)
{
	for(size_t ts=0;ts<mTexStage.size();++ts)
	{
		if(mTexStage[ts].stage == pStage)
		{
			if(mTexStage[ts].state == pState)
			{
				if(mTexStage[ts].value != pValue)
				{
					mTexStage[ts].value = pValue;
					mD3ddev->SetTextureStageState(mTexStage[ts].stage, mTexStage[ts].state, mRender[ts].value);
					return true;
				}
				else return false;
			}
			else		
			{
				// new state, existing stage
				D3D_TEXSTAGE newState = { pStage, pState, pValue };
				mTexStage.push_back(newState);
				mD3ddev->SetTextureStageState(mTexStage.back().stage, mTexStage.back().state, mTexStage.back().value);
				return true;
			}
		}
	}

	// NEW STAGE & NEW STATE
	D3D_TEXSTAGE newState = { pStage, pState, pValue };
	mTexStage.push_back(newState);
	mD3ddev->SetTextureStageState(mTexStage.back().stage, mTexStage.back().state, mTexStage.back().value);
	return true;
}

/**************************************************************************************/
/***								SET SAMPLER STATE								***/
/*** ==> usage: sets a sampler sate to the d3d device if needed 	  				***/
/*** ==> checks current value/states and only updates when needed					***/
/**************************************************************************************/

bool CD3dstateMach::SetSamplerState(const DWORD pSampler, const D3DSAMPLERSTATETYPE pType, const DWORD pValue)
{
	for(size_t ss=0;ss<mSampler.size();++ss)
	{
		if(mSampler[ss].sampler == pSampler)
		{
			if(mSampler[ss].type == pType)
			{
				if(mSampler[ss].value != pValue)
				{
					mSampler[ss].value = pValue;
					mD3ddev->SetSamplerState(mSampler[ss].sampler, mSampler[ss].type, mSampler[ss].value);
					return true;
				}
				else return false;
			}
			else		
			{
				// new state, existing stage
				D3D_SAMPLER newSampler = { pSampler, pType, pValue };
				mSampler.push_back(newSampler);
				mD3ddev->SetSamplerState(mSampler.back().sampler, mSampler.back().type, mSampler.back().value);
				return true;
			}
		}
	}

	// NEW SAMPLER & TYPE
	D3D_SAMPLER newSampler = { pSampler, pType, pValue };
	mSampler.push_back(newSampler);
	mD3ddev->SetSamplerState(mSampler.back().sampler, mSampler.back().type, mSampler.back().value);
	return true;
}



Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!