2016-08-31 11 views
0

私は(MacBook Proの網膜)比較的新しいマシン上でそれをしようとしたときglUseProgramが遅いのはなぜですか?

すべてがうまく働いていたOS X上でGLSLを使用して、異なるデバイスに異なるオーバーレイの数の映像をレンダリングすることができ、ビデオアプリケーションを書いてきましたしかし、私は今は古いマシン(MacPro 4,1、Nvidia GT 120)を持っており、ボトルネックに陥っています。私は解決策を見つけることを望んでいます。

私のアプリケーションは、基本的にテクスチャと単純なプリミティブをレンダリングします。私は別の仕事をするシェイダーをいくつか持っています。テクスチャを描画するために1つ、円を描画するために1つ、バーを描画するために1つ...基本的に、フレームバッファにレンダリングすることによってglUseProgram()を使用してシェーダを順番に適用しています。

ほとんどの場合、レンダリングパスごとに実行は非常に高速ですが(< 5ミリ秒)、時には3〜4個のデバイスにサービスを提供しているときに20ミリ秒以上かかることがあります。フレームあたり24fps = 41.6667ms。

問題は、現在のコンテキストとしてコンテキストを設定した直後にglUseProgramを呼び出すことであることがわかりました。ここでは、コードがあります:

CGLSetCurrentContext(device.renderingContext); 
CGLLockContext(device.renderingContext); 
// Setting and locking the context sometimes causes an inevitable GL error. 
// We must clear the error here to enable proper error checking below. 
glGetError(); 

[device bindFramebuffer]; 
GetError(); 

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 
glClear(GL_COLOR_BUFFER_BIT); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

glViewport(0.0f, 0.0f, deviceSize.width, deviceSize.height); 

glUseProgram(self.texApplyShader.program); 
GetError(); 

誰もこれが原因で、なぜそれが唯一の散発的に起こることができるかを教えてもらえますか?私の描画方法は理にかなっているのですか、それを一台のシェーダで行うのが良いでしょうか?

編集: 私はfreenodeのIRC上でいくつかのOpenGLの男と話をしてきたし、彼らはglUseProgramは自分自身を呼び出す可能性があることを教えてくれました。彼らは確かに正しいです。 OpenGLパイプラインは、シェーダを切り替える前に待機しているようです。 glFinish()コールをglUseProgram()の前に置き、今度はglFinish()が常にかかります。私はパフォーマンスのリークを見つけるためにさらに見ていきます。

+1

どのようにタイミングを特定しましたか?一般に、OpenGLはアプリケーションと非同期で動作するため、各コマンドの実行時間を実際に識別することはできません。 'glUseProgram'の前にいくつかの他のコマンドを実行する必要があるかもしれません。 'GetError'が' glGetError'を呼び出すと仮定すると、すべてのglGet *コマンドがパイプラインをフラッシュするので、これは間違いなくパフォーマンスの問題です。 – BDL

+2

一方、現代のGPUでは、シェーダプログラムを変更することは、できるだけ高価な状態変更(ターゲットフレームバッファを最初に変更すること)が可能です。このNVIDIAプレゼンテーションの[スライド48](http://www.slideshare.net/CassEveritt/beyond-porting)を参照してください(絶対数は関係ありません、そのグラフの形があります)。 – peppe

+1

@BDL:タイマークエリを使用すると、コマンドの所要時間を計測できますが、それ以外の場合は推測できます。たとえば、GLの実装では、バッファスワップが発生したときではなく、バックバッファを変更する最初のコマンドが発行されたときにVSYNCのブロッキングを遅延させる可能性があります。コマンドそのものが異常に遅く、避けたいものだと間違って信じているかもしれません...私はGLの暗黙的な同期*の動作が問題であると言います。ドライバは、それだけで知られている理由から、いくつかのコマンドをブロックします。 –

答えて

1

ここで、私は教育的に推測された推測を行っています。万一、そのシェーダーと組み合わせて均一な値や属性のバインディングを変更していませんか? NV GT120はかなり古いGPUです。そのマシンのドライバが古いものであれば驚くことはありません。特定の状況では、シェーダは現場で再コンパイルされます(現代のドライバであっても)。古いNVidiaドライバは、一様な値変更のような単純なものが発生した場合、特にシェーダの再コンパイルが発生しやすくなりました。たぶんそれはあなたのしゃっくりを引き起こす原因です。

+0

残念なことに、macOSは 'GL_KHR_debug'を公開しませんが、他のOSではNVIDIAドライバが低優先度のデバッグメッセージを介してこのことを通知します。 – peppe

1

私は、glUseProgram呼び出し自体はそれほど長くはかかりませんでしたが、前のglReadPixels操作が完了するのを待っていることがわかりました。

ヒントのため、glGetErrorとglClear呼び出しを削除することで、パフォーマンスをさらに向上させることができます。ありがとう!

関連する問題