C'est quoi l'accélération matérielle ?
Comme le dit fort à propos Wikipédia : L'accélération matérielle consiste à confier une fonction spécifique effectuée par le processeur à un circuit intégré dédié qui effectuera cette fonction de façon plus efficace.
Dans le monde du Web cette possibilité concernera généralement les animations, et reposera sur la présence de deux éléments essentiels :
- Le processeur : CPU (Central Processing Unit)
- La "carte graphique" (ou plutôt un processeur graphique) : GPU (Graphic Processing Unit)
Avertissement : à proprement parler, le phénomène décrit dans cet article ne concerne pas directement "l'accélération matérielle", il s'agit plutôt d'une "mise en calque" d'un élément dans le but d'être traité différemment par le navigateur. Cependant, toutes les ressources mondiales nommant ce comportement "accélération matérielle", je me permets d'en faire de même.
Quel intérêt pour nos pages web ?
Certaines propriétés CSS affectent directement ou indirectement la taille de la boîte d'un élément : width
, height
, mais aussi margin
, padding
, border
, top
, right
, bottom
, left
, etc.
Lorsque l'on modifie l'une de ces valeurs via CSS, le navigateur se voit contraint de recalculer la boîte ainsi que celles qui l'entourent et de "repeindre" la page (repaint).
Ce comportement est généralement insignifiant… sauf en cas de transition ou d'animation CSS : le navigateur, via le processeur, doit alors recalculer tous les éléments à chaque étape-clé de la transition !
La conséquence de cet effort du processeur se traduit par des effets de ralentissements et des saccades qui peuvent devenir très gênantes sur des périphériques de faible puissance, et en particulier sur des tablettes et smartphones.
Lors de vos animations CSS, pensez dans un premier temps à éviter les propriétés de "boîte" (citées précédemment) et remplacez-les avantageusement par des équivalents beaucoup plus performants (mais parfois moins compatibles) telles que les transformations : translations, rotations, déformations.
Et quand ce n'est pas possible,… il sera alors grand temps d'activer l'accélération matérielle via CSS, et le gain en fluidité sera immédiat et perceptible !
Activer l'accélération matérielle (AM) en CSS ?
Appliquer une transformation CSS force un élément à s'afficher dans un "calque" indépendant du reste des éléments, permettant alors au navigateur de le traiter différemment.
L'une des possibilités offertes est alors de basculer tous les traitements et calculs de cet élément du côté de la carte graphique (GPU), et non plus du processeur (CPU). Bref,
Une transformation CSS "classique" (translate
, rotate
, skew
, scale
, matrix
) ne suffit pas à activer l'accélération matérielle, il est nécessaire que cette transformation passe via l'axe de la profondeur (axe Z). En clair, il faut opérer une transformation 3D.
Voici une liste de déclarations CSS 3D permettant d'activer l'accélération matérielle sans altérer l'affichage ou la position de l'élément :
-
transform: translateZ(0);
-
transform: translate3d(0,0,0);
-
perspective: 1000; backface-visibility: hidden;
Les propriétés de transformations 3D sont plutôt bien supportées par les navigateurs, mais dans tous les cas, n'oubliez pas d'ajouter les préfixes constructeurs de rigueur (-webkit-
, -moz-
, -ms-
, -o-
) nécessaires tant que la spécification W3C du module des transformations 3D n'est pas finalisée.
Notez également que certains filtres CSS (CSS3 filters, actuellement à l'état de brouillon), WebGL, la vidéo et l'élément HTML5 <canvas>
contribuent également à l'activation de la carte graphique.
Certains navigateurs permettent d'afficher les informations de la carte graphique et notamment si l'accélération est possible. Par exemple dans Firefox, la commande est about:support
, et dans Chrome la syntaxe est chrome://gpu
:
Un exemple concret ?
Pour mieux comprendre la mise en pratique de l'accélération matérielle, je vous propose un court exemple concret. Le but est de faire apparaître un menu de navigation en transition lors d'un événement :
nav {
transform: translate3d(-100%,0,0); /* activation de l'AM */
transition: transform .4s;
}
nav.open {
transform: translate3d(0,0,0);
}
Variante (plus compatible si les transformations 3D ne sont pas supportées) :
nav {
position: absolute;
left: -100%;
transform: translateZ(0); /* activation de l'AM */
transition: left .4s;
}
nav.open {
left: 0;
}
Les snippets de navigation responsive sur la page goetter.fr/nav activent tant que faire se peut l'accélération matérielle. Je vous invite à les décortiquer et vous les approprier.
Pratique aussi pour les filtres CSS
Les filtres CSS, actuellement en brouillon dans les spécifications, offrent de nouvelles possibilités graphiques fort intéressantes : flou, noir et blanc, sépia, contraste, luminosité, etc.
Cependant, à l'instar des animations, certains filtres CSS tels que blur
(flou) posent des problèmes de lenteur sur mobiles.
Dans ce cas, activer l'accélération matérielle vous sera également d'une grande utilité.
Et aussi pour le lissage des polices !
Le lissage des polices laisse souvent à désirer sur Chrome Windows, je ne vous l'apprends sans doute pas. Sachez que dans ce domaine aussi l'activation de l'accélération matérielle peut faire des miracles.
Prenez deux caractères agrandis et tournés. Dans le premier cas, opérez une rotation simple à l'aide d'une transformation classique. Dans le second cas, ajoutez une transformation CSS 3D afin de solliciter la carte graphique. Vous serez bluffés par le résultat (à voir sur CodePen) :
span {
display: inline-block;
-webkit-transform: rotate(60deg);
}
span+span {
-webkit-transform: rotate(60deg) translate3d(0,0,0);
}
Conclusion
Activer l'accélération matérielle favorise la fluidité des animations CSS, mais provoque également d'autres effets bénéfiques pour les périphériques dont le processeur est parfois à la traîne.
Sachez en profiter sans toutefois en abuser : les cartes graphiques de nos anciens mobiles ne sont pas non plus des foudres de guerre et pourraient facilement pâtir d'un excès de zèle dans vos choix d'activation matérielle.
Commentaires
J'ai pu voir que certaines propriétés causaient qq soucis (notamment dans tes sources), est-ce que tu sais si une propriété fonctionne correctement et à peu près partout pour activer l'accélération matérielle ?
@Nico3333fr : "pose des soucis" ou "n'est pas trop compatible" ? Si c'est une question de compatibilité, c'est assez ouvert : http://caniuse.com/#feat=transforms3d
Faut-il combiner avec requestAnimationFrame ? http://www.paulirish.com/2011/requestanimatio...
@Raphael : non c'est bien "pose des soucis".
"In Chrome and Safari we might see a flickering effect when using CSS transforms or animations. The following declarations can be used to fix the issue:"
Etc.
Est-ce que tu sais si " transform: translate3d(0, 0, 0);" marche mieux ?
Un autre point de limitation : les navigateurs affichés sur un écran virtuel type `xvfb` ne gèrent pas ces animations car le calcul du rendu ne passe par le GPU.
Dit comme ça, ça peut paraître quelconque, mais ça a été source de quelques jours de debug, nos tests d'intégration ne passant pas sur notre système d'intégration continue, mais passant quand reproduits avec contrôle visuel.
Donc, si vous avez des tests d'intégration (déjà, bravo :) ), mais sachez que ceux-ci seront impactés par l'usage de l'accélération matérielle.
@Nico3333fr : Justement, je pense que ta phrase résume très bien l'astuce :
- en général les transformations et animations (classiques) sont ralenties sur Chrome et Safari
- par contre les transformations 3D activent l'AM et corrigent ce problème
C'est ainsi que je comprends cette phrase
Ou alors, on peut aussi ne pas utiliser d'animations. Et hop! Plus de problème...
Ce commentaire pourrait passer pour du troll, mais il n'en est rien. Je pense qu'il est important de rappeler que le meilleur moyen pour qu'un terminal ne rame pas, c'est de ne pas utiliser d'animation. (Quand c'est trop simple, on n'y pense pas)
À noter qu'il y a eu du changement sous iOS6, et que translate3d (utilisé dans les exemples de cet article) ne déclenche plus l'accélération matérielle. Il est préférable d'utiliser translateZ(0) ou perspective. (À lire sur le sujet : http://indiegamr.com/ios6-html-hardware-accel... )
@HTeuMeuLeu : Merci, j'ai ajouté ta ressource et modifié l'un des deux exemples.
Il faut aussi regarder les propriétés utilisées et la promotion des éléments sur le GPU.
Dans Chrome, si vous cochez l'option du devtool: "Show composited layer borders", vous allez être en mesure de vérifier que les éléments voulus obtiennent bien leur layer et y restent.
@jb_gfx : tes veilles technos doivent être palpitantes si tu te limites à lire l'intro des articles :D
@jb_gfx : Oui on peut jouer avec les mots, c'était l'information la plus importante de cet article.
Donc :
- oui, un GPU n'est qu'un processeur graphique et non une carte graphique
- oui un mobile n'a pas de carte graphique, mais un GPU
- oui un processeur (CPU) a quelque chose à voir avec l'AM s'il dispose et/ou gère un chipset GPU
@Raphael : en fait, @hteumeuleu a plus ou moins répondu à ma question :)
J'ai testé ça sur un projet aujourd'hui la différence est vraiment époustouflante, merci beaucoup !
@Raphael, ce dont tu parles dans ton article n'est pas de l'accélération matérielle. les navigateurs dessinent généralement certains éléments de la page dans des "calques" (layers) séparés afin de pouvoir faire certaines optimizations. Appliquer une transforme 3D à un élément va, chez la plupart des navigateurs aujourd'hui, faire en sorte que cet élément ait son propre calque (on parle de layerization dans Gecko).
Les gains de performances que fournissent les astuces que tu proposes sont liés au fait que dans certains cas, la spec nous autorise à ne pas recalculer le reflow de la page, et aussi parce que si, par exemple, un élément se déplace par rapport à ce qu'il y a en dessous et qu'il est dans un calque séparé, le navigateur n'a pas besoin d'invalider et redessiner les pixels des calques d'en dessous. Tout celà est complêtement indépendant de l'accélération matérielle.
J'en profite pour insister sur le fait qu'il faut toujours tester avec et sans ce genre de hacks, parce que "layerizer" des éléments à un coût, donc le faire dans des cas cela n'offre pas d'optimization, peut dégrader les performances et l'utilisation de la mémoire. Avec le temps, les heuristiques de layerization des naigateurs deviendront suffisament bonnes pour que les développeurs web n'aient pas besoin de faire ce genre de hack.
@nical : Merci pour ton commentaire éclairé et pertinent :)
Pas de souci pour moi s'il ne s'agit pas de l'accélération matérielle, mais ce qui m'étonne c'est que je ne suis pas le premier à appeler ça ainsi, que de très grosses ressources et références mondiales (HTML5rocks, Smashingmagazine, Paul Irish, David Walsh, etc.) appellent tous ça "accélération matérielle" :/
@Raphael Oui, la confusion vient du fait qu'on a commencé à tirer parti de la layerization en même temps que l'accélération matérielle, et que le concept de calque est interne au fonctionnement des navigateurs. En revanche, "accélération matérielle" parle à tout le monde. Difficile d'expliquer rapidement les calques dans une conférence. Et il est vrai que la les optimizations de layerization sont plus profitables lorsque le compositing à lieu sur le GPU. En somme c'est beaucoup plus simple de faire l'amalgame entre deux optimizations qui sont utilisées conjointement, plutôt que d'utiliser des termes plus corrects mais un peu abstraits pour ceux qui ne connaissent pas le fonctionnement interne des navigateurs. Une chose est sûre, (au moins dans Gecko) le choix de faire le compositing sur le GPU ne dépend pas de des propriétés CSS, alors que le fait qu'un élément ait son propre layer en dépend.
Désolé, je suis un peu pointilleux là dessus parce que je travaille très exactement sur ça (les layers) dans Gecko.
@nical : Merci pour toutes ces précisions. Je vais tenter de corriger l'article, ou au-moins d'ajouter un warning d'explication. Ton aide / relecture risque d'être fortement appréciée ;)
@nical : je confirme, lecture passionnante ! J'ai bien fait d'aller jusqu'au bout des commentaires :D
Merci @goetter pour cet article, qui est un bon résumé des solutions qu'on trouve aujourd'hui !
bonjour
Je viens de lire l'article et onettement ça reste très confus, je m'explique
ce la fait 20 ans que je suis dans l'informatique et 15 ans que l’accélération matériel graphique m'interpelle. Effectivement j'ai commençais par la conception 3D chez Silicone Graphique (stage) qui sont les pionner dans le domaine, puis la marque NVIDIA a racheté des brevets pour intégrer la possibilité accélérer les graphique 2d et 3d dans ses cartes graphiques qui au par avant n'avait comme tache que d'afficher point par point les information sur l’écran .
En gros on parle d’accélération graphique dans un seul cas: lorsque l'affichage graphique n'est pas à la seul charge du processeur central de l'ordinateur mai confier à un processeur tiers appeler le plus souvant GPU,
CPU: central processing unit et GPU facil : Graphique processing unit.
Donc quelque soit l'application qui demande à afficher sur l’écran son résultat, si pour ce là est utilise le GPU on parle d’accélération graphique.
La difficulté actuelle avec le WEB est de déterminer pour les animations qui est responsable du calcul de celle ci
donc il existe un 3° cas spécifique au WEB.
Soit coté serveur 1° cas
Soit coté client 2 cas :
1 pas de demande d’accélération de la par du navigateur 99,9 % du temps:
2 demande d’accélération de la par du navigateur: ci le navigateur demande au GPU de l'ordinateur client de calculer une partie de l’animation on entre dans le cas de l'accélération graphique comme entendu dans l'article.
les navigateurs WEB pour l'instant n'utilise que très peut les propriétés GPU alors que les jeux on font énormément usage, que les logiciels 3D on sont totalement dépendant, ext..
le souci comme toujours est que il faudrait standardisé les appelles au GPU par les navigateurs (telle instruction fait fonctionner le GPU) pour que ces solutions soient adoptés par les développeurs. Actuellement pour mois ce là reste très confus il me semble.
merci beaucoup pour l'astuce mais c'est toujours insuffisant l'animation utilise beaucoup le CPU y pas d'autres astuces CSS pour réduire encore l'utilisation de CPU et merci beaucuop