gpt4 book ai didi

c++ - 为什么在DX11游戏期间加载D3D10SDKLayers.dll?

转载 作者:行者123 更新时间:2023-12-02 15:17:35 25 4
gpt4 key购买 nike

请参阅下面的编辑更新。原始问题已修改!

我有一个使用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个可以创 build 备的位置,而且都没有命中任何位置。
编辑:检查MSDN后,似乎此dll只是一个调试dll,可能只是被加载以打印出警告本身,没有其他目的。

显式复制案例:

1)Alt + Enter 6次(3个全屏过渡周期,双向,从窗口开始),在7日加载dll,并弹出警告。无论窗口聚焦如何,都会发生这种情况。

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

1)ToggleFullscreen()-我的方法,只有Alt + Enter调用的方法
2)ResizeTargetAndBuffers()-我的方法,下面的子方法
3)DXGISwapChain-> ResizeTarget(frontBufferDesc)将前端缓冲区的大小调整为指定的分辨率
4)DXGISwapChain-> GetFullscreenState()确定全屏状态
5)DXGISwapChain-> SetFullscreenState(TRUE,NULL)进入全屏
6)ResizeDXGIBuffers(width,height,TRUE)我的方法,调整后缓冲区的大小,下面的子方法
7)DXGISwapChain-> ResizeBuffers(计数,宽度,高度,格式,标志)以调整后缓冲区的大小
8)DXGISwapChain-> ResizeTarget(frontBufferDesc)防止刷新率问题。 RefreshRate成员根据MSDN最佳实践归零。
9)DXGISwapChain-> GetFullscreenState()确定全屏状态

方法调用层次结构摘要(进入窗口):

1)ToggleFullscreen()-我的方法,只有Alt + Enter调用的方法
2)ResizeTargetAndBuffers()-我的方法,下面的子方法
3)DXGISwapChain-> ResizeTarget(backBufferDesc)将前端缓冲区的大小调整为指定的分辨率
4)DXGISwapChain-> GetFullscreenState()确定全屏状态
5)DXGISwapChain-> SetFullscreenState(FALSE,NULL)进入全屏
6)DXGISwapChain-> ResizeTarget(backBufferDesc)将窗口前缓冲区的大小调整为窗口的分辨率(帮助解决了一些分辨率问题)
7)ResizeDXGIBuffers(width,height,FALSE)我的方法,调整后缓冲区的大小,下面的子方法
8)DXGISwapChain-> ResizeBuffers(count,width,height,format,flags)调整后台缓冲区的大小
9)DXGISwapChain-> GetFullscreenState()确定全屏状态

其影响是相当严重的。我的捕获Alt + Enter的低级键盘钩子(Hook)不再被调用,因此Windows能够执行其自动Alt + Enter处理,这将完全绕开我的ToggleFullscreen方法并将窗口设置为桌面分辨率。这会导致缓冲区大小错误(因为我没有设置缓冲区,Windows设置了缓冲区大小),从而导致效率低下的警告,并弄乱了程序中的变量,这些变量不再具有正确的缓冲区大小知识以及窗口是否为全屏显示或不。

关于什么可能导致此的任何想法?

附言如果您需要代码示例,请具体说明您要查看的内容,如果可能,我会尝试将其提出。我无法列出整个代码 list 。

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


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:第一次编辑更新可能有错误的假设;如果找到,我将其删除。事实证明,不再调用我的低级键挂钩(我认为,因为其中没有断点或print语句在其中工作),因此,如果我程序中的某些内容意外注销了它,则将导致上述所有问题。明天测试一下...

编辑更新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语句显示直到第六次Alt + Enter之后才调用键挂钩。这是进入窗口模式的第三次过渡。正如我之前认为的那样,我没有必要第四次全屏显示该问题。 MyClassVar调用的所有方法都是内联的,以使按键挂钩尽可能快地运行,因为我知道Windows按键挂钩存在超时。 Alt + Enter的实际处理由MyClass中的线程处理。

另外,有人可以使它成为社区Wiki吗?我认为这个问题过于具体,无法用作Wiki。成为它的唯一原因是我经常通过编辑对其进行定期更新。

最佳答案

我通过完全拔出 key 钩解决了这个问题。处理Alt + Enter的正确方法是创建交换链,然后调用IDXGIFactory1::MakeWindowAssosciation( m_hWnd, DXGI_MWA_NO_ALT_ENTER)。然后,您可以使用WM_SYSKEYDOWNWM_KEYUP从Windows消息过程中使用自己的代码处理Alt + Enter。希望这对其他人有帮助!我很难过要让它工作,因此,如果您很难在自己的应用程序中工作,请给我发送消息,我会尽力帮助您!

关于c++ - 为什么在DX11游戏期间加载D3D10SDKLayers.dll?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8934374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com