Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

Lost devices

Started by phoenix26 Aug 31, 2006 at 6:30 AM 5 replies 1.7k views
Original Post
phoenix26
phoenix26
I’m having a really annoying problem. I have searched and searched for an answer, but haven’t found anything. I am trying to add handling lost devices into an engine that I’m writing, but am not getting anywhere. This is my situation at the moment: My code runs fine (in fullscreen), I can alt-tab out of the app and alt-tab back in, and it doesn’t crash (yay), but nothing draws. The only thing that seems to work is the call to clear the screen. None of my drawing code works. When I close the app and look in visual studio’s output window, I get a whole bunch of notifications about “first chance exceptions”. I eventually tracked it down to any call to DrawPrimitiveUP (or any primitive drawing for that matter). I have taken my drawing code and pasted it into an example dealing with lost devices I found on Drunken Hyena, and it works fine, so I’m guessing that it’s not the drawing code at fault. It must be something to do with how I’m recovering from the lost devices, but I can’t figure out what I’m doing differently from the example that works. Thus the reason for my question. ;o) This is the code in question: bool D3DVideoDriver::BeginScene(bool ClearTarget, bool ClearDepth, bool ClearStencil) { if (!m_pDevice) return false; if (m_DeviceLost) { OutputDebugString("device is lost\n"); if (FAILED(hr = m_pDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) { // Device lost but cannot be reset ReleaseDeviceObjects(); Sleep(250); return true; } if (hr == D3DERR_DEVICENOTRESET) { // Device lost but can be reset hr = m_pDevice->Reset(&m_D3Dpp); if (FAILED(hr)) { // failed to reset device OutputDebugString("Failed to reset device\n"); return true; } Log_Event("Lost device reset.",""); OutputDebugString("device is being reset\n"); RestoreDeviceObjects(); } return true; }// failed to test device cooperative level m_DeviceLost = false; OutputDebugString("device is reset\n"); } if (m_bIsSceneRunning) return true; OutputDebugString("Begin scene\n"); DWORD dw = 0; // Is anything going to be cleared? if (ClearTarget || ClearDepth || ClearStencil) { if (ClearTarget) dw |= D3DCLEAR_TARGET; if (ClearDepth) dw |= D3DCLEAR_ZBUFFER; if (ClearStencil && m_bStencil) { dw |= D3DCLEAR_STENCIL; } if (FAILED(m_pDevice->Clear(0, NULL, dw, m_ClearColour, 1.0f, 0))) { return false; } } if (FAILED(m_pDevice->BeginScene())) { return false; } m_bIsSceneRunning = true; m_Timer.Update(); MOUSE.Refresh(); KEYBOARD.Refresh(); return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool D3DVideoDriver::EndScene() { if (!m_pDevice) return false; if (!m_bIsSceneRunning) return true; int width = (int)((float)m_nWidth * 0.1375f); int height = (int)((float)m_nHeight * 0.1833f); OutputDebugString("Before draw\n"); Draw2DRectangle(Core::Rect(m_nWidth - width - 2, m_nHeight - height - 2, m_nWidth - 2, m_nHeight - 2), SColour(255,255,255,255), 0); OutputDebugString("End scene\n"); hr = m_pDevice->EndScene(); if (FAILED(hr)) { return false; } if (!m_bWindowed || (m_nNumChildWnds <= 0)) { hr = m_pDevice->Present(NULL, NULL, NULL, NULL); } else { hr = m_pChain[m_nActiveWnd]->Present(NULL, NULL, NULL, NULL, 0); } if (hr == D3DERR_DEVICELOST) { if (!m_DeviceLost) Log_Warning("Rendering device lost.",""); m_DeviceLost = true; } m_bIsSceneRunning = false; return true; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool D3DVideoDriver::Draw2DRectangle(const Core::Rect &position, SColour colTopLeft, SColour colTopRight, SColour colBottomRight, SColour colBottomLeft, float rotate) { if (!m_pDevice) return false; if (!m_bIsSceneRunning) return true; OutputDebugString("start of 2d draw\n"); float xTrans = - (float)(m_nWidth>>1); float yTrans = (float)(m_nHeight>>1); D3DXMATRIX world, trans, scale; D3DXMatrixScaling(&scale, (float)(position.BottomRight.x - position.TopLeft.x), (float)(position.BottomRight.y - position.TopLeft.y), 1.0f); D3DXMatrixTranslation(&trans, position.TopLeft.x + xTrans, -position.TopLeft.y + yTrans, 0); world = scale * trans; if (rotate) { D3DXMATRIX rot; D3DXMatrixRotationZ(&rot, rotate); world = scale * rot * trans; } m_pDevice->SetTransform(D3DTS_WORLD, &world); S2DVertex verts[4]; verts[0] = S2DVertex(Core::Vector3df(0,0,1), colTopLeft, Core::Vector2df(0,0)); verts[1] = S2DVertex(Core::Vector3df(1,0,1), colTopRight, Core::Vector2df(0,0)); verts[2] = S2DVertex(Core::Vector3df(1,-1,1), colBottomRight, Core::Vector2df(0,0)); verts[3] = S2DVertex(Core::Vector3df(0,-1,1), colBottomLeft, Core::Vector2df(0,0)); short indices[6] = {0,1,2,0,2,3}; m_pDevice->SetTexture(0,NULL); setRenderMode2D( ((colTopLeft.GetAlpha() < 255) || (colTopRight.GetAlpha() < 255) || (colBottomLeft.GetAlpha() < 255) || (colBottomRight.GetAlpha() < 255)), false, false); setVertexType(OVT_2DVERTEX); OutputDebugString("just before 2d draw\n"); if (FAILED(m_pDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, 4, 2, &indices[0], D3DFMT_INDEX16, &verts[0], sizeof(S2DVertex)))) { OutputDebugString("draw failed!\n"); return false; } OutputDebugString("end of 2d draw\n"); return true; } // bool Draw2DRectangle() The calls to ReleaseDeviceObjects(); and RestoreDeviceObjects(); in the BeginScene() function are basically meaningless, since the functions are empty. I’m not loading any device dependant resources (that I know of). In the drawing function, The setRenderMode2D() call sets all the renderstates that I need to do the 2d drawing, and setVertexType() basically just sets the correct FVF. When I run this is a program that is just calling BeginScene() and then EndScene() in it’s main loop, I get the following output: Begin scene Before draw start of 2d draw just before 2d draw end of 2d draw End scene Begin scene Before draw start of 2d draw just before 2d draw end of 2d draw End scene device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is lost device is being reset device is lost device is reset Begin scene Before draw start of 2d draw just before 2d draw First-chance exception at 0x7c57e592 in OrangeGUIEditor.exe: Microsoft C++ exception: long @ 0x0012f61c. draw failed! End scene Begin scene Before draw start of 2d draw just before 2d draw First-chance exception at 0x7c57e592 in OrangeGUIEditor.exe: Microsoft C++ exception: long @ 0x0012f61c. draw failed! End scene Begin scene Before draw start of 2d draw just before 2d draw First-chance exception at 0x7c57e592 in OrangeGUIEditor.exe: Microsoft C++ exception: long @ 0x0012f61c. draw failed! End scene Begin scene Before draw start of 2d draw just before 2d draw First-chance exception at 0x7c57e592 in OrangeGUIEditor.exe: Microsoft C++ exception: long @ 0x0012f61c. draw failed! End scene Can anybody see what I’m doing wrong? As far as I can see, I’m doing everything that needs to be done, but I’ve never done this before, so I can’t be sure. Please help me, cause this is really starting to annoy me. Thanks in advance
blaze02
blaze02
DrawPrimitiveUP and Present can return a fail value (D3DERR_DEVICELOST) indicating a lost device. I'm assuming your not rendering because your device is lost.

So what have you done to handle the lost device. Do you plan on reset'ing the device or recreating. I've just been recreating my device. It takes about 2-3 seconds and I haven't had any trouble with it. I don't know what kind of speed you get by just reset'ing the device. But it sounds like you aren't doing either :( haha. If you are trying, make sure your call to recreate or reset do not fail. And if they do, its most likely in the fullscreen and backbuffer size/type values of the d3d present parameters struct.

Hope that helps.

Edit: Now that I look at your code...
I would guess you are using a variable that left scope during reset and never came back. Probably a texture, make sure you recreate them(unless they are managed). Vertex buffers and index buffers, etc.
Evil Steve
Evil Steve
When you reset the device, you need to reset all render states, matrices, stream sources, etc. My guess is that one of these isn't being reset. I can't see anything wrong with your code offhand though.
XiotexStudios
XiotexStudios
I know it can get slow but enable full debug output from the DX runtimes - it will tell you what resource is still lingering about.
Byron Atkinson-JonesXiotex Studioswww.xiotex.com
phoenix26
phoenix26
Wow! Thanks for all the quick replys. In response:

I'm not using any vertex\index buffers, as far as I know I'm not loading any textures. I think i took most of them out while trying to track down this stupid bug. I'll make sure though... Other than that, all the values I use in the call are local to the function, so won't be out of scope. I catch the D3DERR_LOSTDEVICE failed call of the Present() function, and the DrawPrimitiveUP() function fails and says there is something wrong with the call. It is apparently invalid. Doesn't day why. Very helpful.

All my render states are set just before the call to the drawprimitive in setRenderMode2D().

How do I enable the full debug on the DX runtimes? Where does the output go?

Thanks again
sirob
sirob
Quote:
Original post by phoenix26
How do I enable the full debug on the DX runtimes? Where does the output go?


There is a utility in the Control Panel (If you're using the August SDK this has been moved to the Start Menu). You'll need to select to use the "Debug Runtimes" from that utility, and set the warning level.

After that, the debug output should show in the output window in Visual Studio.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
phoenix26
phoenix26
Fantastic! Thanks everyone. after enabling the debug run-times,i found that i wasn't resetting my vertex format (due to some optimisations i put it. DOH!). Once i fixed that everything works perfectly.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.