提问人:Mad Scientist 提问时间:2/23/2013 最后编辑:Mad Scientist 更新时间:12/22/2014 访问量:14283
绘制路径和硬件加速
Drawing paths and hardware acceleration
问:
在我看来,我正在绘制一条相当大的路径,并且遇到了一些性能问题。该路径目前长 32,000 个点,但我的应用程序应扩展到至少 128,000 个点。我真的无法对路径的大小做任何事情,因为数据集太大了,我需要能够一次显示整个路径并允许放大。
我使用的是运行 Android 4.2 的 Nexus 10,默认情况下,它为未明确禁用它的应用程序启用硬件加速。
该路径是使用以下代码创建的(我省略了一些设置和其他不相关的部分):
dataPath.moveTo(0, offset - (float) data[leftLimit]/ scalingFactor);
for (int i = leftLimit; i < rightLimit; ++i) {
x = (i - leftLimit) * dx;
y = offset - (float) data[i]/ scalingFactor;
dataPath.lineTo(x, y);
}
然后用方法画出:onDraw()
canvas.drawColor(Color.WHITE);
canvas.drawPath(dataPath, linePaint);
我测量了使用和不使用硬件加速绘制视图所需的时间,令我惊讶的是,硬件加速要慢得多:adb shell dumpsys gfxinfo
使用硬件加速:
没有硬件加速:
硬件加速版本每帧大约需要 200-300 毫秒,大部分时间在处理阶段。非加速版本大约需要 50 毫秒,其中 2/3 在绘制阶段,1/3 在处理阶段。
显然,即使是没有硬件加速的更快版本,仍然太慢,无法达到 60 fps,或者当我移动到更大的数据集时甚至几乎无法使用。
在我的情况下,呈现位图的路径,然后仅转换该位图以适合屏幕的想法也是有问题的。我需要支持在路径上放大得很远,并且为了在不使路径质量变差的情况下启用放大,我将不得不渲染路径的超大位图(并且可能会遇到内存限制和纹理大小限制)。当放大到很远时,我将不得不只为路径的一部分创建更新的图像,或者切换到直接渲染路径,如果性能仍然与我现在相似,这可能会导致延迟大于帧速率。
我现在想知道的是
- 绘制线条/路径只是 GPU 不擅长的事情,不应该尝试硬件加速,还是我可能做错了什么导致性能不佳?
- 我能做些什么来绘制具有可接受性能的如此巨大的路径吗?
答:
似乎您可能会在 GPU 中遇到一般瓶颈。请查看以下链接:
尤其是第一个,它建议你制作一个位图并绘制它。看起来如果你改用 openGL,你可以获得更好的性能。可能有一些神奇的方法可以使现有方法起作用,但我目前还不知道这一点。
为什么你会看到你的行为,可能是因为你在每次绘制之间将所有数据发送到GPU。您应该将其缓存在 GPU 上,并使用翻译代替。不重新创建数据并将其全部发送到 GPU。您可能受 I/O 限制,这意味着 CPU 和 GPU 之间的传输速率是限制性能的原因。根据您提供的数据,我无法 100% 确定这一点,但这是我最好的猜测。尝试不同的缓存技术,主要是链接 #1 中的 png-cache。
绘制线条/路径只是 GPU 不擅长的东西吗 不应该尝试硬件加速,或者我可能会做点什么 导致性能不佳的错误?
路径始终使用 CPU 呈现。当应用进行硬件加速时,这意味着渲染器将首先使用 CPU 将路径绘制到位图中,然后将该位图作为纹理上传到 GPU,最后在屏幕上绘制纹理。
线路完全由硬件加速。在这种情况下,我建议您不要使用 a。Path
Canvas.drawLines()
我能做些什么来画出如此巨大的路径 性能?
您应该自己使用路径或将路径呈现为您管理的路径。Canvas.drawLines()
Bitmap
评论
Bitmap
Shape path too large to be rendered into a texture
Canvas.drawLines(float[], Paint)
Canvas.drawLine(int. int, int, int)
Canvas.drawLines()
绘制路径将涉及的不仅仅是“告诉”GPU 绘制线条。路径具有许多特征,例如如何处理线的末端或线的虚线,这些特征不是 GPU 加速的。当您遇到那么多行时,可能会有另一个小插曲,使 CPU 和 GPU 加速的组合变慢。上面建议的解决方案是移动到而不是尝试不使用花哨的方法可能会有所帮助。canvas.drawLines
canvs.drawPath
Paint
如果这没有帮助,您可以尝试使用 GLSurfaceView 并将线条直接渲染到其中。这将涉及一些 OpenGL ES 知识,但应该不会非常困难,而且可能会更有效。
评论