• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 8  文章 - 26  trackbacks - 0
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(5)

            隨筆檔案

            文章分類

            文章檔案

            相冊

            C++語言

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            directx中丟失的設備(lost device)
            2008-05-10 23:02

            丟失的設備

            一個Microsoft? Direct3D?可以處于操作狀態或丟失狀態。操作狀態是設備的正常狀態,設備按預期運行并present所有渲染結果。當事件發生時,如全屏應用程序失去鍵盤輸入焦點,設備就轉變到丟失狀態,這會導致渲染無法進行。丟失狀態表現為所有渲染操作的悄然失敗,這意味著即使渲染操作失敗所有的渲染方法仍可以返回成功碼。在這種情況下,IDirect3DDevice9:
            resent返回錯誤碼D3DERR_DEVICELOST。

            Direct3D有意沒有對可能導致設備丟失的所有情況進行詳細說明。一些典型的例子包括窗口失去焦點,例如用戶按下了ALT+TAB或彈出了一個系統對話框。設備也會因為電源管理事件而丟失,或者另一個應用程序進行全屏操作。另外,任何對IDirect3DDevice9::Reset調用的失敗會把設備置為丟失狀態。

            注意    可以保證所有繼承自IUnknown的方法在設備丟失后仍能正常工作。設備丟失后,每個函數一般有三種可能:

            調用失敗,返回值為D3DERR_DEVICELOST – 這意味著應用程序必須發現設備已經丟失,從而知道一些事情沒有按照預期進行。
            悄然失敗,返回值為S_OK或其它值 – 若函數調用悄然失敗,則應用程序一般無法區分出“調用成功”或“悄然失敗”。
            函數返回一個返回值。
            對丟失的設備作出響應

            設備在被重置后,應該重新創建資源(包括顯存資源)。如果設備丟失了,那么應用程序應該查詢設備狀態,看是否可以將之恢復回操作狀態。如果不行,那么就等到設備可以被恢復為止。

            如果設備可以被恢復,那么應用程序應該銷毀所有顯存資源和交換鏈,并準備恢復。然后,應用程序調用IDirect3DDevice9::Reset方法。Reset方法是當設備丟失時唯一有效的方法,并且是應用程序可用來把設備從丟失狀態恢復到操作狀態的唯一方法。除非應用程序釋放所有在D3DPOOL_DEFAULT中分配的資源,包括用IDirect3DDevice9::CreateRenderTarget和IDirect3DDevice9::CreateDepthSstencilSurface方法創建的資源,否則Reset將會失敗。

            Direct3D中大部分被頻繁調用的方法不返回任何關于設備是否已丟失的信息。應用程序可以繼續調用渲染方法,如IDirect3DDevice9:
            rawPrimitive,而不會收到設備丟失的通知。在Direct3D內部,這些操作被拋棄,直到設備被重置為操作狀態為止。

            通過查詢IDirect3DDevice9::TestCooperativeLevel方法的返回值,應用程序可以決定在遇到設備丟失時如何處理。

            管理資源


            資源管理是將資源從系統內存提升到設備可訪問存儲器及從設備可訪問存儲器中拋棄的過程。Microsoft? Direct3D?運行庫有自己的基于最近最少使用(least-recently-used)優先級技術的管理算法。當Direct3D檢測到在一幀中——在IDirect3DDevice9::BeginScene和IDirect3DDevice9::EndScene調用之間——設備可訪問內存無法同時存儲所有資源時,它就切換到最近最多使用(most-recently-used)優先級技術。

            在創建時使用D3DPOOL_MANAGED標志指定一個由系統管理的資源。由系統管理的資源在設備的丟失狀態和操作狀態間的轉換中持續存在。通過調用IDirect3DDevice9::Reset設備可以被重置,并且這類資源可以繼續正常運作而無需重新載入圖片。但是,如果設備必須被銷毀和重建,那么所有用D3DPOOL_MANAGED創建的資源也必須被重建。

            在創建時使用D3DPOOL_DEFAULT標志指定把資源放在默認的池中。在默認的池中的資源在設備從丟失狀態到操作狀態的轉換過程中不持續存在,這些資源必須在調用Reset之前釋放,然后重建。

            更多有關設備的丟失狀態的信息,請參閱丟失的設備。

            注意不是所有的類型和用途都支持資源管理。例如,用D3DUSAGE_RENDERTARGET標志創建的對象不支持資源管理。另外,不建議對需要頻繁改變其內容的對象使用資源管理。例如,在某些硬件上對一個每幀都需改變的頂點緩存進行自動管理會嚴重降低性能。但是,對紋理資源來說這不是一個問題。


            例子(摘自codesampler):

            以下內容為程序代碼:

            //-----------------------------------------------------------------------------
            // Name: invalidateDeviceObjects()
            // Desc: If the lost device can be restored, the application prepares the
            //        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 could 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 to
            //        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 ),
                                             640.0f / 480.0f,
                                             //(float)(g_d3dpp.BackBufferWidth / g_d3dpp.BackBufferHeight),
                                             0.1f, 100.0f );
                 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, NULL, NULL, &g_pTeapotMesh );
                 return S_OK;
            }

            //-----------------------------------------------------------------------------
            // Name: render()
            // Desc:
            //-----------------------------------------------------------------------------
            void render( void )
            {
                 //
                 // Before we render, we need to make sure we haven''t lost 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 the
                             // device by destroying all video-memory resources and any
                             // swap chains.
                             //

                             invalidateDeviceObjects();

                             //
                             // Then, the application calls the 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_fSpinX), 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, NULL, NULL );

            if( g_bHandleLostDevice == true )
            {
            if( hr == D3DERR_DEVICELOST )
            g_bDeviceLost = true;
            }
            }

             

            『當設備丟失之后』

              不論通過任何方式發生了設備丟失,所有的操作幾乎都會失效,只有Release()可以用——其實D3D會保證有部分操作可以成功,但是也僅僅是“可以”成功而不是“一定”成功,所以你還不如認定丟失的時候全都會失敗比較好——以及IDirect3DDevice9::TestCooperativeLevel。因此在設備丟失之后,你應該停止整個游戲循環,而通過反復調用IDirect3DDevice9::TestCooperativeLevel判斷設備是否可用。

            『IDirect3DDevice9::TestCooperativeLevel』

              這個方法檢測當前的設備狀態。返回值有四種:D3D_OK一切正常,D3DERR_DEVICELOST設備丟失,D3DERR_DEVICENOTRESET設備可以Reset。另外還有D3D9新增的D3DERR_DRIVERINTERNALERROR,遇到這個你就完蛋了,基本不可能恢復了,終止程序吧。
              按照順序來講,如果游戲在正常運行,D3D_OK會返回;如果發生了設備丟失并且在這個時候不能恢復,比如全屏幕模式的時候用戶切換到了Windows桌面,就會返回D3DERR_DEVICELOST;如果用戶又切換回了游戲,設備可以恢復了(還沒恢復呢!只是“可以”恢復而已),就會返回D3DERR_DEVICENOTRESET。
              另外,IDirect3DDevice9::Present也會返回類似的值,不過你最好別指望這個,老老實實的用TestCooperativeLevel。因為Present在設備可以恢復的時候還是返回D3DERR_DEVICELOST(外一句:D3D10的時候TestCooperativeLevel就會完全整合到Present里面了,可喜可賀可喜可賀)

            『處理設備丟失』

              看下面的偽代碼:

            switch (IDirect3DDevice9::TestCooperativeLevel()){
              case D3D_OK:
                GameLoop();
                break;
              case D3DERR_DEVICELOST:
                break;
              case D3DERR_DEVICENOTRESET
                OnLostDevice();
                IDirect3DDevice9::Reset();
                OnResetDevice();
                break;
              default:
                QuitGame();
                break;
            }

              GameLoop()就是你的游戲運行的過程了。把這個switch寫在我們游戲框架的GameMain()部分,具體的位置可以看任何一話附帶的源代碼。
              好像我一直沒有講IDirect3DDevice9::Reset的參數啊?因為只有一個參數,就是指向D3DPRESENT_PARAMS的指針。把你第一次創建設備時使用的D3DPRESENT_PARAMS結構保存起來,供Reset來用。
              OnLostDevice()就是Release掉所有D3DPOOL_DEFAULT的資源,OnResetDevice()就是Create*()恢復啦!你可能注意到ID3DXFont、ID3DXSprite等等都有同名的方法,就是在這個時候調用的。如果你沒有這么做,也就是說還保留著任何D3DPOOL_DEFAULT的資源的話,IDirect3DDevice9::Reset就一定會失敗。
              另外在OnResetDevice里面你還要重新進行SetRenderState、SetSamplerState等等,Reset之后這些東西也丟失了。實際上Reset和重新創建一次設備類似,所不同的是重新創建設備的話你需要連D3DPOOL_MANAGED的資源也Release掉。這個話題就不討論了。
              從代碼可以看出來,D3DERR_DEVICELOST時程序什么都沒做,只是在傻等。我認為這是一個好習慣,因為實在不能保證在D3DERR_DEVICELOST時除了Release還能干什么,與其這樣還不如等設備能用了再說。

              實在懶得管資源的話,全部D3DPOOL_MANAGED好了。至于渲染對象?自己想辦法。

            『人工制造“設備丟失”』

              “干嘛還要制造設備丟失???”如果更改游戲分辨率、色深、切換全屏幕及窗口狀態,進行這樣的操作也要通過Reset,同樣的,Reset之前也要釋放掉所有D3DPOOL_DEFAULT資源(其實嚴格來說,還有更多的資源也要釋放,不過在2D下基本不會創建這類資源,你就不用管了)并且調用ID3DXSprite::OnLostDevice之類的方法。這就是人工制造“設備丟失”了。實際上在這個過程設備并沒有真正的丟失,只是會有一段時間處于不可用的狀態,此時Reset尚未返回,整個D3D設備就好像死了一樣。舉個例子,你切換桌面分辨率,會有那么一段時間顯示器上什么都不顯示,然后很快就正常了。和這個現象是同一個原因。Reset成功后記得恢復資源。
              你可能注意到這里的Reset和上面的Reset不是一回事。的確是這樣,這里是為了重設狀態而不是恢復設備。因此更改分辨率、色深的Reset需要寫到switch外面,也就是別和它攪和的意思-_-bb。而且你只需要OnLostDevice -> Reset -> OnResetDevice。記?。赫_的調用Reset不會造成設備丟失,這個概念別弄混了。  

            轉自:http://blog.csdn.net/zdl1016/archive/2007/07/04/1678507.aspx

            posted on 2008-07-18 10:27 楊彬彬 閱讀(1472) 評論(0)  編輯 收藏 引用 所屬分類: Directx
            久久亚洲AV无码西西人体| 久久青草国产手机看片福利盒子| 88久久精品无码一区二区毛片| 97超级碰碰碰久久久久| 久久精品国产影库免费看| 国产香蕉97碰碰久久人人| 亚洲精品成人久久久| 无码专区久久综合久中文字幕| 99久久久精品免费观看国产| 成人精品一区二区久久久| 一本大道久久香蕉成人网| 精品久久久久久久无码 | 国产精久久一区二区三区| 日韩精品久久久久久久电影| 精品熟女少妇a∨免费久久| 精品久久综合1区2区3区激情 | 国产成人精品久久二区二区| 久久e热在这里只有国产中文精品99 | 99久久精品免费| 久久久久青草线蕉综合超碰| 99久久婷婷免费国产综合精品| 无码国内精品久久人妻麻豆按摩 | 99久久国产综合精品女同图片| 精品一区二区久久久久久久网站| 亚洲精品午夜国产va久久| 国产69精品久久久久9999| 国产成人精品免费久久久久| 久久精品一本到99热免费| 久久高潮一级毛片免费| 久久97精品久久久久久久不卡| 中文精品99久久国产 | 久久精品一本到99热免费| 久久这里只有精品视频99| 欧美精品一区二区精品久久 | 亚洲av日韩精品久久久久久a| 久久丝袜精品中文字幕| 99久久国产综合精品成人影院| av无码久久久久久不卡网站| 一本色道久久99一综合| 精品国产乱码久久久久软件| 久久99九九国产免费看小说|