2012-01-19 16 views
4

請看下面的編輯更新。原始問題已被修改!D3D10SDKLayers.dll爲什麼在DX11遊戲中加載?

我有一個使用DX11設備的工作窗口。當我嘗試使用Alt + Enter全屏時,出現問題。如果沒有集中的窗口,我得到一個調試輸出,上面寫着:

'MyGame.exe': Loaded 'C:\Windows\SysWOW64\D3D10SDKLayers.DLL', Cannot find or open the PDB file

,然後警告

DXGI Warning: IDXGISwapChain::Present: Fullscreen presentation inefficiencies incurred due to application not using IDXGISwapChain::ResizeBuffers appropriately, specifying a DXGI_MODE_DESC not available in IDXGIOutput::GetDisplayModeList, or not using DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH

我相當肯定一個DX11遊戲不應該被加載D3D10SDKLayers .dll,特別是在執行過程中。從MSDN文檔中,我收集到這個DLL是在設備創建時加載的:if a device is created with the appropriate layer flag, this DLL is loaded automatically。所以我查看了我的設備創建方法是否在執行過程中以某種方式被調用,而不是。在我的遊戲中,只有2個位置存在設備創建,並且兩個位置都沒有被擊中。 編輯:在檢查MSDN後,它似乎只是一個調試DLL,可能只是加載打印出警告本身,沒有其他目的。

顯式再現的情況:

1)Alt + Enter鍵6次(3個全屏過渡週期,這兩種方式,在開始加窗),在第七的DLL被加載並顯示該警告彈出。無論窗口焦點如何,都會發生這種情況

方法調用層次摘要(去全屏):

1)ToggleFullscreen() - 我的方法,只能通過Alt鍵名爲+ Enter鍵
2)ResizeTargetAndBuffers()方法 - 下面
我的方法,子方法 3)DXGISwapChain-> ResizeTarget(frontBufferDesc)調整大小前緩衝器指定RES
4)DXGISwapChain-> GetFullscreenState()來確定全屏狀態
5)DXGISwapChain-> SetFullscreenState(TRUE,NULL)去全屏
6) ResizeDXGI緩衝器(寬度,高度,TRUE)我的方法,調整大小後緩衝器,子方法下面
7)DXGISwapChain-> ResizeBuffers(計數,寬度,高度,格式標誌)調整後緩衝器
8)DXGISwapChain-> ResizeTarget (frontBufferDesc)可以防止刷新率問題。根據MSDN最佳實踐,RefreshRate成員歸零。
9)DXGISwapChain-> GetFullscreenState()來確定全屏狀態

方法調用層次摘要(去窗口):

1)ToggleFullscreen() - 我的方法,只能通過Alt鍵+叫輸入
方法2)ResizeTargetAndBuffers() - 我的方法,下面
3)DXGISwapChain-> ResizeTarget(backBufferDesc)調整大小前緩衝器指定RES
4)DXGISwapChain-> GetFullscreenState()來確定全屏狀態
5)DXGISwapCh子方法6)DXGISwapChain-> ResizeTarget(backBufferDesc)將窗口的res重新調整大小(幫助解決某些res問題)
7)ResizeDXGIBuffers(width,height,FALSE)myDisabled方法,調整大小後緩衝器,子方法下面
8)DXGISwapChain-> ResizeBuffers(計數,寬度,高度,格式標誌)調整後緩衝器
9)DXGISwapChain-> GetFullscreenState()來確定全屏狀態

這種影響相當嚴重。我不再調用捕獲Alt + Enter的低級別鍵盤鉤子,因此Windows能夠執行自動的Alt + Enter處理,它完全繞過了我的ToggleFullscreen方法,並將窗口設置爲桌面分辨率。這會導致緩衝區大小錯誤(因爲我沒有設置它們,窗口也是這樣),導致無效警告,並且弄亂了我的程序中的變量,這些變量不再具有緩衝區大小的正確知識以及窗口是否全屏或不。

有關可能會導致此問題的任何想法?

P.S.如果您需要代碼示例,請具體說明您想要查看的內容,如果可能的話,我會嘗試將其提供。我無法忍受整個代碼清單。

編輯:設備創建代碼如下。


     hr = D3D11CreateDevice( pAdapter, 
            driverType, 
            NULL, 
            rDeviceSettings.m_CreateFlags, 
            &rDeviceSettings.m_eD3DDeviceFeatureLevel, 
            1, 
            D3D11_SDK_VERSION, 
            &pGraphicsDevice, 
            &eFeatureLevel, 
            &pDeviceContextI 
      ); 


      if (FAILED(hr)) { 
       pAdapter = NULL; 
       // Remote desktop does not allow you to enumerate the adapter. In this case, we let D3D11 do the enumeration. 
       if (driverType == D3D_DRIVER_TYPE_UNKNOWN) { 
        hr = D3D11CreateDevice(pAdapter, 
              driverType, 
              NULL, 
              rDeviceSettings.m_CreateFlags, 
              &rDeviceSettings.m_eD3DDeviceFeatureLevel, 
              1, 
              D3D11_SDK_VERSION, 
              &pGraphicsDevice, 
              &eFeatureLevel, 
              &pDeviceContextI 
        ); 
       } 

第一次通話成功99%的時間,即當你不使用遠程桌面,所以我只會關注它。我給它的適配器,driverType爲D3D_DRIVER_TYPE_HARDWARE,m_CreateFlags爲D3D11_CREATE_DEVICE_DEBUG,m_eFeatureLevel爲D3D_FEATURE_LEVEL_11_0。相當標準的通話,它總是成功。

編輯更新1:經過一些廣泛的調試後,我發現當dll被加載並且彈出低效率警告時,會出現一些非常有趣的情況。它們列在下面:

1)VS2010調試器不再觸發鑰匙鉤中的斷點。
2)打印輸出不再在鑰匙鉤中工作。
3)窗口可能變得不可重新調整大小,如果它在
之前可調整大小,4)窗口可能變爲不可移動。
5)三重線程退出。

編輯更新2:第一次編輯更新可能有不正確的假設;如果我找到它,我會刪除它。事實證明,我的低級別的關鍵鉤子不再被調用(我認爲,因爲沒有斷點或打印語句在裏面工作),所以如果我的程序中的某些東西無意中註銷它,那麼會導致所有上述問題。明天測試這個...

編輯更新3:我不知道發生了什麼事。我在家用電腦和工作電腦上測試了同樣的清潔項目,並得到了不同的結果。在家裏,我可以無限期地Alt + Enter而不會出現任何問題,但是在工作中Alt + Enter第7次會導致不再調用密鑰鉤子併發生緩衝區問題。

編輯更新4:更多測試(在工作中)。在第三次轉換到窗口模式之後,鍵鉤肯定會被移除。它不再在關鍵掛鉤方法內打印,並且不管觸發什麼鍵都不觸發斷點。我想我會打開一個單獨的問題,因爲我上面描述的所有其他問題只是不調用ToggleFullscreen()的這個關鍵鉤子的後果。作爲參考,我在下面提供了關鍵的鉤子代碼。


LRESULT _stdcall MyClass::WindowsKeyHook(s32 nCode, WPARAM wParam, LPARAM lParam) { 
    printf("Key hook called, nCode: %d. ", nCode); 
    if(nCode < 0 || nCode != HC_ACTION) { // do not process message 
     return CallNextHookEx(MyClassVar.GetWindowsKeyHook(), nCode, wParam, lParam); 
    } 
    printf(" Key hook status ok.\n"); 

    BOOL bEatKeystroke = FALSE; 
    KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam; 
    switch(wParam) { 
     //NOTE: Alt seems to be a system key when it is PRESSED, but a regular key when it is released... 
     case WM_SYSKEYDOWN: 
      if(p->vkCode == VK_MENU || p->vkCode == VK_LMENU || p->vkCode == VK_RMENU) { 
       MyClassVar.SetAltPressed(TRUE); 
      } 
      if(MyClassVar.IsAltPressed() && p->vkCode == VK_RETURN) { 
       bEatKeystroke = TRUE; 
       MyClassVar.SetAltEnterUsed(TRUE); 
       printf("Alt+Enter used.\n"); 
      } 
      break; 
     case WM_SYSKEYUP: 
      //NOTE: releasing alt+enter causes a SYSKEYUP message with code 0x13: PAUSE key... 
      break; 
     case WM_KEYDOWN: 
      break; 
     case WM_KEYUP: { 
      if(p->vkCode == VK_MENU || p->vkCode == VK_LMENU || p->vkCode == VK_RMENU) { 
       MyClassVar.SetAltPressed(FALSE); 
      } 
      bEatKeystroke = (!MyClassVar.IsShortcutKeysAllowed() && 
           (p->vkCode == VK_LWIN || p->vkCode == VK_RWIN)); 
      break; 
     } 
    } 

    if(bEatKeystroke) { 
     return 1; 
    } 
    else { 
     return CallNextHookEx(MyClassVar.GetWindowsKeyHook(), nCode, wParam, lParam); 
    } 
} 

printf語句顯示鑰匙鉤正在被調用,直到第6個Alt + Enter之後。這是進入窗口模式的第3次轉換。正如我之前所想的那樣,我不需要第四次全屏顯示導致問題。所有由MyClassVar調用的方法都是內聯的,以使得關鍵掛鉤儘可能快,因爲我知道windows關鍵掛鉤存在超時。 Alt + Enter的實際處理由MyClass中的線程處理。

此外,有人可以讓這不是一個社區維基?我認爲這個問題太具體,不能用作維基。它成爲一個唯一的原因是我已經定期更新它的編輯。

+0

您提到設備創建不會在執行過程中發生,但是,創建初始設備時可能無法設置標誌?此外,是否有可能顯示您的設備創建,這可能有助於@josephthomas – josephthomas

+0

我已添加所需的代碼。我懷疑標誌是從最初的設備創建,因爲我只有在切換到全屏時纔會收到警告。這表明我在全屏切換代碼中出現錯誤,但我不知道它是什麼。 – Darkhydro

回答

1

我解決了這個問題,完全拿掉了鑰匙扣。處理Alt + Enter的正確方法是創建交換鏈,然後致電IDXGIFactory1::MakeWindowAssosciation(m_hWnd, DXGI_MWA_NO_ALT_ENTER)。然後,您可以使用WM_SYSKEYDOWNWM_KEYUP從Windows消息過程中使用自己的代碼處理Alt + Enter。我希望這可以幫助別人!我有一段時間讓它工作,所以如果你很難在自己的應用中使用它,給我發一條消息,我會盡力幫助你!

相關問題