Pourquoi D3D10SDKLayers.dll est-il chargé lors de mon jeu DX11?

VOIR LES MISES À JOUR DES MODIFICATIONS CI-DESSOUS. La question originale a été modifiée!

J’ai une fenêtre de travail qui utilise un périphérique DX11. Mon problème survient lorsque j’essaie d’aller en plein écran en utilisant Alt + Entrée. Si la fenêtre n’est pas concentrée, j’obtiens une sortie de débogage indiquant:

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

et puis l’avertissement

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

Je suis assez certain qu’un jeu DX11 ne doit PAS charger D3D10SDKLayers.dll, en particulier au milieu de l’exécution. À partir des documents MSDN, j’ai compris que cette DLL était chargée lors de la création du périphérique: if a device is created with the appropriate layer flag, this DLL is loaded automatically . J’ai donc vérifié si les méthodes de création de mon appareil étaient appelées d’une manière ou d’une autre au cours de l’exécution, mais elles ne le sont pas. Je n’ai que 2 spots dans mon jeu où la création de périphérique existe, et aucun spot n’est touché. EDIT: après vérification de MSDN, il semble que cette DLL ne soit qu’un fichier de débogage et qu’elle puisse juste être chargée pour imprimer l’avertissement lui-même, sans autre but.

Cas de reproduction explicite:

1) Alt + Entrez 6 fois (3 cycles de transition en plein écran, dans les deux sens, en lançant une fenêtre), le 7 le dll est chargé et l’avertissement apparaît. Cela se produit indépendamment de la focalisation de la fenêtre.

Récapitulatif de la hiérarchie des appels de méthode (en plein écran):

1) ToggleFullscreen () – ma méthode, seule méthode appelée par Alt + Entrée
2) ResizeTargetAndBuffers () – ma méthode, sous-méthodes ci-dessous
3) DXGISwapChain-> ResizeTarget (frontBufferDesc) redimensionne le tampon avant à la res spécifiée
4) DXGISwapChain-> GetFullscreenState () pour déterminer l’état du plein écran
5) DXGISwapChain-> SetFullscreenState (TRUE, NULL) pour aller en plein écran
6) ResizeDXGIBuffers (width, height, TRUE) ma méthode, redimensionne le tampon arrière, sous-méthode ci-dessous
7) DXGISwapChain-> ResizeBuffers (count, width, height, format, flags) pour redimensionner le tampon
8) DXGISwapChain-> ResizeTarget (frontBufferDesc) empêche les problèmes de fréquence de rafraîchissement. Le membre RefreshRate est mis à zéro conformément aux meilleures pratiques MSDN.
9) DXGISwapChain-> GetFullscreenState () pour déterminer l’état du plein écran

Récapitulatif de la hiérarchie des appels de méthode (allant dans une fenêtre):

1) ToggleFullscreen () – ma méthode, seule méthode appelée par Alt + Entrée
2) ResizeTargetAndBuffers () – ma méthode, sous-méthodes ci-dessous
3) DXGISwapChain-> ResizeTarget (backBufferDesc) redimensionne le tampon avant à la résolution spécifiée
4) DXGISwapChain-> GetFullscreenState () pour déterminer l’état du plein écran
5) DXGISwapChain-> SetFullscreenState (FALSE, NULL) pour aller en plein écran
6) DXGISwapChain-> ResizeTarget (backBufferDesc) pour redimensionner le tampon avant en res (permet de résoudre certains problèmes)
7) ResizeDXGIBuffers (width, height, FALSE) ma méthode, redimensionne le tampon arrière, les sous-méthodes ci-dessous
8) DXGISwapChain-> ResizeBuffers (count, width, height, format, flags) pour redimensionner le tampon
9) DXGISwapChain-> GetFullscreenState () pour déterminer l’état du plein écran

Les répercussions sont assez graves. Mon hook de clavier de bas niveau qui intercepte Alt + Entrée n’est plus appelé. Windows est donc en mesure de gérer automatiquement Alt + Enter, qui ignore complètement la méthode ToggleFullscreen et définit la fenêtre sur la résolution du bureau. La taille des tampons est donc incorrecte (puisque je ne les ai pas définies, Windows ne l’a pas fait), provoquant un avertissement d’inefficacité et perturbant les variables de mon programme qui n’ont plus une connaissance correcte de la taille des tampons et si la fenêtre est plein écran. ou pas.

Des idées sur ce qui pourrait causer cela?

PS Si vous avez besoin d’échantillons de code, soyez précis sur ce que vous voulez voir et j’essaierai de le présenter si possible. Je ne peux pas mettre la liste complète du code.

EDIT: le code de création de périphérique est ci-dessous.

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

Le premier appel réussit 99% du temps, à savoir lorsque vous n’utilisez pas le bureau à distance, alors je vais me concentrer uniquement sur celui-ci. Je lui donne l’adaptateur, driverType comme D3D_DRIVER_TYPE_HARDWARE, m_CreateFlags comme D3D11_CREATE_DEVICE_DEBUG et m_eFeatureLevel comme D3D_FEATURE_LEVEL_11_0. Joli appel standard, et il réussit toujours.

EDIT UPDATE 1: Après un débogage approfondi, j’ai constaté que lorsque la DLL est chargée et que l’avertissement d’inefficacité apparaît, certaines circonstances très intéressantes se produisent. Ils sont énumérés ci-dessous:

1) Le débogueur VS2010 ne déclenche plus de points d’arrêt dans le hook de clé.
2) La sortie imprimée ne fonctionne plus dans le crochet de la clé.
3) la fenêtre peut devenir non redimensionnable si elle était redimensionnable avant
4) la fenêtre peut devenir non mobile.
5) un sortingo de threads sortent.

EDIT UPDATE 2: La première mise à jour de modification peut avoir des hypothèses incorrectes; si je le trouve, je le supprimerai. Il se trouve que mon hook de clé de bas niveau n’est plus appelé (je pense, car aucun point d’arrêt ou instruction d’impression ne fonctionne à l’intérieur), donc si quelque chose le désenregistre accidentellement, cela provoquerait tous les problèmes ci-dessus . Tester cela demain …

EDIT UPDATE 3: Je ne suis plus sûr de ce qui se passe. J’ai testé le même projet sur mon ordinateur et mon ordinateur de travail, et j’ai obtenu des résultats différents. À la maison, je peux continuer Alt + Enter indéfiniment sans problème, mais au travail, Alt + Enter à la 7ème fois ne déclenche plus l’appel de la clé et les problèmes de tampon se produisent.

EDIT UPDATE 4: Plus de tests (au travail). Le hook de clé est définitivement supprimé après la 3ème transition en mode fenêtré. Il n’imprime plus du tout dans la méthode de hook de clé et les points d’arrêt ne sont pas déclenchés, quelle que soit la touche utilisée. Je pense que je vais ouvrir une question distincte à ce sujet, car tous les autres problèmes que je décris ci-dessus ne sont que des conséquences de ce crochet de clé ne pas appeler ToggleFullscreen (). Pour référence, j’ai fourni le code de crochet principal ci-dessous.

 LRESULT _stdcall MyClass::WindowsKeyHook( s32 nCode, WPARAM wParam, LPARAM lParam ) { printf("Key hook called, nCode: %d. ", nCode); if( nCode 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 ); } } 

Les instructions printf indiquent que le hook de la clé est appelé jusqu’à la 6ème Alt + Entrée. C’est la 3ème transition en mode fenêtré. Il n’est pas nécessaire pour moi de faire le plein écran une quasortingème fois, comme je le pensais auparavant, pour provoquer le problème. Toutes les méthodes appelées par MyClassVar sont en ligne pour que le hook de la clé soit aussi rapide que possible, car je sais qu’il y a un délai d’attente pour les raccourcis clavier de Windows. Le traitement actuel de Alt + Enter est géré par un thread dans MyClass.

En outre, quelqu’un peut-il en faire un wiki communautaire? Je pense que cette question est beaucoup trop spécifique pour être utile en tant que wiki. La seule raison pour laquelle il en est devenu un, c’est que je l’ai régulièrement mis à jour avec des modifications.

J’ai résolu ce problème en retirant entièrement le crochet de la clé. La méthode appropriée pour gérer Alt + Entrée consiste à créer votre chaîne de swap, puis à appeler IDXGIFactory1::MakeWindowAssosciation( m_hWnd, DXGI_MWA_NO_ALT_ENTER) . Ensuite, vous pouvez gérer Alt + Entrée avec votre propre code à partir de votre procédure de message Windows en utilisant WM_SYSKEYDOWN et WM_KEYUP . J’espère que cela aide les autres! J’ai eu beaucoup de mal à faire fonctionner cela, alors si vous avez du mal à le faire fonctionner dans votre propre application, envoyez-moi un message et j’essaierai de vous aider!