Auteur Sujet: Culling de patch / de primitives sur le GPU  (Lu 2563 fois)

0 Membres et 1 Invité sur ce sujet

Salut !

J'utilise OpenGL pour exécuter des rendus qui ne sont pas forcement du rendu "traditionnel" mais qui se rapprochent un peu du GP-GPU.

J'ai un algo qui fonctionne bien, mais pour lequel je pourrais augmenter significativement les performances en appliquant un test de culling au niveau de tesselation control shader ou du geometry shader.

Voila comment ça fonctionne, en gros :

1/ Vertex shader :
=> beaucoup de vertex sont traités, un certain nombre inutilement (il ne participeront pas tous au résultat final du calcul), mais l’exécution est très très rapide (cette étape ne fait pratiquement rien, les données sont pré-traitées) donc je ne touche à rien ici.

2/ Tesselation Control shader :
=> ici je calcule des facteur de "raffinement local" du calcul final. Le calcul est relativement lourd mais avec moins d’exécutions (les patchs contiennent 4 vertex), donc ça va, et on ne peut pas vraiment y couper.

3/ Tesselation Evaluation shader :
=> une des étapes les plus lourdes, ici y'a pas mal de trucs à faire

4/ Geometry shader :
=> quelques calculs, mais pas énormes

5/ Fragment shader :
=> une des étapes les plus lourdes, ici y'a pas mal de trucs à faire


Pour l'optimisation, je pourrais éliminer des patchs entiers (ceux qui sortent du frustum de la camera en gros) à la sortie du Tesselation Control en écrivant des facteurs à 0. Du coup, je fais ça :
- dans le vertex shader, je place un booléen à true ou false pour indiquer si le vertex est dans le frustum ou pas
- dans le tesselation control shader, si tous les vertex en entrée sont "pas visible" j'élimine le patch

Ca marche bien... sauf si le patch "croise" le frustum : si 2 vertex sont en dehors d'un coté et 2 autres vertex en dehors de l'autre coté, il faudrait quand même exécuter ce patch mais il se retrouve éliminé.

Du coup je vois pas très bien comment faire le test de culling "complet" pour être sûr de ne jamais éliminer un patch qui ne devrait pas l'être : les algos CPU qui font ce genre de choses me paraissent très complexe à mettre en place dans un shader...

Existe-t-il des "astuces" pour effectuer ce genre de test de culling ?

Et j'aimerais aussi faire la même chose au niveau du geometry shader pour éliminer des primitives produites par le tesselateur mais qui sont finalement inutiles...


Merci d'avance pour les pistes / conseils !

Effectivement c'est un vieux problème qu'on avait déjà dans le clipping software... ;D

Le mieux est encore de rajouter un test dans le tess control où, si tu as 4 vertex à 0 donc potentiellement à virer, tu lances un test supplémentaire avec les 4 plans (6 ?) du frustum : en effet, tu peux effectivement virer le patch si ses 4 vertices sont tous d'un même côté d'un des 4 plans. Donc ce test est très rapide à faire...

Reste les cas les plus chiants :



Là, le patch est pas forcément derrière un seul plan et pourtant il peut être viré...

Bref, la seule solution est encore d'appliquer un bon vieil algo de clipping à l'ancienne : tu clippes ton patch avec chacun des 4 plans de frustum pour éventuellement obtenir une liste de vertex clippés vide, auquel cas tu peux virer le patch. Mais vu que c'est gourmand et chiant à coder, je suis pas certain que t'y gagnes par rapport à tout balourder  à la carte sans te poser de question... ;D


Je me demandais aussi un truc : tes patchs ont du displacement ou non ? Car s'ils sont déformés (ce qui est souvent le but) alors c'est même pas la peine de faire du culling à la pogne...

Merci pour la réponse !

Même si bon, c'est un peu ce que je craignais...

En fait, je cherche une astuce du genre :

1/ dans le vertex shader, placer 6 bits (ou 12 ?) pour chaque plan du frustum, avec 0 ou 1 pour indiquer de quel coté est le sommet
2/ dans le tesselation control shader, un bon vieux mélange de AND, OR, XOR (le shérif de l'espace) pour déterminer le culling très rapidement

Mais bon, je cherche encore.

Sinon, oui, le patch ont du displacement, mais il est appliqué à l'ensemble du patch dans le vertex shader, donc le culling reste valable. Ensuite il y a encore un displacement qui est appliqué à chaque primitive dans le tesselation evaluatation shader, mais l'algo garanti que les sommets ajoutés dans le patch restent "à l'intérieur" du patch initial, donc le culling reste pertinent.

Et pour finir, les calculs appliqués dans le tesselation evaluation shader et dans le fragment shader sont tellement lourds, que oui, ça reste utile de faire du culling.

Ca suffira pas de faire des opérations logiques : il faut vraiment que tu clippes les edges du patch avec chacun des 4 plans...

Tu peux pas déplacer le code du TES dans le GS et faire le culling dedans ? Tu seras 4x moins parallèle mais si ça process suffisamment moins de data derrière ça peut gagner...

Ben non pas trop, la charge de travail est déjà lourde dans le tesselation evalutation.

Et le problème reste le même : un algo de culling de primitive efficace sur GPU.