Le mot clé precise en GLSL (introduit avec l’extension GL_ARB_gpu_shader5) permet de dire au compilteur GLSL de ne pas faire d’optimisation sur le calcul d’une variable. En virgule flottante, a*b*c peut être différent de a*c*b à cause des erreurs d’arrondi.
Dans MSI Kombustor, j’avais testé ce mot clé avec quelques variables car je cherchais à résoudre un bug dans la tessellation. Mais le bug n’était pas lié aux erreurs d’arrondi et autres optimisations faites par le compilateur. J’ai trouvé la solution plus tard. Le problème c’est que j’ai mal nettoyé mon code GLSL et j’ai oublié un keyword precise… A ce moment là, j’avais une Radeon HD 6870 dans ma machine de dev et cet oubli était passé inaperçu. Mais plusieurs jours après quand j’ai branché une GeForce GTX 460 dans ma machine, j’ai eu une mauvaise surprise. Le rendu de mon object avec tessellation et shadow mapping était passé en mode tacheté:
Dans Kombustor, il y a plusieurs tests 3D qui utilisent la tessellation sur les objets 3D avec du shadow mapping pour créer des ombres. Le shadow mapping utilise en gros deux passes: une passe ambiente pour initialiser le z-buffer et dessiner la scene avec l’eclairage ambient, et une seconde passe, dite passe d’illumination, pour colorier les pixels en fonction de la shadow map. La seconde passe etant rendue avec un glDepthFunc(GL_EQUAL) (et du blending) pour ne colorier que les pixels nécessaires.
Le rendu avec GL_EQUAL fonctionne bien si les vertices calculés dans la seconde passe ont exactement la même position finale que ceux calculés dans la première passe. Mais dans le cas de Kombustor, j’avais oublié une variable avec le mot clé precise dans un des shaders de tessellation (le TES, Tessellation Evaluation Shader) de la passe d’illumination. Sur les Radeons (HD 6800 et HD 6900) cela n’a posé aucun problème mais sur une GeForce, ça ne pardonne pas. La position des vertices calculés dans la passe d’illumination est très légèrement différente à cause du mot clé précise et du coup, certains pixels de la seconde passe, n’ayant plus exactement le même Z que ceux de la première passe, ont été eliminés par le test de profondeur ou depth-test. D’où l’apparition des tâches qui correspondent aux endroits où les pixels n’ont pas le bon Z.
J’ai passé quelques heures sur ce sale bug et après avoir compris que le mot clé précise était la source de tous mes ennuis, j’ai enfin retrouvé le bon rendu:
Le mot clé précise semble avoir plus d’influence sur les optimisations faites par le compilteur GLSL de NVIDIA que celui d’AMD. Le mot clé précise est-il pris en compte par le compilo GLSL d’AMD? Y’a-t-il des optimisations dans les calculs flottants avec les cartes Radeon (j’imagine que oui)?
Maintenant je comprends pour NVIDIA insiste souvent, dans les presentations OpenGL 4, sur l’importance du mot clé precise avec les GeForce.
Salut et bravo pour ton article qui est très intéressant, je ne connaissais pas ce mot clé qui peut être bien utile. J’ai d’ailleurs cru qu’il résoudrait mon problème, j’essaye simplement de calculer le pixel où va être rasterizé un point, mon code est mathématiquement correcte et fonctionne très bien avec une carte ATI mais j’ai un problème de précision qui doit se jouer à un Epsilon près par rapport au calcul que fait la carte graphique (dans le cas où c’est une NVIDIA) et du coup mon calcul est faux dans certains cas très rares (quand le point est “entre” deux pixels j’imagine). Si tu as une idée ? ^^