2014-01-07 49 views
0

我j使用一個無國界的窗口和複製從YouTube視頻設備復位代碼,並在那裏工作,但我只是從那裏得到消息:DIRECTX9:按Ctrl + Alt + Del鍵後重置設備

if(FAILED(hr)){ 
    MessageBox(0, "Failed to reset device!", 0, 0); 
    return; 
} 

我哪裏錯了?我忘了InvalidateDeviceObjects()的東西嗎?我可以給你更多的代碼,但不是全部,因爲它太長了。 我真的需要幫助......

重置設備:

void Render(){ 

if(HandleDeviceLost/*VK_F1*/){ 
    if(DeviceLost){ 
     Sleep(100); 
     if(FAILED(hr=d3ddev->TestCooperativeLevel())){ 

      if(hr==D3DERR_DEVICELOST){ 
       return; 
      } 
      if(hr==D3DERR_DEVICENOTRESET){ 

       //clean 
       InvalidateDeviceObjects(); 

       //reset device 
       hr=d3ddev->Reset(&d3dpp); 

       if(FAILED(hr)){ 
        MessageBox(0, "Failed to reset device!", 0, 0); 
        return; 
       } 

       //restore 
       RestoreDeviceObjects(); 
      } 
      return; 
     } 
    } 
} 
DeviceLost=0; 

/* 
    Stuff 
*/ 

hr=d3ddev->Present(NULL, NULL, NULL, NULL); 
if(hr==D3DERR_DEVICELOST){ 
    DeviceLost=1; 
} 
} 


發行對象:

void InvalidateDeviceObjects(){ 

    buffShipMaterial->Release(); 
    Wall_large->Release(); 
    Wall_small->Release(); 
    space_text->Release(); 
    meshWall->Release(); 
    menuText->Release(); 
    menuText2->Release(); 
    menuText3->Release(); 
    text_cpu->Release(); 
    text_player->Release(); 
    text_player2->Release(); 
    number_0->Release(); 
    number_1->Release(); 
    number_2->Release(); 
    number_3->Release(); 
    number_4->Release(); 
    number_5->Release(); 
    number_6->Release(); 
    number_7->Release(); 
    number_8->Release(); 
    number_9->Release(); 
    number_10->Release(); 
} 
+1

我在切換用戶或鎖定屏幕時遇到過XP - 這似乎是一個驅動程序問題,唯一的解決方法是拆卸並重建整個DX9系統,就像在應用程序啓動時一樣。具有不同gfx卡的類似系統可以。 –

+0

我想這是在代碼中的東西,因爲我嘗試(下載)一個簡單的遊戲與設備重置和它的工作。 – Vider7CC

+0

所以你有這個簡單的遊戲工作的源代碼?如果是這樣,你可以比較。我唯一能看到的是,如果第一個'Reset'失敗,那麼對'InvalidateRect'進行另一次重繪是正常的,所以你再試一次。 –

回答

2

在這種工作,你鏈接的樣品,上Reset錯誤導致returnrender函數再次被調用。這很正常 - 沒有理由爲什麼Reset必須在第一次調用中成功,所以通常會繼續重試,而不是像在代碼中那樣顯示錯誤消息。

如果你在消息循環中進行渲染,就像在那個例子中一樣,只要做同樣的事情 - 當你遇到錯誤時不要停下來。

如果你沒有在消息循環中渲染,但使用WM_PAINT方法,那麼這是我使用的一般模式 - 雖然有時我設置了一個定時器而不是調用InvalidateRect,它取決於應用程序 - 但是這個對於許多應用程序足夠強大。您可以看到Reset在失敗時會如何重複,而不是在第一次失敗時拋出錯誤消息。這可能是一個想法,通過這種模式:

void CMyClass::DrawScene() 
{ 
    // perform all dx9 scene drawing 
    HRESULT hr; 

    // if device was lost, try to restore it 
    if (m_bDeviceLost) 
    { 
     // is it ok to render again yet? 
     if (FAILED(hr = m_pD3DDevice->TestCooperativeLevel())) 
     { 
      // the device has been lost but cannot be reset at this time 
      if (hr == D3DERR_DEVICELOST) 
      { 
       // request repaint and exit 
       InvalidateRect(NULL); 
       return; 
      } 

      // the device has been lost and can be reset 
      if (hr == D3DERR_DEVICENOTRESET) 
      { 
       // do lost/reset/restore cycle 
       OnLostDevice(); 
       hr = m_pD3DDevice->Reset(&m_pD3Dpp); 
       if (FAILED(hr)) 
       { 
        // reset failed, try again later 
        InvalidateRect(NULL); 
        return; 
       } 
       OnResetDevice(); 
      } 
     } 

     // flag device status ok now 
     m_bDeviceLost = false; 
    } 

    // ... clear to background and do the drawing ... 

    // display scene 
    hr = m_pD3DDevice->Present(NULL, NULL, GetSafeHwnd(), NULL); 
    m_bDeviceLost = (hr == D3DERR_DEVICELOST); 

    // request repaint if device has been lost 
    if (m_bDeviceLost) 
    { 
     InvalidateRect(NULL); 
    } 
} 

此外,還必須確保TestCooperativeLevelReset是從被用來創建設備在同一個線程調用。

+0

謝謝,但我試過了,它失敗了重置並崩潰在第二InvalidateDeviceObjects()/ OnLostDevice()。我添加了一些使用InvalidateDeviceObjects()/ OnLostDevice()一次(錯誤?),但它只是失敗了每次重置。我不使用線程。 – Vider7CC

+0

是否有一個列表或什麼 - >釋放()/刪除或 - > onlostdevice()?我不使用紋理,字體或精靈。只是網格和光。 – Vider7CC

+0

@ Vider7CC是的,引用[from here](http://msdn.microsoft.com/en-us/library/windows/desktop/bb174425(v = vs.85).aspx) - *「調用IDirect3DDevice9 :: Reset導致所有紋理內存表面丟失,管理的紋理從視頻內存中被刷新,並且所有的狀態信息都將丟失。在調用設備的IDirect3DDevice9 :: Reset方法之前,應用程序應釋放任何顯式的渲染目標,深度模板表面,與設備關聯的附加交換鏈,狀態塊和D3DPOOL_DEFAULT資源。「*。 –