WebGPU vs WebGL en 2025 : ce qui a changé
WebGPU est l'API graphique de nouvelle génération pour le navigateur, conçue pour exposer directement Vulkan, Metal et D3D12. Après plusieurs années en behind-a-flag, le cap critique est franchi en 2025 : Chrome et Edge (Chromium 113+) l'ont livré en stable à tous les utilisateurs, Safari 26 (macOS 26, iOS 26) l'active par défaut, et Firefox a levé la principale barrière technique en supprimant l'option de compilation qui bloquait la livraison. En août 2025, on dépasse les 85 % d'utilisateurs desktop compatibles selon StatCounter.
La différence avec WebGL ne tient pas qu'au rendu. WebGL est une API d'il y a quinze ans, mappée sur OpenGL ES 2.0/3.0 : état global, syncrone, pensée pour dessiner des triangles. WebGPU apporte un modèle moderne : passes de rendu explicites, pipelines précompilés, objets immuables, et surtout un**compute shader** natif. C'est cette dernière brique qui change la donne pour les apps B2B.
En pratique, WebGL contraignait tout calcul GPU à des pirouettes : encoder les données dans des textures, exécuter un fragment shader, relire le résultat. Avec WebGPU, un compute shader prend un `storage buffer` en entrée, le transforme en parallèle, et l'écrit dans un autre buffer. Le GPU devient un coprocesseur générique utilisable depuis JavaScript. Pour la première fois, des workloads jusque-là réservés au natif (rendering CAD, vidéo processing, simulation, inférence ML) deviennent légitimes dans le navigateur.
Cas d'usage B2B qui justifient l'investissement
WebGPU a un coût réel : compétences spécialisées (WGSL, pipelines, mémoire GPU), complexité de fallback, debugging plus ardu. On ne le déploie pas pour un effet visuel. On le déploie quand le produit tire une valeur directe du calcul GPU local. Quatre familles de cas B2B le justifient en 2025.
Le premier : **le traitement vidéo et image dans le navigateur**, sur le modèle d'Adobe Express ou de Canva. Filtres colorimétriques, keying, débruitage, encodage de prévisualisation, tracking de mouvement : tout ce qui aurait exigé un transcodage serveur devient exécutable en local. Sur un Intel Arc A380 desktop, un compute shader de blur gaussien 4K tourne à 16 ms/frame contre 240 ms en Canvas2D — un facteur 15 qui transforme l'UX.
Le deuxième : **les configurateurs produit 3D et la visualisation CAD**. Meubles sur-mesure, cuisine équipée, packaging pliable, installations industrielles. Ici, c'est le rendu (et non le compute) qui parle : PBR complet, ombres temps réel, dizaines de millions de polygones. three.js r170 expose un `WebGPURenderer` mature qui exploite ces capacités, et Babylon.js 7 a basculé WebGPU en premier-class.
Le troisième : **la visualisation scientifique et la data-vox à haute densité**. Imagerie médicale (volumes DICOM), simulation CFD, cartographie 3D de réseaux IoT, flux financiers ordonnancés sur des millions de points. Le compute shader trie, agrège et filtre côté GPU, le rendu affiche le résultat. Plus de bouchons JS au-delà de 100k points.
Le quatrième, et probablement le plus stratégique pour 2025-2026 : **l'inférence ML locale**, abordée en détail plus bas.
Le compute shader : le vrai déclic
Un compute shader exécute des milliers de threads en parallèle sur le GPU. La granularité est explicite : groupes de travail (`workgroups`) de 64 à 256 threads, dimensions x/y/z, barrières de synchronisation. C'est le bon modèle pour tout algorithme à parallélisme massif : produit matriciel, tri, réduction, simulation N-body, traitement d'image, convolutions.
Sur un benchmark interne (réduction d'un tableau de 16M de float32, somme + min + max) : un compute shader WebGPU sur RTX 3060 s'exécute en 1,1 ms, un équivalent JavaScript typé en boucle prend 78 ms, un Web Worker 81 ms. Facteur 70. Pour un bitonic sort sur 1M d'entiers, on passe de 420 ms (JS) à 6 ms (GPU). Ces nombres changent l'architecture d'une app : ce qui était un job serveur devient un calcul local instantané.
Concrètement, le pattern d'usage est verbeux mais stable. On déclare un pipeline avec un module WGSL, on alloue un `GPUBuffer` `STORAGE` avec `mappedAtCreation`, on écrit les données via un `ArrayBuffer`, on encode une `dispatch(x, y, z)`, on soumet, on recopie vers un buffer mappable, on relit. La machine tourne en 80 lignes de TypeScript. C'est plus direct que l'équivalent WebGL et incomparablement plus performant.
IA on-device via WebGPU : transformers.js, web-llm, ONNX
Le cas le plus visible en 2025 est l'inférence de petits modèles de langage directement dans le navigateur. Trois runtimes cohabitent : `transformers.js` (Hugging Face, WASM + WebGPU backend), `@mlc-ai/web-llm` (MLC, optimisé WebGPU pur) et ONNX Runtime Web (Microsoft, backend WebGPU depuis 1.17). Tous exploitent les compute shaders pour la couche matmul du transformer.
Le gain est double. **Latence** : pas d'aller-retour réseau, premier token en 200-500 ms sur un laptop moyen. **Confidentialité** : aucune donnée ne quitte l'appareil, argument décisif pour les cas juridiques, RH, santé, finance. Sur un Intel Ultra 7 155H avec 32 Go, Llama 3.2 1B tourne à 38 tok/s en WebGPU, 3B à 14 tok/s. Gemma 2B passe à 22 tok/s, Phi-3.5 mini (3.8B) à 11 tok/s. En dessous du premier token, on reste sur des modèles quantifiés en q4f16 — la qualité reste exploitable pour de la classification, du résumé, du RAG sur contexte court.
Ce qui **ne tient pas** en local : modèles 7B+ (Llama 3.1 8B, Mistral 7B) sauf sur GPU haut de gamme (RTX 4070+, 12 Go VRAM+), contextes longs (>8k tokens), et toute génération en streaming multi-utilisateurs. La règle pragmatique : on-device pour l'assistance, le pré-classification, le reranking, le résumé de document court. Serveur pour les workloads lourds, multi-tenant, ou exigeant une garantie de qualité.
Cadre de décision : quand WebGPU, quand rester sur WebGL/CPU
Nous appliquons un cadre simple en amont de tout projet WebGPU. Trois conditions cumulatives doivent être réunies : (1) le besoin GPU apporte une valeur produit identifiée (latence, confidentialité, économie serveur) ; (2) l'équipe accepte la dette de maintenance (compétences WGSL, debugging, tests) ; (3) la cible matérielle tient le choc sur le percentile p75 des utilisateurs réels. Si l'une manque, on reste sur WebGL ou CPU.
Le signal le plus clair est la migration depuis une étape serveur payante. Si une page produit déclenche 50 ms de calcul serveur pour générer un rendu, un compute shader local à 5 ms supprime ce coût et la latence réseau. Si un appel à un LLM cloud coûte 0,005 € par requête et que le cas tient dans un 3B local, l'économie passe par le coût de bande passante du modèle (1 à 2 Go, mis en cache après première visite via Cache API). Sur un SaaS B2B à 10k sessions/jour, le ROI se materialise en quelques semaines.
L'histoire progressive enhancement reste centrale. Sur les navigateurs sans WebGPU, on dégrade proprement : inférence via `transformers.js` backend WASM (2 à 4x plus lent mais fonctionnel), rendu via WebGL2 (ou canvas 2D pour les simples configurateurs), compute via Web Worker (Typed Arrays + SharedArrayBuffer). La fonctionnalité reste, seule la vitesse change. C'est non négociable : bloquer 15 % d'utilisateurs sur une feature critique n'est pas acceptable.
Pièges production : mobile, batterie, blocklist OS
Le piège numéro un, et le plus sous-estimé : **la diversité matérielle**. Un GPU mobile (Adreno 740, Apple A17) est typiquement 8 à 12 fois plus lent qu'un GPU desktop milieu de gamme sur un compute shader. Un tri de 1M d'entiers à 6 ms sur RTX 3060 prend 55 ms sur iPhone 15 Pro. Pour du rendering, l'écart est encore plus large sur les effets gourmands (ray tracing,ombres soft). Il faut mesurer sur cible réelle, jamais extrapoler depuis le desktop.
Le piège numéro deux : **l'impact batterie sur laptop**. Un compute shader qui tourne en continu draine un MacBook Air M2 en 2h au lieu de 12h. Pour une app B2B métier utilisée 6h/jour, c'est un rejet utilisateur quasi certain. Règle pratique : limiter la fréquence (throttle à 30 fps si possible), interrompre quand l'onglet est masqué (`document.visibilityState`), exposer un toggle utilisateur, et surveiller `navigator.gpu`'s `adapter.info` pour Downscaler la résolution sur batterie (`navigator.getBattery()`).
Le piège numéro trois : **la blocklist OS/pilote**. Chrome maintient une liste de pilotes buggés (Intel HD 4600 sur vieux Windows, certains Mali sur Android 12) où WebGPU est désactivé silencieusement. `navigator.gpu.requestAdapter()` renvoie alors `null`, même si `navigator.gpu` existe. Il faut gérer ce cas explicitement et basculer sur le fallback sans erreur visible. Idem sur Linux Firefox où certains pilotes Mesa sont sur liste grise. Le test `if (!navigator.gpu)` ne suffit pas ; toujours tester le résultat de `requestAdapter()`.
Dernier point : la télémétrie. Remontez en production le statut WebGPU (`adapter.requestAdapterInfo().vendor`, architecture, fallback utilisé). Sans données réelles, on ne sait pas quel pourcentage de la base profite réellement de l'accélération. Sur un de nos clients B2B desktop-first (finance), on observe 91 % WebGPU, 7 % fallback WebGL, 2 % WASM. Sur un client mixte desktop/mobile (logistique), c'est 58 % / 34 % / 8 %. Ces chiffres pilotent les arbitrages.