Baisse de performance dans un jeu DirectX sur win2000

Baisse de performance dans un jeu DirectX sur win2000 - C++ - Programmation

Marsh Posté le 02-02-2003 à 14:47:15    

J'ai un jeu 2D fonctionnant avec DirectDraw. Il marche bien sur Win98 mais sur Win2000, le nombre de flip à la seconde baisse énormément. J'ai remarqué que la cause de ce ralentissement vient de 2 problèmes différents:
 
1. lorsque j'initialise DirectMusic
2. lorsque j'ai une triple boucle for. Une double boucle sert à lire dans un tableau a 2 dimensions les coordonnées x et y et la troisième boucle sert à comparer les valeurs entre un tableau de coordonnées et les coordonées x et y. En gros c'est à peu pres ca.
 
Voila, c'est tres bizarre car sur win98 c'est tout a fait fluide. Peut être que win2000 supporte pas les 3 boucles, par contre je vois pas pourquoi il ralentit lorque j'active le son. Si quelqu'un connaît l'un ou l'autre de ces problème qu'il m'aide svp!

Reply

Marsh Posté le 02-02-2003 à 14:47:15   

Reply

Marsh Posté le 02-02-2003 à 15:44:13    

(idée a la con, vite fait bien fait : t'as DX en mode debug ou release ?)

Reply

Marsh Posté le 02-02-2003 à 15:44:39    

>> 1. lorsque j'initialise DirectMusic
 
peut-être un problème de drivers. je me souviens qu'à la sortie de 2000, il n'y avait pas de drivers spécifiques. certains fabricants ont mis longtemps à se mettre à jour, regarde de ce côté-là.
 
ou peut-être un mixing hardware sous 98 et software sous 2000. ou l'inverse.
 
>> 2. lorsque j'ai une triple boucle for.  
 
aucune chance qu'un os ne rame à cause d'une triple boucle ;) les valeurs de boucle sont-elles identiques sur les deux os ? tu fais quoi dans la boucle ? si c'est qq chose comme lecture en ram vidéo, ça peut encore être ramené à un problème de drivers.

Reply

Marsh Posté le 02-02-2003 à 22:09:28    

j'ai dx9 version release.
Mes drivers sont tous a jour, même le son, j'ai ceux spécifique à 2000.
C'est quoi un mixing?

Reply

Marsh Posté le 02-02-2003 à 22:12:05    

Bkadoum a écrit :

C'est quoi un mixing?

la façon de jouer plusieurs sons ensemble à différentes fréquences. ça peut être fait par windows ou par la carte. je me souviens avoir lu par ci par là des problèmes liés au mixing hardware qui bouffaient beaucoup de cpu. je ne vois que ça comme problème ... tu devrais peut-être demander sur hardware si ta carte son peut causer ce genre de problème.

Reply

Marsh Posté le 02-02-2003 à 23:03:45    

ok je verrai ca, mais maintenant j'aimerai résoudre le problème de la boucle, car elle cause aussi un ralentissement. J'ai testé sans initialiser le son, ca ralentit toujours si je laisse cette triple boucle. J'ai essayé de faire la même triple boucle mais simplifiée, pour vous montrer, et bien ca ralentit toujours, voici le code:
 

Code :
  1. void Exemple()
  2. {
  3.    int x, y, tilex[640], tiley[480], posx[10], posy[10], i;
  4.    for (x = 0; x < 640; x++)
  5.       for (y = 0; y < 480; y++)
  6.          for (i = 0; i < 10; i++)
  7.             if ((posx[i] == tilex[x]) & (posy[i] == tiley[y]))
  8.                break;
  9. }


 
Et j'ai remarqué que si au if, on enlève la deuxième condition, on a un petit gain de performance :) alors, vous pigez quelque chose? Si jamais, essayez d'appeler cette fonction en boucle dans un de vos programmes, lancez le sur win2000, ca ramera je suis sure!


Message édité par bkadoum le 02-02-2003 à 23:13:49
Reply

Marsh Posté le 03-02-2003 à 01:19:04    

c'est beaucoup de code si tu l'executes  
beaucoup de fois par frame (meme une fois).
en plus je n'ai pas l'impression qu'il fait grand chose
ce code...
Tu peux pas transformer cette routine pour qu'elle soit plus rapide?
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 03-02-2003 à 09:34:34    

3 072 000 itérations quand même !
 
Attention, c'est && qu'il faut utiliser.
 
Tu peux essayer de compter vers 0, et de mettre le plus grand compte en dernier:

Code :
  1. for (i = 10-1 ; i >=0 ; --i)
  2. for (y = 480-1 ; y >=0; --y)
  3.  for (x = 640-1 ; x>=0 ; --x)


Ou alors de passer au pointeurs:

Code :
  1. int tilex[640], tiley[480], posx[10], posy[10];
  2. int *ppx, *ppy, *pty, *ptx;
  3. for (ppx=posx,ppy=posy ; ppx!=posx +10  ; ++ppx,++ppy)
  4. for        (pty=tiley ; pty!=tiley+480 ; ++pty)
  5.  for       (ptx=tilex ; ptx!=tilex+640 ; ++ptx)
  6.   if ((*ppx == *ptx) && (*ppy == *pty))
  7.    break;

Mais c'est moins lisible, et l'optimiseur le fait peut-être déjà.
 
 
C'est vrai qu'elle est bizarre cette boucle... quel traitement fait-elle ?


Message édité par Musaran le 03-02-2003 à 09:35:28

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 03-02-2003 à 12:51:39    

Il ne peut pas y a voir des problèmes de segmentation de mémoire ? (question conne, je reconnais, mais je ne connais pas le modèle de gestion de la mémoire sous Win2K).
 
A part ça, je me demande si on ne pourrait pas réécrire la boucle comme suit :

Code :
  1. void Exemple()
  2. {
  3.   int tilex[640], tiley[480], posx[10], posy[10];
  4.   for (int i = 0; i < 10; i++) {
  5.     for (int y = 0; y < 480; y++)
  6.       if (posy[i] == tiley[y]) {
  7.         for (int x = 0; x < 640; x++) {
  8.           if (posx[i] == tilex[x]) {
  9.             break;
  10.           }
  11.         }
  12.       }
  13.     }
  14.   }
  15. }


Avantage : s'il n'y a rien à trouver, on ne fait que 4800 itérations maxi au lieu des 3 millions initiales.


Message édité par BifaceMcLeOD le 03-02-2003 à 12:53:58
Reply

Marsh Posté le 03-02-2003 à 12:58:01    

non il fait pas grand chose, mais dans cet example, c'est juste pour vous montrer car si je vous envoie mon vrai code ce serait trop le bordel, faudrait que je vous envoie toues les sources des mes classes.
C'est vrai que ca fait beaucoup de traitement mais c'est tout ce que j'ai trouvé pour faire ce que je veux. En fait, les 2 première boucles servent à lire un tableau 2d qui correspond a des petits carrés d'images formant le décor de mon jeu (c'est le principe de tile engine). la troisième boucle c'est pour tester les collisions entres ces petits carrés et des autre objets du jeu, ces objets sont contenus dans un tableau.
 

Code :
  1. void Exemple()
  2. {
  3.   int x, y, tilex[640], tiley[480], posx[10], posy[10], i;
  4.   //carrés à l'horizontale
  5.   for (x = 0; x < 640; x++)
  6.      //carrés à la verticale  
  7.      for (y = 0; y < 480; y++)
  8.         //objets  
  9.         for (i = 0; i < 10; i++)
  10.            //tests des collisions  
  11.            if ((posx[i] == tilex[x]) & (posy[i] == tiley[y]))
  12.               break;
  13. }

 

Reply

Marsh Posté le 03-02-2003 à 12:58:01   

Reply

Marsh Posté le 03-02-2003 à 13:04:19    

Il n'empêche qu'en l'espéce il vaut mieux utiliser l'opérateur booléen "&&" plutôt que l'opérateur bit à bit "&" pour combiner tes conditions.
Et aussi complexe soit-elle dans ton propre code, je pense qu'en réécrivant ta boucle comme je l'ai indiqué, cela devrait diminuer sa complexité, donc améliorer son efficacité dans tous les cas. (par contre, je te déconseille de passer aux pointeurs comme l'a suggéré Musaran : il y a beaucoup d'autres optimisations à envisager avant d'utiliser celle-là, qui sacrifie énormément la lisibilité du programme, donc augmente de manière déraisonnable le risque qu'un bug s'y glisse...)

Reply

Marsh Posté le 03-02-2003 à 13:11:44    

je comprends tjs pas ce que fait cette boucle [:ddr555] Et doit surement avoir moyen de faire plus fin qu'une recherche exhaustive.
y'a quoi dans pos[i] ? ca correspond a quoi, la valeur contenue ?

Reply

Marsh Posté le 03-02-2003 à 13:55:47    

Je vais toujours chercher trop loin moi, vous aviez raison, c'etait l'opératuer && qu'il fallait utiliser, la performance est maintenant égale a celle sur 98! Mais pourquoi? quelle est vraiment la différence entre & et &&? Je me suis toujours demandé, est-ce que les && peuvent aussi faire office de |?
 
Ok le problème 1 est réglé, merci! mais maintenant quand j'initialise le son ca ralentit pareil, mais vraiment pareil! les fps baissent au même taux, c'est fou!

Reply

Marsh Posté le 03-02-2003 à 14:12:09    

"&" est un opérateur qui attend deux entiers en argument et retourne un entier. C'est un opérateur bit à bit. Par exemple, "11 & 3" renvoit 3, parce qu'en binaire "1011 & 0011 = 0011".
 
"&&" est un opérateur qui, logiquement, attend deux booléens en argument et retourne un booléen. En pratique, comme le type booléen n'existe pas formellement, "&&" renvoie zéro si les 2 arguments valent zéro, et il renvoie un sinon.  
 
Ce qui signifie que "&&" est un opérateur beaucoup plus simple que "&", donc le compilateur va pouvoir optimiser beaucoup plus facilement le code qu'il génère.


Message édité par BifaceMcLeOD le 03-02-2003 à 14:12:34
Reply

Marsh Posté le 04-02-2003 à 04:32:41    

BifaceMcLeOD: J'aurais dû voir cette optimisation. :jap:
D'accord pour les pointeurs pas lisibles.
 
Je persiste à trouver ce code étrange.

Code :
  1. int tilex[640], tiley[480]; //ça m'étonnes toujours...
  2. int tiles[480][640]; //...pour moi un terrain de jeu c'est comme ça.
  3. //et le test de collison sur terrain comme ça:
  4. for (int i = 0; i < 10; i++)
  5. if (tiles[posy[i], posx[i]] == valObstacle) //ou switch si plusieurs interractions
  6.  /*colision sol*/;


S'il y a des astuces au problème de collisons inter-sprite, ça m'intéresse aussi.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 04-02-2003 à 04:57:21    

ben si il y a trois sprites a l'ecran
ca sert a rien de parcourir tout l'ecran a la recherche de deux sprites a la meme position:
 
tu fais un test pour chaque couple de sprite (n*(n-1)/2).
Et s'il y a du decor, pour chaque eleement mobile
tu testes s'il se trouve sur un element du decor (n tests avec n nombre de sprites).
De plus en subdivisant ton ecran en cases,  
tu peux arriver a ne faire que tres peu de tests.
(subdivision binaire ou bien cases de taille fixes)
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 04-02-2003 à 22:48:02    

t'as raison Musaran, faut un tableau 2d pour le terrain, je l'ai fait mais pour les id de chaque tiles du tableau, dans cet example c'est des tableaux pour les coordonnées des tiles... bref, le problème de boucle est résolu.
Maintenant je cherche toujours une solution pour le son. J'ai découvert que le coupable dans l'initialisationde DirectMusic est la fonction InitAudio. Si je lui passe d'autres paramètres ca remonte les fps mais ne joue pas les sons, bien sûr!
 
Voilà ce que j'ai testé (pour ceux qui connaissent DirectMusic):
 

Code :
  1. IDirectMusicPerformance8 *Performance;
  2. //cette solution rame!
  3. Performance->InitAudio(NULL, NULL, NULL, DMUS_APATH_DYNAMIC_STEREO, 16, DMUS_AUDIOF_ALL, NULL);
  4. //cette solution rame pas mais ne marche pas!
  5. Performance->InitAudio(NULL, NULL, NULL, DMUS_APATH_DYNAMIC_STEREO, 16, DMUS_AUDIOF_STREAMING);
  6. /*
  7. Notez que ca rame pas forcément lorsque les sons sont joués mais lorsque j'initialise les sons. Rien que d'appeler cette fonction InitAudio sans jouer un seul son dans le jeu ca fait ramer!
  8. */


 
Voilà, ca marche sûrement pas car streaming n'est pas fait pour les wav et les midi mais y a aucune valeure pour ces types!


Message édité par bkadoum le 04-02-2003 à 22:54:20
Reply

Marsh Posté le 04-02-2003 à 23:11:24    

c'est une impression ou tu appelles initAudio
sur un pointeur non initialise?
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 04-02-2003 à 23:33:23    

de plus dans quelle mesure baissent tes perfs?
 
Si tu actives le synthe soft ca parait logique
que les perfs baissent "un peu",
ca fait un thread de plus avec lequel il faut se synchroniser.
 
reste a voir dans quelle mesure:
tu as des chiffres?
 
Legreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 05-02-2003 à 00:09:53    

Les perfs baissent de 50% par rapport à Win98! d'apres mon compteur, ca baisse de 80 à 40 fps!! Ca gène quand même beaucoup.
Le problème peut aussi venir que plusieurs sons peuvent être joués en même temps. J'ai fait une classe Sound regroupant les objets directmusic: IDirectMusicLoader8, IDirectMusicPerformance8, IDirectMusicSegment8. Chaque fois que je construis un objet Sound ca initialise le tout. J'ai vu que sur Win2000, plus tu construit de ces Sound plus les perfs baissent, alors que sur Win98 tu peux en créer autant que tu veux.
Bon, je suis crevé je verrai ca demain, merci pour l'aide et bonne nuit!

Reply

Marsh Posté le 05-02-2003 à 09:19:12    

Ouais ca coule de source, j'ai essayé ce matin de construire 50 objets sounds. Sur 98: 80 fps. Sur 2000: 8 fps. A votre avis ca peut être dut à quoi? la mémoire?

Reply

Marsh Posté le 05-02-2003 à 11:24:09    

 Ce problème me fait penser à celui du jeu Grand Prix 4 ou quand tu passes sous 2000/XP, il rame pas possible à cause du son. Cela se résoud en désactivant l'accélération matériel du son (panneau de config -> son -> avancé ).
 
  Est-ce que tu pourrais le faire pour ton programme. Le résultat m'intéresse (juste par curiosité) ?
  Ca résoudra pas ton problème, mais ça pourrait aider à le comprendre.

Reply

Marsh Posté le 05-02-2003 à 11:50:27    

ca change rien quand je mes l'accélération max, par contre l'accélération min ca rame encore plus!

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed