Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [Résolu] [SFML 2.0] La fonction sf::sleep ne fonctionne pas comme il faut.  (Lu 5582 fois)

0 Membres et 1 Invité sur ce sujet

Opulus

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Bonjours,

Je poste aujourd'hui car j'ai repéré un gros soucis avec la fonction sleep.

Deja je tiens a dire que les fonctions setFrameRateLimit et setVerticalSyncEnabled ne me conviennent
pas du tout étant donné qu'elles provoquent une discontinuité de l'affichage pour la 1ère (avec des temps
de boucles a chaque fois différents) et une trainée derrières les sprites lors des déplacements rapides
pour la 2ème.

J'ai donc voulu fixer les intervalles d'affichage a l'aide de la fonction sf::sleep.

Et la j'ai fais mon enquête car rien ne fonctionnait comme prévu.

Le test donne donc le résultat suivant :

Code : (juste la partie concercée)

                /*Fonctions déplaçant un cube témoin pour analyser la fluidité.
                Très simple, et non buguée, elle ajoute simplement 3, ou retire 3 a la
                coordonnée x du sprite */

               
                Window.clear(Color(0, 0, 0));
                Window.draw(sprite);

                t1=tempsAffichage-horloge.getElapsedTime();                    
                t2=horloge.getElapsedTime();
                sleep(t1);

                std::cout<<"HORLOGE : "<<horloge.getElapsedTime().asMicroseconds()<<std::endl;
                Window.display();
                std::cout<<"Temps de l'affichage : "<<horloge.getElapsedTime().asMicroseconds()<<"        "<<t1.asMicroseconds()<<"         "<<t2.asMicroseconds()<<std::endl;
                horloge.restart();

Dans ce code j'execute une fonction sleep pour attendre le temps d'affichage moins le temps
correspondant aux étapes depuis le précédent affichage.

La console affiche ensuite les valeurs suivantes :

...
HORLOGE : 29253
Temps de l'affichage : 30357        16579         88
HORLOGE : 29586
Temps de l'affichage : 30693        16514         153
HORLOGE : 29364
Temps de l'affichage : 30660        16615         52
HORLOGE : 29415
Temps de l'affichage : 30725        16636         31
HORLOGE : 29296
Temps de l'affichage : 30913        16624         43
HORLOGE : 29018
Temps de l'affichage : 30087        16631         36
HORLOGE : 29197
Temps de l'affichage : 29860        16629         46
HORLOGE : 29176
Temps de l'affichage : 30515        16626         41
HORLOGE : 28946
Temps de l'affichage : 29978        16625         42
...

Donc en gros, le temps à l'entrée de la fonction sleep tourne autour de 40 millisecondes.
Le temps t1 affiche bien la valeur manquante pour arriver a un temps correspondant
au temps d'affichage (qui est de 0.0166667f secondes - pour un ips voulu d'environ 60).
Jusqu'ici aucun problème, sauf qu'à la sortie de la fonction sleep, l'horloge affiche
environ 29000 millisecondes. Soit une attente presque deux fois plus longue que celle demandée.

La fonction sleep ne fait donc ici pas son travail correctement, comme dit sur la doc :
"Make the current thread sleep for a given duration."

Pouvez vous m'aider, merci !
« Modifié: Avril 21, 2013, 11:01:49 pm par Opulus »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : La fonction sf::sleep ne fonctionne pas comme il faut.
« Réponse #1 le: Avril 21, 2013, 07:44:30 pm »
Déjà, commence par tester avec un code aussi minimal que possible, et montre le nous. Le fait que tu tombes sur un os quelque soit la méthode que tu essayes... c'est louche.

Ensuite, une fois qu'on aura connaissance de ton code et qu'on aura validé qu'il est bien censé fonctionner, on pourra discuter ;)
Laurent Gomila - SFML developer

Opulus

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : La fonction sf::sleep ne fonctionne pas comme il faut.
« Réponse #2 le: Avril 21, 2013, 08:12:16 pm »
J'ai simplifié le code.
Le probleme est toujours le meme et la console affiche la meme chose.

Code :

#include <SFML/Graphics.hpp>
#include <iostream>

using namespace sf;

int main()
{
        RenderWindow Window(VideoMode(800, 600, 32), "SFML Sample Application");
        Window.setFramerateLimit(0);
        Window.setVerticalSyncEnabled(false);

        Clock horloge;
        Time t1, t2;
        Time tempsAffichage;
        tempsAffichage=seconds(0.0166667f);

        horloge.restart();

        while (Window.isOpen())
        {
                Event Event;
                while (Window.pollEvent(Event))
                {
                        switch (Event.type)
                        {
                        case Event::Closed:
                                Window.close();
                                break;
                        default:
                                break;
                        }
                }

                Window.clear(Color(0, 0, 0));

                t1=tempsAffichage-horloge.getElapsedTime();
                t2=horloge.getElapsedTime();
                sleep(t1);

                std::cout<<"HORLOGE : "<<horloge.getElapsedTime().asMicroseconds()<<std::endl;
                Window.display();
                std::cout<<"Temps de l'affichage : "<<horloge.getElapsedTime().asMicroseconds()<<"        "<<t1.asMicroseconds()<<"         "<<t2.asMicroseconds()<<std::endl;
                horloge.restart();
        }

        return 0;
}
 

EDIT : Info supplémentaire - J'ai regardé quelques vidéos et j'ai réessayer le programme, et le
temps affiché à "HORLOGE : " est passé a une autre valeur. Toujours trop lente mais différente.
Je comprend de moins en moins, du coup cela doit dépendre d'autre chose que le code
lui même. De quoi se sert la fonction sf::sleep ?
« Modifié: Avril 21, 2013, 10:00:46 pm par Opulus »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] La fonction sf::sleep ne fonctionne pas comme il faut.
« Réponse #3 le: Avril 21, 2013, 10:01:16 pm »
Quel est ton OS ?

Chez moi ça fonctionne bien. Mais il est facile d'expliquer ton problème : le temps de sommeil du thread dépend de la résolution de l'ordonnanceur de l'OS. En clair, si l'ordonnanceur s'exécute toutes les 16 ms, alors peu importe que tu veuilles endormir ton thread 1, 8 ou 15 ms, il va dormir 16 ms. Et il y a de fortes chances pour que la valeur réelle (dépendante de l'OS) soit de cet ordre.

Par contre il faudrait en effet que je le signale dans la doc ;)

Ensuite concernant la synchronisation verticale, c'est elle qui devrait fonctionner le mieux, et justement éviter les artefacts graphiques. Si tu veux de l'aide à ce sujet, poste un code minimal qui reproduit ton problème.

Pour ce qui est de setFramerateLimit, elle ne fait rien d'autre que ce que tu fais là, un sf::sleep couplé à un sf::Clock.
Laurent Gomila - SFML developer

Opulus

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : [SFML 2.0] La fonction sf::sleep ne fonctionne pas comme il faut.
« Réponse #4 le: Avril 21, 2013, 10:32:06 pm »
Aaah ok, d'ou l'effet similaire que provoque le setFrameRateLimit...
Donc en bref, il n'y a aucune autre solution que la synchronisation verticale ?

Parce que l'affichage n'est vraiment pas propre.
J'ai fais un test en affichant l'horloge a chaque affichage de la fenetre et ca donne ca :

Temps de l'affichage : 15844
Temps de l'affichage : 15818
Temps de l'affichage : 15848
Temps de l'affichage : 15717
Temps de l'affichage : 15811
Temps de l'affichage : 15587
Temps de l'affichage : 15855
Temps de l'affichage : 15728
Temps de l'affichage : 15665
Temps de l'affichage : 12492
Temps de l'affichage : 16161
Temps de l'affichage : 15492
Temps de l'affichage : 16409
Temps de l'affichage : 16240
Temps de l'affichage : 15909
Temps de l'affichage : 15991

Ca varie beaucoup.

Du moins concrètement, le simple déplacement de sprite est saccadé. (jonché d'accoups, comme ci toutes
les quelques frames, la boucle s'effectue plusieurs fois avant d'afficher le sprite).

« Modifié: Avril 21, 2013, 10:35:15 pm par Opulus »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] La fonction sf::sleep ne fonctionne pas comme il faut.
« Réponse #5 le: Avril 21, 2013, 10:42:57 pm »
Il faut oublier les timings précis à la milliseconde près. Ca n'est possible que sur des OS temps réel, ce que ne sont pas les OS de bureau qu'on utilise au quotidien. Au contraire, il faut plutôt faire en sorte que ton application ne soit pas aussi sensible à la variation de framerate.

Citer
Du moins concrètement, le simple déplacement de sprite est saccadé. (jonché d'accoups, comme ci toutes
les quelques frames, la boucle s'effectue plusieurs fois avant d'afficher le sprite).
Ca c'est pas normal. Si tu veux de l'aide sur ce sujet, il faut que tu fasses une demande en bonne et dûe forme, avec code complet minimal et description précise du problème ;)
Laurent Gomila - SFML developer

Opulus

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : [SFML 2.0] La fonction sf::sleep ne fonctionne pas comme il faut.
« Réponse #6 le: Avril 21, 2013, 10:55:00 pm »
Ok, en tout cas merci pour toutes les réponses !
Jsuis a présent fixé sur pas mal de choses.

Je vais opter pour changer la structure de mes programme alors, en prenant en compte le
temps en référence.

Je reposterais pour mon autre problème proprement ! ;)

Lolilolight

  • Hero Member
  • *****
  • Messages: 1232
    • Voir le profil
J'ai exactement le même problème que toi, poste ton code un coup si tu sais.