Un bug intéressant est venu que je n'ai pas de chance avec. Dans un programme Direct3D9 fenêtré en utilisant le code natif, je gère un appareil perdu en utilisant quelque chose de semblable à ce qui suit:Pourquoi Direct3D ne récupérera-t-il pas après avoir débranché un moniteur sous Windows XP?
void MyClass::RecoverFromDeviceLost(LPDIRECT3DDEVICE9 deviceToRecover, D3DPRESENT_PARAMETERS devicePresentParams)
{
HRESULT hr = deviceToRecover->TestCooperativeLevel();
if(hr == D3DERR_DEVICELOST) {
//Code to shutdown all D3DPOOL_DEFAULT allocated objects
}else if(hr == D3DERR_DEVICENOTRESET){
hr = deviceToRecover->Reset(&devicePresentParams);
if(SUCCEEDED(hr))
{
//Code to rebuild all D3DPOOL_DEFAULT objects
}
}
}
Cela fonctionne bien sur Vista, mais semble avoir des problèmes majeurs sur XP. Si le moniteur est débranché ou éteint du PC via un KVM, je ne reçois jamais le D3DERR_DEVICELOST
. La seule valeur de retour de TestCooperativeLevel que je reçois est D3DERR_DEVICENOTRESET
. Et chaque appel à Reset donne un D3DERR_INVALIDCALL. J'ai essayé de forcer le programme à utiliser le code d'arrêt en faisant ceci:
...
else if(hr == D3DERR_DEVICENOTRESET){
hr = deviceToRecover->Reset(&devicePresentParams);
if(SUCCEEDED(hr))
{
//Code to rebuild all D3DPOOL_DEFAULT objects
}else {
//Duplicate of code to shutdown all D3DPOOL_DEFAULT objects
}
}
...
Mais il n'y avait aucun changement. Ce problème semble seulement affecter Windows XP (testé jusqu'à présent sur SP2, SP3). J'utilise le DXSDK d'août 2007 et je ne peux pas mettre à jour pour le moment. Quelqu'un a-t-il déjà vu ce problème ou a-t-il une idée de la raison pour laquelle je ne peux pas réinitialiser mon appareil?
MISE À JOUR: Je crois que j'ai found a solution, mais je suis toujours perplexe par l'échec du second segment de code énuméré ci-dessus. Après avoir exécuté l'exécution de DirectX Debug pour le débogage à distance, j'ai réalisé que la raison pour laquelle la fonction de réinitialisation continuait à échouer était parce qu'il y avait des ressources inédites. Cependant, le même code de version, lorsqu'il est appliqué comme indiqué dans la réponse, a résolu le problème. J'ai vérifié que le programme ne créait pas d'objets D3DPOOL_DEFAULT entre les appels à la fonction recover. Y a-t-il quelque chose dans la structure de Direct3D qui pourrait causer un problème si vous effectuez une réinitialisation comme indiqué dans les segments de code de cette question?
Je rencontrais une condition similaire où TestCooperativeLevel() renvoyait D3DERR_DEVICENOTRESET, mais l'appel de Reset() échouait. Je libérais les objets D3DPOOL_DEFAULT lorsque TestCooperativeLevel() renvoyait D3DERR_DEVICELOST. La résolution était d'attendre que TestCooperativeLevel() retourne D3DERR_DEVICENOTRESET; – Chris