0

FBO で浮動小数点テクスチャにレンダリングし、CPU 上のそのテクスチャのすべてのピクセルの平均値が必要です。したがって、ミップマッピングを使用して平均を計算して 1x1 ミップマップにするのは非常に便利だと思いました。CPU の計算時間を節約し、1024x1024 ピクセルの代わりに 1 ピクセルを CPU に転送するだけでよいからです。

だから私はこの行を使用します:

glGetTexImage(GL_TEXTURE_2D, variableHighestMipMapLevel, GL_RGBA, GL_FLOAT, fPixel);

ただし、常に 1x1 ピクセルのサイズである最高のミップマップ レベルのみを具体的に要求しているにもかかわらず、そのコード行が完了するまでにかかる時間は、テクスチャのレベル 0 ミップマップのサイズによって異なります。これは私には意味がありません。たとえば、私のテストでは、この行は 1024x1024 のベース テクスチャの場合、32x32 のベース テクスチャの場合よりも約 12 倍長くかかります。

fPixel の結果は正しく、必要なピクセルのみが含まれていますが、時間はテクスチャ セット全体が転送されたことを明確に示しています。これは、CPU への転送が明らかにボトルネックであるため、私の主な理由を殺します。

私は Win7 と opengl を使用し、これを ATI Radeon HD 4800 と GeForce 8800 GTS でテストしました。

誰もその問題について何か知っていますか、または最高のミマップの1ピクセルのみをCPUに転送するスマートな方法を持っていますか?

4

1 に答える 1

3
glGenerateMipmap( GL_TEXTURE_2D );
float *fPixel = new float[4];
Timer.resume();
glGetTexImage(GL_TEXTURE_2D, highestMipMapLevel, GL_RGBA, GL_FLOAT, fPixel);
Timer.stop();

これをあなたへの教訓にしましょう:常に完全な情報を提供してください。

12倍長くかかる理由は、ミップマップをCPUに転送するのにかかる時間ではなく、ミップマップの生成にかかる時間を測定しているためです。glGenerateMipmap、ほとんどのレンダリングコマンドと同様に、実際には、戻るまでに終了していません。確かに、それが始まってさえいない可能性は高いです。OpenGLをCPUから独立して実行できるため、これは優れています。レンダリングコマンドを発行すると、しばらくしてから完了します。

ただし、そのテクスチャから読み取りを開始した瞬間、OpenGLはCPUを停止し、そのテクスチャに接触するすべてのものが終了するまで待機する必要があります。したがって、タイミングは、テクスチャに対してすべての操作を実行するのにかかる時間と、データを転送するのにかかる時間を測定しています。

より正確な測定が必要な場合は、タイマーを開始するglFinish 前にaを発行してください。

さらに重要なことに、ピクセルデータの非同期読み取りを実行する場合は、バッファオブジェクトへの読み取りを実行する必要があります。これにより、OpenGLはCPUストールを回避できますが、それまでに実行できる他の作業がある場合にのみ役立ちます。

たとえば、HDRトーンマッピングのシーンの全体的な照明を把握するためにこれを行う場合は、現在のフレームではなく、前のフレームのシーンデータに対してこれを行う必要があります。誰も気付かないでしょう。したがって、シーンをレンダリングし、ミップマップを生成し、バッファオブジェクトに読み込み、次のフレームのシーンをレンダリングし、ミップマップを生成し、別のバッファオブジェクトに読み込み、前のシーンのバッファから読み込みを開始します。

そうすれば、前回の読み取り結果を読み始めるまでに、それらは実際にそこにあり、CPUストールは発生しません。

于 2012-09-25T16:51:32.010 に答える