Sign in to follow this  
BrentBarrett

Help Me: Visual tearing with Direct3D 9

Recommended Posts

BrentBarrett    154
I am creating a 2D using quads with an orthogonal projection in Direct3D 9. I'm having a problem with tearing happening in my game. I'm programming all this on my laptop, which is locked to a 60 hertz refresh rate. I don't want to lock my game's display to wait for teh vsync, as that would force my game's fps to cap at 60 fps. Is there any way to make my game be able to run fast without tearing and without waiting for the vsync? Here's how I've initializeed my Direct3D. It should also be noted that I'm running this at full screen on a 1024x768 screen.

	D3DDISPLAYMODE d3ddm;

	D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);

	PParams.BackBufferWidth = d3ddm.Width;
	PParams.BackBufferHeight = d3ddm.Height;
	PParams.BackBufferFormat = D3DFMT_X8R8G8B8;
	PParams.Windowed = false;
	PParams.BackBufferCount = 1;
	PParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
	PParams.MultiSampleType = D3DMULTISAMPLE_NONE;
	PParams.EnableAutoDepthStencil = true;
	PParams.AutoDepthStencilFormat = D3DFMT_D16;
	PParams.FullScreen_RefreshRateInHz = d3ddm.RefreshRate;
	PParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
	PParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

	D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GameWindow,
		D3DCREATE_HARDWARE_VERTEXPROCESSING, &PParams, &Device);

	D3DXMATRIX matProjection;
	ZeroMemory(&matProjection, sizeof(matProjection));
	D3DXMatrixOrthoLH(&matProjection, d3ddm.Width, d3ddm.Height, -1000.0f, 1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &matProjection);

	//Set View
	D3DXMATRIX matView;
	ZeroMemory(&matView, sizeof(matView));
	D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f, -5.0f),
				 &D3DXVECTOR3(0.0f, 0.0f,  0.0f),
				 &D3DXVECTOR3(0.0f, 1.0f,  0.0f));
	Device->SetTransform(D3DTS_VIEW, &matView);

	//Set World
	D3DXMATRIX matWorld;
	D3DXMatrixIdentity(&matWorld);
	Device->SetTransform(D3DTS_WORLD, &matWorld);

	//Set Render States
	Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	Device->SetRenderState(D3DRS_LIGHTING, FALSE);
	Device->SetRenderState(D3DRS_ALPHABLENDENABLE,  TRUE);
	Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	Device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
	Device->SetRenderState(D3DRS_ALPHAREF, 0x01);
	Device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
	Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);

	Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
	Device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
	Device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	Device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);

	Device->SetFVF(FVF_SIMPLETEXMAPVERTEX);




Share this post


Link to post
Share on other sites
turnpast    1011
If you call persent on the swap chain instead of on the device you can use the D3DPRESENT_DONOTWAIT flag avoid wasting cycles waiting for VSYNC.

Enable VSYNC with DEFAULT or ONE present interval.
Do your rendering.
Get the swap chain from the device and call Present with the DONOTWAIT flag.
If it returns D3DERR_WASSTILLDRAWING than do some other stuff with your cycles.
call Present again.

If your app runs beyond the refresh rate you are either drawing stuff that is never seen or you are more than once to each frame and you get tearing. Exceeding the frame rate != running fast.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this