このジオメトリシェーダーがプログラムをそれほど遅くするのはなぜですか?


27

OpenGLプログラムを使用しており、地形メッシュをレンダリングしています。頂点バッファーで頂点を移動しますが、フラグメントシェーダーではまだ実際に色付けしていません。ジオメトリシェーダーを1つずつ追加します。

ジオメトリシェーダーを追加する前に、パイプラインのフラグメントと頂点のシェーディングステップをプログラミングしていたとき、約30+のフレームレートを取得していました。ちょっぴり気付かないくらいでした。ジオメトリシェーダーを追加すると、1秒あたり約5フレームになります。どうして?これは、ジオメトリシェーダー全体です。

#version 420

layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

void main()
{
    for (int i = 0; i < gl_in.length(); i++)
    {
        gl_Position = gl_in[i].gl_Position;
        EmitVertex();
    }
    EndPrimitive();
}

これは、ジオメトリシェーダーなしでOpenGLが行っていたこととまったく同じではありませんか?

回答:


40

これは、ジオメトリシェーダーなしでOpenGLが行っていたこととまったく同じではありませんか?

いいえ、そうではありません。GSはオプションのステップであり、デフォルトのステップではありません。

OpenGLがジオメトリシェーダーを実行するには、「プリミティブアセンブリ」と呼ばれるものを実行する必要があります。を使用して一連の三角形をレンダリングするとGL_TRIANGLE_STRIP、OpenGLは内部の処理を実行して、隣接する3つの頂点ごとに個々の三角形に変換し、ワインディングの順序を適切に変更します。

通常、GSを使用しない場合、このプロセスは1回実行されます。ただし、GSを使用する場合は、GSを実行する前に実行する必要があります。ただし、GSはまったく異なるプリミティブタイプ(クワッドなど)を出力できるため、GSのに実行する必要もあります。

だから今、あなたはシステムに基本的に無料でたくさんの余分な仕事をさせています。結局のところ、OpenGLはGSが何もしていないと仮定することはできません(これは決定できない問題です)。

さらに、GSが存在する場合、多くの最適化が機能しなくなります。インデックス付きレンダリングを検討してください。

要素配列バッファーの各インデックスは、頂点シェーダーから同じ出力を生成します。そのため、GPUはこれらの出力をT&L後のキャッシュにキャッシュすることがよくあります。すでにキャッシュ内にあるインデックスが見つかった場合、VSは再度実行されません。キャッシュからデータを取得するだけです。

それは何ですか"?「それ」は... プリミティブアセンブリユニットです。GSを使用すると2回実行されることです。インデックスキャッシングのもの?GS の入力に対してのみ機能します。

では、GSの出力はどうなりますか?まあ、それはハードウェアに依存しています。しかし、それは何らかの種類のメモリバッファに入る必要があります。そして、そこに問題があります。そのバッファはまったくインデックス付けされていません。glDrawArraysのような状況です。

したがって、のインデックスバッファを送信すると0, 1, 2, 0, 2, 3、T&L後のキャッシュで4つの頂点に変換されます。ただし、GS後の頂点バッファーには、6つの頂点が含まれています。ポストGSバッファはより多くのスペースを使用します。したがって、T&L後に最適化された三角形のリストまたはストリップを適切に作成する問題を経験し、パススルーGSを自分のようにひっくり返すと、基本的にその最適化によるパフォーマンスの約半分が失われます。

役に立たなかったわけではありませんが、痛いです。

これに加えて、多くのGL 3.xクラスGPU(別名:DX10)にはかなり小さなGS後のバッファーがありました。バッファが小さいほど、同時にアクティブにできるGS呼び出しが少なくなります。したがって、GSでハードウェアが効果的にボトルネックになります。テッセレーションは4.xクラスのハードウェアの大きな機能であるため、このようなハードウェアのほとんどは、GSをより重いものに使用するのに十分なバッファーを備えています。

そのため、GSを使用すると、コードの頂点処理がボトルネックになる可能性が高くなります。もちろん、頂点シェーダーとフラグメントシェーダーをより複雑にすることで、その時点での無料のパフォーマンスであるため、いつでもそれを有利に使用できます。

GSによるスローダウンの詳細については、この記事を参照してください

ここでGSの程度親指の基本的なルールは次のとおりです。あなたはそれをレンダリングするようになりますと思うので、GSを使用することはありません速いです。あなたがしようとしていることを可能にするとき、あなたはそれを使うべきですしようとしていることが最適化である場合は、別のものを使用します。

これの一般的な例外は次のとおりです。


最高の高さを取り、最低の高さを差し引くことで、各ポリゴンの急勾配を計算しようとしています。ただし、ジオメトリシェーダーが必然的にこの量だけ遅くなる場合は、頂点シェーダーで創造的に行うことができると思います。
アヴィ

1
@Aviは、三角形の最高点と最低点では急峻性が得られないことに注意してください。3つのポイントすべてが必要です。
サムホセバー

2
個人的には、GSよりもポイントスプライトの方がインスタンス化の方が便利だといつも思っています。
マキシマスミニマス

1
ポイントスプライトの例外は、シェーダーに一般化されますlayout(points) in;か?それとも、固定出力サイズですか?またはおそらく両方?
フィリップ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.