Почему D3D10SDKLayers.dll загружается во время моей игры DX11? - PullRequest
4 голосов
/ 20 января 2012

СМОТРЕТЬ ОБНОВЛЕНИЯ ОБНОВЛЕНИЙ НИЖЕ.Исходный вопрос был изменен!

У меня есть рабочее окно, в котором используется устройство 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.

Кроме того, кто-то может сделать это не вики сообщества? Я думаю, что этот вопрос слишком специфичен для использования в вики. Единственная причина, по которой он стал, это то, что я регулярно обновлял его с изменениями.

1 Ответ

1 голос
/ 03 февраля 2012

Я решил эту проблему, полностью убрав хук ключа.Правильный способ обработки Alt + Enter - создать цепочку обмена, а затем вызвать IDXGIFactory1::MakeWindowAssosciation( m_hWnd, DXGI_MWA_NO_ALT_ENTER).Затем вы можете обрабатывать Alt + Enter с вашим собственным кодом из процедуры сообщений Windows, используя WM_SYSKEYDOWN и WM_KEYUP.Я надеюсь, что это помогает другим!У меня было чертовски много времени, чтобы заставить это работать, поэтому, если вам трудно заставить его работать в вашем собственном приложении, отправьте мне сообщение, и я постараюсь помочь вам!

...