2016-08-10 5 views
2

典型的なOpenGLの呼び出しは次のようになります。現在バインドされているバッファなどのOpenGLの状態をキャッシュする必要がありますか、とにかくOpenGLで行いますか?

GLuint buffer; 
glGenBuffers(1, &buffer); 
glBindBuffer(GL_SOME_BUFFER, buffer); 
... 

私はバッファや他の同様の機能の結合は非常に高価になることができていることを読みました。バインドする前に、現在バインドされているバッファを保存してチェックする価値はありますか?このような:

void StateManager::bindBuffer(GLenum bufType, GLuint bufID) { 
    if (this->m_currentBuffer[bufType] != bufID) { 
     glBindBuffer(bufType, bufID); 
     this->m_currentBuffer[bufType] = bufID; 
    } 
} 

これはbufIDがすでにバインドされている場合glBindBufferに高価な呼び出しが失われていることであることの背後にある考え方。これは価値あるアプローチですか?私は、OpenGLがこのような最適化をすでに実装している可能性が高いと考えましたが、このパターンは現在いくつかのプロジェクトで使用されていますので、私は疑問を抱いています。私は単に実装するのはかなりシンプルなものだから単純に興味がありますが、あまり違いがなければ、スキップします(早すぎる最適化を避ける)。

+0

あなたはこれを実装するつもりなら、あなたは*正しく*それを実装する必要があります。単一の「現在のバッファ」はありません。各 'bufType'は独自の*現在のバッファを持ちます。 –

+0

もちろん、アイデアはまだ立っています。私は投稿を編集します。 – HexCoder

+0

私は一度似たような質問をしました。しかし、回答ではそれほど満足していないので、重複としてマークしません。 http://stackoverflow.com/questions/22094960/storing-opengl-state – lisyarus

答えて

3

これはプラットフォームとベンダーによって大きく異なります。場合は、求めている

"OpenGLが実装し..."。すでにわかっているように、OpenGLはAPI仕様です。多くの異なる実装が存在し、冗長な状態の変更をチェックするかどうかは実装の決定とは完全に異なる(実装される)こともあります。

あなたも、与えられた実装が状態のすべての部分で同じ本を扱うことを期待すべきではありません。

このトピックは、過去の経験に基づいて、私の心にやや近いので、私はいくつかの暴言などの小さなエッセイを書くように誘惑されました。しかし、私はので、ここで具体的な例で冗長な状態変化のために与えられたOpenGLの実装・テストあれば影響を与える可能性検討事項のリストだけがある、それはここに属していないことを決定した:

  • それが実際に変更する方法に高価です状態?それが非常に安ければ、冗長な変更をチェックするだけではそれほど価値がないかもしれません。
  • 冗長な変更を確認するのはどれくらいの費用がかかりますか?通常はそれほど多くはありませんが、私たちはソフトウェアを少しずつ調べています。
  • 重要なアプリケーション/ベンチマークは、頻繁に重複してこの状態を重複して変更していますか?
  • アプリケーションの責任とOpenGL実装の責任の考え方は何ですか?

そして、はい、これは誰にとっても不幸です。ベンダーやプラットフォーム間で理想的なパフォーマンスを望んでいるアプリ作家として、本当に簡単な解決策はありません。コードにチェックを追加すると、OpenGL実装で同じチェックを持つプラットフォームでは、無駄になり、余分なオーバーヘッドが追加されます。あなたのコードにチェックがなく、最初にこれらの重複した状態の変化を避けることができない場合は、OpenGLの実装がチェックされていないプラットフォームのテーブルにパフォーマンスを残すかもしれません。

+0

私は参照してください。これは私が疑っていたほどのものです。 DirectXまたはVulkanのいずれかが同様の問題を抱えているかどうかを知りませんか?私は実装の特異性のためにそれらが必要であると思います。 – HexCoder

+0

@ user3183526:Vulkanは低レベルです。ある状態をコマンドバッファにバインドすると、それをバインドするコストが発生することが予想されます。 –

2

状態のキャッシングは悪い考えである理由は単純です:あなたは間違ってそれをやっています。 いつもが間違っている危険があります。

必ずああ、あなたは別のバッファバインディングが異なる状態を持っていることを、私が指摘したミスを修正。そして、キャッシュを作成したときに存在しなかった新しい拡張子がadds a new buffer binding pointであっても、検索をすばやく行うハッシュテーブルを使用している可能性があります。

しかし、それは限り特異性を結合オブジェクトとして単に氷山の一角です。例えば

、あなたはGL_ELEMENT_ARRAY_BUFFERが実際にコンテキスト状態ではないことを実感しましたか?それは実際にはVAO状態であり、新しいVAOをバインドするたびに、そのバッファーバインディングが変更されます。したがって、VAOキャッシュはシャドーされた要素バッファーのバインディングも変更する必要があります。

また、オブジェクトを自動的に削除すると、は現在バインドされているすべてのコンテキストバインディングポイントからバインド解除されます。これは、コンテキストにバインドされた別のオブジェクトにアタッチされているオブジェクトであっても当てはまります。削除されたオブジェクトは自動的に切り離されます。

これは、特定のオブジェクトタイプための唯一の真実であることを除いて。そして、それでも、オブジェクトが削除されたときのの現在のコンテキストの場合は、です。他の文脈は影響を受けない。

私のポイントはこれです:状態の適切なキャッシングが本当に難しいです。あなたが間違っている場合は、あなたのアプリケーションに非常に微妙なバグの多くを作成します。一方、OpenGLが複数のバインディングが単純に起こらないように、OpenGLにコードを組み立ててもらうと、問題はありません。

+0

私は参照してください。しかし、現在バインドされている 'GL_ELEMENT_ARRAY_BUFFER'は、別の' vao'がバインドされたときに自動的にバインドされます。その場合、スピードを上げることはできませんが、バグは発生していません。 2番目の例では、何かが削除されたときに現在のキャッシュ設定を無効な数値(バッファの場合は0)に設定して、次のオブジェクトが無関係にバインドされるようにすることはできません。どちらの方法でも、指定されたバッファタイプでそれが起こらない場合は、最悪の場合、それを2倍以上バインドしています。これは問題ではありません。 – HexCoder

+0

@ user3183526: "*その場合、スピードを上げることはできませんが、バグはありません。" VAO Qがバインドされている間にバッファAをバインドするとしましょう。その後、バッファーBを使用するVAO Rに切り替えます。そして、バッファーAをバインドしようとします。キャッシュは、Aが*既にバインドされていると考えるので、再度バインドしません。これは、VAO RがバッファAを使用するように変更したいときにバッファBを使用していることを意味します。 –

+0

"何かが削除されたときには設定できません。しかし、私の全体的なポイントはこれです:前にこの問題を認識していたのですか?どのようにこれらの問題をすべて発見したのか、あなたはどのように確信できますか?そしてもしあなたが*確実でないなら、それは信頼できません。壊れたコードは、パフォーマンスの低いコードよりも悪いです。 –

関連する問題