本文介绍了为什么在我的DX11游戏过程中加载了D3D10SDKLayers.dll?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看下面的编辑更新。原始问题已修改!



我有一个使用DX11设备的工作窗口。我的问题出现了,当我尝试使用Alt + Enter全屏显示。如果窗口不聚焦,我得到一个调试输出说:



'MyGame.exe':Loaded'C:\Windows \\ \\ SysWOW64 \D3D10SDKLayers.DLL',找不到或打开PDB文件



,然后出现警告



DXGI警告:IDXGISwapChain :: Present:由于应用程序未正确使用IDXGISwapChain :: ResizeBuffers而导致的全屏显示效率低下,指定DXGI_MODE_DESC在IDXGIOutput :: GetDisplayModeList中不可用, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH



我相当肯定DX11游戏不应该加载D3D10SDKLayers.dll,尤其是在执行过程中。从MSDN文档,我收集了这个DLL加载设备创建:如果一个设备创建了相应的层标志,这个DLL自动加载。所以我检查,看看我的设备创建方法是否在执行的中间被调用,而他们不是。我在我的游戏中只有两个点,其中存在设备创建,并且没有点被击中。
编辑:检查MSDN后,似乎这个DLL只是一个调试DLL,可能只是被加载打印出警告本身,没有其他目的。



显式复制案例:



1)Alt +输入6次(3个全屏过渡周期,开始窗口),在第7的dll加载和警告弹出。



方法调用层次结构摘要(全屏显示):



1)ToggleFullscreen() - 我的方法,只有方法调用Alt + Enter

2)ResizeTargetAndBuffers() - 我的方法,下面的子方法

3)DXGISwapChain-> ResizeTarget(frontBufferDesc)将前缓冲区调整为指定的res

4)DXGISwapChain-> GetFullscreenState()确定全屏状态

5)DXGISwapChain-> SetFullscreenState(TRUE,NULL)全屏

6)ResizeDXGIBuffers(width,height,TRUE)我的方法,调整缓冲区大小,下面的子方法

7)DXGISwapChain-> ResizeBuffers(count, height,format,flags)来调整缓冲区大小

8)DXGISwapChain-> ResizeTarget(frontBufferDesc)防止刷新率问题。 RefreshRate成员根据MSDN的最佳做法归零。

9)DXGISwapChain-> GetFullscreenState()确定全屏状态



方法调用层次结构摘要p>

1)ToggleFullscreen() - 我的方法,只有通过Alt + Enter调用的方法

2)ResizeTargetAndBuffers() - 我的方法,

3)DXGISwapChain-> ResizeTarget(backBufferDesc)将前缓冲区调整为指定的res

4)DXGISwapChain-> GetFullscreenState()确定全屏状态

5)DXGISwapChain-> SetFullscreenState(FALSE,NULL)全屏

6)DXGISwapChain-> ResizeTarget(backBufferDesc)将前缓冲区调整到窗口res(帮助解决一些res问题)
7)ResizeDXGIBuffers(width,height,FALSE)我的方法,调整缓冲区大小,下面的子方法

8)DXGISwapChain-> ResizeBuffers(count,width,height,调整缓冲区大小

9)DXGISwapChain-> GetFullscreenState()以确定全屏状态



这样做的后果相当严重。我的低级键盘钩子捕获Alt + Enter不再被调用,所以Windows可以做自动Alt + Enter处理,这绕过了我的ToggleFullscreen方法,并将窗口设置为桌面分辨率。这导致缓冲区的大小错误(因为我没有设置它们,窗口),导致无效率警告,以及弄乱我的程序中的变量,不再正确的知道缓冲区大小和窗口是否全屏或不。



有什么想法可能导致这种情况?



如果你需要代码示例具体关于你想看到什么,我会尽量把它放在可能的。我不能把整个代码列表。



编辑:设备创建代码如下。

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


if(FAILED(hr)){
pAdapter = NULL;
//远程桌面不允许枚举适配器。在这种情况下,我们让D3D11做枚举。
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)如果在
$之前可以重新调整大小,窗口可能会变得不可扩展b $ b 4)窗口可能变得不可移动。

5)三个线程退出。



编辑更新2:第一次编辑更新可能有不正确的假设;如果我发现它,我会删除它。事实证明,我的低级别的键钩不再被调用(我认为,因为没有断点或打印语句在其内部工作),所以如果我的程序中的东西注销它意外,那将导致所有上述问题。明天测试...



编辑更新3:我不知道发生了什么。我在我的家庭计算机和工作计算机上测试了相同的清洁项目,并得到不同的结果。在家里,我可以Alt + Enter无限期没有发生任何问题,但在工作Alt +输入第7次导致键钩不再被调用,缓冲区问题发生。



编辑更新4:更多的测试(在工作)。在第三次过渡到窗口模式后,钥匙钩肯定被移除。它不再打印在钥匙挂钩方法内,并且不触发断点,不管按下什么键。我想我将打开一个单独的问题,因为我上面描述的所有其他问题只是这个键钩,不调用ToggleFullscreen()的结果。

  
LRESULT _stdcall MyClass :: WindowsKeyHook(s32 nCode, WPARAM wParam,LPARAM lParam){
printf(Key hook called,nCode:%d。,nCode);
if(nCode return CallNextHookEx(MyClassVar.GetWindowsKeyHook(),nCode,wParam,lParam);
}
printf(Key hook status ok.\\\
);

BOOL bEatKeystroke = FALSE;
KBDLLHOOKSTRUCT * p =(KBDLLHOOKSTRUCT *)lParam;
switch(wParam){
//注意:Alt似乎是一个系统键,当它是PRESSED,但一个常规键,当它被释放...
case WM_SYSKEYDOWN:
if(p-> vkCode == VK_MENU || p - > vkCode == VK_LMENU || p - > vkCode == VK_RMENU){
MyClassVar.SetAltPressed
}
if(MyClassVar.IsAltPressed()&& p1> vkCode == VK_RETURN){
bEatKeystroke = TRUE;
MyClassVar.SetAltEnterUsed(TRUE);
printf(Alt + Enter used.\\\
);
}
break;
case WM_SYSKEYUP:
//注意:释放alt + enter会导致代码为0x13的SYSKEYUP消息: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之后。这是到窗口模式的第三个转换。没有必要像我以前一样第四次去全屏,导致问题。 MyClassVar调用的所有方法都是内联的,以使键挂钩尽可能快,因为我知道Windows键钩子有一个超时。 Alt + Enter的实际处理由MyClass中的线程处理。



此外,有人可以让这不是一个社区wiki吗?我认为这个问题太具体,不能用作维基。它成为一个唯一的原因是我已经定期更新它的编辑。

解决方案

我通过完全取出键钩子解决了这个问题。处理Alt + Enter的正确方法是创建你的交换链,然后调用 IDXGIFactory1 :: MakeWindowAssosciation(m_hWnd,DXGI_MWA_NO_ALT_ENTER)。然后,您可以使用 WM_SYSKEYDOWN WM_KEYUP 从Windows消息过程中使用您自己的代码处理Alt + Enter。我希望这能帮助别人!我有一段时间让这个工作,所以如果你很难在自己的应用程序工作,给我一个消息,我会尽力帮助你!


SEE EDIT UPDATES BELOW. Original question has been modified!

I have a working window that uses a DX11 device. My problem comes along when I try to go fullscreen using Alt+Enter. If the window is not focused, i get a debug output that says:

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

and then the warning

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

I'm fairly certain a DX11 game should NOT be loading D3D10SDKLayers.dll, especially during the middle of execution. From the MSDN docs, I gathered that this dll is loaded upon device creation: if a device is created with the appropriate layer flag, this DLL is loaded automatically. So i checked to see if my device creation methods were being called somehow during the middle of execution, and they are not. I only have 2 spots in my game where device creation exists, and neither spot is getting hit.EDIT: after checking MSDN, it seems this dll is only a debug dll and might just be loaded to print out the warning itself, with no other purpose.

Explicit reproduction cases:

1) Alt+Enter 6 times (3 fullscreen transition cycles, both ways, starting windowed), on 7th the dll is loaded and the warning pops up. This happens regardless of window focusing.

Method Call Hierarchy Summary (going fullscreen):

1) ToggleFullscreen() - my method, only method called by Alt+Enter
2) ResizeTargetAndBuffers() - my method, sub-methods below
3) DXGISwapChain->ResizeTarget(frontBufferDesc) resizes front buffer to specified res
4) DXGISwapChain->GetFullscreenState() to determine fullscreen state
5) DXGISwapChain->SetFullscreenState(TRUE, NULL) to go fullscreen
6) ResizeDXGIBuffers(width, height, TRUE) my method, resizes back buffer, sub-method below
7) DXGISwapChain->ResizeBuffers(count, width, height, format, flags) to resize back buffer
8) DXGISwapChain->ResizeTarget(frontBufferDesc) prevents refresh rate issues. RefreshRate member zeroed out as per MSDN best practices.
9) DXGISwapChain->GetFullscreenState() to determine fullscreen state

Method Call Hierarchy Summary (going windowed):

1) ToggleFullscreen() - my method, only method called by Alt+Enter
2) ResizeTargetAndBuffers() - my method, sub-methods below
3) DXGISwapChain->ResizeTarget(backBufferDesc) resizes front buffer to specified res
4) DXGISwapChain->GetFullscreenState() to determine fullscreen state
5) DXGISwapChain->SetFullscreenState(FALSE, NULL) to go fullscreen
6) DXGISwapChain->ResizeTarget(backBufferDesc) to resize front buffer to window's res (helped resolve some res issues)
7) ResizeDXGIBuffers(width, height, FALSE) my method, resizes back buffer, sub-methods below
8) DXGISwapChain->ResizeBuffers(count, width, height, format, flags) to resize back buffer
9) DXGISwapChain->GetFullscreenState() to determine fullscreen state

The repercussions of this are quite severe. My low-level keyboard hook that catches Alt+Enter is no longer called, so windows is able to do its automatic Alt+Enter handling, which bypasses my ToggleFullscreen method entirely and sets the window to desktop resolution. This causes the buffers to be the wrong size (since I didn't set them, windows did), causing the inefficiency warning, and messing with the variables in my program which no longer have correct knowledge of buffer sizes and whether the window is fullscreen or not.

Any ideas as to what might be causing this?

P.S. If you need code samples be specific about what you want to see and I will try to put it up if possible. I can't put up the entire code listing.

EDIT: Device Creation code is below.


         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
                    );
                }

The first call succeeds 99% of the time, namely when you are not using remote desktop, so I will focus only on it. I give it the adapter, driverType as D3D_DRIVER_TYPE_HARDWARE, m_CreateFlags as D3D11_CREATE_DEVICE_DEBUG, and m_eFeatureLevel as D3D_FEATURE_LEVEL_11_0. Pretty standard call, and it always succeeds.

EDIT UPDATE 1: After some extensive debugging, I've found that when the dll is loaded and the inefficiency warning pops up, some very interesting circumstances arise. They are listed below:

1) VS2010 debugger no longer triggers breakpoints in the key hook.
2) Printed output no longer works in the key hook.
3) window may become non-re-sizable if it was re-sizable before
4) window may become un-movable.
5) a trio of threads exit.

EDIT UPDATE 2: The first edit update may have incorrect assumptions; if i find it does, i will delete it. It turns out that my low-level key hook is no longer being called (i think, since no breakpoints or print statements work inside of it), so if something in my program is unregistering it accidentally then that would cause all of the above problems. Testing this tomorrow...

EDIT UPDATE 3: I'm not sure what is going on anymore. I tested the same clean project on my home computer and work computer, and got different results. At home, I can Alt+Enter indefinitely without any problems occuring, but at work Alt+Enter the 7th time causes the key hook to no longer be called and the buffer problems to happen.

EDIT UPDATE 4: More testing (at work). The key hook is definitely being removed after the 3rd transition into windowed mode. It no longer prints inside the key hook method at all, and breakpoints are not triggered, regardless of what key is pressed. I think I'm going to open a separate question regarding this, as all the other problems I describe above are just consequences of this key hook not calling ToggleFullscreen(). For reference, I have provided the key hook code below.


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 );
    }
}

The printf statements show that the key hook is being called until right after the 6th Alt+Enter. This is the 3rd transition into windowed mode. It is not necessary for me to go fullscreen a 4th time, as I thought before, to cause the problem. All methods called by MyClassVar are inline to make the key hook go as fast as possible, as I know there is a timeout on windows key hooks. The actual processing of Alt+Enter is handled by a thread in MyClass.

Also, can someone make this not a community wiki? I think this question is far too specific to be of use as a wiki. The only reason it became one is I've been updating it regularly with edits.

解决方案

I resolved this problem by taking out the key hook entirely. The proper way to handle Alt+Enter is to create your swap chain, then call IDXGIFactory1::MakeWindowAssosciation( m_hWnd, DXGI_MWA_NO_ALT_ENTER). Then you can handle Alt+Enter with your own code from your windows message procedure using WM_SYSKEYDOWN and WM_KEYUP. I hope this helps others! I had a hell of a time getting this to work, so if you are having a hard time getting it to work in your own app, send me a message and I'll try to help you!

这篇关于为什么在我的DX11游戏过程中加载了D3D10SDKLayers.dll?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-04 23:39