Pipeline de rendu | WebGPU | Vidéo

Nous examinerons en détail comment définir notre pipeline de rendu dans notre projet Fun Triangle.

Keywords: WebGPU, infographie, le pipeline de rendu, le rendu en temps réel, tutoriel

By Carmen Cincotti  

Vidéo

Nous continuons cette série en examinant comment configurer le pipeline de rendu de WebGPU pour rendre notre triangle de WebGPU :

WebGPU Triangle

Ne pouvez-vous pas attendre la fin de la série ?

Si vous souhaitez aller de l’avant sans attendre la prochaine vidéo de la série, je vous recommande de faire défiler jusqu’au code ci-dessous ou de consulter mon article : dessinons un triangle avec WebGPU.

Le code de la série vidéo

Au cours de cette série, nous étudierons ce code que vous pouvez retrouver dans cet article où on commence la série.

Avant de pouvoir rendre ce code, vous devez télécharger un navigateur capable d’exécuter du code WebGPU.

Le pipeline de rendu de WebGPU

Un pipeline de rendu est représenté comme une fonction complète exécutée par une combinaison du hardware GPU, des driveurs sous-jacents et de l’agent utilisateur.

Le but d’un pipeline de rendu est de traiter les données d’entrée, telles que les sommets, et de produire une sortie telle que les couleurs sur notre écran.

Le pipeline de rendu

Les docs de WebGPU nous indiquent qu’un pipeline de rendu de WebGPU se compose avec les étapes suivantes dans cet ordre particulier :

  1. Stockage des sommets, contrôlé par GPUVertexState.buffers
  2. Shader de vertex, contrôlé par GPUVertexState
  3. Assemblage primitif, contrôlé par GPUPrimitiveState
  4. Rastérisation, contrôlé par GPUPrimitiveState, GPUDepthStencilState, et GPUMultisampleState
  5. Shader de fragment, contrôlé par GPUFragmentState
  6. Test et opération Stencil, contrôlé par GPUDepthStencilState
  7. Test de profondeur et écriture, contrôlé par GPUDepthStencilState
  8. Fusion des sorties, contrôlé par GPUFragmentState.targets.

Nous avons déjà rencontré certaines de ces étapes au cours des deux derniers articles !

Par exemple, nous avons déjà défini et stocké nos sommets.

Nous avons également déjà défini nos shaders de vertex et de fragment.

La prochaine étape consistera à rassembler tous ces différents bits dans une configuration de pipeline de rendu cohérent de type GPURenderPipeline. Faisons-le maintenant !

Configuration du pipeline de rendu WebGPU

Avant de passer au code, il y a encore un point important que je veux mentionner…

Notez que toutes les parties du pipeline de rendu ne sont pas configurables.

Étapes programmables

Les étapes du pipeline que nous pouvons configurer sont considérées comme programmables.

Quelques exemples d’étapes programmables seraient le contenu du shader de vertex et de fragment, car nous sommes responsables de l’écriture du code pour chacun de ces types de shader.

Étapes fixes

Les étapes du pipeline qui ne sont pas configurables sont considérées comme fixes.

Un exemple d’étapes fixes serait le traitement qu’un sommet subit avant la rastérisation.

Vous pouvez visiter ce lien pour en savoir plus sur les différentes étapes du pipeline.

Le code

Comme prévu, nous devons utiliser le GPUDevice, device, afin de communiquer avec notre GPU.

Afin de configurer notre pipeline de rendu, la méthode que nous devons appeler sur notre device est createRenderPipeline().

const pipeline = device.createRenderPipeline({ layout: "auto", vertex: { module: shaderModule, entryPoint: "vertex_main", buffers: vertexBuffersDescriptors, }, fragment: { module: shaderModule, entryPoint: "fragment_main", targets: [ { format: presentationFormat, }, ], }, primitive: { topology: "triangle-list", }, });

Nous regarderons ensemble comment configurer notre pipeline dans les parties suivantes !

layout

Le champ layout signifie le ‘layout’, ou configuration, de notre pipeline de WebGPU.

Nous y mettons une valeur d’auto, qui signifie que nous voulons utiliser une configuration simple pour notre pipeline.

Cependant, faites attention avec la valeur auto, car (les docs de WebGPU nous donnent l’avertissement)[https://www.w3.org/TR/webgpu/#pipeline-base] que le layout configuré avec auto n’est pas recommandé pour les layouts plus complexes.

Pour l’instant, pour ne rendre qu’un triangle, auto marche assez bien.

vertex, GPUVertexState

Regardons que le champ vertex est de type GPUVertexState :

vertex: { module: shaderModule, entryPoint: "vertex_main", buffers: vertexBuffersDescriptors, },

module

Le champ module contiendra notre configuration de shaders. Nous avons déjà défini la valeur shaderModule dans l’article précédent, mais je l’inclurai pour que vous ne deviez pas suivre le lien :

const shaderModule = device.createShaderModule({ code: ` struct VertexOut { @builtin(position) position : vec4<f32>, @location(0) color : vec4<f32>, }; @vertex fn vertex_main(@location(0) position: vec4<f32>, @location(1) color: vec4<f32>) -> VertexOut { var output : VertexOut; output.position = position; output.color = color; return output; } @fragment fn fragment_main(fragData: VertexOut) -> @location(0) vec4<f32> { return fragData.color; } `, });

entryPoint

Le champ entryPoint signifie le nom de la fonction de notre shader de vertex.

Nous y mettons vertex_main, car il correspond au nom que nous avons déjà défini dans notre définition du shader de vertex.

buffers

Le champ buffers s’attend aux descriptors de notre tampon de sommets.

Rappelons que nous avons déjà défini un descripteur, vertexBuffersDescriptors, comme suit :

const vertexBuffersDescriptors = [ { attributes: [ { // Position shaderLocation: 0, offset: 0, format: "float32x4", }, { // Color shaderLocation: 1, offset: 16, format: "float32x4", }, ], arrayStride: 32, stepMode: "vertex", // https://www.w3.org/TR/webgpu/#enumdef-gpuvertexstepmode }, ];

fragment, GPUFragmentState

Ensuite, regardons le champ fragment est de type GPUFragmentState :

fragment: { module: shaderModule, entryPoint: "fragment_main", targets: [ { format: presentationFormat, }, ], },

module

Nous avons déjà parlé de ce champ en parlant du champ vertex. Il suffit donc d’utiliser la valeur shaderModule.

entryPoint

Égale à la configuration du champ vertex, nous mettons la valeur fragment_main pour ce champ, car il correspond au nom que nous avons déjà défini dans notre définition du shader de fragment.

targets

Le champ targets tient une liste de colorStates.

Bref, on configure les cibles sur lesquelles nous voulons rendre.

Dans ce projet, nous n’avons qu’un seul cible. On configure ce cible en configurant son champ format avec la valeur presentationFormat… qui est le format preferré de notre élément canvas

Cette variable est liée à une configuration que nous verrons dans l’article suivante, où nous configurons un descripteur d’un render pass, renderPassDescriptor.

primitive, GPUPrimitiveState

Le champ primitive est de type GPUPrimitiveState définit le type du primitive que nous voulons construire.

Pour le triangle, il suffit d’utiliser triangle-list, car nous voulons rendre des triangles… ou dans notre cas, un triangle seul.

Le code de la partie 6

Vous pouvez trouver le code de cette partie dans ce GitHub Gist.

La suite

Nous continuerons ce projet sur YouTube ! À la prochaine !

Des ressources (en français et anglais)


Comments for Pipeline de rendu | WebGPU | Vidéo



Written by Carmen Cincotti, computer graphics enthusiast, language learner, and improv actor currently living in San Francisco, CA.  Follow @CarmenCincotti

Contribute

Interested in contributing to Carmen's Graphics Blog? Click here for details!