动画和模糊内容的 GPU 加速
GPU Acceleration of animated and blurred content
问题:为什么我的CPU在应用模糊时注册~30%而不是~ 6% 当没有对动画对象应用模糊时?
详情:
我在页面上有一组随机生成的项目,这些项目分配了 CSS 动画(在 CSS 文件中)和随机生成的宽度、高度值,重要的是,模糊,内联应用。
CSS 文件样式如下:
animation-name: rise;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-iteration-count: 1;
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
-webkit-transform: translate3d(0,0,0);
transform: translateZ(0);
宽度、高度和模糊通过 style
属性内联应用。
<div class="foo" style="width:99px;height:99px;
filter:blur(2px);
-webkit-filter:blur(2px) opacity(0.918866247870028);
-moz-filter:blur(2px) opacity(0.918866247870028);
-o-filter:blur(2px) opacity(0.918866247870028);
-ms-filter:blur(2px) opacity(0.918866247870028);"></div>
启用模糊后,我的 CPU 使用率约为 30%。当我禁用模糊时,CPU 使用率下降到 ~6%。
这里发生了什么? chrome 是否只有在不应用模糊时才能进行 GPU 加速?如果是,为什么?
更新 1:
动画rise
如下所示:
@keyframes rise {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(-1000px);
}
}
不要在内联样式中模糊它。把你的模糊放在样式文件中。
我不认为模糊实际上是导致您的问题的原因,它只是看起来比以前更明显了。问题是动画中的 transform: translateY
覆盖了您用来强制 GPU 加速的 transform: translateZ(0)
。
这是您现在 运行 代码的时间线记录,请注意主线程和光栅线程上的所有这些 activity:
现在将此与我将 will-change: transform
应用于 .foo
的录音进行比较:
没有 activity 在主要和光栅上。
应用此修复程序有两个步骤:
将will-change: transform
应用到.foo
。这将使浏览器知道您打算更改 属性 并让它在 GPU 上渲染该元素以解决这个问题。
目前没有支持 will-change
的 Edge 和 IE 版本。因此我们将在动画中使用 transform: translate3d(0, -1000px, 0);
来强制 GPU 加速。请注意,这是一个 hack,因此我们将检测对 will-change
的支持并在支持它的浏览器中使用 transform: translateY
。
最终代码:
@keyframes rise {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, 1000px, 0);
}
}
@supports (will-change: transform) {
@keyframes rise {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(1000px);
}
}
}
div {
width: 100px;
height: 100px;
background: #f00;
animation: rise forwards 2s linear infinite;
will-change: transform;
}
问题:为什么我的CPU在应用模糊时注册~30%而不是~ 6% 当没有对动画对象应用模糊时?
详情:
我在页面上有一组随机生成的项目,这些项目分配了 CSS 动画(在 CSS 文件中)和随机生成的宽度、高度值,重要的是,模糊,内联应用。
CSS 文件样式如下:
animation-name: rise;
animation-fill-mode: forwards;
animation-timing-function: linear;
animation-iteration-count: 1;
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
-webkit-transform: translate3d(0,0,0);
transform: translateZ(0);
宽度、高度和模糊通过 style
属性内联应用。
<div class="foo" style="width:99px;height:99px;
filter:blur(2px);
-webkit-filter:blur(2px) opacity(0.918866247870028);
-moz-filter:blur(2px) opacity(0.918866247870028);
-o-filter:blur(2px) opacity(0.918866247870028);
-ms-filter:blur(2px) opacity(0.918866247870028);"></div>
启用模糊后,我的 CPU 使用率约为 30%。当我禁用模糊时,CPU 使用率下降到 ~6%。
这里发生了什么? chrome 是否只有在不应用模糊时才能进行 GPU 加速?如果是,为什么?
更新 1:
动画rise
如下所示:
@keyframes rise {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(-1000px);
}
}
不要在内联样式中模糊它。把你的模糊放在样式文件中。
我不认为模糊实际上是导致您的问题的原因,它只是看起来比以前更明显了。问题是动画中的 transform: translateY
覆盖了您用来强制 GPU 加速的 transform: translateZ(0)
。
这是您现在 运行 代码的时间线记录,请注意主线程和光栅线程上的所有这些 activity:
现在将此与我将 will-change: transform
应用于 .foo
的录音进行比较:
没有 activity 在主要和光栅上。
应用此修复程序有两个步骤:
将
will-change: transform
应用到.foo
。这将使浏览器知道您打算更改 属性 并让它在 GPU 上渲染该元素以解决这个问题。目前没有支持
will-change
的 Edge 和 IE 版本。因此我们将在动画中使用transform: translate3d(0, -1000px, 0);
来强制 GPU 加速。请注意,这是一个 hack,因此我们将检测对will-change
的支持并在支持它的浏览器中使用transform: translateY
。
最终代码:
@keyframes rise {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, 1000px, 0);
}
}
@supports (will-change: transform) {
@keyframes rise {
0% {
transform: translateY(0px);
}
100% {
transform: translateY(1000px);
}
}
}
div {
width: 100px;
height: 100px;
background: #f00;
animation: rise forwards 2s linear infinite;
will-change: transform;
}