handling lost devices

posted in Gamedev info
Published September 05, 2013
Advertisement
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]DX9 Lost Device Example[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]I decided to implement Alt-tab in my project, and went looking for info on handling[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]lost devices. The DirectX docs were their usual disappointment. Eventually a serach[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]of Gamedev and the Web found all the bits an pieces needed, but not in one place.[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]So I decided to post what I'd found for use by others.[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]First, you'll want to make sure you load all non-dynamic resources into managed memory pool,[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]not default. This essentially keep a backup copy of resources in regular ram that D3D can use [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]to automtically restore vidram as needed. [/background]

[/font][/font][/color]



[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Here's the basic algo:[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]result=Present();[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]if (result == D3DERR_DEVICELOST) do_lost_device();[/background]

[/font][/font][/color]



[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]do_lost_device:[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]while ( TestCooperativeLevel() != D3DERR_DEVICENOTRESET ) [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]{[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]do_win_messages();[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Sleep(10);[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]}[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]release_stuff();[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]d3d_device_ptr->Reset(&params);[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]while ( TestCooperativeLevel() != D3D_OK ) [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]{[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]do_win_messages();[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Sleep(10);[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]}[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]reload_stuff();[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]reset_stuff();[/background]

[/font][/font][/color]


[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]release_stuff:[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]call OnLostDevice for all your interfaces (fonts, sprite object, etc). You don't[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]have to release them. Release all default memory pool resources: dynamic textures,[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]dynamic bitmaps, index and vertex buffers you allocate, etc. Note that [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]LoadMeshFromX with no flags defaults to D3DPOOL_DEFAULT, and Mesh.GetVertexBuffer[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]returns a copy of the mesh's vertex buffer object, not its address. Both of these[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]bit me when trying to find all the places I created something in D3DPOOL_DEFAULT. [/background]

[/font][/font][/color]


[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]reload_stuff:[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Call OnResetDevice for your interfaces (fonts, sprite object, etc).[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Reload / recreate your D3DPOOL_DEFAULT resources: dynamic textures, dynamic[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]bitmaps, index and vertex buffers you allocate, etc. This is basically a copy [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]and paste of the code where you do this the first time.[/background]

[/font][/font][/color]




[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]reset_stuff:[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Pretty much all of D3D's internal states get wiped on lost device, so you have to[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set everything back to the way you want it again. This will vary by title. [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]I reset everyting that I set between the time I create the D3D device and the [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]time I start the game itself:[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set default material[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set flexible vertex format[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set projection matrix[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set default texture stage states[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set gourard shading[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]turn on mipmaps[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set min mag filetrs to anisotropic[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]set ambient light level[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]turn on normalizing normals (I do scaling and lighting)[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]turn on specular[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]turn on alpha blending[/background]

[/font][/font][/color]




[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]I saw one posting that tested co-op level before calling present, but that would[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]add an unnecessary check when things are running correctly, i would think.[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]The basic idea is you wait for "device not reset". You have to process windows [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]messages while you do so. It has to do with D3D knowing when you get focus back [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]apparently. The call to Sleep() releases clock cycles to the OS while you wait.[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]When you get "Device not reset", you release stuff from vidram. Then you call[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Reset(). [/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]IF YOU STILL HAVE STUFF IN VIDRAM, Reset() WILL FAIL WITH "Invalid Call"![/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]If Reset() succeeds, you then have to wait for DirectX to come back alive. So you[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]test cooperative level until you get "D3D_OK". During this time, apparenly windows[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]will switch the resolution to match your desired resolution, thus the need to wait[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]a moment. Again, windows messages must be processed while you wait, and you want [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]to Sleep() to give clock cycles back to the OS. Once you get "D3D_OK", you own [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]the video card again, and you're pretty much back where you were when you first[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]created your D3D device, except your managed stuff is still loaded. Call OnReset()[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]for your interfaces (font, sprite, etc), reload or re-create your non-managed[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]resources, reset D3D back to the way you want it, and your done! smile.png[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Ok, so you do all this, and it doesn't work, or it works sometimes, but not at[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]other times. Then what? Enter the dreaded "Purple Screen"! purplescreen(); is [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]a simple tesing routine that you can insert into your code to determine where [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]you are creating things in vidram that you're not releasing. In semi-pseudocode:[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]void purplescreen()[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]{[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]int a;[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]a=0;[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]do[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]{[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]beginscene[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]clear // clear screen to purple 100,0,50[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]endscene[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]result=present[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]if result == D3DERR_DEVICELOST do_lost_device()[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]do_win_messages();[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]if (keypressed(VK_ESCAPE)) a=1;[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Sleep(10);[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]}[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]while (a != 1);[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]}[/background]

[/font][/font][/color]


[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]While the purple screen is displayed, you can alt-tab to and from your game, then[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]hit Esc to continue. Use it to "bracket" where you're using vidram you need to[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]relase. If you can alt-tab from the purple screen and back, your ok. If you get [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]"invalid call" when you Reset(), you've loaded something you haven't released.[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]So you put the purple screen at program start, right after you load everything.[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]well of course it works there, you used that code to decide what to release![/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]So add another purple screen later on, like right after you draw your scene and[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]present it. OK, doesn't work there. Now you know D3D is allocating vidram[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]somewhere between those two points. Move around your calls to purplescreen[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]until you find where. Once you find the resource, add it to release_stuff()[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]and reload_stuff(). Test it again. Eventually you'll find them all, and all of[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]a sudden it will work![/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]The info in this post came from about 4 different sources and took me about two [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]days to find and put together into working code. It took me another two days [/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]to find, release, and reload/recreate everything in my project. In my case it was[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]finding index and vertex buffers used to draw procedurally height mapped ground[/background]

[/font][/font][/color]
[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]quads.[/background]

[/font][/font][/color]

[color=rgb(40,40,40)][font=arial][font=helvetica]

[background=rgb(250,251,252)]Hopefully this post will save someone some time in the future.[/background]

[/font][/font][/color][color=rgb(40,40,40)][font=arial] [/font][/color]
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement