Présentation des différents HLSL
Etudions maintenant les différents HLSL concurrents et honneur au précurseur oblige nous allons commencer par nous intéresser au HLSL de nVidia qui fut le premier à être disponible : le Cg. Le développement du Cg a commencé au début de l’année 2001, avec plusieurs objectifs en tête.
Le premier était la simplicité : nVidia s’est rapidement rendu compte que dans le domaine de la programmation des shaders les programmeurs marchaient par tâtonnements essayant diverses expérimentations avant de trouver la bonne. Et pour ça l’assembleur était clairement un obstacle, permettre de tester rapidement de nouvelles idées étaient donc une priorité pour le HLSL. Un deuxième point à avoir bénéficié de l’attention de nVidia était la portabilité : le langage devrait supporter différentes classes de GPU, d’API ou d’OS. Parmi les autres objectifs de nVidia on trouve évidemment la performance, et l’extensibilité.
Une fois ces objectifs posés il a fallut définir le langage, et là les premiers problèmes se sont posés : langage dédié ou générique ? A base de programme unique ou de multi programmes ? Dans un souci d’offrir un langage certes de haut niveau, mais restant tout de même suffisamment proche du hardware (impératif dicté par l’objectif de performance) nVidia a tranché pour un langage générique et multi programmes : un pour le processeur de sommet et l’autre pour le processeur de fragment.
Mais ceci n’était rien en comparaison du principal obstacle qui attendait nVidia : comment supporter une gamme étendue de GPU aux fonctionnalités très diverses le tout sous différentes API via un seul langage ? Une forme d’émulation ? Impossible les performances auraient été désastreuses. Définir un ensemble de fonctionnalités minimum et imposer que toute implémentation du langage les supporte toutes ? Cette approche ne résoud pas le problème : en fixant un sous ensemble trop bas on bride les nouveaux GPU, et en le fixant trop haut on se prive d’une base installée conséquente.
La solution trouvée par nVidia tiens en un mot : profil ! Chaque profil définit quel sous-ensemble de fonctionnalités du Cg est supporté par le GPU. Ainsi nVidia a trouvé une parade élégante permettant de combiner ses objectifs à savoir un support de toute sa gamme de GPU sans brider l’évolutivité de son langage. On trouve donc des profils pour DirectX8, DirectX9, ARB_fragment_program et ARB_vertex_program, NV_fragment_program, NV_vertex_program… Cette solution présente toutefois l’inconvénient qu’un programme correct syntaxiquement et sémantiquement peut ne pas compiler tout simplement à cause de restrictions du profil auquel il est destiné.
Inutile de s’étendre sur DirectX HLSL le langage de shading de haut niveau de Microsoft car il est quasiment identique au Cg. La raison est simple nVidia et Microsoft ont collaboré sur ce projet il en résulte que Cg et DirectX HLSL sont deux implémentations d’un même langage. La seule différence concerne les compilateurs et bien évidemment le fait que DirectX HLSL n’est pas indépendant de l’API. Ah non une autre petite différence, contrairement au Cg DirectX HLSL ne supporte pas le type fixed cher à nVidia…
DirectX HLSL est exclusivement lié à l’API de Microsoft, en lieu et place des profils on trouve des compile targets dans la terminologie DirectX. Il existe des compile targets pour les vs1.1, vs2 et vs3 et pour les ps1.1, ps1.2, ps1.3, ps1.4, ps2 et ps3. Comme pour les profils du Cg si le programme excède les capacités de la cible le programme ne compilera pas.
C’est en 2001 que 3DLabs a proposé un ensemble de nouvelles fonctionnalités à ajouter à OpenGL, étant donné leur caractère résolument novateur la version d’OpenGL regroupant toutes ces nouveautés fut surnommée officieusement OpenGL 2.0 afin de bien marquer l’évolution. Mais jusqu’ici rien n’était officiel car seul l’ARB est habilité à définir les nouvelles versions d’OpenGL. Il faut donc bien comprendre que contrairement à ce que beaucoup pensaient OpenGL 2.0 est plus une « vision » qu’un véritable produit.
Au centre de cette proposition se trouvait un langage de shading de haut niveau, inspiré directement du Stanford Shading Language, qui sera finalement baptisé GLSLANG. Ayant reçu le support de l’ARB pour pousser plus en avant dans cette voie, 3DLabs a donc défini une première version des spécifications du nouveau langage, et a développé un compilateur disponible en licence open source. Finalement après un gros effort de la part de tous les membres de l’ARB le langage est finalement disponible sous forme d’extension dans la dernière version d’OpenGL : OpenGL 1.5.
Les objectifs de ce langage étaient multiples. Tout d’abord définir un langage spécifique à OpenGL permettant de remplacer toutes les fonctionnalités du pipeline fixe. Un tel choix permet de se référer à des états OpenGL directement depuis un shader, le langage de shading et l’API étant intimement liés les interactions entre les deux sont donc plus intuitives. Tout comme pour nVidia un autre facteur primordial dans la définition du langage était sa simplicité d’utilisation. Le langage devait donc être le même que ce soit lors du traitement des sommets ou lors du traitement des fragments. L’écriture des shaders devait être simplifiée à son maximum, les tâches ingrates étant à la charge du compilateur.
Un des points les plus délicats pour 3DLabs était d’offrir un langage exploitable aujourd’hui sans pour autant sombrer rapidement dans l’obsolescence. Pour cela 3DLabs a opté pour une approche différente de ses concurrents. Au lieu de définir des sous ensembles du langage supportés par les diverses gammes de chips graphiques, il n’existe qu’une définition de GLSLANG et actuellement aucun chip graphique ne la supporte dans son intégralité (GLSLANG autorise par exemple l’échantillonnage de texture dans un vertex program ce qu’aucun chip actuel ne permet) ! GLSLANG a clairement été conçu pour limiter au maximum les extensions du langage, et ça se ressent : la plupart des limites que l’on retrouve dans ce genre de langage (nombre d’instructions, nombre de registres temporaires…) sont soit placées très haut, soit carrément non fixées !