web-dev-qa-db-ja.com

描画パスとハードウェアアクセラレーション

私の考えではかなり大きな道を描いていて、パフォーマンスの問題に直面しています。パスは現在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_を使用してビューを描画するのにかかる時間を、ハードウェアアクセラレーションの有無にかかわらず測定しましたが、ハードウェアアクセラレーションの方がはるかに遅いと思います。

ハードウェアアクセラレーションあり:

enter image description here

ハードウェアアクセラレーションなし:

enter image description here

ハードウェアアクセラレーションバージョンは、フレームあたり約200〜300ミリ秒かかり、ほとんどがプロセスステージで費やされます。非加速バージョンは約50ミリ秒かかり、2/3が描画ステージにあり、1/3がプロセスステージにあります。

明らかに、ハードウェアアクセラレーションを使用しない高速バージョンでも、60 fpsを達成するには遅すぎるか、大きなデータセットに移動してもほとんど使用できません。

ビットマップへのパスをレンダリングし、そのビットマップのみを画面に合わせて変換するという考えも、私の場合問題があります。パスへの非常に遠くのズームインをサポートする必要があり、パスの品質を大幅に低下させずにズームインを有効にするには、パスの特大のビットマップをレンダリングする必要があります(メモリ制限とテクスチャサイズの制限に達する可能性があります)。そして、遠くにズームインするときは、パスの一部のみの新しい画像を作成するか、パスを直接レンダリングするだけに切り替える必要があります。これは、パフォーマンスが私が持っているものと同じである場合、フレームレートよりも大きな遅延につながる可能性があります。今。

私が今思っているのは

  • 線/パスの描画はGPUの欠点であり、ハードウェアアクセラレーションを試みるべきではありませんか、それともパフォーマンスの低下を引き起こすような何か間違ったことをしているのでしょうか?
  • 許容できるパフォーマンスでそのような巨大なパスを描画するために私ができることはありますか?
36
Mad Scientist

線/パスの描画はGPUの欠点であり、ハードウェアアクセラレーションを試みるべきではありませんか、それともパフォーマンスの低下を引き起こすような何か間違ったことをしているのでしょうか?

パスは常にCPUを使用してレンダリングされます。アプリがハードウェアアクセラレーションされている場合、レンダラーは最初にCPUを使用してパスをビットマップに描画し、次にそのビットマップをテクスチャとしてGPUにアップロードし、最後に画面にテクスチャを描画します。

ラインは完全にハードウェアアクセラレーションされています。この場合、Pathを使用する代わりにCanvas.drawLines()を使用することをお勧めします。

許容できるパフォーマンスでそのような巨大なパスを描画するために私ができることはありますか?

Canvas.drawLines()を使用するか、自分で管理するBitmapにパスを自分でレンダリングする必要があります。

49
Romain Guy

GPUで一般的なボトルネックが発生しているようです。次のリンクをご覧ください。

ルート描画をより効率的にする方法

Androidキャンバスパスのリアルタイムパフォーマンス

キャンバスからOpenGLへの切り替え

特に最初のものは、ビットマップを作成し、代わりにそれを描くことを示唆しています。 openGLに変更すると、パフォーマンスが向上するようです。既存のメソッドを機能させる魔法の方法があるかもしれませんが、私は現時点ではそれを知りません。

動作を確認する理由は、各描画の間にすべてのデータをGPUに送信するためです。 GPUにキャッシュして、代わりに変換を使用する必要があります。データを再作成してすべてをGPUに送信しない。あなたはおそらく I/Oバウンド です。これは、CPUとGPUの間の転送速度がパフォーマンスを制限していることを意味します。あなたが提供したデータに基づいてこれを100%確信することはできませんが、それが私の推測です。さまざまなキャッシング手法を試してください。主にリンク#1のpngキャッシュです。

5
Automatico

パスを描くには、GPUを「伝える」だけで線を引くのではありません。パスには多くの特性があります。たとえば、線の端がどのように処理されるか、または線が点線で示される、not GPUアクセラレーションなどです。 CPUとGPUアクセラレーションの組み合わせを遅くする多くの行に遭遇すると、おそらくanotherヒックアップが発生します。 canvas.drawLinesの代わりにcanvs.drawPathに移動し、派手なPaintメソッドを使用しないようにする上記の推奨される解決策が役立つ場合があります。

それでも問題が解決しない場合は、GLSurfaceViewを使用して、ラインを直接レンダリングしてみてください。これにはOpenGL ESの知識が必要になりますが、信じられないほど難しくはなく、はるかに効果的です。

3