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

Auteur Sujet: Performance, sf::RenderTexture et nombreux Shaders  (Lu 10966 fois)

0 Membres et 1 Invité sur ce sujet

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Performance, sf::RenderTexture et nombreux Shaders
« le: Septembre 20, 2013, 12:37:13 pm »
Bonjour !  :)

Dans le cadre de mon projet je suis ammené à utiliser beaucoup de shaders pour mes effets. Cependant j'ai quelques questions à propos de l'utilisation de ceux-ci.

On peut les séparer en deux catégorie différentes :
-> Ceux qui ne s'appliquent qu'à un seul objet
-> Ceux qui s'appliquent à la scène en globalité

Dans les deux cas, il faudra parfois passer par des sf::RenderTexture (si un shader à besoin de plusieurs "pass").
Pour avoir donc une architecture propre, je voudrais donc passer par une classe abstraite (qui hérite de sf::Drawable et sf::Transform) pour manipuler mes objets graphiques (ils sont purement graphiques, les calculs de jeux sont dans un GameEngine).

Pour ainsi dire, je voudrais pour chaque objet, le dessiner avant tout dans un sf::RenderTexture (afin d'appliquer les shaders spécifique à chaques objets).
Dans un second temps, je dessinerais le résultat de chaques objet dans un autre sf::RenderTexture qui lui contiendra la scène entière a afficher sur l'écran. J'appliquerais sur ce dernier les shaders "globaux".
Je dessinerais enfin ma scène finale sur l'écran.

J'ai donc plusieurs questions :
-> Premièrement, systématiquement passer par des sf::RenderTexture est-il adapté à l'implémentation de nombreux shaders ? (en gros, est-ce que je suis pas en plein délire)
-> Draw / Clear de nombreux sf::RenderTexture n'est-il pas trop gourmand en ressources ?

Cordialement

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #1 le: Septembre 20, 2013, 01:54:34 pm »
Citer
-> Premièrement, systématiquement passer par des sf::RenderTexture est-il adapté à l'implémentation de nombreux shaders ? (en gros, est-ce que je suis pas en plein délire)
Il n'y a a priori pas d'autre solution que de dessiner sur des textures intermédiaires pour appliquer plusieurs shaders. Donc la question des performances ne se pose pas, c'est la seule façon de faire.

Citer
-> Draw / Clear de nombreux sf::RenderTexture n'est-il pas trop gourmand en ressources ?
Dessiner sur un sf::RenderTexture c'est pareil que sur un sf::RenderTarget.
Dessiner un sf::RenderTexture via un sprite c'est pareil que de dessiner n'importe quelle texture via un sprite.
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #2 le: Septembre 20, 2013, 01:57:08 pm »
D'accord. Je vais partir là dessus alors.
J'essaierai d'apporter des feedback ici  :).

Merci beaucoup Laurent !

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #3 le: Septembre 30, 2013, 02:01:11 pm »
Bonjour !

J'apporte un peu mon ressenti après notre discussion.


J'ai été confronté à un problème de performance lors de l'application de shader "globaux".
En effet, pour appliquer un effet de flou gaussien sur ma scène, je devais dessiner dans deux textures de la taille de ma fenêtre à chaques frames.
Or draw des renderTexture de 1920*1080 est super gourmand (mes fps étaient divisé par deux).

Le tutoriel explique que les sf::RenderTexture sont un bon moyen d'appliquer des shader globaux, or je ne suis pas d'accord au vu de l'expérience que j'en ai tiré.
L'utilisation de sf::RenderTexture est très utile en effet pour l'application de multiple shader, or appliquer un shader à tout une scène est beaucoup trop gourmand en ressources.
Il vaut donc mieux appliqué le même shader à chaques objets en utilisant de petite sf::RenderTexture.

Je ne pense pas que ce soit un problème d'implémentation mais bien un problème de performance (soit venant de SFML, soit matériel, voir même les deux).

Ëtes vous d'accord avec mon propos Laurent ?

Cordialement.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #4 le: Septembre 30, 2013, 02:05:52 pm »
Ca ne devrait pas être aussi lent, à moins que tu aies une carte graphique très vieille.

Le problème avec l'application de shader individuellement sur chaque objet, c'est que ça limite beaucoup le nombre d'effets implémentables. Par exemple tu ne peux pas réaliser un flou gaussien comme ça (pas un flou global en tout cas).

Il n'y a pas d'autre solution complètement équivalente.
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #5 le: Septembre 30, 2013, 02:25:14 pm »
Au niveau de la carte graphique je ne pense pas trop être à la ramasse  :)
http://www.notebookcheck.net/NVIDIA-Quadro-NVS-5100M.24946.0.html

C'est pourtant flagrant. Dès que j'active mon shadering global, les fps du jeux dégringolent (de 60 à 30).

Voilà la boucle qui ralentit le jeux dès que la fenêtre devient trop grande :

Avec :
std::list<Shader*>::iterator it, end  // Mes itérator sur ma list de shader
class Shader : public sf::Shader
sf::RenderTexture _buffer1, _buffer2   // De la taille de ma fenêtre
sf::Sprite tmpRes

  while (it != end)
    {
      if (lastBuffer == 1)
        {
          tmpRes.setTexture(_buffer1.getTexture());
          _buffer2.draw(tmpRes, (*it));
          lastBuffer = 2;
        }
      else
        {
          tmpRes.setTexture(_buffer2.getTexture());
          _buffer1.draw(tmpRes, (*it));
          lastBuffer = 1;
        }
      ++it;
    }
 


Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #6 le: Septembre 30, 2013, 02:45:35 pm »
Est-ce que tu as activé une limite de framerate, ou bien la synchro verticale ? 60, 30, ça a l'air bloqué tout ça, essaye de mesurer les performances sans aucune limitation (regarde aussi dans les options de ton driver graphique).

Note que tu aurais un code plus simple avec deux pointeurs que tu peux échanger, plutôt qu'un entier qui te dit dans quelle render-texture travailler.

Et n'oublie pas les appels à display().

sf::RenderTexture* front = &_buffer1;
sf::RenderTexture* back = &_buffer2;

while (it != end)
{
    front->draw(sf::Sprite(back->getTexture()), *it);
    front->display();
    std::swap(front, back);
}
« Modifié: Septembre 30, 2013, 02:49:12 pm par Laurent »
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #7 le: Septembre 30, 2013, 03:17:11 pm »
Citer
Est-ce que tu as activé une limite de framerate, ou bien la synchro verticale ? 60, 30, ça a l'air bloqué tout ça, essaye de mesurer les performances sans aucune limitation (regarde aussi dans les options de ton driver graphique).

Bien vu ! En désactivant la syncro verticale c'est beaucoup plus fluide. Normal d'un côté mais je n'y avais pas pensé.
Pas mal votre bout de code aussi ! Beaucoup plus pro que le miens en effet. Merci !

Autre question par rapport au sf::RenderTexture.
Est-ce que l'appel à sf::RenderTexture::create est long en temps normal ?
Imaginons que j'ai un personnage qui tire des projectiles de façon rapide et répété (disons 10/sec) et que je veux appliquer des shader sur chaque projectile. Si je créer un/deux sf::RenderTexture pour chaque projectile, le programme ne va-y-il pas en souffrir ? (sachant que mes RenderTexture sont petites, disons 20*20)
Le mieux serait peut être de partager deux sf::RenderTexture entre tous les projectiles ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #8 le: Septembre 30, 2013, 03:25:35 pm »
Citer
Est-ce que l'appel à sf::RenderTexture::create est long en temps normal ?
Oui, très.

Citer
Imaginons que j'ai un personnage qui tire des projectiles de façon rapide et répété (disons 10/sec) et que je veux appliquer des shader sur chaque projectile. Si je créer un/deux sf::RenderTexture pour chaque projectile, le programme ne va-y-il pas en souffrir ?
Oublie tout de suite ce genre de stratégie, tu vas plomber tes performances avec ça ;)

Citer
Le mieux serait peut être de partager deux sf::RenderTexture entre tous les projectiles ?
Voire entre tous tes objets. Ce n'est pas parce qu'un objet fait 20x20 qu'il ne peut pas utiliser un bout d'une render-texture de 50x50 par exemple (n'oublie pas Sprite::setTextureRect).
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #9 le: Septembre 30, 2013, 03:30:35 pm »
D'accord !

Je venais de tester en effet et à chaque tir j'ai un gros lag (alors que ma texture fait 15*15).  :)

Citer
Citer
Le mieux serait peut être de partager deux sf::RenderTexture entre tous les projectiles ?
Voire entre tous tes objets. Ce n'est pas parce qu'un objet fait 20x20 qu'il ne peut pas utiliser un bout d'une render-texture de 50x50 par exemple (n'oublie pas Sprite::setTextureRect).

Je vais donc partir là dessus, et d'un côté ça m'arrange car ça sera plus propre au niveau du code.

Merci beaucoup Laurent !

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #10 le: Octobre 01, 2013, 10:19:28 am »
Bonjour  :)

Je vais exposer ici un problème de performance que j'ai et qui d'après moi est tout a fait normal. Je cherche juste la meileure solution afin de contourner ce problème.

Reprenons l'exemple que j'ai donner plus tôt dans ce topic.

Citer
Imaginons que j'ai un personnage qui tire des projectiles de façon rapide et répété (disons 10/sec) et que je veux appliquer des shader sur chaque projectile

Pour l'instant, j'ai deux sf::RenderTexture partagée entre tout mes objets. Cependant, si dans une frame j'ai 200 projectiles à dessiner, cela prend du temps (200 * (clear + draw)).
Forcément, le programme en souffre.

J'ai donc penser à un sf::VertexArray.
Pourquoi :
Utiliser un vertexArray pour afficher tout mes projectiles d'un coup. Cependant cela me limite au niveau des shaders (si je veux plusieurs projectiles différents, il me faut plusieurs vertexArray). Ce sera quoi qu'il en soit toujours plus performant que l'implémentation actuelle.

Y-aurait-il une autre approche que les vertexArray ?

Cordialement.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #11 le: Octobre 01, 2013, 10:36:02 am »
Moi je reste toujours bloqué sur le fait que tu n'arrives pas à avoir des performances correctes en appliquant tes shaders sur tout l'écran. Tu ne devrais pas avoir à bidouiller comme tu le fais là.

Est-ce que tu pourrais écrire un code complet minimal qui reproduit ton problème de performances ? J'aimerais bien m'assurer que tu n'as pas de bêtise dedans ;)
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #12 le: Octobre 01, 2013, 10:54:02 am »
Citer
Moi je reste toujours bloqué sur le fait que tu n'arrives pas à avoir des performances correctes en appliquant tes shaders sur tout l'écran. Tu ne devrais pas avoir à bidouiller comme tu le fais là.

Ce problème (limitation des fps à 30) était causé par la syncronisation verticale. Vous aviez pointé ce problème. De plus j'ai pour le moment enlever l'application des shaders globaux car la structure de base n'est pas encore tout à fait à mon goût.
Je vais quand même faire un code minimal au cas où je verrais mal la chose.
Cependant, corriger ce problème ne me permettrait de contourner pas le soucis que j'ai pour afficher de nombreux objets à chaques frames (car le nombre d'appel à clear/draw sera toujours aussi important).

Au passage, j'ai une petite question un peu plus "technique".
Est-ce que SFML met plus de temps à draw lorsqu'on lui passe un shader en paramètre ?
Si j'ai bien compris openGL, les shaders "prennent la place" de certains module dans le pipeline d'openGL.
Conclusion, les performances devraient être à peu près équivalente, n'est-ce pas ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #13 le: Octobre 01, 2013, 11:10:59 am »
Citer
Cependant, corriger ce problème ne me permettrait de contourner pas le soucis que j'ai pour afficher de nombreux objets à chaques frames (car le nombre d'appel à clear/draw sera toujours aussi important).
Ok. Donc là on ne parle plus de shaders, juste d'optimiser l'affichage des objets ?

Citer
Est-ce que SFML met plus de temps à draw lorsqu'on lui passe un shader en paramètre ?
Si j'ai bien compris openGL, les shaders "prennent la place" de certains module dans le pipeline d'openGL.
Conclusion, les performances devraient être à peu près équivalente, n'est-ce pas ?
En effet. Cependant, suivant la complexité des shaders et leur nombre, tu peux avoir des trucs assez lourds. En l'occurence, si on parle toujours bien d'un shader de flou gaussien, les nombreuses passes et texture lookup (désolé j'ai pas d'équivalent en français :P) sont typiquement assez lourds en exécution.
Laurent Gomila - SFML developer

PetitPoney

  • Newbie
  • *
  • Messages: 44
    • Voir le profil
Re : Performance, sf::RenderTexture et nombreux Shaders
« Réponse #14 le: Octobre 01, 2013, 11:23:07 am »
Citer
Citer
Cependant, corriger ce problème ne me permettrait de contourner pas le soucis que j'ai pour afficher de nombreux objets à chaques frames (car le nombre d'appel à clear/draw sera toujours aussi important).
Ok. Donc là on ne parle plus de shaders, juste d'optimiser l'affichage des objets ?

Exact  :). Car dans une frame je peux me retrouver avec une (voir plusieurs, je ne veux limiter en aucun cas mon projet) centaines d'objet à dessiner.
J'ai déjà piqué votre système de particule pour faire mes explosions, et je pensais faire quelque chose d'a peu près identique pour gérer ma/mes centaines de projectile. Cependant si je veux plusieurs projectiles différents (en utilisant des shaders différents), je dois passer par plusieurs vertexArray du coup.

Exact ?  :D

PS : Je reviendrais plus tard sur mon application de shader globaux