[DirectX] Problème limitation FPS 2D

Le côté programmation du développement d'un jeu vidéo.

Problème limitation FPS 2D

Messagepar Zack » 08 Mar 2007, 01:43

Bonjour,

programmant un petit moteur 2D, j'ai quelques problèmes à insérer la fonctionnalité permettant de limiter le fps à un taux indiqué par l'utilisateur (60 par exemple).

Voici le simple algorithme, dans la boucle locale des messages :

Code: Tout sélectionner
while( msg.message != WM_QUIT && !GExit )
    {
      SetCursor(LoadCursor(NULL, IDC_ARROW));
        if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
        {
         TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        else
      {
         if( limitFPS )
         {
                  fps_startTime = timeGetTime();
                  if( fps_startTime >= fps_nextFrame )
                  {
                     if( m_Graphics->DeviceRecup() )
                        GameLoop();

                     else if( m_Graphics->getDeviceResettable() )
                        RestoreDevice();

                     fps_nextFrame = fps_startTime + fps_waitTime;
                  }
         }

         else
         {
            if( m_Graphics->DeviceRecup() )
               GameLoop();

            else if( m_Graphics->getDeviceResettable() )
               RestoreDevice();
         }
      }
   }


fps_startTime, fps_waitTime, fps_nextFrame sont tous les trois de type DWORD (unsigned long). fps_nextFrame est bien initialisé à 0 dès l'instanciation de la classe l'incorporant. fps_waitTime est initialisé à 1000/(fps demandé) en même temps que l'initialisation à true de limitFPS, via cette fonction :

Code: Tout sélectionner
void CCore::lockFPS( int framerate )
{
   fps_waitTime = 1000 / framerate;
   limitFPS = true;
}



Cet algorithme marche sur une application, un jeu que j'avais créé indépendament du moteur : il me limite le framerate vers 58 ou 59 voire 63 des fois, bref aux alentours des 60 que j'avais spécifié, ainsi que des valeurs proches si je fais d'autres choix.
Mais ici, je n'ai même pas le problème des arrondis (1000/60 = 16,6666666...), j'obtiens 32 en fps, voire 40 maintenant si je lui indique 60, et 64 en fps si je lui indique un chiffre supérieur à 62 (même si je lui indique 300). Et bien sûr, ça marche si je lui indique un chiffre inférieur à 32.

Récapitulation du résultat :
Indication FPS obtenu
x < 32 FPS ok
32 < x < 62 32 / 40
x > 62 64


Mon PresentParameters :
Code: Tout sélectionner
// Initialisation des paramètres du device
    ZeroMemory(&PresentParameters, sizeof(D3DPRESENT_PARAMETERS));
    PresentParameters.FullScreen_RefreshRateInHz = 0;
    PresentParameters.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
    PresentParameters.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
    PresentParameters.BackBufferWidth            = m_Largeur;
    PresentParameters.BackBufferHeight           = m_Hauteur;
    PresentParameters.BackBufferFormat           = SetFormat;
   PresentParameters.BackBufferCount          = 1;
    PresentParameters.Windowed                   = true;
    PresentParameters.EnableAutoDepthStencil     = false;


Grâce à l'interval_immediate, j'obtiens, sans activer la limitation de fps foireuse, un framerate moyen de 1000 images par secondes sur ce pc, en debug. Il n'y a donc pas de problème de ce côté là.

Est-il possible que ce soit dû à certaines lib que j'ai linké ou je ne sais quoi ? J'utilise fmod sur ce moteur. Est-ce lui qui me bouffe mes images ?

C'est incompréhensible.

En clair, je devrais au moins obtenir une limitation avec une marge de quelques images (erreur arrondi) pour un choix de 60.

Ma configuration est correcte pour cet simple application :
Athlon xp 2800+
ati radeon 9600 pro se
1 go ddr 3200


Je précise que cela se produit alors même qu'il n'y a que deux sprites affichés, voire rien ! Ce n'est donc pas parceque j'essaye d'afficher des tonnes de primitives.


[EDIT] : Le problème a été plus que résolu grâce à l'utilisation de QueryPerformanceCounter(), très puissant. Utilisant le sdk directx de décembre 2006, voire Février 2007 sur un autre poste, je n'ai aucune compatibilité avec les machines tournant sous windows ME, 98, 95... Donc ça ne me posera pas de problèmes de compatibilité avec les vieilles, très vieilles machines, dans mon cas.
Avatar de l’utilisateur
Zack
Hello World, I'm new !
 
Messages: 8
Inscription: 25 Juil 2005, 00:41

Messagepar Whirly » 08 Mar 2007, 16:13

C'est bill comme code, si déjà tu n'as pas l'intention d'utiliser le temps machine autant le rendre à quelqu'un qui en aura l'utilité en utilisant un sleep.
Whirly
Hello World, I'm new !
 
Messages: 89
Inscription: 01 Mar 2007, 21:42
Localisation: Strasbourg

Messagepar Zack » 08 Mar 2007, 23:15

Oui bien sûr, c'est ce que j'ai rajouté, histoire de le laisser se désordonnancer pour laisser la main à d'autres processus. J'ai bien retenu ma leçon... :)
Avatar de l’utilisateur
Zack
Hello World, I'm new !
 
Messages: 8
Inscription: 25 Juil 2005, 00:41


Retourner vers Programmation

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 28 invités

cron