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

Auteur Sujet: Demande d'infos : sfml 1.6-2.0, ATI et solutions  (Lu 14302 fois)

0 Membres et 2 Invités sur ce sujet

coco

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
    • Galhmac Game Studio
Re : Demande d'infos : sfml 1.6-2.0, ATI et solutions
« Réponse #30 le: Août 20, 2012, 02:30:51 pm »
Bonjour !

Je reviens sur ce thread car j'ai toujours des soucis de compatibilité ATI et/ou 2.0 que j'ai absolument besoin de corriger.

J'ai testé un peu cette histoire de RAM graphique et normale. Il semble que le programme charge les nouvelles images en RAM normale lorsque la RAM graphique est pleine.

J'avais parlé plus tôt dans ce thread d'un bug sur les Threads avec les cartes ATI ( nécessité de déclarer un contexte explicitement, contrairement à Nvidia, sinon les images ne s'affichent pas ). J'ai l'impression que les images ne sont pas correctement déchargées au bout d'un moment. Sur un PC ATI ( Windows 7-64 ), la ram graphique augmente jusqu'a un point proche du max ( ~960/1024 ). Pendant un petit moment à charger/décharger des images, la RAM graphique oscille et la normale ne bouge pas. Au bout d'un moment, c'est la ram normale qui augmente, mais ne diminue plus lorsque les images sont détruites. lorsque la ram normale atteint un chiffre élevé ( ~1go ), le programme bloque dans la dll openGL d'ati ( pendant le rendu ou pendant un bind texture ).

Je n'ai pas réussi à reproduire ce comportement sur un pc Nvidia ( Windows 7 64 ).

Pour le moment je n'ai pas trouvé la source du problème ( et je galère un peu ). J'ai essayé de déclarer un contexte au moment de la destruction des textures ( et non plus uniquement à la création ), mais j'avais d'autres problèmes...

Petites questions au passage :
- Est-ce qu'une image chargée dans un thread doit être détruire dans le même thread ( même contexte )  ?
- J'ai vu dans les sources SFML qu'il y a une liste de internalContexts qui s'empilent pour chaque nouveau thread, et qui sont détruites uniquement dans la fonction de cleanUp global. C'est probablement de la que vient une partie de la fuite décrite dans ce bug : https://github.com/SFML/SFML/issues/120, et je me demandais si ça pouvait avoir un rapport avec mon problème.

je vais essayer de résumer le fonctionnement, au cas ou quelqu'un détecterait un problème potentiel :

on a un main thread qui fait quasiment tout ( affichage, physique... ). Lorsque le joueur change de map, on a un premier thread qui effectue l'initialisation des nouvelles maps, et qui envoie des requêtes de chargement de textures, effectuées par un troisième thread ( tout ça pendant que le jeu tourne dans le main ). Lorsqu'on s'éloigne d'une map, le premier thread désinitialise les maps et il détruit les textures.

Depuis le passage à la 2.0, on a aussi des chutes de framerate brutales ( localisées principalement dans l'affichage ), que nous n'avions pas sur la 1.6.

Je vais poursuivre mes investigations, et je mettrai a jour si je trouve quelque chose.

Je prends toute info ou suggestion pour essayer de localiser/corriger ce bug ( dans SFML si nécessaire ).

Merci de votre aide.

ps : Lorsque j'ai créé ce thread, j'ai pris le snapshot 2.0-rc-42-[...].
Actuellement c'est le 74 je crois. Serais-ce une bonne idée de mettre a jour au passage ?

ps2 : question "hors sujet" : Est ce qu'il y a déjà eu des jeux commerciaux sortis utilisant SFML ?

edit rapide : J'ai repris et modifié légèrement le code proposé par Ceylo ( https://github.com/SFML/SFML/issues/120 ) de la façon suivante :

#define TEX_SIZE 2048
sf::Image sharedImage;

void thread_func(void *data)
{
   // Reuse the same texture object
   sf::Texture** tex = ((sf::Texture **)data);
   (*tex) = new sf::Texture();

   //sf::Context ctx;

   // Should just erase the previous data
   (*tex)->loadFromImage(sharedImage);
}

int main()
{
   sf::Texture* tex = NULL;
   sharedImage.create(TEX_SIZE, TEX_SIZE, sf::Color::Red);
   sf::Thread th(thread_func, (void *)(&tex));

   sf::RenderWindow window;
   window.create(sf::VideoMode(256,256,32), "test");

   // Create one thread/sec
   while (true)
   {
          th.launch();
          th.wait();

          window.clear();
          sf::Sprite sprite;
          sprite.setTexture(*tex,true);

          window.draw(sprite);
          window.display();
          sprite.setTexture(sf::Texture(), true);
          delete tex;
   }

   return 0;
}
 

Résultat ( toujours sur mon pc win7 64 ATI ) : si je commente la déclaration du contexte dans le thread, j'ai une leak beaucoup plus importante ( ~16 Mo par itération ) contre beaucoup moins si je déclare le contexte dans le thread... C'est probablement lié a la nécessite de déclarer un contexte pour charger les images sur ATI. Si ça peut aider...
« Modifié: Août 20, 2012, 03:35:07 pm par coco »

coco

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
    • Galhmac Game Studio
Re : Demande d'infos : sfml 1.6-2.0, ATI et solutions
« Réponse #31 le: Août 21, 2012, 04:42:37 pm »
MAJ

J'ai fait quelques tests supplémentaires au niveau de l'utilisation de la mémoire graphique. J'ai utilisé le programme GPU-Z de TechPowerUp pour tracer la quantité de mémoire graphique utilisée par notre jeu.

J'ai remarqué que la mémoire graphique ne descendait presque jamais après la destruction d'une texture ( glDeleteTextures() dans le destructeur de Texture ). Après quelques recherches, je suis tombé sur un thread où ils conseillaient d'appeller glFlush() pour s'assurer que la mémoire opengl était correctement désallouée. J'ai donc rajouté des glFlush() juste après la destructions d'images, et, ô miracle, la mémoire graphique semble correcte ( augmente et diminue au fil des chargements/dechargements d'images ). En revanche, j'ai été obligé de placer le glFlush dans le même thread que le déchargement des images, sinon la mémoire n'était pas libérée ( problème de contexte openGL ? ).

Pour obtenir ces résultats, j'ai testé sur les deux pc ( Win 7 64, un avec une Nvidia, un avec une ATI ). J'ai le même comportement avec les deux configs au niveau de la mémoire graphique avec et sans glFlush(), même si le pc Nvidia semble "moins" affecté lorsque sa RAM graphique est blindée que l'ATI.

Est-ce correct d'appeller glFlush() manuellement ? Si quelqu'un a des infos...

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Demande d'infos : sfml 1.6-2.0, ATI et solutions
« Réponse #32 le: Août 21, 2012, 09:00:44 pm »
Il est correct d'appeler glFlush manuellement, tout ce que ça fait c'est exécuter les instructions en attente maintenant au lieu de plus tard.

Le seul inconvénient, c'est que ça force une resynchronisation entre le CPU et le GPU, et ça casse tout le parallèlisme entre les deux au moment où tu l'appelles. C'est donc sans danger dans un code final où les appels sont maîtrisés, mais c'est moins évident à placer dans SFML sans savoir de quelles manières seront appelées les fonctions.

Ceci-dit ça m'aide à avancer, merci. Je pense que comme les contextes "éphémères" créés par SFML en interne ne sont détruits qu'à la fin du programme, sans glFlush il se peut que certaines commandes OpenGL n'aient jamais l'occasion d'être exécutées. Du coup ça produit exactement ce que tu as constaté -- et peut-être même plus.
Laurent Gomila - SFML developer

christophedlr

  • Full Member
  • ***
  • Messages: 153
    • Voir le profil
    • E-mail
Re : Re : Demande d'infos : sfml 1.6-2.0, ATI et solutions
« Réponse #33 le: Septembre 07, 2012, 11:37:08 am »
Citer
- Spécifique ATI, apparement :
En parcourant le forum, j'ai cru comprendre qu'il n'y avait plus besoin de déclarer un sf::Context dans les threads pour charger les textures. Sur une nvidia ça fonctionne, par contre sur un pc avec une ATI, une texture chargée dans un thread, puis liée à un sprite lui même dessiné dans le main thread ne s'affiche pas. Déclarer un sf::Context dans le thread corrige le problème.
Je veux bien un code complet minimal, et un peu plus d'infos (OS, ...).

Citer
Ensuite si on le dessine ( avec cette texture "vide" ), puis on change de texture pour une texture "valide", le sprite avec la nouvelle texture ne s'affiche pas a l'écran.
Il faut utiliser le second paramètre de setTexture.

Citer
A part cela, j'aurais une petite question sur les sf::Texture. Si j'ai bien compris, elle sont chargées sur la RAM graphique. Que se passe t'il si on essaie de charger une image alors qu'il n'y a plus de RAM graphique ( a moins que ça ne puisse pas arriver ) ?
Une erreur, j'imagine. Mais mieux vaut ne pas en arriver là, si tu veux mon avis ;)

Non pas d'erreur. si c'est une carte graphique standard, le traitement ne sera pas fait tan que la carte n'aura pas de nouveau de la mémoire disponible. Si maintenant c'est une carte graphique dédiée, elle est extensible, elle prend donc sur la RAM de l'ordinateur.