СМОТРЕТЬ ОБНОВЛЕНИЯ ОБНОВЛЕНИЙ НИЖЕ.Исходный вопрос был изменен!
У меня есть рабочее окно, в котором используется устройство 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
IЯ уверен, что игра DX11 НЕ ДОЛЖНА загружать D3D10SDKLayers.dll, особенно в середине выполнения.Из документов MSDN я понял, что эта библиотека загружается при создании устройства: if a device is created with the appropriate layer flag, this DLL is loaded automatically
.Поэтому я проверил, вызывались ли мои методы создания устройства как-то во время выполнения, а они нет.У меня есть только 2 места в моей игре, где существует создание устройств, и ни одно из них не получило удар.РЕДАКТИРОВАТЬ: после проверки MSDN кажется, что эта DLL-библиотека является только отладочной DLL и может быть просто загружена для распечатки самого предупреждения, без какой-либо другой цели.
Явные случаи воспроизведения:
1) Alt + Enter 6 раз (3 полноэкранных цикла перехода, оба пути, начиная с окна), 7-го числа загружается dll и появляется предупреждение.Это происходит независимо от фокусировки окна.
Сводка иерархии вызовов методов (в полноэкранном режиме):
1) ToggleFullscreen () - мой метод, единственный метод, вызываемый Alt + Enter2) ResizeTargetAndBuffers () - мой метод, под-методы ниже3) DXGISwapChain-> ResizeTarget (frontBufferDesc) изменяет размер переднего буфера до указанного разрешения4) DXGISwapChain-> GetFullscreenState () для определения состояния полного экрана5) DXGISwapChain-> SetFullscreenState (TRUE, NULL) для перехода в полноэкранный режим6) ResizeDXGIBuffers (ширина, высота, ИСТИНА) мой метод, изменяет размер заднего буфера, под-метод ниже7) DXGISwapChain-> ResizeBuffers (количество, ширина, высота, формат, флаги) для изменения размера заднего буфера8) DXGISwapChain-> ResizeTarget (frontBufferDesc) предотвращает проблемы с частотой обновления.Член RefreshRate обнулен в соответствии с рекомендациями MSDN.9) DXGISwapChain-> GetFullscreenState () для определения состояния полного экрана
Сводная информация об иерархии вызовов методов (собирается в окно):
1) ToggleFullscreen () - мой метод, единственный метод, вызываемый Alt + Enter2) 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 (количество, ширина, высота, формат, флаги) для изменения размера заднего буфера9) DXGISwapChain-> GetFullscreenState () для определения состояния полного экрана
Последствия этого довольно серьезны.Мой низкоуровневый хук клавиатуры, который перехватывает Alt + Enter, больше не вызывается, поэтому windows может выполнять свою автоматическую обработку Alt + Enter, которая полностью обходит мой метод ToggleFullscreen и устанавливает для окна разрешение рабочего стола.Это приводит к тому, что буферы имеют неправильный размер (так как я их не устанавливал, окна сделали), вызывая предупреждение о неэффективности и путаясь с переменными в моей программе, которые больше не имеют правильного знания размеров буфера и является ли окно полноэкраннымили нет.
Есть идеи, что может быть причиной этого?
PS Если вам нужны примеры кода, определите, что вы хотите увидеть, и я постараюсь поднять его, если это возможно.Я не могу выложить весь список кода.
РЕДАКТИРОВАТЬ: код создания устройства ниже.
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: Больше тестирования (на работе). Ключевой хук определенно удаляется после 3-го перехода в оконный режим. Он больше не печатает внутри метода перехвата клавиш, и точки останова не срабатывают, независимо от того, какая клавиша нажата. Я думаю, что собираюсь открыть отдельный вопрос по этому поводу, так как все другие проблемы, которые я описал выше, являются просто последствиями этого ключевого хука, не вызывающего 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. Это третий переход в оконный режим. Мне не нужно выходить в полноэкранный режим 4-го раза, как я думал раньше, чтобы вызвать проблему. Все методы, вызываемые MyClassVar, являются встроенными, чтобы заставить хук клавиш идти как можно быстрее, так как я знаю, что для хуков клавиш Windows есть тайм-аут. Фактическая обработка Alt + Enter обрабатывается потоком в MyClass.
Кроме того, кто-то может сделать это не вики сообщества? Я думаю, что этот вопрос слишком специфичен для использования в вики. Единственная причина, по которой он стал, это то, что я регулярно обновлял его с изменениями.