# Problem reseting device when using render target

How can I reset the device when I am rendering to a surface, and then stretching that surface to the back buffer. If i don't change the render target everything goes well, but when i change the render target(only once when the game starts), i get D3DERR_INVALIDCALL. What do i have to do to stop getting this error. I've tried to set the render target back to the backbuffer, and then after resetting the device back to the surface but it didn't work.

EDIT:

HRESULT result;

initD3Dpp();
sprite->OnLostDevice();

device3d->SetRenderTarget(0, oldSurface);

if(oldSurface) oldSurface->release();
SAFE_RELEASE(surface);

result = device3d->Reset(&d3dpp);

device3d->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device3d->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

device3d->CreateRenderTarget(GAME_WIDTH, GAME_HEIGHT, d3dpp.BackBufferFormat, d3dpp.MultiSampleType, d3dpp.MultiSampleQuality, false, &surface, NULL);
device3d->GetRenderTarget(0, &oldSurface);
device3d->SetRenderTarget(0, surface);

sprite->OnResetDevice();

return result;


From the D3D documentation for SetRenderTarget:

If NULL, the color buffer for the corresponding RenderTargetIndex is disabled. Devices always must be associated with a color buffer.

You don't have a colour buffer associated with your device when you're calling Reset, in other words, so Bad Things may happen.

In general your management of this seems a little screwed. You're also not saving out the original render target here; something like this seems more appropriate:

// when creating and after reset; this stores a copy of the original
// colour buffer so that we can restore it properly when we need to
device->GetRenderTarget (0, &savedrendertarget);
device->SetRenderTarget (0, &newrendertarget);

// when destroying and before reset; restores the original render target;
// note that we Release the saved copy *after* resetting it otherwise we'll
// leak it; assumes that we also want to Release the new one as part of
// normal operation
device->SetRenderTarget (0, &savedrendertarget);
savedrendertarget->Release ();
newrendertarget->Release ();

• I replaced the code and reedited the question with the new code but it still doesn't work. Am I not doing it right? – balauru Mar 26 '13 at 3:19
• Solved the problem. I was using SAFE_RELEASE(...) which was releasing and then setting it to NULL. Changed the SAFE_RELEASE at oldSurface with if(oldSurface) oldSurface->release() and it works. It takes some time but it works – balauru Mar 26 '13 at 8:34

You've probably forgotten to call IUnknown::Release on the render targets. This includes your new rendertarget and the copy you've taken to restore.

Before you call reset, you are required to release all D3DPOOL_DEFAULT resources (which includes rendertargets), so release them!

You can find all the details on msdn

You can avoid this by using a IDirect3DDevice9Ex device, but then you can't run on XP (which is probably fine these days)

• it doesn't work even if i release the surface. I'll post the code with the release in 1 min – balauru Mar 26 '13 at 0:22