Comparer le pipeline de nuanceur OpenGL ES 2.0 à Direct3D
API importantes
Conceptuellement, le pipeline de nuanceur Direct3D 11 est très similaire à celui d’OpenGL ES 2.0. Toutefois, en termes de conception d’API, les principaux composants de création et de gestion des phases de nuanceur font partie de deux interfaces principales, ID3D11Device1 et ID3D11DeviceContext1. Cette rubrique tente de mapper les modèles d’API de pipeline de nuanceur OpenGL ES 2.0 courants aux équivalents Direct3D 11 dans ces interfaces.
Examen du pipeline du nuanceur Direct3D 11
Les objets de nuanceur sont créés avec des méthodes sur l’interface ID3D11Device1, comme ID3D11Device1 ::CreateVertexShader et ID3D11Device1 ::CreatePixelShader.
Le pipeline graphique Direct3D 11 est géré par les instances de l’interface ID3D11DeviceContext1 et comporte les étapes suivantes :
- Étape d’assembleur d’entrée. L’étape d’assembleur d’entrée fournit des données (triangles, lignes et points) au pipeline. Les méthodes ID3D11DeviceContext1 qui prennent en charge cette phase sont précédées de « IA ».
- Étape de vertex-nuanceur : l’étape du nuanceur de vertex traite les sommets, en général en effectuant des opérations telles que les transformations, l’apparence et l’éclairage. Un nuanceur de vertex prend toujours un sommet d’entrée unique et produit un seul sommet de sortie. Les méthodes ID3D11DeviceContext1 qui prennent en charge cette étape sont précédées de « VS ».
- Étape de sortie de flux : l’étape de sortie de flux diffuse les données primitives du pipeline vers la mémoire sur son chemin vers le rastériseur. Les données peuvent être diffusées en continu et/ou passées dans le rastériseur. Les données diffusées en mémoire peuvent être recirculées dans le pipeline en tant que données d’entrée ou lecture à partir du processeur. Les méthodes ID3D11DeviceContext1 qui prennent en charge cette phase sont précédées de « SO ».
- Étape de rastériseur : le rastériseur extrait les primitives, prépare les primitives pour le nuanceur de pixels et détermine comment appeler des nuanceurs de pixels. Vous pouvez désactiver la rastérisation en indiquant au pipeline qu’il n’existe aucun nuanceur de pixels (définissez l’étape du nuanceur de pixels sur NULL avec ID3D11DeviceContext ::P SSetShader) et désactivez les tests de profondeur et de gabarit (définissez DepthEnable et StencilEnable sur FALSE dans D3D11_DEPTH_STENCIL_DESC). En cas de désactivation, les compteurs de pipeline liés à la rastérisation ne sont pas mis à jour.
- Étape du nuanceur de pixels : l’étape du nuanceur de pixels reçoit des données interpolées pour une primitive et génère des données par pixel, telles que la couleur. Les méthodes ID3D11DeviceContext1 qui prennent en charge cette phase sont précédées de « PS ».
- Étape de fusion de sortie : l’étape de fusion de sortie combine différents types de données de sortie (valeurs du nuanceur de pixels, informations de profondeur et de gabarit) avec le contenu des mémoires tampons de cible de rendu et de profondeur/gabarit pour générer le résultat final du pipeline. Les méthodes ID3D11DeviceContext1 qui prennent en charge cette étape sont précédées de « OM ».
(Il existe également des étapes pour les nuanceurs de géométrie, les nuanceurs de coque, les pavages et les nuanceurs de domaine, mais comme ils n’ont pas d’analogues dans OpenGL ES 2.0, nous ne les aborderons pas ici.) Pour obtenir la liste complète des méthodes de ces étapes, reportez-vous aux pages de référence ID3D11DeviceContext et ID3D11DeviceContext1. ID3D11DeviceContext1 étend ID3D11DeviceContext pour Direct3D 11.
Création d’un nuanceur
Dans Direct3D, les ressources de nuanceur ne sont pas créées avant de les compiler et de les charger ; au lieu de cela, la ressource est créée lorsque le HLSLis est chargé. Par conséquent, il n’existe aucune fonction directement analogue à glCreateShader, qui crée une ressource de nuanceur initialisée d’un type spécifique (par exemple, GL_VERTEX_SHADER ou GL_FRAGMENT_SHADER). Au lieu de cela, les nuanceurs sont créés après le chargement de HLSL avec des fonctions spécifiques telles que ID3D11Device1 ::CreateVertexShader et ID3D11Device1 ::CreatePixelShader, qui prennent le type et le HLSL compilé en tant que paramètres.
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glCreateShader | Appelez ID3D11Device1 ::CreateVertexShader et ID3D11Device1 ::CreatePixelShader après avoir chargé l’objet nuanceur compilé, en les transmettant en tant que mémoire tampon. |
Compilation d’un nuanceur
Les nuanceurs Direct3D doivent être précompilés en tant que fichiers objet de nuanceur compilé (.cso) dans les applications plateforme Windows universelle (UWP) et chargés à l’aide de l’une des API de fichier Windows Runtime. (Les applications de bureau peuvent compiler les nuanceurs à partir de fichiers texte ou de chaîne au moment de l’exécution.) Les fichiers CSO sont générés à partir de tous les fichiers .hlsl qui font partie de votre projet Microsoft Visual Studio et conservent les mêmes noms, uniquement avec une extension de fichier .cso. Assurez-vous qu’ils sont inclus dans votre colis lorsque vous envoyez !
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glCompileShader | N/A. Compilez les nuanceurs dans les fichiers .cso dans Visual Studio et incluez-les dans votre package. |
Utilisation de glGetShaderiv pour l’état de compilation | N/A. Consultez la sortie de compilation du compilateur FX (FXC) de Visual Studio en cas d’erreurs dans la compilation. Si la compilation réussit, un fichier CSO correspondant est créé. |
Chargement d’un nuanceur
Comme indiqué dans la section sur la création d’un nuanceur, Direct3D 11 crée le nuanceur lorsque le fichier CSO correspondant est chargé dans une mémoire tampon et passé à l’une des méthodes du tableau suivant.
OpenGL ES 2.0 | Direct3D 11 |
---|---|
ShaderSource | Appelez ID3D11Device1 ::CreateVertexShader et ID3D11Device1 ::CreatePixelShader après avoir correctement chargé l’objet nuanceur compilé. |
Configuration du pipeline
OpenGL ES 2.0 a l’objet « programme de nuanceur », qui contient plusieurs nuanceurs pour l’exécution. Les nuanceurs individuels sont attachés à l’objet de programme de nuanceur. Toutefois, dans Direct3D 11, vous travaillez directement avec le contexte de rendu (ID3D11DeviceContext1) et créez des nuanceurs sur celui-ci.
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glCreateProgram | N/A. Direct3D 11 n’utilise pas l’abstraction d’objet du programme de nuanceur. |
glLinkProgram | N/A. Direct3D 11 n’utilise pas l’abstraction d’objet du programme de nuanceur. |
glUseProgram | N/A. Direct3D 11 n’utilise pas l’abstraction d’objet du programme de nuanceur. |
glGetProgramiv | Utilisez la référence que vous avez créée pour ID3D11DeviceContext1. |
Créez une instance d’ID3D11DeviceContext1 et ID3D11Device1 avec la méthode D3D11CreateDevice statique.
Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
// ...
D3D11CreateDevice(
nullptr, // Specify nullptr to use the default adapter.
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
creationFlags, // Set set debug and Direct2D compatibility flags.
featureLevels, // List of feature levels this app can support.
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for UWP apps.
&device, // Returns the Direct3D device created.
&m_featureLevel, // Returns feature level of device created.
&m_d3dContext // Returns the device's immediate context.
);
Définition de la ou des fenêtres d’affichage
La définition d’une fenêtre d’affichage dans Direct3D 11 est très similaire à la façon dont vous définissez une fenêtre d’affichage dans OpenGL ES 2.0. Dans Direct3D 11, appelez ID3D11DeviceContext ::RSSetViewports avec un CD3D11_VIEWPORT configuré.
Direct3D 11 : Définition d’une fenêtre d’affichage.
CD3D11_VIEWPORT viewport(
0.0f,
0.0f,
m_d3dRenderTargetSize.Width,
m_d3dRenderTargetSize.Height
);
m_d3dContext->RSSetViewports(1, &viewport);
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glViewport | CD3D11_VIEWPORT, ID3D11DeviceContext ::RSSetViewports |
Configuration des nuanceurs de vertex
La configuration d’un nuanceur de vertex dans Direct3D 11 est effectuée lorsque le nuanceur est chargé. Les uniformes sont passés sous forme de mémoires tampons constantes à l’aide de l’ID3D11DeviceContext1 ::VSSetConstantBuffers1.
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glAttachShader | ID3D11Device1 ::CreateVertexShader |
glGetShaderiv, glGetShaderSource | ID3D11DeviceContext1 ::VSGetShader |
glGetUniformfv, glGetUniformiv | ID3D11DeviceContext1 ::VSGetConstantBuffers1. |
Configuration des nuanceurs de pixels
La configuration d’un nuanceur de pixels dans Direct3D 11 est effectuée lorsque le nuanceur est chargé. Les uniformes sont passés sous forme de mémoires tampons constantes à l’aide de l’ID3D11DeviceContext1 ::P SSetConstantBuffers1.
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glAttachShader | ID3D11Device1 ::CreatePixelShader |
glGetShaderiv, glGetShaderSource | ID3D11DeviceContext1 ::P SGetShader |
glGetUniformfv, glGetUniformiv | ID3D11DeviceContext1 ::P SGetConstantBuffers1. |
Génération des résultats finaux
Une fois le pipeline terminé, vous dessinez les résultats des étapes du nuanceur dans la mémoire tampon arrière. Dans Direct3D 11, tout comme avec Open GL ES 2.0, cela implique d’appeler une commande de dessin pour générer les résultats sous forme de mappage de couleurs dans la mémoire tampon arrière, puis de renvoyer cette mémoire tampon à l’affichage.
OpenGL ES 2.0 | Direct3D 11 |
---|---|
glDrawElements | ID3D11DeviceContext1 ::D raw, ID3D11DeviceContext1 ::D rawIndexed (ou d’autres méthodes Draw* sur ID3D11DeviceContext1). |
eglSwapBuffers | IDXGISwapChain1 ::P resent1 |
Portage de GLSL vers HLSL
GLSL et HLSL ne sont pas très différents au-delà de la prise en charge de type complexe et de la syntaxe d’une syntaxe globale. De nombreux développeurs trouvent qu’il est plus simple de porter entre les deux en alias les instructions et définitions d’OpenGL ES 2.0 courantes vers leur équivalent HLSL. Notez que Direct3D utilise la version du modèle nuanceur pour exprimer l’ensemble de fonctionnalités du HLSL pris en charge par une interface graphique ; OpenGL a une spécification de version différente pour HLSL. Le tableau suivant tente de vous donner une idée approximative des ensembles de fonctionnalités de langage de nuanceur définis pour Direct3D 11 et OpenGL ES 2.0 en termes de version de l’autre.
Langue du nuanceur | Version de fonctionnalité GLSL | Modèle nuanceur Direct3D |
---|---|---|
Direct3D 11 HLSL | ~4.30. | SM 5.0 |
GLSL ES pour OpenGL ES 2.0 | 1.40. Les anciennes implémentations de GLSL ES pour OpenGL ES 2.0 peuvent utiliser 1.10 à 1.30. Vérifiez votre code d’origine avec glGetString(GL_SHADING_LANGUAGE_VERSION) ou glGetString(SHADING_LANGUAGE_VERSION) pour le déterminer. | ~SM 2.0 |
Pour plus d’informations sur les différences entre les deux langages de nuanceur, ainsi que les mappages de syntaxe courants, lisez la référence GLSL-to-HLSL.
Portage des intrinsèques OpenGL vers la sémantique HLSL
La sémantique HLSL Direct3D 11 est des chaînes qui, comme un nom uniforme ou d’attribut, sont utilisées pour identifier une valeur passée entre l’application et un programme de nuanceur. Bien qu’il s’agit d’une variété de chaînes possibles, la meilleure pratique consiste à utiliser une chaîne telle que POSITION ou COLOR qui indique l’utilisation. Vous attribuez ces sémantiques lorsque vous construisez une mise en mémoire tampon constante ou une disposition d’entrée de mémoire tampon. Vous pouvez également ajouter un nombre compris entre 0 et 7 à la sémantique afin d’utiliser des registres distincts pour des valeurs similaires. Par exemple : COLOR0, COLOR1, COLOR2...
La sémantique qui est précédée de « SV_ » est une sémantique de valeur système écrite par votre programme de nuanceur ; votre application elle-même (en cours d’exécution sur l’UC) ne peut pas les modifier. En règle générale, ces valeurs contiennent des entrées ou des sorties d’une autre phase de nuanceur dans le pipeline graphique, ou sont générées entièrement par le GPU.
En outre, SV_ sémantiques ont des comportements différents lorsqu’ils sont utilisés pour spécifier l’entrée ou la sortie d’une étape de nuanceur. Par exemple, SV_POSITION (sortie) contient les données de vertex transformées pendant l’étape du nuanceur de vertex, et SV_POSITION (entrée) contient les valeurs de position de pixel interpolées pendant la rastérisation.
Voici quelques mappages pour les intrinsèques du nuanceur OpenGL ES 2.0 courants :
Valeur système OpenGL | Utiliser cette sémantique HLSL |
---|---|
gl_Position | POSITION(n) pour les données de mémoire tampon de vertex. SV_POSITION fournit une position de pixel au nuanceur de pixels et ne peut pas être écrit par votre application. |
gl_Normal | NORMAL(n) pour les données normales fournies par la mémoire tampon de vertex. |
gl_TexCoord[n] | TEXCOORD(n) pour les données de coordonnées UV de texture (ST dans une documentation OpenGL) fournies à un nuanceur. |
gl_FragColor | COLOR(n) pour les données de couleur RVBA fournies à un nuanceur. Notez qu’il est traité de façon identique pour coordonner les données ; la sémantique vous aide simplement à identifier qu’il s’agit de données de couleur. |
gl_FragData[n] | SV_Target[n] pour écrire à partir d’un nuanceur de pixels dans une texture cible ou une autre mémoire tampon de pixels. |
La méthode par laquelle vous codez la sémantique n’est pas la même que l’utilisation d’intrinsèques dans OpenGL ES 2.0. Dans OpenGL, vous pouvez accéder directement à la plupart des intrinsèques sans aucune configuration ni déclaration ; Dans Direct3D, vous devez déclarer un champ dans une mémoire tampon constante spécifique pour utiliser une sémantique particulière ou la déclarer comme valeur de retour pour la méthode main() d’un nuanceur.
Voici un exemple de sémantique utilisée dans une définition de mémoire tampon constante :
struct VertexShaderInput
{
float3 pos : POSITION;
float3 color : COLOR0;
};
// The position is interpolated to the pixel value by the system. The per-vertex color data is also interpolated and passed through the pixel shader.
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 color : COLOR0;
};
Ce code définit une paire de mémoires tampons constantes simples
Voici un exemple de sémantique utilisée pour définir la valeur retournée par un nuanceur de fragments :
// A pass-through for the (interpolated) color data.
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color,1.0f);
}
Dans ce cas, SV_TARGET est l’emplacement de la cible de rendu dans laquelle la couleur de pixel (définie en tant que vecteur avec quatre valeurs flottantes) est écrite lorsque le nuanceur termine l’exécution.
Pour plus d’informations sur l’utilisation de la sémantique avec Direct3D, lisez la sémantique HLSL.