绘图路径和硬件加速

Mad*_*ist 36 graphics android opengl-es

我在我的视野中画了一条相当大的路径,我遇到了一些性能问题.该路径目前长达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);
        }
Run Code Online (Sandbox Code Playgroud)

然后在onDraw()方法中绘制:

canvas.drawColor(Color.WHITE);
canvas.drawPath(dataPath, linePaint);
Run Code Online (Sandbox Code Playgroud)

我测量了使用adb shell dumpsys gfxinfo和不使用硬件加速来绘制视图所需的时间,令我惊讶的是硬件加速速度要慢得多:

通过硬件加速:

在此输入图像描述

没有硬件加速:

在此输入图像描述

硬件加速版本每帧大约需要200-300毫秒,大多数花费在处理阶段.非加速版本大约需要50 ms,Draw阶段为2/3,处理阶段为1/3.

显然,即使我没有硬件加速的更快版本仍然太慢而无法实现60 fps,或者当我迁移到更大的数据集时甚至几乎无法使用.

在我的情况下,将路径呈现为位图然后仅转换该位图以适合屏幕的想法也存在问题.我需要支持在路径上放大很远,并且在没有路径质量变差的情况下启用放大我将不得不渲染路径的超大位图(并且可能会遇到内存限制和纹理大小限制).当放大远时我不得不创建仅部分路径的新图像,或者切换到仅直接渲染路径,如果性能仍然与我的权限相似,这可能会导致延迟大于帧速率现在.

我现在想知道的是

  • 绘制线条/路径只是GPU不好的事情而且不应该尝试硬件加速,或者我是否可能做错了会导致性能不佳?
  • 我有什么办法可以用可接受的性能画出如此巨大的路径吗?

Rom*_*Guy 48

绘制线条/路径只是GPU不好的事情而且不应该尝试硬件加速,或者我是否可能做错了会导致性能不佳?

始终使用CPU呈现路径.当应用程序是硬件加速时,这意味着渲染器将首先使用CPU将路径绘制到位图中,然后将该位图作为纹理上传到GPU,最后在屏幕上绘制纹理.

线条完全是硬件加速的.而不是使用Path我推荐你Canvas.drawLines()在这种情况下使用.

我有什么办法可以用可接受的性能画出如此巨大的路径吗?

您应该Canvas.drawLines()自己使用或渲染路径到Bitmap您管理的路径中.

  • 至于绘制路径手动进入"位图"并允许它们在屏幕上移动,我推送了简单的代码[这里](https://github.com/barthand/android-pathbitmap).我使用相同的技术来实现在GPU加速的MapView上绘制这样的路径作为叠加层(其中通常的GPU加速方法在叠加上绘制路径导致"形状路径太大而无法渲染到纹理"错误,因为纹理GPU上的大小限制). (2认同)

Aut*_*ico 5

看起来你可能遇到了GPU中的一般瓶颈.看看以下链接:

如何使路线绘图更有效率

Android画布路径实时性能

从canvas切换到OpenGL

特别是第一个,它建议你制作一个位图并绘制它.如果您更改为openGL,看起来可以获得更好的性能.可能有一些神奇的方法可以让现有的方法起作用,但我现在还没有意识到这一点.

为什么你看到你所做的行为可能是因为你在每次抽奖之间将所有数据发送到GPU.您应该将其缓存在GPU上并使用转换.不重新创建数据并将其全部发送到GPU.您可能受I/O限制,这意味着CPU和GPU之间的传输速率限制了您的性能.根据您提供的数据,我无法100%确定这一点,但这是我最好的猜测.尝试不同的缓存技术,主要是来自链接#1的png缓存.