Sign in to follow this  
Adriano

Hardware trouble - ATI Radeon 9000

Recommended Posts

Hi. I just tried to run my volume shadows code on a ATI Radeon 9000 and I noticed it draws the volumes too... and I didn't ask it to do that! However I already ran the same code on an old 3D Prophet 4500 and on a (quite) new GeForce 6800 and everything is OK. I took a look with CapsViewer and I saw Radeon 9000 and 3D Prophet 4500 don't support double sided stencil, while GeForce obviously does, so I exclude it's a technique problem. Also, program runs on both Radeon and Prophet with D3DFMT_X8R8G8B8 (Windowed) adapter format, EDIT: but the former uses D3DFMT_D24S8 depth/stencil format, while the latter uses D3DFMT_D24X4S4. So why do they behave differently? Any ideas about what causes the problem? [Edited by - Adriano on March 28, 2006 2:57:04 AM]

Share this post


Link to post
Share on other sites
What does the reference rasterizer do? Do you have the latest drivers for all the cards? Are you checking the return value of your DX functions to see if any fail, and do yuou have the debug runtimes installed? (That'll tell you if any function fails, and why)

Share this post


Link to post
Share on other sites
Thx for the reply Evil Steve.
I don't have debug runtime installed on the Radeon computer as I use it only for testing release versions of my software. I'd rather not install everything on this computer, if possible...
Ref rast gives no problems. I emulated a D3DFMT_D24S8 depth/stencil (EDIT: using single sided stencil) on Prophet computer (where debug libraries are installed) and shadows were drawn correctly.
I check all critical DX functions return value but they seems to work fine. It runs quite ok on Radeon but it simply draws volumes, as if depth write was enabled while rendering to stencil (but it isn't).
Lastly I didn't find any specific driver updates for the Radeon 9000 on the net.
I wonder if this is a strictly hardware related problem, or due to system configuration, or so on...

Share this post


Link to post
Share on other sites
Do you want to try it on a more recent ATI card? I can try running on my 9600xt if you want. I also have a quad-core machine with a 7800gt if you would like to try it on that as well.

Share this post


Link to post
Share on other sites
Here are the screenshots

Expected: (GeForce)
http://www.hostingfiles.net/image.php?id=3579

I get: (Radeon)
http://www.hostingfiles.net/image.php?id=3580

I'm glad to know that on newer hardware it works fine. I hope it's just a local problem... Anyhow any suggestions are still welcome
Thank you a lot this forum really rocks!

Share this post


Link to post
Share on other sites
I have an ATI Radeon 9000, so I tried out your program. Here's what I get:

image hosting by imagevenue.com

So I get the shadow volumes shown too, and I'm using the latest drivers.

However I've used shadow volumes in an MDX application and they work fine for me using the single sided stencil method. So I don't think the hardware is the problem.

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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::Render
void 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::Render
void 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! :(

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