Introduction
Avec l’omniprésence de DirectX de nos jours on a tendance à l’oublier, mais il y a une dizaine d’années une véritable guerre était engagée entre Microsoft et SGI sur le terrain des API 3D. Les deux sociétés rivalisaient d’efforts pour séduire les développeurs, Microsoft utilisant ses moyens financiers et SGI jouant pour sa part sur son expérience et sa renommée dans le domaine de la 3D temps réel. Dans ce David contre Goliath des temps modernes, le « petit » a tout d’abord remporté des points précieux en remportant le support du plus célèbre des programmeurs : John Carmack. Le succès des moteurs de Quake aidant, un bon support d’OpenGL est devenu suffisamment important pour motiver les fabricants de cartes 3D à fournir des drivers complets.
Microsoft pendant ce temps partait de zéro et il est évident que l’apprentissage allait prendre du temps. Pendant plusieurs années Direct3D a donc été en retard en termes de fonctionnalités tout en offrant une interface que beaucoup de programmeurs jugeaient nettement plus confuse que celle d’OpenGL. Mais s’il y a une chose qu’on ne peut pas reprocher à Microsoft c’est de se décourager trop vite. Au fil des versions Direct3D a petit à petit rattrapé son retard sur OpenGL, les ingénieurs de Redmond ayant aussi fait énormément d’effort pour rendre les performances comparables à celles obtenues par l’API concurrente.
Un tournant a été atteint avec DirectX 8 sorti en 2001 : pour la première fois l’API de Microsoft ne se contentait pas de reproduire ce que faisait SGI mais apportait des innovations propres comme le support des vertex et des pixel shaders. Parallèlement, SGI dont les revenus étaient principalement basés sur la vente d’onéreuses stations de travail dédiées à la 3D était dans une mauvaise situation, n’ayant pas senti que l’explosion des cartes 3D pour joueurs allait inciter ATI et NVIDIA à investir le marché professionnel avec des prix tellement bas (du fait des volumes) que SGI ne pouvait plus suivre. L’évolution d’OpenGL souffrait également de querelles internes. L’ARB, le groupe chargé de ratifier l’évolution de l’API, étant constitué d’un grand nombre de sociétés concurrentes il était difficile d’arriver à un accord sur les fonctionnalités à ajouter à l’API, chaque société essayant de tirer la couverture dans son sens. A l’inverse Microsoft de son côté se contentait de travailler avec ATI et NVIDIA, tranchant en dernier recours en cas de désaccord.
Avec DirectX 9 Microsoft a définitivement enfoncé le clou en imposant son API comme incontournable pour les développeurs. Seuls John Carmack et ceux qui se souciaient de la portabilité restaient fidèles à OpenGL mais cela représentait une part de plus en plus négligeable. Pourtant un retournement de situation n’était pas à exclure : on l’a vu dans le domaine des navigateurs Internet, même avec une situation de quasi monopole si l’on s’endort sur ses lauriers il n’est pas rare de voir un concurrent renaître de ses cendres. La prise de contrôle d’OpenGL par le groupe Khronos il y a deux ans laissaient donc entrevoir de nombreux espoirs que l’on espérait voir se concrétiser au SIGGRAPH de cette année. C’est en effet le mois dernier que Khronos devait annoncer OpenGL 3, une large révision de l’API qui devait permettre de recoller avec celIe de Microsoft dont la version 11 allait elle aussi être présentée. Pourtant tout ne s’est pas vraiment passé comme prévu…
OpenGL 3 (3Dlabs et l’évolution d’OpenGL)
Pour bien comprendre l’ampleur de la controverse qui a entouré l’annonce d’OpenGL 3 il faut revenir quelques années en arrière, plus précisément en 2002. A cette époque comme nous l’avons vu en introduction, OpenGL est en perte de vitesse : alors que jusqu’ici DirectX se contentait de copier ses fonctionnalités c’est désormais l’API de SGI qui est à la traîne. Microsoft a introduit DirectX 9 supportant un langage de shaders de haut niveau : HLSL et OpenGL n’ a rien à proposer en face. Il faut savoir qu’OpenGL tire ses origines d’IRIS GL, une API initialement créée par SGI pour exposer les fonctionnalités de son hardware. Pendant longtemps ATI et NVIDIA se sont contentés de suivre le modèle de rendu de SGI ce qui a permis à OpenGL d’être particulièrement bien adapté aux dernières cartes avant même leur sortie, mais avec l’introduction des shaders les nouveaux GPU se démarquent du pipeline de rendu traditionnel.
A l’époque une société s’est rendu compte de l’importance d’une évolution rapide d’OpenGL afin de l’adapter aux GPU modernes : 3DLabs. Ce n’est pas étonnant car cette société a abandonné les cartes pour joueurs après la Permedia 2, se concentrant sur le marché professionnel sur lequel OpenGL est incontournable. 3DLabs va présenter un plan en plusieurs points pour faire entrer OpenGL dans une nouvelle ère : tout d’abord l’intégration d’un langage de shaders de haut niveau : GLSL. Ensuite une remise à plat complète de l’API : de nombreuses fonctionnalités n’ont plus de sens sur les cartes 3D modernes mais l’obligation de rétrocompatibilité oblige les fabricants de GPU à les supporter au moins en software. Non seulement cela complexifie l’écriture des drivers augmentant la possibilité de bugs, mais en plus l’abondance de fonctionnalités rend l’API confuse pour un nouveau programmeur. Il existe ainsi de nombreuses façons d’aboutir à un résultat donné, certaines étant dramatiquement plus rapides que les autres mais ce n’est pas évident de prime abord.
L’objectif de 3DLabs est donc d’exposer un sous ensemble de fonctionnalités garantissant une exécution efficace sur le GPU en éliminant les fonctionnalités dépassées ou redondantes. Ce sous ensemble est baptisé OpenGL 2.0 Pure, et était destiné aux développeurs de nouvelles applications. Pour la rétrocompatibilité l’ensemble des autres fonctionnalités d’OpenGL 1.x était disponible dans Open GL 2.0.
Malheureusement après d’interminables discussions au sein de l’ARB ce plan ne sera finalement pas retenu et lorsqu’OpenGL 2 sera finalement disponible il se contentera principalement d’ajouter le support du GLSL à l’API, toutes les autres propositions de 3DLabs partiront donc aux oubliettes laissant OpenGL à la traîne face à l’API de Microsoft.
La nécessité d’un changement
Un autre épisode marquera l’impossibilité pour l’ARB de prendre des décisions rapides et efficaces : pendant longtemps OpenGL s’est reposé sur une technique appelé pbuffers pour effectuer le rendu dans une texture. Tous les programmeurs s’accordaient à dire que cette technique était très mal conçue, pénible à utiliser et peu performante. ATI va donc proposer une extension pour la remplacer : über-buffers. L’extension est très ambitieuse : outre le rendu dans une texture ATI souhaite permettre le rendu dans un tableau de sommets et autres fonctionnalités avancées de ce genre. Au final tout cela est peut être même trop ambitieux car l’extension prend trop de temps à être définie, les programmeurs s’impatientent et au final NVIDIA et 3DLabs font une proposition concurrente visant à permettre au moins le rendu dans une texture de façon efficace sans la généricité de l’extension ATI. Au final il aura fallut plusieurs années pour voir le résultat de tous ces efforts, une extension appelée framebuffer_object afin d’offrir enfin une fonctionnalité de base de DrectX 9 !
En 2005 OpenGL aura donc rattrapé l’API Microsoft de 2002. Tous les acteurs majeurs (ATI, NVIDIA, 3DLabs et les développeurs) s’accordent à dire que les choses ne peuvent plus continuer ainsi sous peine de quoi OpenGL disparaîtra petit à petit du fait de son obsolescence. C’est dans ce contexte agité qu’en 2006 l’ARB passe le relais à Khronos lui confiant ainsi l’évolution d’OpenGL. Dans le même temps ATI et NVIDIA jurent le cœur sur la main de laisser leurs querelles de côté et de collaborer efficacement dans le but de faire enfin passer OpenGL dans le 21ème siècle. Les développeurs sont enthousiastes, le groupe Khronos s’étant montré très efficace dans sa gestion d’OpenGL ES, l’API 3D destinées aux périphériques mobiles.
Très vite le groupe Khronos commence à communiquer sur l’avenir d’OpenGL. Là encore le plan repose sur une remise à plat de l’API en deux temps : la première révision, Long Peaks, devait proposer un niveau de fonctionnalités de type R300/NV30 (Shader Model 2) ainsi qu’un nouveau modèle de programmation plus flexible pour le programmeur et plus clair. Un peu à l’image d’OpenGL 2.0 Pure proposé par 3DLabs des années auparavant, le groupe Khronos envisage de se séparer d’un ensemble d’API jugées obsolètes, se focalisant sur un petit nombre de fonctions modernes, ce sous ensemble est baptisé OpenGL Lean & Mean. La deuxième grosse révision, baptisée Mount Evans, devait reprendre la nouvelle API en en corrigeant les défauts apparus entre temps avec le recul, et lui ajouter des fonctionnalités de type R600/G80 (Shader Model 4). Le planning prévisionnel était très serré, prévoyant notamment l’arrivée de Mount Evans moins de six mois après celle de Longs Peak, mais les membres de Khronos semblaient confiants.
Autre changement par rapport à l’ARB, Khronos a décidé de communiquer plus ouvertement. Une lettre d’information est désormais disponible sur le site d’OpenGL, commençant à éduquer les développeurs sur la nouvelle API et réclamant leurs impressions. Tout semblait se passer au mieux jusqu’à la fin de l’année 2007. Alors que la spécification définitive de Longs Peak était attendue pour septembre le groupe Khronos annonce qu’un certain nombre de problèmes ont entraîné un retard de la spécification sans plus de détail. Les efforts de communication initiés quelques mois plus tôt sont donc déjà oubliés et le groupe Khronos poursuit le reste de son travail dans un blackout complet : plus de lettre d’information ni même de nouvelle du tout concernant les progrès de la nouvelle API.
La révélation
On n’entendra plus parler d’OpenGL 3 jusqu’au mois d’Août 2008, au Siggraph. Mais alors que certains attendaient une bonne surprise, Khronos aura réservé une sérieuse désillusion aux fans d’OpenGL : non seulement l’API a près d’un an de retard mais en plus la plupart des nouveautés de Longs Peak ont été abandonnées ! Après le fiasco OpenGL 2.0 qui n’était qu’un OpenGL 1.6 rebaptisé, cet OpenGL 3.0 ressemble furieusement à une version 2.2. Cette mauvaise surprise couplée à l’absence de communication depuis plusieurs mois engendrera des réactions très agressives envers le groupe Khronos sur l’ensemble des forums. Devant l’ampleur des réactions Khronos a répondu sur le forum officiel d’OpenGL par l’intermédiaire de Barthold Lichtenbelt de chez NVIDIA. La réponse très détaillée a permis d’en savoir un peu plus sur ce qui c’était passé en coulisses. On apprend donc que certains points d’implémentation n’étaient pas réglés dans les temps et que parallèlement, beaucoup sentaient qu’il devenait urgent d’offrir à OpenGL un support pour les derniers GPU disponibles. Le plan a donc été modifié afin d’étendre OpenGL 2 à des fonctionnalités de type Direct3D 10.
Si l’argumentation se tient, ce que l’on peut reprocher à Khronos c’est qu’il aurait mieux valu désamorcer la crise immédiatement plutôt que de couper subitement toutes les communications avec l’extérieur. De plus la similitude avec ce qui s’est passé 6 ans plus tôt avec OpenGL 2.0 n’incite pas vraiment à l’optimisme pour la suite : après deux promesses de réécriture et deux échecs comment avoir confiance en l’évolution d’OpenGL ? Enfin un commentaire de John Carmack lors de la dernière QuakeCon n’a pas vraiment arrangé les choses. Interrogé sur l’état d’OpenGL 3 celui-ci ne s’est pas privé de donner une réponse un peu moins politiquement correcte que celle de M. Lichtenbelt.
Selon lui si OpenGL 3 n’est pas ce qu’il aurait du être c’est principalement la faute de certains développeurs de logiciels de CAO qui n’étaient pas vraiment favorables à Longs Peak. En effet ils avaient peur des problèmes de compatibilité avec leurs applications résultants de la disparition de certaines anciennes fonctions. Cette version des faits est d’ailleurs confirmée à demi-mot par M. Lichtenbelt : « Durant la phase de design de Longs Peak nous sommes entrés en désaccord sur les fonctionnalités à supprimer de l’API. (…) le désaccord est du aux besoins des différents marchés. (…) nous nous sommes aperçus que nous ne pouvions pas faire une API pour tout le monde ».
OpenGL 3 est donc au final une mise à jour incrémentale, l’API n’est pas modifiée, Khronos se contentant de marquer certaines fonctionnalités comme dépréciées et permettant de créer un contexte dans lequel l’utilisation de ces fonctionnalités provoquent des erreurs. C’est loin de ce qui était promis (les développeurs de drivers doivent toujours supporter l’ensemble des fonctionnalités) mais c’est un premier pas en avant en permettant aux développeurs de se préparer aux futures versions qui offriront peut être enfin un vrai mode Lean & Mean. OpenGL 3 introduit aussi la notion de profile, pour l’instant il n’existe qu’un seul profile mais à terme il est envisagé de créer un profile pour les jeux et un autre pour la CAO par exemple, chacun supportant un sous ensemble de fonctions différents.
A côté de ça les fonctionnalités supportées par OpenGL 3 sont à peu près les mêmes que celles offertes par Direct3D 10 si l’on omet les Geometry Shader et le Geometry Instancing qui n’ont été ajoutés à l’API que sous forme d’une extension. En revanche on trouve certaines fonctionnalités de Direct3D 10.1 comme les modes de blending indépendants pour les MRT.
Direct 3D 11
Avec Direct3D 10 Microsoft a entrepris la plus importante remise à plat de son API depuis sa création. Il faut dire que des années de compatibilité commençaient à handicaper fortement l’évolution de son API, l’objectif était donc de fournir une base saine pour les évolutions futures. Pourtant l’accueil réservé à cet API a été plutôt mitigé tant du côté des joueurs que des développeurs.
Microsoft est en grande partie responsable : en ayant largement vanté les mérites de son API plusieurs années avant qu’elle soit disponible il fallait forcément s’attendre à un retour de bâton lorsque les joueurs se sont rendus compte que dans l’état ça ne changeait pas grand-chose pour eux. Associé au fait que cette API était exclusive à Vista, il n’en fallait pas plus pour générer une animosité envers ce qui avait été présenté comme une petite révolution. Du côté des développeurs les choses étaient encore plus compliquées : en associant Direct3D 10 et Vista Microsoft limitait largement le parc de machines susceptibles de faire tourner un jeu utilisant l’API. De plus ,et ce n’est un secret pour personne, l’importance du PC en tant que plate-forme de jeux a diminué ces dernières années avec l’émergence des nouvelles consoles vers qui se sont réfugiés plusieurs développeurs, anciens grands noms de la scène PC. Qu’il s’agisse d’Id Software, Epic ou Lionhead tous désormais travaillent sur des projets multi-plateformes quand il ne s’agit pas d’exclusivités consoles ! Sachant que les deux consoles HD du marché sont équipées de GPU DirectX 9 il n’en fallait pas plus pour motiver les développeurs à rester fidèles à cette API.
Dans ce cas pourquoi vous parler de Direct3D 11 aujourd’hui ? Tout d’abord parce que Microsoft a enfin levé le voile sur son API et qu’il s’agit malgré tout d’un petit évènement permettant d’anticiper ce que nous réservera le hardware de l’an prochain. De plus il y a de fortes chances que Direct3D 11 soit au final une étape plus importante que la version 10 dans l’histoire de l’API. En effet alors que Direct3D 10 était une réécriture complète avec tous les risques que ça comporte, Microsoft bénéficie cette fois du recul nécessaire et peut ajuster les problèmes levées par la première nouvelle mouture de son API. Direct3D 11 est donc une grosse mise à jour, mais une mise à jour incrémentale : elle reprend largement tous les concepts introduits avec Direct3D 10, elle est compatible avec la version précédente et avec le hardware de la génération précédente. Enfin elle sera disponible sur Windows 7 mais également sur Vista. Microsoft corrige donc la plupart des gros problèmes de la version précédente, il se murmure donc parmi les développeurs que certains n’hésiteraient pas à se passer de Direct3D 10 et à passer directement à la version 11 pour leurs futurs jeux.
Ce raisonnement se tient pour plusieurs raisons : les jeux actuels prennent entre 2 et 4 ans à être développés, ainsi lorsqu’un jeu dont le développement débute aujourd’hui sortira, Direct3D 11 sera déjà largement implanté sur les PC vu qu’il équipera tous les PC équipés de Windows 7 mais qu’il sera aussi disponible à la grosse majorité équipés de Vista. De plus il semble très probable que, quelle que soit leur date de sortie, les futures consoles soient équipées de GPU compatibles Direct3D 11 (ou de quelque chose de proche tout comme le Xenos de la Xbox 360 est un sur ensemble de DirectX 9). Par conséquent viser ce niveau de fonctionnalités permettra aux développeurs de prendre en quelque sorte de l’avance sur la prochaine génération de consoles. Mais nous ne sommes pas ici pour faire une étude de marché, d’un point de vue technique quels sont les apports de cette nouvelle API ?
Rendu multithreadé
Rendu multithreadé ? Mais ça fait plusieurs années que nous sommes équipés de CPU multicores et les développeurs ont fini par s’adapter : multithreader leurs moteurs donc n’a rien de nouveau avec Direct3D 11, allez vous me dire. Pourtant cela vous surprendra peut être mais les moteurs actuels n’utilisent toujours qu’un seul thread pour effectuer le rendu. Les autres threads sont dédiés au son, à la décompression des ressources, à la physique etc… Mais le rendu est pourtant un gros consommateur de temps CPU donc pourquoi ne pas le threader lui aussi ? Il y a plusieurs raisons, certaines liés à la façon dont les GPU fonctionnent, d’autres à l’API 3D. Microsoft s’est donc attaché à résoudre ces dernières et à tenter de contourner les premières.
Tout d’abord threader le rendu semble séduisant au premier abord mais quand on y regarde de plus près on se rend compte qu’il n’y a qu’un seul GPU (et même lorsqu’il y en a plusieurs tout le principe du SLI ou du Crossfire est de donner l’illusion qu’il n’y a qu’un GPU virtuel) et par conséquent un seul buffer de commandes. Qui dit ressource unique partagée par plusieurs threads dit donc mutex afin d’empêcher plusieurs threads d’écrire des commandes simultanément, se marchant sur les pieds ! Tous les bénéfices d’utiliser plusieurs threads sont donc annulés par cette section critique qui serialise tout le code. Aucune API ne peut résoudre ce problème inhérent à la façon dont communiquent le CPU et le GPU, mais Microsoft a proposé une API pour essayer de le contourner. Direct3D 11 introduit ainsi des buffers de commandes annexes qui peuvent être sauvegardés pour être utilisés ensuite.
Chaque thread dispose donc d’un contexte différé, les commandes qui y sont écrites sont enregistrées dans une liste d’affichage qui peut ensuite être insérée dans le flux de commande principal. Evidemment il faut toujours s’assurer lorsqu’une liste d’affichage est appelée par le thread principal (le « Execute » du schéma ci-dessus) que son thread a terminé de la remplir. Il y a donc toujours une synchronisation mais ce modèle d’exécution permet au moins de paralléliser une partie du travail de rendu même si l’accélération ne peut pas être idéale.
Un autre problème des versions précédentes de Direct3D concernait la création des ressources comme par exemple les textures. Dans les versions actuelles de l’API (9 comme 10) la création des ressources devait se faire dans le thread de rendu. Les développeurs contournaient le problème en créant un thread qui lisait et décompressait la texture depuis le disque par exemple et remplissait la ressource (l’object direct3D) qui était lui créé sur le thread principal.
Mais comme on le voit une part importante du travail restait à la charge du thread principal déjà surchargé ce qui ne garantissait pas une bon équilibre et donc un bon temps d’exécution. Microsoft introduit donc une nouvelle interface avec Direct3D 11 : un programmeur peut créer un objet device par thread qui sera utilisé pour le chargement des ressources. La synchronisation au sein des fonctions d’un device est géré plus finement que dans Direct3D 10 et est beaucoup plus économe en temps CPU.
Tesselation
La grosse nouveauté de Direct3D 10 concernait l’apparition des Geometry Shader qui permettait enfin de créer ou de détruire des sommets sur le GPU, mais le rôle de cette unité a été quelque peu mal interprété. Loin d’être utile à une expansion massive de géométrie, son rôle est plus utile pour implémenter des Point Sprites plus flexibles, gérer du Fur Shading ou calculer la silhouette d’un objet pour l’algorithme des volumes d’ombre. Pour réaliser de la tesselation rien ne vaut une unité dédiée. Initialement prévue pour Direct3D 10 (ce qui explique sa présence dans les Radeon HD) il semble que Microsoft, ATI et NVIDIA n’ait pas pu se mettre d’accord à temps et elle a donc disparue des spécifications… pour revenir en force avec Direct3D 11 ! La tesselation est donc la grosse nouveauté de Direct3D 11, tout du moins la plus facile à vendre pour des non spécialistes.
Microsoft introduit donc trois nouveaux stages à son pipeline de rendu :
Contrairement aux autres étapes du pipeline ceux-ci ne fonctionnent pas avec des triangles comme primitives mais en utilisant des patchs. Le Hull shader prend donc en entrée les points de contrôle d’un patch, détermine certains paramètres du Tesselator qui est une unité fixe, comme par exemple le TessFactor qui indique la finesse de la tesselation. Le Tesselator est une unité fixe par conséquent le programmeur ne contrôle pas comment est opéré la tesselation, celui-ci renvoie les points générés au domain shader qui peut appliquer des opérations sur ces derniers. Un exemple devrait permettre d’éclaircir tout ça, prenons le cas qui ressort à chaque génération depuis la Parhelia du Displacement Mapping :
En entrée du vertex shader on trouve donc les points de contrôle du patch. Le programmeur peut les animer comme il le souhaite, ceux-ci sont peut nombreux : il s’agit pour simplifier d’une version très grossière du mesh final. Ces points transformés sont ensuite passés au Hull shader qui détermine combien de fois subdiviser chaque côté du patch (par exemple en fonction de la taille du patch en pixels à l’écran). Le Tesselator se charge de la tesselation à proprement parler c’est-à-dire de la création de la géométrie, celle-ci est passée au domain shader. Ce dernier transforme les points générés dans l’espace adéquat (les points sortant du Tesselator étant dans l’espace du patch) produisant ainsi des sommets classiques qu’il peut déplacer en fonction d’une texture pour obtenir du Displacement Mapping.
Les possibilités sont énormes, grâce à la tesselation il devient possible de se passer des normal map et d’implémenter un niveau de détail directement sur le GPU permettant d’utiliser des modèles très détaillés (plusieurs millions de polygones au lieu de la dizaine de milliers des jeux actuels). Tout du moins en théorie, en pratique la tesselation pose un certain nombre de problème qui ont jusqu’ici empêché l’essor de cette technique. Direct3D 11 et les cartes compatibles pourront-ils éviter ces écueils et proposer une version fonctionnelle ? Il est trop tôt pour le dire mais en tout cas tout le monde n’est pas convaincu et Id Software travaille à résoudre le même problème de la géométrie avec une approche complètement différente à base de raycasting de voxels.
Compute Shader & compression de textures
Compute Shader
Nous évoquions ce secret de polichinelle en conclusion de notre article sur CUDA : Microsoft n’allait pas laisser le marché du GPGPU lui échapper et propose donc son langage pour tirer parti de nos GPU pour autre chose que produire de belles images. Pas de surprise, le modèle choisit, tout comme OpenCL, semble assez proche de CUDA, confirmant la justesse des choix de NVIDIA. L’avantage par rapport à la solution de NVIDIA vient de la portabilité, un compute shader fonctionnant sur GPU NVIDIA comme ATI et sur le futur Larrabee, et d’une meilleure intégration avec Direct3D même si CUDA offre déjà un certain support à ce niveau. Nous ne nous attarderons pas plus sur le sujet qui est vaste comme en témoigne notre article sur CUDA et nous réserverons sans doute un article à OpenCL et au Compute Shader dans quelques mois afin d’étudier tout ceci plus en détail.
Une compression de texture améliorée
Apparue avec DirectX 6 il y a maintenant 10 ans la compression de texture DXTC s’est rapidement répandu dans les GPU et a été massivement utilisée par les développeurs depuis. Il faut dire que la technologie mise au point par S3 était efficace et en plus le coût hardware était déjà faible ce qui explique sans doute un tel succès. Mais de nos jours les besoins ont changé, le DXTC n’ayant pas été prévu pour compresser des images HDR ou des normal maps. L’objectif de Direct3D était donc double : permettre la compression d’images HDR et limiter l’aspect « blocky » des modes DXTC traditionnels. Pour cela Microsoft introduit deux nouveaux modes : BC6 pour les images HDR et BC7 visant à améliorer la qualité de la compression pour les images LDR.
Shader Model 5, divers
Avec le Shader Model 5 Microsoft apporte certains concepts de la programmation orientée objet à son langage de shaders : HLSL. Contrairement aux versions précédentes qui apportaient de nouvelles fonctionnalités (branchement dynamique, support des entiers…) l’objectif est cette fois de faciliter la tâche des programmeurs en résolvant un problème courant dans les moteurs de jeux actuels : l’explosion du nombre de shaders du à un nombre de permutations très important. Prenons un exemple concret, supposons qu’un moteur gère deux types de matériaux, plastic et metal et deux types de lumière : spot et omni. Un programmeur doit écrire 4 shaders pour gérer tous les cas :
{
…
// rendu plastique utilisant une lumière de type spot
…
}
renderPlasticOmni ()
{
…
// rendu plastique utilisant une lumière de type omni
…
}
renderMetalSpot()
{
…
//rendu métal utilisant une lumière de type spot
…
}
renderMetalOmni()
{
…
//rendu métal utilisant une lumière de type spot
…
}
Cet exemple est très simple vu qu’il n’y a que deux matériaux et deux types de lumière mais en pratique il peut y en avoir plusieurs dizaines. Evidemment, il est ingérable de travailler comme ceci, beaucoup de code serait dupliqué et à chaque correction de bug d’un côté il faudrait le corriger dans tous les autres shaders. Pour résoudre ce problème les programmeurs utilisent ce qu’on appelle communément un über –shader qui synthétise toutes les combinaisons :
{
#ifdef METAL
// code spécifique au matériau métal
#elif PLASTIC
// code spécifique au matériau plastique
#endif
#ifdef SPOT
// code spécifique à une lumière de type spot
#elif
OMNI
// code spécifique à une lumière de type omni
#endif
}
Cette solution résout le problème en générant les shaders à la volée à partir de fragments de code communs mais en contrepartie elle rend la lecture des shaders difficiles et demande des efforts supplémentaires pour être sûr que tous les fragments s’insèrent bien aux divers endroits. Avec Direct3D 11 il est maintenant possible de rendre tout cela plus lisible en utilisant une interface et des classes dérivées :
Material myMaterial ;
Render()
{
myMaterial.render () ;
myLight.shade () ;
}
Light et Material sont des interfaces, le code est contenu dans les classes dérivées OmniLight et SpotLight ainsi que PlasticMaterial et MetalMaterial. Le code est donc dans un seul endroit ce qui rend la correction de bug plus aisée et en même temps la lecture n’en souffre pas du fait de l’organisation du code qui rappelle les concepts de fonctions virtuelles des langages orientés objets. Cette fonctionnalité sera donc très appréciée des programmeurs mais n’aura aucun impact pratique sur les joueurs.
Divers
Vous vous en doutez, nous n’avons fait que survoler les nouvelles fonctionnalités de Direct3D 11 et Microsoft n’a pas encore dévoilé tous les détails. Parmi les sujets que nous n’avons pas abordés nous pouvons citer l’augmentation de la taille maximale des textures à 16K x 16k au lieu de 4K x 4K et la possibilité de limiter le nombre de mipmaps chargés en VRAM. Mentionnons aussi la possibilité de modifier la valeur de profondeur d’un pixel sans pour autant désactiver les fonctionnalités de type Early Z test, le support du type flottant double précision, les écritures mémoires aléatoires (scatter writes), etc.
Conclusion
Nous attendions beaucoup d’OpenGL 3 et comme vous avez pu le constater à la lecture de cet article nous avons été déçu, tant sur le fond (disparition de fonctionnalités annoncées) que sur la forme (retard d’un an et absence de communication claire de la part de Khronos). Avec cette version OpenGL raccroche tout juste au wagon de Direct3D 10, à l’heure même où Microsoft choisit de dévoiler les premiers détails de la version 11 de son API.
Pas de révolution chez Microsoft non plus, mais contrairement à OpenGL, Direct3D a déjà subi une large remise à plat de son architecture il y a deux ans. Celle-ci ne s’est pas passée sans encombre mais aujourd’hui Microsoft peut bénéficier des efforts fournis à l’époque pour faire évoluer son API sur des bases saines. Il est donc indéniable que la firme de Redmond se projette dans le futur alors que l’on a l’impression que Khronos se contente du support des GPU actuels. En espérant qu’ils nous fassent mentir en faisant évoluer rapidement OpenGL 3, qui reste la seule API disponible dans le cadre d’un développement multi-plateformes, mais à forces d’espoirs déçus on n’ose y croire.