IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SDL Discussion :

Problèmes de performances -- RenderCopyEx() [SDL 2.0]


Sujet :

SDL

  1. #1
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut Problèmes de performances -- RenderCopyEx()
    Salutations !!

    Je suis en train d'essayer, avec mes élèves, d'écrire une application en mode graphique en ANSI C avec SDL2.

    Nous sommes tous contents nous avons une jolie interface graphique... cependant, rien que le fait de l'afficher avec juste quelques processes "traitements" dans la boucle principale, qui peuvent être désactivés facilement, nous avons remarqué:

    + la taille de la mémoire occupée par l'application augmente de 4.0k toutes les cinq secondes, on ne sait pas pourquoi... et nous imaginons qu'à un moment le système va finir par "trasher"... (swapper à n'en plus finir)
    + sur les systèmes multi-coeur que ce soit amd ou intel, il y a un ou deux coeurs qui "montent" à 70% voire 90%, alors qu'il y a une temporisation dans la boucle principale qui boucle jusqu'à ce qu'on ferme la fenêtre, la while(bRunning) que tout le monde connaît.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
     
            ...	
            DisplayUI();
    	SDL_RenderPresent(r_Dessinateur);
    	Log(logFile,"[START] Graphics --> OK");
    	Log(logFile,"[MAIN LOOP]");
    	int rotation=10;
    	while(bRunning)
    	{
    		SDL_Delay(100);	// pour éviter que le processeur monte à 100% :{ 
    										// (boucle infinie --> obligation de taper une tempo sinon le processus va s'accaparer tout le "temps" processeur)
    		while (SDL_PollEvent(&UnEvenement))
    		{
    			switch(UnEvenement.type)
    			{
    				case SDL_QUIT:	SDL_Delay(500);
    												bRunning=false;
    												break;
    				case SDL_KEYDOWN:	
    //												fprintf(stderr,"[DEBUG] Touche appuyée %d\n",UnEvenement.key.keysym.scancode);
    												scancode=UnEvenement.key.keysym.scancode;
    												if(bReleased)
    												{
    													switch(scancode)
    													{
    														case SDL_SCANCODE_LEFT:	
    															break;
    														case SDL_SCANCODE_RIGHT:
    															break;
    														case SDL_SCANCODE_UP:
    															break;
    														case SDL_SCANCODE_DOWN:
    															break;
    														case SDL_SCANCODE_SPACE:
    														case SDL_SCANCODE_F1:
    															SDL_Delay(500);
    															bRunning=false;
     
    													}
    												}
    												bReleased=false;
    												break;
    				case SDL_KEYUP: 
    												bReleased=true;
    												//AfficherInterface(r_Dessinateur);
    												break;
    				case SDL_MOUSEMOTION:
    												positionSouris.x=UnEvenement.motion.x;
    												positionSouris.y=UnEvenement.motion.y;
    												break;
    				case SDL_MOUSEBUTTONDOWN:
    												whichbutton=UnEvenement.button.button;
    												switch(whichbutton)
    												{
    													case 3:	
    																	fprintf(stdout,"Clic bouton droit\n");
    																	break;
    													case 1:	
    																	fprintf(stdout,"Clic bouton gauche\n");
    																	//toggleArduinoOnline(7); 
    																	targetArduino=GetObject(positionSouris);
    																	toggleArduinoOnline(targetArduino); 
    													        //UpdateUI();
    																	break;
    													case 2:	
    																	fprintf(stdout,"Clic bouton milieu\n");
    												}
    												break;
    			}
    			fflush(stdout);
    			fflush(stderr);
    		}
    		#ifdef PERFS_KO
    		lc_Datas *tmpDatas=lc_search(pile_graphics,idBoutonPlay);		// fonction "interne" qui retrouve un objet (par rapport à son identifiant) dans une liste chaînée
    		t_Objet	 *tmpObject=(t_Objet*)tmpDatas->value;							// l'élément de la liste est "transformé" en "objet"
    		SDL_SetRenderDrawColor(r_Dessinateur, 0, 0, 0, 255);  			// couleur de fond noire
    		SDL_RenderClear(r_Dessinateur);															// on efface l'ardoise
    		tmpObject->bDisabled=true;																	// l'objet en question ne doit pas être dessiné
                    #endif
    		UpdateUI();
                    #ifdef PERS_KO																									// on dispose tous les objets à mettre à jour sauf celui-ci
    		SDL_RenderCopyEx(r_Dessinateur,tmpObject->pTexture,NULL,&tmpObject->position,rotation,NULL,SDL_FLIP_HORIZONTAL);
    		rotation+=10;																								// changement de l'angle de rotation (sens des aiguilles d'une montre)
    		#endif
    		SDL_RenderPresent(r_Dessinateur);														// nous avons fini de dessiner
    	}
    	Log(logFile,"[QUIT] Libération des ressources...");
     
    	lc_empty(pile_texts);
    	lc_empty(pile_shadows);
    	lc_empty(pile_graphics);
    	lc_empty(pile_background);
     
    	SDL_DestroyWindow(FenetrePrincipale);
    	TTF_Quit();
    	SDL_Quit();
     
    	Log(logFile,"Fin du programme... retour au shell !!");
     
    	fclose(logFile);
     
    	return (EXIT_SUCCESS);
    }
     
    // Faire mieux que retracer tout l'écran
     
    void UpdateUI(void)
    {
    	SDL_SetRenderDrawColor(r_Dessinateur, 0, 0, 0, 255);  // couleur de fond noire
    	SDL_RenderClear(r_Dessinateur);												// effacer "la toile"
    	DisplayUI();																					// dessiner la "toile"
    	SDL_RenderPresent(r_Dessinateur);											// exposer la "toile"	
    }
     
    int GetObject(Coordonnee coord)
    {
    	lc_Datas	*tmpDatas;
    	t_Objet		*tmpObject;
    	int currentTarget;
     
    	for(currentTarget=0;currentTarget<pile_graphics->NbElem;currentTarget++)
    	{
    		tmpDatas=lc_get(pile_graphics,currentTarget);
    		tmpObject=(t_Objet*)tmpDatas->value;
     
    		// Vérifier si le clic a eu lieu sur un objet...
     
    		if(coord.x>=tmpObject->position.x && coord.y>=tmpObject->position.y && 
    				coord.x<=tmpObject->position.x+tmpObject->position.w && coord.y<=tmpObject->position.y+tmpObject->position.h) 
    		{
    			if(currentTarget<MAXARDUINO)
    				return 7-currentTarget;	 // vu que les textures sont empilées (LIFO) le premier élément à enlever de la pile est toujours le dernier entré...
     
    		}
    	}
            ...
    }

  2. #2
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Citation Envoyé par hurukan Voir le message
    la taille de la mémoire occupée par l'application augmente de 4.0k toutes les cinq secondes, on ne sait pas pourquoi... et nous imaginons qu'à un moment le système va finir par "trasher"... (swapper à n'en plus finir)
    sans code effectivement on ne peut pas définir ce qui éventuellement ne va pas.
    Il y a des optimisations éventuelles à apporter.
    Cependant la SDL c'est un wrapper sensé faciliter les choses et faire un rendu en quelques lignes de code, on ne peut pas faire d'optimisation sur le code du rendu.
    Donc éventuellement passer à Open GL ou Direct X

    Citation Envoyé par hurukan Voir le message
    l
    + sur les systèmes multi-coeur que ce soit amd ou intel, il y a un ou deux coeurs qui "montent" à 70% voire 90%, alors qu'il y a une temporisation dans la boucle principale qui boucle jusqu'à ce qu'on ferme la fenêtre, la while(bRunning) que tout le monde connaît.
    re c'est la même chose; avec Direct X on peut optimiser le rendu

  3. #3
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Normalement quand je fais des applications de ce type je "découpe" l'application en threads: un thread qui gère le clavier (ce que semble faire SDL) un thread qui gère l'affichage, et ainsi de suite...
    Après je "m'amuse" à synchroniser le tout soit avec des "completion routines" soit avec des IPC (sémaphores, mutexes, etc...).

    Ici j'ai essayé de faire cela en SDL1 et j'avais obtenu quelque chose de plus ou moins satisfaisant, mais en SDL2 il n'y a pas moyen d'afficher quoi que ce soit à partir d'un thread créé avec SDL_CreateThread() ou pthread_create().

    Oui, cette application, si je ne l'ai pas encore précisé, fonctionne uniquement sur Linux.

  4. #4
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    salut créer des threads à tout bout de champs je ne suis pas certain que ça soit une bonne idée ; contrairement à ce que l'on pourrait penser ça peut même ralentir l'affichage parce qu'il y a des problèmes de synchronisation éventuels.
    Sans créer aucun thread est-ce que c'est moins performant ?
    Par exemple créer un thread pour le clavier je n'en vois pas franchement l'utilité à moins de vouloir créer un jeu où il faut une pression rapide sur les touches

  5. #5
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui, j'ai fait de plus amples tests, c'est une de mes fonctions qui part en vrille, donc je vous tiens au courant...

  6. #6
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Mega méa-culpa...

    En fait, dans une fonction je parcours une liste chaînée, de laquelle je n'enlève aucun élément... le soucis c'est que la boucle se base sur le nombre d'élément comme condition de sortie de boucle.
    Le soucis, c'est que, sans doute un copier/coller malheureux, dans cette même fonction appelée 10 fois par seconde j'ajoutais des éléments à la liste... au bout de quelques secondes je voyais "monter" le "coeur" à 80%, et en
    tapant la valeur du nombre d'éléments dans la liste dans un log, horrifié, j'étais arrivé à 4000 ou 5000 éléments... alors que, normalement je devais parcourir une vingtaine d'éléments à chaque boucle, tout au plus :{

    Désormais, avec ces six lignes de trop dans le code de la fonction, je n'ai plus la mémoire qui augmente toutes les secondes et, surtout je suis "revenu" à quelque chose de très correct à savoir 1 à 2% de temps processeur pris par
    mon petit programme bien sympa.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     extrait de la fonction DisplayUI() 
    ...
    for(cpt=0;cpt<pile_shadows->NbElem;cpt++)     ...en amont dans le code de la fonction, je faisais deux appels à la fonction AddText() qui ajoutait un texte à la "pile" pile_texts et pile_shadows en vue
    d'être affichés ici
    	{
    		lc_Datas *tmp=lc_get(pile_shadows,cpt);        Je récupère l'objet à l'indice 'cpt' dans la liste chaînée (LIFO)
    		
    		if(tmp==NULL) 
    		{
    			fprintf(stderr,"[DisplayUI] %05d -- %s\n",__LINE__,ERR_NULLPOINTER);
    			return;																															
    		}
    		
    		t_Objet	*tmpObjet=(t_Objet*)tmp->value;      cet objet peut ensuite être "promu" en pointeur sur un t_objet qui contient une texture préalablement créée
    		SDL_SetTextureBlendMode(tmpObjet->pTexture,SDL_BLENDMODE_BLEND);
    		SDL_RenderCopy(r_Dessinateur,tmpObjet->pTexture,NULL,&tmpObjet->position);
    	}
    	
    	
    	for(cpt=0;cpt<pile_texts->NbElem;cpt++)
    	{
    		lc_Datas *tmp=lc_get(pile_texts,cpt);
    		
    		if(tmp==NULL) 
    		{
    			fprintf(stderr,"[DisplayUI] %05d -- %s\n",__LINE__,ERR_NULLPOINTER);
    			return;																															
    		}
    		
    		t_Objet	*tmpObjet=(t_Objet*)tmp->value;
    		SDL_SetTextureBlendMode(tmpObjet->pTexture,SDL_BLENDMODE_BLEND);
    		SDL_RenderCopy(r_Dessinateur,tmpObjet->pTexture,NULL,&tmpObjet->position);
    	}
    ...
    Voici ce que fait AddText() la fonction qui ne doit surtout pas être appelée dans la fonction DisplayUI()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    bool AddText(char *message,int posX,int posY,struct s_RGB couleur,int taille)
    {
    	// Si message est invalide, en tant que pointeur on sort directement de la fonction, même chose si la chaine est vide...
    	if(message==NULL) return false;																																																															
    	if(!strlen(message)) return false;
     
    	// On va chercher la police à générer en mode graphique...
     
    	f_Police=TTF_OpenFont("/usr/share/fonts/truetype/6809char.ttf",taille);  //	/usr/share/fonts/truetype/airmolea.ttf 
     
    	if(f_Police==NULL)
    	{
    		fprintf(stderr,"Impossible d'ouvrir la police :{ [%s]",SDL_GetError());
    		return false;
    	}
     
    	// création des surfaces
     
     
    	s_Texte=TTF_RenderUTF8_Blended(f_Police,message,(SDL_Color){couleur.Red,couleur.Green,couleur.Blue,couleur.alpha});
    	s_Ombre=TTF_RenderUTF8_Blended(f_Police,message,(SDL_Color){couleur.Red/4,couleur.Green/4,couleur.Blue/4,couleur.alpha-64});
     
    	// création des textures à partir des surfaces
     
    	t_Ombre=SDL_CreateTextureFromSurface(r_Dessinateur,s_Ombre);
    	t_Texte=SDL_CreateTextureFromSurface(r_Dessinateur,s_Texte);
     
    	// comme les textures ont été créées nous n'en avons plus besoin
     
    	SDL_FreeSurface(s_Ombre);
    	SDL_FreeSurface(s_Texte);
     
    	// déterminer les "zones" de texte et d'ombre...
     
    	SDL_Rect posOmbre;
    	SDL_Rect posTexte;
     
    	posTexte.x=posX;   // *taille/2
    	posTexte.y=posY;
    	posTexte.w=taille*strlen(message);
    	posTexte.h=taille;
     
    	posOmbre.x=posTexte.x+1;
    	posOmbre.y=posTexte.y+1;
    	posOmbre.w=posTexte.w+1;
    	posOmbre.h=posTexte.h+1;
     
    	// obtenir un nouvel espace mémoire pour chaque élément...
     
    	t_Objet *tmpTexte=malloc(sizeof(t_Objet));
    	t_Objet *tmpOmbre=malloc(sizeof(t_Objet));
     
    	// ajouter les objets dans leurs piles respectives...
     
    	tmpTexte->pTexture=t_Texte;
    	tmpTexte->position=posTexte;
    	lc_insert((void*)tmpTexte,pile_texts,cssmuserdef,sizeof(t_Objet));
     
    	tmpOmbre->pTexture=t_Ombre;
    	tmpOmbre->position=posOmbre;
    	lc_insert((void*)tmpOmbre,pile_shadows,cssmuserdef,sizeof(t_Objet));
     
    	// nous n'avons plus besoin de la fonte...
     
    	TTF_CloseFont(f_Police);
    return true;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de performance avec LEFT OUTER JOIN
    Par jgfa9 dans le forum Requêtes
    Réponses: 6
    Dernier message: 17/07/2005, 13h17
  2. [jeu]problème de performance d'un algo
    Par le Daoud dans le forum Algorithmes et structures de données
    Réponses: 12
    Dernier message: 30/05/2005, 16h07
  3. [C#] Probléme de performance avec IsDbNull
    Par jab dans le forum Windows Forms
    Réponses: 8
    Dernier message: 04/04/2005, 11h39
  4. [oracle 9i][Workbench]Problème de performance
    Par nuke_y dans le forum Oracle
    Réponses: 6
    Dernier message: 03/02/2005, 17h38
  5. [ POSTGRESQL ] Problème de performance
    Par Djouls64 dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 26/05/2003, 16h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo