
En infographie , un shader est une opération programmable appliquée aux données lors de leur passage dans le pipeline de rendu . Les shaders agissent sur des données telles que les sommets et les primitives, génèrent ou transforment des géométries et des fragments , et calculent les couleurs d'une image rendue.
Les shaders peuvent exécuter une grande variété d'opérations. En infographie temps réel moderne , ils sont exécutés sur des unités de traitement graphique (GPU), des matériels dédiés permettant l'exécution parallèle des programmes. Le rendu d'images étant un problème parallélisable de manière optimale (son indice d'Amdahl est de un), les shaders tirent un grand profit du calcul parallèle , notamment grâce au matériel SIMD . La recherche d'un rendu plus rapide a conduit au développement de processeurs hautement parallèles, tels que les GPU, désormais utilisés pour le calcul à usage général . Les shaders utilisés à des fins générales sont communément appelés shaders de calcul .
Histoire
Le terme « shader » a été introduit pour la première fois dans le public par Pixar avec la version 3.0 de leur spécification d'interface RenderMan , initialement publiée en mai 1988.
Avec l'évolution des processeurs graphiques , les principales bibliothèques logicielles graphiques telles qu'OpenGL et Direct3D ont commencé à prendre en charge les shaders. Les premiers GPU compatibles avec les shaders ne prenaient en charge que le pixel shading , mais les vertex shaders ont rapidement été introduits une fois que les développeurs ont pris conscience de leur potentiel. La première carte graphique dotée d'un pixel shader programmable fut la Nvidia GeForce 3 (NV20), sortie en 2001. Les geometry shaders ont été introduits avec Direct3D 10 et OpenGL 3.2. Le matériel graphique a évolué vers un modèle de shader unifié , uniformisant ainsi tous les shaders.
shaders graphiques
L'utilisation traditionnelle des shaders consiste à manipuler les données du pipeline graphique pour contrôler le rendu d'une image. Les shaders graphiques sont classés selon leur position dans le pipeline, les données manipulées et l'API graphique utilisée.
shaders de vertex
Les shaders de vertex sont exécutés une fois pour chaque sommet 3D transmis au processeur graphique. Leur but est de transformer la position 3D de chaque sommet dans l'espace virtuel en ses coordonnées 2D à l'écran (ainsi qu'en une valeur de profondeur pour le tampon Z). Les shaders de vertex peuvent manipuler des propriétés telles que la position, la couleur et les coordonnées de texture, mais ne peuvent pas créer de nouveaux sommets. Le résultat du shader de vertex est transmis à l'étape suivante du pipeline : soit un shader de géométrie (s'il est présent), soit le rasteriseur . Les shaders de vertex permettent un contrôle précis de la position, du mouvement, de l'éclairage et de la couleur dans toute scène contenant des modèles 3D .
shaders géométriques
Les shaders géométriques ont été introduits dans Direct3D 10 et OpenGL 3.2 ; ils étaient auparavant disponibles dans OpenGL 2.0+ grâce à des extensions. Ce type de shader peut générer de nouvelles primitives graphiques , telles que des points, des lignes et des triangles, à partir des primitives transmises au début du pipeline graphique.
Les programmes de shaders de géométrie sont exécutés après les shaders de vertex. Ils prennent en entrée une primitive complète, éventuellement accompagnée d'informations d'adjacence. Par exemple, lors du traitement de triangles, les trois sommets constituent l'entrée du shader de géométrie. Ce dernier peut alors générer zéro ou plusieurs primitives, qui sont rasterisées et leurs fragments finalement transmis à un shader de pixels .
Les shaders de géométrie sont généralement utilisés pour générer des sprites de points, tesseller la géométrie , extruder des volumes d'ombre et effectuer un rendu en une seule passe sur une cube map . Un exemple concret de l'intérêt des shaders de géométrie est la modification automatique de la complexité d'un maillage. Une série de segments de ligne représentant les points de contrôle d'une courbe est transmise au shader de géométrie ; selon la complexité requise, celui-ci peut générer automatiquement des segments supplémentaires, chacun offrant une meilleure approximation de la courbe.
shaders de fragments
Les shaders de fragments, également appelés shaders de pixels , calculent la couleur et d'autres attributs de chaque « fragment » : une unité de rendu affectant au maximum un seul pixel de sortie . Les shaders de pixels les plus simples produisent une valeur de couleur pour un pixel de l'écran ; des shaders plus complexes avec plusieurs entrées/sorties sont également possibles. Les shaders de pixels peuvent se contenter de produire toujours la même couleur, appliquer une valeur d'éclairage , gérer le bump mapping , les ombres , les reflets spéculaires , la translucidité et d'autres effets. Ils peuvent modifier la profondeur du fragment (pour le Z-buffering ) ou produire plusieurs couleurs si plusieurs cibles de rendu sont actives. En infographie 3D, un shader de pixels seul ne peut pas produire certains effets complexes car il opère uniquement sur un fragment, sans connaître la géométrie de la scène (c'est-à-dire les données de vertex). Cependant, les shaders de pixels connaissent les coordonnées de l'écran affichées et peuvent échantillonner l'écran et les pixels voisins si le contenu de l'écran entier est fourni comme texture au shader. Cette technique permet d'appliquer une grande variété d'effets de post-traitement bidimensionnels, tels que le flou ou la détection /amélioration des contours pour les shaders de type cartoon/cel . Les shaders de pixels peuvent également être utilisés en étapes intermédiaires sur n'importe quelle image bidimensionnelle ( sprites ou textures) du pipeline , tandis que les shaders de vertex nécessitent toujours une scène 3D. Par exemple, seul un shader de pixels peut servir de post-processeur ou de filtre pour un flux vidéo après sa rastérisation .
shaders de tessellation
OpenGL 4.0 et Direct3D 11 ont introduit une nouvelle classe de shaders appelée shader de tessellation. Celle-ci a ajouté deux nouvelles étapes de shader au modèle traditionnel : les shaders de contrôle de tessellation (également appelés shaders d'enveloppe) et les shaders d'évaluation de tessellation (également appelés shaders de domaine ). Ensemble, ils permettent de subdiviser des maillages simples en maillages plus fins à l'exécution, selon une fonction mathématique. Cette fonction peut être liée à diverses variables, notamment la distance par rapport à la caméra, afin de permettre une mise à l'échelle active du niveau de détail . Ainsi, les objets proches de la caméra peuvent présenter des détails fins, tandis que les objets plus éloignés peuvent avoir des maillages plus grossiers, tout en conservant une qualité visuelle comparable. Cela permet également de réduire considérablement la bande passante requise pour le maillage, car les maillages sont affinés directement dans les unités de shader, au lieu d'être sous-échantillonnés en mémoire pour les maillages très complexes. Certains algorithmes peuvent suréchantillonner n'importe quel maillage, tandis que d'autres permettent d'« indiquer » les sommets et arêtes les plus caractéristiques des maillages.
shaders primitifs et de maillage
Aux alentours de 2017, la microarchitecture AMD Vega a ajouté la prise en charge d'une nouvelle étape de traitement des shaders — les shaders primitifs — qui s'apparentent aux shaders de calcul et ont accès aux données nécessaires au traitement de la géométrie.
Nvidia a introduit les shaders de maillage et de tâches avec sa microarchitecture Turing en 2018, qui sont également inspirés des shaders de calcul. Nvidia Turing est la première microarchitecture GPU au monde à prendre en charge le mesh shading via l'API DirectX 12 Ultimate, plusieurs mois avant la sortie de la série Ampere RTX 30.
En 2020, AMD et Nvidia ont lancé les microarchitectures RDNA 2 et Ampere , qui prennent toutes deux en charge le mesh shading via DirectX 12 Ultimate . Ces shaders de mesh permettent au GPU de gérer des algorithmes plus complexes, déchargeant ainsi une plus grande partie du travail du CPU vers le GPU et, lors du rendu intensif en algorithmes, augmentant la fréquence d'images ou le nombre de triangles dans une scène d'un ordre de grandeur. Intel a annoncé que les GPU Intel Arc Alchemist, commercialisés au premier trimestre 2022, prendront en charge les shaders de mesh.
shaders de lancer de rayons
Les shaders de ray tracing sont pris en charge par Microsoft via DirectX Raytracing , par Khronos Group via Vulkan , GLSL et SPIR-V , par Apple via Metal . Nvidia et AMD ont appelé « cœurs de ray tracing » les parties du matériel responsables de l’exécution de ces shaders.
Noyaux de calcul
Les noyaux de calcul sont des routines compilées pour les accélérateurs à haut débit (tels que les unités de traitement graphique (GPU), les processeurs de signaux numériques (DSP) ou les réseaux de portes programmables (FPGA)), distinctes du programme principal mais utilisées par celui-ci (généralement exécuté sur une unité centrale de traitement ). Ils peuvent être spécifiés par un langage de programmation distinct tel qu'OpenCL C , sous forme de « shaders de calcul » écrits dans un langage de shaders , ou intégrés directement dans le code de l'application écrit dans un langage de haut niveau . Les noyaux de calcul correspondent approximativement aux boucles internes lors de l'implémentation d'algorithmes dans les langages traditionnels (à l'exception de l'absence d'opération séquentielle implicite), ou au code passé aux itérateurs internes . Microsoft prend en charge cette fonctionnalité sous le nom de DirectCompute .
Ce paradigme de programmation « un programme, plusieurs données » s'adapte parfaitement aux processeurs vectoriels : il repose sur l'hypothèse que chaque invocation d'un noyau au sein d'un lot est indépendante, permettant ainsi une exécution parallèle des données . Toutefois, des opérations atomiques peuvent parfois être utilisées pour la synchronisation entre les éléments (pour les travaux interdépendants), dans certains cas. Chaque invocation se voit attribuer des indices (dans une ou plusieurs dimensions) à partir desquels un adressage arbitraire des données du tampon peut être effectué (y compris des opérations de dispersion et de regroupement ), à condition que l'hypothèse de non-chevauchement soit respectée.
L' API Vulkan fournit la représentation intermédiaire SPIR-V pour décrire les shaders graphiques et les noyaux de calcul de manière indépendante du langage et de la machine . L'objectif est de faciliter l'évolution des langages et d'offrir une capacité plus naturelle à exploiter les capacités de calcul du GPU, en phase avec les développements matériels tels que l' architecture UMA (Unified Memory Architecture) et l'architecture HSA (Heterogeneous System Architecture) . Ceci permet une coopération plus étroite entre le CPU et le GPU.
De nombreux travaux ont été menés sur la génération de noyaux par le biais de modèles linéaires à grande échelle (LLM) comme moyen d'optimisation du code. KernelBench [23], créé par le Scaling Intelligence Lab de Stanford, fournit un cadre d'évaluation de la capacité des LLM à générer des noyaux GPU efficaces. Kevin 32 - B pour générer des noyaux CUDA efficaces ; il s'agit actuellement du modèle le plus performant sur KernelBench.
shaders de calcul
Les shaders de calcul désignent des noyaux de calcul écrits dans un langage de shaders . Ces shaders partagent des unités d'exécution avec les shaders de vertex et de pixels sur les GPU, illustrant ainsi le fonctionnement du GPGPU . Ils peuvent être utilisés dans les pipelines graphiques pour des tâches telles que des étapes supplémentaires dans les algorithmes d'animation ou d'éclairage (par exemple, le rendu direct par tuiles ), ou à des fins non graphiques. Certaines API de rendu permettent aux shaders de calcul de partager facilement des ressources de données avec le pipeline graphique, ce qui simplifie l'intégration du rendu et du calcul.
shaders tenseurs
Les shaders tenseurs sont des programmes d'accélération qui effectuent des opérations matricielles sur de grands tableaux , un type d'opération couramment utilisé dans l'IA basée sur les réseaux de neurones . Ils peuvent être exécutés sur des NPU ou des GPU . Les shaders tenseurs sont pris en charge par Microsoft via DirectML , par Khronos Group via OpenVX , par Apple via Core ML , par Google via TensorFlow et par la Linux Foundation via ONNX . Nvidia et AMD appellent « cœurs tenseurs » les composants matériels responsables de l'exécution de ces shaders.
Programmation
Il existe plusieurs langages de programmation dédiés à l'écriture de shaders, et le choix du langage dépend de l'environnement cible. OpenGL utilise GLSL , tandis que Direct3D utilise HLSL . Le framework Metal , utilisé par les appareils Apple, possède son propre langage de shaders appelé Metal Shading Language (MSL) .
Dans les API graphiques modernes, les shaders sont de plus en plus souvent compilés en SPIR-V , un langage intermédiaire , avant d'être distribués à l'utilisateur final. Cette norme offre une plus grande flexibilité dans le choix du langage de shaders, quelle que soit la plateforme cible. Initialement pris en charge par Vulkan et OpenGL, SPIR-V est également adopté par Direct3D.
Éditeurs de shaders d'interface graphique
Les plateformes modernes de développement de jeux vidéo telles que Unity , Unreal Engine et Godot intègrent de plus en plus d'éditeurs nodaux permettant de créer des shaders sans écrire de code. L'utilisateur dispose d'un graphe orienté de nœuds connectés, lui permettant d'appliquer diverses textures, maps et fonctions mathématiques pour obtenir des valeurs de sortie comme la couleur diffuse, la couleur et l'intensité spéculaires, la rugosité/métallicité, la hauteur, la normale, etc. Ce graphe est ensuite compilé en un shader.
Dans le domaine du développement web, des outils de shaders visuels et basés sur des composants ont également vu le jour. Des plateformes comme shaders.com proposent une composition de shaders pilotée par composants pour leur intégration dans des frameworks frontend tels que Vue , React et Svelte , tandis que des outils comme Shadertoy et FragCoord.xyz se concentrent sur la création et le débogage de shaders de bas niveau.