God knows what a d3d device is missing and what it will do after it is lost...

Source: Internet
Author: User

Http://blog.csdn.net/cglover/archive/2007/06/01/1634300.aspx

Lost Device)
Lost Device

One Microsoft? Direct3d? It can be in an operational or lost state. The operation status is the normal status of the device. The device runs as expected and present all rendering results. When an event occurs, if the full-screen application loses the keyboard input focus, the device changes to the lost State, resulting in rendering failure. The loss state shows the silent failure of all rendering operations, which means that even if the rendering operation fails, all rendering methods can still return a success code. In this case, idirect3ddevice9: resent returns the error code d3derr_devicelost.

Direct3d intentionally did not describe in detail all the possible causes of device loss. Some typical examples include window focus loss. For example, you press Alt + TAB or a system dialog box is displayed. The device is also lost due to a power management event, or another application performs full screen operations. In addition, if the call to idirect3ddevice9: reset fails, the device is lost.

Note that all methods inherited from iunknown can still work normally after the device is lost. After a device is lost, each function may have three possibilities:

Call failed. The returned value is d3derr_devicelost-this means that the application must discover that the device has been lost, so that it knows that something has not been done as expected.
Quietly failed. Return Value: s_ OK or other values-if the function call fails quietly, the application generally cannot distinguish "Call successful" or "quietly failed ".
The function returns a return value.
Respond to lost Devices

After the device is reset, you should re-create resources (including memory resources ). If the device is lost, the application should query the device status to see if it can be restored. If not, wait until the device is restored.

If the device can be recovered, the application should destroy all the memory resources and swap chains and prepare for recovery. Then, the application calls the idirect3ddevice9: reset method. The reset method is the only valid method when a device is lost, and is the only method that an application can use to restore the device from the lost status to the operation status. The reset will fail unless the application releases all resources allocated in d3dpool_default, including resources created using the idirect3ddevice9: createrendertarget and idirect3ddevice9: createdepthsstencilsurface methods.

Most frequently called methods in direct3d do not return any information about whether the device has been lost. The application can continue to call the rendering method, such as idirect3ddevice9: rawprimitive, without receiving notifications of device loss. In direct3d, these operations are discarded until the device is reset to the operation status.

By querying the return value of the idirect3ddevice9: testcooperativelevel method, the application can decide how to handle the loss of the device.

Manage resources

Resource management is a process of raising resources from the system memory to the memory accessible to the device and discarding the memory accessible to the device. Microsoft? Direct3d? The Runtime Library has its own management algorithm based on the least recently used (least-recently-used) priority technology. When direct3d detects that a frame is in the same frame -- between idirect3ddevice9: beginscene and idirect3ddevice9: endscene call -- the device can access the memory and cannot store all resources at the same time, it switches to the most recently used (most-recently-used) priority technology.

Use the d3dpool_managed flag during creation to specify a resource managed by the system. Resources managed by the system exist continuously in the switching between the lost and operational statuses of devices. The idirect3ddevice9: reset device can be reset, and such resources can continue to work normally without reloading images. However, if the device must be destroyed and rebuilt, all resources created with d3dpool_managed must also be rebuilt.

Use the d3dpool_default flag during creation to specify that resources are placed in the default pool. Resources in the default pool do not exist continuously during the transition from the lost status to the operational status of the device. These resources must be released before calling the reset and then rebuilt.

For more information about the loss status of a device, see lost devices.

Note that not all types and purposes support resource management. For example, the object created with the d3dusage_rendertarget flag does not support resource management. In addition, resource management is not recommended for objects that require frequent changes to their content. For example, automatic management of a vertex cache that needs to be changed per frame on some hardware will seriously reduce performance. However, this is not a problem for texture resources.

Example (from codesampler ):

The following is the program code:

//-----------------------------------------------------------------------------
// Name: invalidatedeviceobjects ()
// Desc: If the lost device can be restored, the application prepares
// Device by destroying all video-memory resources and any
// Swap chains. This is typically accomplished by using the safe_release
// Macro.
//-----------------------------------------------------------------------------
Hresult invalidatedeviceobjects (void)
{
//
// To see how mismanagement of an object's reference counter can cause us
// Problems when calling reset on the device, uncomment the line below.
// The line below will call addref () on the vertex buffer object, which W
// Ill add one to the vertex buffer's reference count. This will cause it
// To hang around after we call release () on it, which is not what we
// Wanted to happen here.
//
// G_pvertexbuffer-> addref ();

//
// Note: You cocould use the safe_release macro to invalidate your device
// Objects like so:
//
Safe_release (g_ptexture)
Safe_release (g_pvertexbuffer)
Safe_release (g_pteapotmesh)

Return s_ OK;
}

//-----------------------------------------------------------------------------
// Name: restoredeviceobjects ()
// Desc: You are encouraged to develop applications with a single code path
// Respond to device loss. This code path is likely to be similar, if not
// Identical, to the code path taken to initialize the device at startup.
//-----------------------------------------------------------------------------
Hresult restoredeviceobjects (void)
{
//
// Set some important State settings...
//

D3dxmatrix matproj;
D3dxmatrixperspectivefovlh (& matproj, d3dxtoradian (45.0f ),
640366f/480366f,
// (Float) (g_d3dpp.backbufferwidth/g_d3dpp.backbufferheight ),
0.1f, 100366f );
G_pd3ddevice-> settransform (d3dts_projection, & matproj );

G_pd3ddevice-> setrenderstate (d3drs_zenable, true );
G_pd3ddevice-> setrenderstate (d3drs_lighting, true );
G_pd3ddevice-> setrenderstate (d3drs_specularenable, true );

G_pd3ddevice-> setlight (0, & g_plight0 );
G_pd3ddevice-> lightenable (0, true );

G_pd3ddevice-> setrenderstate (d3drs_ambient, d3dcolor_colorvalue (0.2f, 0.2f, 0.2f, 1.0f ));

//
// Create a texture object...
//

D3dxcreatetexturefromfile (g_pd3ddevice, "test.bmp", & g_ptexture );

G_pd3ddevice-> setsamplerstate (0, d3dsamp_minfilter, d3dtexf_linear );
G_pd3ddevice-> setsamplerstate (0, d3dsamp_magfilter, d3dtexf_linear );

//
// Create a vertex buffer...
//
// Note: When a device is lost, vertex buffers created using
// D3dpool_default must be released properly before calling
// Idirect3ddevice9: reset.
//

G_pd3ddevice-> createvertexbuffer (4 * sizeof (quadvertex ),
D3dusage_writeonly,
Quadvertex: fvf_flags,
// D3dpool_managed, // does not have to be properly released before calling idirect3ddevice9: reset
D3dpool_default, // must be released properly before calling idirect3ddevice9: reset
& G_pvertexbuffer, null );
Void * pvertices = NULL;

G_pvertexbuffer-> lock (0, sizeof (g_quadvertices), (void **) & pvertices, 0 );
Memcpy (pvertices, g_quadvertices, sizeof (g_quadvertices ));
G_pvertexbuffer-> unlock ();

//
// Create a mesh object...
//
// Note: When a device is lost, meshes created using d3dxmesh_dynamic
// Must be released properly before calling idirect3ddevice9: reset.
//

D3dxloadmeshfromx ("teapot. X ",
// D3dxmesh_systemmem, // does not have to be properly released before calling idirect3ddevice9: reset
// D3dxmesh_managed, // does not have to be properly released before calling idirect3ddevice9: reset
// D3dxmesh_writeonly, // does not have to be properly released before calling idirect3ddevice9: reset
D3dxmesh_dynamic, // must be released properly before calling idirect3ddevice9: reset
G_pd3ddevice,
Null, null, & g_pteapotmesh );
Return s_ OK;
}

//-----------------------------------------------------------------------------
// Name: render ()
// Desc:
//-----------------------------------------------------------------------------
Void render (void)
{
//
// Before we render, we need to make sure we haven'tlost our device.
// If we have, we'll need to restore it before we can continue.
//

Hresult hr;

If (g_bdevicelost = true)
{
// Yield some CPU time to other processes
Sleep (100); // 100 milliseconds

//
// Test the cooperative level to see if it's okay to render.
// The application can determine what to do on encountering a lost
// Device by querying the return value of the testcooperativelevel
// Method.
//

If (failed (hR = g_pd3ddevice-> testcooperativelevel ()))
{
// The device has been lost but cannot be reset at this time.
// Therefore, rendering is not possible and we'll have to return
// And try again at a later time.
If (hR = d3derr_devicelost)
Return;

// The device has been lost but it can be reset at this time.
If (hR = d3derr_devicenotreset)
{
//
// If the device can be restored, the application prepares
// Device by destroying all video-memory resources and any
// Swap chains.
//

Invalidatedeviceobjects ();

//
// Then, the application callthe reset method.
//
// Reset is the only method that has an effect when a device
// Is lost, and is the only method by which an application can
// Change the device from a lost to an operational state.
// Reset will fail unless the application releases all
// Resources that are allocated in d3dpool_default, including
// Those created by the idirect3ddevice9: createrendertarget
// And idirect3ddevice9: createdepthstencilsurface methods.
//

HR = g_pd3ddevice-> Reset (& g_d3dpp );

If (failed (HR ))
Return;

//
// Finally, a lost device must re-create resources (including
// Video memory resources) after it has been reset.
//

Restoredeviceobjects ();
}

Return;
}

G_bdevicelost = false;
}

//
// Render a teapot and textured quad...
//

G_pd3ddevice-> clear (0, null, d3dclear_target | d3dclear_zbuffer,
D3dcolor_colorvalue (0.35f, 0.53f, 0.7f, 1.0f), 1.0f, 0 );

G_pd3ddevice-> beginscene ();
{
D3dxmatrix matview;
D3dxmatrix matworld;
D3dxmatrix matrotation;
D3dxmatrix mattranslation;

D3dxmatrixidentity (& matview );
G_pd3ddevice-> settransform (d3dts_view, & matview );

// Place and render first teapot...
D3dxmatrixrotationyawpitchroll (& matrotation, d3dxtoradian (g_fspian), d3dxtoradian (g_fspiny), 0.0f );
D3dxmatrixtranslation (& mattranslation, 1.5f, 0.0f, 6.0f );
Matworld = matrotation * mattranslation;
G_pd3ddevice-> settransform (d3dts_world, & matworld );

G_pd3ddevice-> setmaterial (& g_teapotmtrl );
G_pteapotmesh-> drawsubset (0 );

// Place and render textured quad...
D3dxmatrixtranslation (& mattranslation,-1.5f, 0.0f, 6.0f );
Matworld = matrotation * mattranslation;
G_pd3ddevice-> settransform (d3dts_world, & matworld );

G_pd3ddevice-> setmaterial (& g_quadmtrl );
G_pd3ddevice-> settexture (0, g_ptexture );
G_pd3ddevice-> setstreamsource (0, g_pvertexbuffer, 0, sizeof (quadvertex ));
G_pd3ddevice-> setfvf (quadvertex: fvf_flags );
G_pd3ddevice-> drawprimitive (d3dpt_trianglestrip, 0, 2 );
}
G_pd3ddevice-> endscene ();

//
// If present fails with d3derr_devicelost the application needs to be
// Notified so it cleanup resources and reset the device.
//

HR = g_pd3ddevice-> present (null, null );

If (g_bhandlelostdevice = true)
{
If (hR = d3derr_devicelost)
G_bdevicelost = true;
}
}

 

"When the device is lost 』

No matter the device is lost in any way, almost all operations will fail, and only release () can be used. In fact, d3d will ensure that some operations can be successful, however, it is only "acceptable" to succeed rather than "certain" to succeed. Therefore, it is better to think that all failures will fail when lost -- And idirect3ddevice9: testcooperativelevel. Therefore, after a device is lost, you should stop the entire game loop and call idirect3ddevice9: testcooperativelevel repeatedly to determine whether the device is available.

"Idirect3ddevice9: testcooperativelevel 』

This method detects the current device status. There are four types of return values: d3d_ OK: everything is normal, d3derr_devicelost is lost, and d3derr_devicenotreset can be reset. In addition, there is also the d3derr_driverinternalerror added by d3d9. When this happens, you will be finished, and it is basically impossible to recover. Stop the program.
In order, if the game is running properly, d3d_ OK will return; if the device is lost and cannot be recovered at this time, for example, when the full screen mode is enabled, the user switches to the Windows desktop, d3derr_devicelost will be returned. If the user switches back to the game, the device can be restored (not recovered yet! Only "yes"), and d3derr_devicenotreset will be returned.
In addition, idirect3ddevice9: Present will return a similar value, but you 'd better not count on this, honestly using testcooperativelevel. Because the present still returns d3derr_devicelost when the device can be restored (in other words, testcooperativelevel will be fully integrated into the present when the device is d3d10)

"Processing device loss 』

See the following pseudocode:

Switch (idirect3ddevice9: testcooperativelevel ()){
Case d3d_ OK:
Gameloop ();
Break;
Case d3derr_devicelost:
Break;
Case d3derr_devicenotreset
Onlostdevice ();
Idirect3ddevice9: reset ();
Onresetdevice ();
Break;
Default:
Quitgame ();
Break;
}

Gameloop () is the process of running your game. Write the switch in the gamemain () part of our game framework. You can view the source code that comes with any of the specific locations.
It seems that I have never talked about the idirect3ddevice9: reset parameter? Because there is only one parameter, It is the pointer to d3dpresent_params. Save the d3dpresent_params structure you used when creating the device for reset.
Onlostdevice () is to release all d3dpool_default resources, and onresetdevice () is to create * () to restore! You may notice that id3dxfont and id3dxsprite all have methods of the same name, which are called at this time. If you do not do this, that is, keep any d3dpool_default resources, idirect3ddevice9: reset will certainly fail.
In addition, in onresetdevice, you need to re-set setrenderstate, setsamplerstate, and so on. After reset, these items are also lost. In fact, reset is similar to re-creating a device. The difference is that you need to release the resources of d3dpool_managed if you re-create a device. This topic will not be discussed.
It can be seen from the code that the program did not do anything when d3derr_devicelost was just dumb. I think this is a good habit, because there is no guarantee what can be done in addition to release in d3derr_devicelost, so it is better to wait for the device to use it.

If you are too lazy to manage resources, all d3dpool_managed is better. As for rendering objects? Find a solution.

"Manual Manufacturing" device loss "』

"Why do we need to make devices lost ?" If you want to change the game resolution, color depth, and switch the full screen and window status, you must also use reset. Similarly, all d3dpool_default resources must be released before reset (strictly speaking, there are more resources to be released, but you don't need to worry about creating such resources in 2D.) And call methods such as id3dxsprite: onlostdevice. This is the "device loss" of manual manufacturing. In fact, in this process, the device is not really lost, but it will be unavailable for a period of time. At this time, the reset has not yet returned, and the entire d3d device is like dead. For example, if you switch the desktop resolution, nothing will be displayed on the monitor for a while, and then it will soon become normal. This is the same reason. After successful reset, remember to restore the resource.
You may notice that the reset here is not the same as the reset above. This is indeed the case. This is to reset the status rather than recover the device. Therefore, to change the resolution and color of a reset, you need to write it out of the switch, that is, do not mix it with the meaning-_-BB. And you only need onlostdevice-> Reset-> onresetdevice. Remember: Calling reset correctly will not cause device loss. Do not confuse this concept.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.