Hardware trouble - ATI Radeon 9000

Started by
14 comments, last by Adriano 18 years ago
Quote:Original post by chub
By the way your program only runs at about 2 fps on my machine, so maybe you have some optimising to do?

Yea, it ran very slowly on both of my machines as well, so it may be something you want to look into.
Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )
Advertisement
I noticed shadow volumes are rendered correctly in cubemaps so it might have something to do with the render target format, is this right?
But I really can't found the bug...
Chub, would you be able to tell me the adapter format, the depth stencil format and the multisampling type and level your MDX application uses?

Quote:
Original post by chub
By the way your program only runs at about 2 fps on my machine, so maybe you have some optimising to do?


Yes it runs very slow, because of meshes shadow volumes. I have to update them one or two times per frame (backbuffer and cubemaps) and those meshes have 2500+ vertices... I have to make a low polys model of those!

[Edited by - Adriano on March 30, 2006 8:37:53 AM]
I'm using adapter format X8R8G8B8 and depth stencil format D24S8. I'm not using multisampling.

Are you using the z-pass or z-fail method to do your stencil shadows? I had some problems with the z-fail method until I got the shadow volumes caps right. The z-pass method is easier as caps are not required.

It's a good idea to use low poly versions of the meshes for shadow volumes as you generally only need an impression of the shape on the ground. I'm sure you only need to update the volumes maximum once a frame, since you should be able to reuse the same volumes for different renders. In fact you probably only need to update them once every few frames since the meshes and lights are not changing that rapidly, so I think the shadow would look about the same for a few frames.
I used mixed zfail and zpass. I followed your advice, now I update shadows only once per frame.
Look what happens on the radeon 9000.

Hardware vertex processing, zpass
HVP, z-pass - Radeon 9000
Shadow volumes are rendered from front cap to ground

Hardware vertex processing, zfail
HVP, z-fail - Radeon 9000
Shadow volumes are rendered from ground to infinity

Software vertex processing, z-fail/z-pass
SVP, Radeon 9000
Everything is OK!!!!

And most of all the code executed is always the same and it works greatly on the GeForce with Puredevice, HVP and SVP:

WHY???

I'm so sorry to bother you this way...
Something weird is going on here and I can't realize what.
I've already lost a lot of time and still haven't resolved anything
Quote:Original post by Adriano
WHY???

Don't know, sorry! It is strange how hardware vertex processing affects the results.

What do you mean by mixed zfail and zpass? Do you mean you use either zfail or zpass depending on some setting? 'Mixed' to me sounds like you're doing both at the same time which doesn't seem right.

Quote:Something weird is going on here and I can't realize what.
I've already lost a lot of time and still haven't resolved anything

Could you maybe post some of the shadow code? Maybe someone could spot something wrong that you may have missed?
i guess "mixed" wasn't the right word... Anyhow I use zfail when camera is in shadow volume(check occurs for each render target. eg: backbuffer, cubemaps...), otherwise I use zpass. This causes shadows to be updated one(usually) or two (maximum) times per frame.

Here's the code:

This is the main render function, that calls for each render target it's render method
friend void RenderPasses(CD3DManager* pD3D, CD3DDevice* pDevice, CCamera* pCamera,	                     ONFRAMERENDER_METHOD* pRenderMethod, void* pRenderContext,						 D3DCOLOR backgroundColor = 0x0){	// Reset ambient light	pDevice->pD3Ddevice->SetRenderState(D3DRS_AMBIENT, 0x0);	// Reset active lights for this device, in order to add only	// the ones needed for rendering the scene	for (UINT i = 0; i < pDevice->activeLightsCount; i++)		pDevice->pD3Ddevice->LightEnable( i, FALSE );	pDevice->activeLightsCount = 0;	// See if to render shadows and set rendering passes	if (pD3D->renderShadows)	{		pDevice->renderShadows = true;		pD3D->renderPassesCount = max(2, pD3D->renderPassesCount);		// Z-Fill and ambient pass on first pass		// Turn OFF color buffer		pDevice->pD3Ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);			// Turn ON lighting, turn OFF ambient light by default		pDevice->pD3Ddevice->SetRenderState(D3DRS_LIGHTING, TRUE);		// Turn ON depth buffer		pDevice->pD3Ddevice->SetRenderState(D3DRS_ZENABLE, TRUE);		pDevice->pD3Ddevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);		// Turn OFF stencil buffer		pDevice->pD3Ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);	}	else	        // Default to stencil buffer OFF when not rendering shadows		pDevice->pD3Ddevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);			// Clear the backbuffer and the zbuffer	pDevice->pD3Ddevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 									backgroundColor, 1.0f, 0);	if(SUCCEEDED(pDevice->pD3Ddevice->BeginScene()))	{		// Call Render method		if (pRenderMethod != NULL)			for (UINT i = 0; i < pD3D->renderPassesCount; i++)			{				// Apply rendering camera				pCamera->Render(*pDevice);						// Clear stencil buffer				pDevice->pD3Ddevice->Clear(0, NULL, D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);				// Render				pDevice->renderPassNumber = i;				pRenderMethod(*pDevice, *pCamera, pD3D->Time, pD3D->elapsedTime, pRenderContext);			}	}	// End the scene	pDevice->pD3Ddevice->EndScene();};


Here is the frame render method, executed once for zfill and ambient, and then one time for each light.
void OnFrameRender(CD3DDevice& device, CCamera camera, double time, float elapsedTime,				   void* pContext){	device.pD3Ddevice->SetRenderState(D3DRS_AMBIENT, 0x007A7A7A);        // Render shadows and light	if (device.GetRenderPassNumber() == 1)	{		shadow.Render();		light.Render();	}	// Render meshes	meshes[0].Render();	meshes[1].Render();	world.Render();}


So on 2nd pass first renders the light shadows
// CShadow::Rendervoid Render (CD3DDevice dev, CCamera camera, DWORD ambientShadow) throw (HResultException){		// Shadow rendering occurs only from second pass	if (dev.renderShadows && dev.renderPassNumber >= 1)	{		HRESULT hr;		        // Choose technique for shadow rendering		if (update)		{		}					// Turn OFF depth buffer writing		dev.pD3Ddevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);			// Turn ON colour buffer		dev.pD3Ddevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );		dev.pD3Ddevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );		dev.pD3Ddevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );		// Turn OFF lighting		dev.pD3Ddevice->SetRenderState(D3DRS_LIGHTING, FALSE);		// Turn ON stencil buffer		dev.pD3Ddevice->SetRenderState(D3DRS_STENCILENABLE,		TRUE);		dev.pD3Ddevice->SetRenderState(D3DRS_STENCILFUNC,		D3DCMP_ALWAYS);		dev.pD3Ddevice->SetRenderState(D3DRS_CCW_STENCILFUNC,	D3DCMP_ALWAYS);		dev.pD3Ddevice->SetRenderState(D3DRS_STENCILMASK,		0xffffffff);		dev.pD3Ddevice->SetRenderState(D3DRS_STENCILWRITEMASK,	0xffffffff);		// Render volume shadow		D3DXMATRIX cameraWorld;		D3DXMatrixIdentity (&cameraWorld);		// OPTIMISED: use support for 2-sided stencil		if (dev.D3DCaps.StencilCaps & D3DSTENCILCAPS_TWOSIDED)		{			// Radeon 9000 use single sided stencil		} 		else 		{			// USE THE TRADITIONAL 2-PASS METHOD			if (depthpass)			{				// Configure the necessary render states				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILREF,		0x1);				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILZFAIL,		D3DSTENCILOP_KEEP);				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILFAIL,		D3DSTENCILOP_KEEP);				// Set stencil to increment				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILPASS,      D3DSTENCILOP_INCR);				// Render front faces				...				// Set stencil to decrement				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILPASS,      D3DSTENCILOP_DECR);				// Render back faces                                ...				// Reset any necessary states				dev.pD3Ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);				// Alter stencil buffer				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILFUNC,		D3DCMP_GREATER);				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILPASS,		D3DSTENCILOP_KEEP);				}			else if (depthfail)			{				// Carmack's reverse.								// Configure the necessary render states				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILPASS,	D3DSTENCILOP_KEEP );				// Draw back sides, doing nothing with depth pass and incrementing with depth				// fail.				// Set stencil to increment				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILZFAIL,		D3DSTENCILOP_INCR);				// Render back faces				...				// Draw front sides, doing nothing with depth pass and decrementing with depth				// fail.				// Set stencil to decrement				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILZFAIL,		D3DSTENCILOP_DECR);				// Render front faces				...				// Alter stencil buffer				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILFUNC,		D3DCMP_GREATER);				dev.pD3Ddevice->SetRenderState(D3DRS_STENCILZFAIL,		D3DSTENCILOP_KEEP);			}		}		// Turn ON ambient light		dev.pD3Ddevice->SetRenderState(D3DRS_AMBIENT, ambientShadow);		// Set color buffer		dev.pD3Ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);		if (dev.D3DCaps.DestBlendCaps & D3DPBLENDCAPS_SRCCOLOR)			dev.pD3Ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);		else			dev.pD3Ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);	}}


Then renders the light
// CLight::Rendervoid Render(CD3DDevice& dev, D3DMATERIAL9 material) throw(InvalidOperationException){			// SHADOWS	// Render a light for each pass, beginning from second pass	if (dev.renderShadows && dev.renderPassNumber >= 1)	{		dev.pD3Ddevice->SetMaterial(&material);		dev.pD3Ddevice->SetLight(dev.activeLightsCount, &light);		// Turn ON current light, turn OFF previously used one		dev.pD3Ddevice->LightEnable(dev.activeLightsCount, enabled);		if(dev.activeLightsCount > 1)			dev.pD3Ddevice->LightEnable(dev.activeLightsCount-1,false);		dev.pD3Ddevice->SetRenderState(D3DRS_LIGHTING, TRUE);		// Increment active lights only if this one is enabled		if (enabled)			dev.activeLightsCount++;	}}


It's not very straightforeward.

The execution order is:
RenderPasses()
- OnFrameRender() // Zfill+ambient
-- mesh.Render() // Render objects
- OnFrameRender() // Each light
-- shadow.Render() // draw volumes to stencil
-- light.Render() // Enable current light lighting, disable previous
-- mesh.Render() // Render objects

Surely problem is a conseguence of the software architecture.
I understand it's quite difficoult to find the cause. I found on the internet that I was not the only one that had problems when running shadow volumes that worked on GeForce on a Radeon 9000. I sent this guy an e-mail and I'm still waiting his response, but I quite gave up! :(

This topic is closed to new replies.

Advertisement