Dans son blog, il donne son point de vue sur la conception d'OpenGL et y explique pourquoi la bibliothèque est en retard par rapport aux récentes solutions proposées par les concurrents (DirectX 12 et Mantle). Même si certains de ces points peuvent être mineurs et négligeables, cela décourage bien souvent les développeurs voulant s'intégrer dans l'écosystème OpenGL.
20 ans d'héritage, OpenGL nécessite une refonte
Il faut qu'OpenGL suive le concept KISS (Keep It Simple, Stupid). En cas de doute, on doit se débarrasser de tel ou tel élément. La bibliothèque doit être extrêmement simplifiée, notamment en enlevant le mode de compatibilité. DirectX 12 et Mantle vont être très agressifs du point de vue de la performance alors que le système de contexte global et le modèle basé sur les liaisons sont pourris. Une bibliothèque reposant sur un accès à l'état direct (Direct State Access) devrait être maintenant un standard.
La plupart des développeurs vont préférer une transition douce en portant leur code de rendu PS4/Xbox One vers DirectX 12 et/ou Mantle. Ils ne vont pas réécrire leur pipeline de rendu en entier pour utiliser un regroupement super agressif des ordres de rendu et autres techniques avancées comme la communauté OpenGL le conseille depuis quelques temps afin d'améliorer les performances. Mais à cause de cela, OpenGL sera toujours considéré comme une solution de seconde zone et aucun portage ne sera fait tant qu'il n'y aura pas de modernisation et simplification de la bibliothèque.
La création de contexte OpenGL est un enfer
La création d'un contexte OpenGL moderne est une source d'erreur inimaginable. Le processus est même dépendant de la plateforme et Rich recommande aux développeurs de ne jamais utiliser des bibliothèque GLX/WGL/... mais plutôt des bibliothèques de plus haut niveau comme SDL ou GLFW (et un truc comme GLEW pour récupérer les pointeurs de fonctions et autres extensions).
Le principe de devoir utiliser des bibliothèques tierces est nul. La bibliothèque devrait être simplifiée et normalisée afin que l'utilisation d'une bibliothèque tierce ne soit plus une nécessité lors de la création d'un contexte.
Le thread du contexte courant pourrait être un pointeur "this" implicite
Les fonctions retournées par GetProcAddress() ne peuvent (ou ne devraient, suivant la plateforme) pas être utilisées globalement car elles peuvent être fortement liées au contexte (en langage OpenGL : dépendante ou indépendante du contexte). En d'autres mots, l'appel à la fonction GetProcAddress() sur un contexte et l'utilisation du pointeur retourné dans un autre contexte est mauvais et provoquera des crashs.
Déficience de glGet()
Ceci est peut-être fortement lié au tracing des appels OpenGL mais cela impacte indirectement les développeurs car les outils sont inefficaces ou inexistants.
La série de fonction glGet* (glGetIntergerv, glGetTexImage...) ne possède pas de paramètre "taille_maximale", donc il est possible pour le pilote d'écraser les données des tampons suivant les paramètres ou l'état du contexte global. Avec un paramètre de taille, la fonction pourrait retourner une erreur si la taille maximale est trop petite et non provoquer un écrasement de mémoire.
Le calcul de la taille du tampon de texture lu ou écrit par le pilote dépend de plusieurs état du contexte global, ce qui est mauvais.
Il y a une centaine d'énumérations acceptées par la fonction glGet() et certaines ne sont acceptées que par des pilotes spécifiques. Si vous écrivez un débogueur ou un traceur, il n'y a aucune méthode officielle pour déterminer comment les valeurs seront gérées par le pilote.
glGetError
Il n'y a pas de glSetLastError() comme dans la bibliothèque Win32, rendant le tracing d'application difficile. Certaines applications n'appellent jamais glGetError(), d'autres une fois par image, d'autres seulement lors de la création des ressources. Certaines l'appelle des centaines de fois à l'initialisation et plus jamais par la suite. Rich a vu des applications dans le commerce ayant des erreurs OpenGL à chaque image (est-ce que les développeurs le savent ?).
Impossibilité de faire des requêtes sur des éléments clés
Comme il n'est pas possible de faire des requêtes sur des éléments tels que les cibles de texture, le débogage d'application est encore plus difficile, notamment dans les cas de rendu d'ombre. Tous les états devraient pouvoir être accessibles.
Les bibliothèques en accès directs aux états ne sont pas un standard et pas toujours correctement supportés
L'accès direct aux états permettra une grande différence dans le surcoût des appels des fonctions OpenGL.
La spécification n'est toujours pas complète en 2014
La spécification XML ne possède pas d'information de types pour les paramètres. Par exemple :
Code xml : | Sélectionner tout |
1 2 3 4 5 | <command> <proto>void <name>glBindVertexArray</name></proto> <param><ptype>GLuint</ptype> <name>array</name></param> <glx type="render" opcode="350"/> </command> |
Code : | Sélectionner tout |
GlFunction(Void, "glBindVertexArray", [(GLarray, "array")]),
Pas d'outils standard/officiel pour OpenGL
Il y a besoin de :
- outil d'aide pour la conversion de texture et de pixel qui ne repose pas sur le pilote ou un contexte OpenGL ;
- équivalent de DXTEX pour le format KTX (équivalent du DDS), qui fonctionne avec tous les fichiers ;
- outil de conversion d'image vers KTX ;
- une bibliothèque pour compiler les shaders.
Extensions décrient comme des diff par rapport à la spécification
Pour comprendre la documentation des extensions, il faut connaître parfaitement la spécification.
Horreur de MakeCurrent()
La fonction peut être extrêmement coûteuse, tout en ayant des coûts supplémentaires avec certaines extensions (NB_bindless_texturing), peut provoquer des crashs si elle est appelée entre des blocs glBegin()/glEnd(). Le comportement de cette fonction devrait mieux être expliqué aux développeurs.
Les pilotes ne devraient pas crasher le GPU, ni le CPU, ni même freezer lors des comportements indéterminés de la bibliothèque
Soit les pilotes devraient mieux être testés, soit la bibliothèque doit être restructurée pour éliminer les comportements indéfinis.
Le pilote freeze en cas de trop nombreux appels à glBufferSubData(). Le pilote peut caler tout le pipeline pendant vos opérations de rendu et rien ne vous indique la raison. Les requêtes peuvent aussi provoquer ce comportement.
Destruction des objets
Bonne chance si l'objet en cours de destruction est lié à un autre contexte.
L'appel de glGet() sur un objet partiellement détruit (encore existant car lié dans un autre contexte) provoque des comportements qui diffèrent entre les pilotes.
Compilation et édition des liens des shaders
Il y a de nombreux problèmes de performances liés à la compilation des shaders. Le système utilisé dans Direct3D fonctionne. En plus, OpenGL n'accepte que des shaders en texte. Les temps de compilation entre les pilotes sont très variables et certains utilisent des techniques d'optimisation alors que d'autres ne le font pas (compilation en parallèle, système de cache).
Multithreading
Certains développeurs ont décidé d'activer leur pilote multithread alors que ceux-ci sont bogués et cela, plusieurs mois après les tests des développeurs de jeux. Même les glGet() peuvent être bogués lorsque le parallélisme est activé. Il n'y a aucune méthode pour savoir si le pilote est multithreadé ou non.
Votre opinion
Que pensez-vous de tous les défauts rapportés par Rich Geldreich ? Sont-ils légitimes ?
Trouvez-vous que DirectX propose une meilleure bibliothèque, exempt de défauts ?
Utilisez-vous OpenGL directement, ou préférez-vous l'utilisation d'un moteur ? Lequel et pourquoi ?
Voir aussi
La vérité sur la qualité des pilotes graphiques OpenGL
Les développeurs de Dolphin dressent un tableau de la qualité du support d'OpenGL
Conférence de Rich Geldreich aux Steam Dev Days
Game Connection 2013 - Europe : Techniques OpenGL ES avancées dans la série des GTA
Source
Blog de Rich Geldreich