2017-09-19 4 views
0

J'utilise DirectX 11. Pour plus de simplicité et de reproduire le problème, je rétréci vers le bas les étapes suivantes:StepTimer.GetTotalSeconds() produit des valeurs qui n'augmentent pas toujours

  1. Créer un nouveau " DirectX et XAML App (UWP) "dans Visual Studio (j'utilise VS 2017).
  2. Remplacer la Sample3DSceneRenderer :: méthode de mise à jour avec le code suivant:

    void Sample3DSceneRenderer::Update(DX::StepTimer const& timer) 
    { 
        if (!m_tracking) 
        { 
         double total = timer.GetTotalSeconds(); 
    
         // Convert degrees to radians, then convert seconds to rotation angle 
         float radiansPerSecond = XMConvertToRadians(m_degreesPerSecond); 
         double totalRotation = total * radiansPerSecond; 
         float radians = static_cast<float>(fmod(totalRotation, XM_2PI)); 
    
         DX::DebugTrace(L"num = %4.2f\t%4.2f\n", radians, total); 
    
         Rotate(radians); 
        } 
    } 
    
  3. Ajoutez la fonction suivante pour tracer les valeurs dans la fenêtre de sortie:

    inline void DebugTrace(const wchar_t *format, ...) 
    { 
        // Generate the message string. 
        va_list args; 
        va_start(args, format); // initialize the argument list 
        wchar_t buffer[1024]; 
        va_end(args); 
    
        OutputDebugStringW(buffer); // this is a Windows function 
    } 
    

Quand je lance l'application, la fenêtre de sortie affiche les valeurs suivantes:

num = 0.01 0.01 
    num = 0.02 0.02 
    num = 0.00 0.00 // decreased 
    num = 0.00 0.01 // decreased 
    num = 0.03 0.04 
    num = 0.05 0.06 
    num = 0.02 0.02 // decreased 
    num = 0.06 0.07 
    num = 0.03 0.04 // decreased 
    num = 0.07 0.09 
    num = 0.04 0.06 // decreased 
    num = 0.08 0.11 
    num = 0.06 0.07 // decreased 
    num = 0.10 0.12 
    num = 0.07 0.09 // decreased 
    num = 0.11 0.14 
    num = 0.08 0.11 // decreased 
    num = 0.12 0.16 
    num = 0.10 0.12 // decreased 
    num = 0.11 0.14 
    num = 0.14 0.17 
    num = 0.12 0.16 // decreased 
    num = 0.15 0.19 
    num = 0.16 0.21 
    num = 0.14 0.17 // decreased 
    num = 0.18 0.22 
    num = 0.15 0.19 // decreased 
    num = 0.16 0.21 
    num = 0.19 0.24 
    num = 0.20 0.26 
    num = 0.18 0.22 // decreased 
    etc. 

Question: Pourquoi les valeurs de TotalSeconds augmentent-elles puis diminuent puis augmentent à nouveau, etc.? Par exemple: 0,01, 0,02, 0,00, 0,01. Ne devraient-ils pas toujours augmenter?

+0

J'ai étudié ce problème plus loin et il est apparu que le constructeur DirectXPage a été appelé deux fois: une fois par le cadre (méthode ActivateInstance) et une autre fois par l'application elle-même (un appel m_directXPage = ref nouvelle DirectXPage () dans App.xaml.cpp). La question demeure: pourquoi la page XAML est-elle instanciée deux fois? Est-ce un bug? – ata6502

+0

Clarification: parce que la page est instanciée deux fois, la méthode Update est appelée deux fois et il y a donc deux minuteurs travaillant en parallèle. Ca ressemble à un bug, n'est-ce pas? – ata6502

Répondre

0

Le bug est dans App :: OnLaunched. La version dans le modèle crée deux DirectXPage s:

  • Affectation directe: m_directXPage = ref new DirectXPage();
  • Navigation: rootFrame->Navigate(TypeName(DirectXPage::typeid), e->Arguments);

j'ai une version modifiée qui crée seulement une seule version en prenant une référence à la un créé lors de la navigation, mais je n'ai pas passé beaucoup de temps à vérifier les cas d'erreur.

void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e) 
{ 
#if _DEBUG 
     if (IsDebuggerPresent()) 
     { 
       DebugSettings->EnableFrameRateCounter = true; 
     } 
#endif 

     if (e->PreviousExecutionState == ApplicationExecutionState::Terminated) 
     { 
       m_directXPage->LoadInternalState(ApplicationData::Current->LocalSettings->Values); 
     } 

     auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content); 

     // Do not repeat app initialization when the Window already has content, 
     // just ensure that the window is active 
     if (rootFrame == nullptr) 
     { 
       // Create a Frame to act as the navigation context and associate it with 
       // a SuspensionManager key 
       rootFrame = ref new Frame(); 

       rootFrame->NavigationFailed += ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(this, &App::OnNavigationFailed); 

       // Place the frame in the current Window 
       Window::Current->Content = rootFrame; 
     } 

     if (rootFrame->Content == nullptr) 
     { 
       // When the navigation stack isn't restored navigate to the first page, 
       // configuring the new page by passing required information as a navigation 
       // parameter 
       rootFrame->Navigate(TypeName(DirectXPage::typeid), e->Arguments); 
     } 

     if (m_directXPage == nullptr) 
     { 
       m_directXPage = dynamic_cast<DirectXPage^>(rootFrame->Content); 
     } 

     // Ensure the current window is active 
     Window::Current->Activate(); 
} 
+0

Bonjour Bob, Oui, c'est un bug. Je suis surpris que Microsoft le laisse entrer si longtemps. Quoi qu'il en soit, j'ai vraiment besoin d'une solution pour ce problème. Votre code ne fonctionne que partiellement. Il lancera une exception NullReferenceException lorsque l'application se lancera à partir de l'état Terminé, car m_directXPage est null. D'un autre côté, ne pas initialiser m_directXPage entraîne une exception de violation d'accès à la mémoire lorsque l'application est fermée. Des idées? – ata6502

+0

Essayez de déplacer le chèque: ' si (e> PreviousExecutionState == ApplicationExecutionState :: Terminated) { m_directXPage-> LoadInternalState (ApplicationData :: current-> LocalSettings-> Valeurs); } ' au bas de la méthode. –

+0

Ça fonctionne bien maintenant. Merci. – ata6502