ネタバレ: 私は答えがNO
であるとかなり確信していますが、それは非常に苛立たしいデバッグの 1 日後のことです。それが実際に当てはまるかどうか(もしそうなら、私がどのように知っていたのか)、それとも完全に間違ったことをしているだけなのかを知りたいです。
これが状況です。OpenGL ES 2.0 を使用して、さまざまなファイル (.obj、.md2 など) からロードしたメッシュをレンダリングしています。パフォーマンスとユーザー エクスペリエンスのために、これらのメッシュとそれに関連するテクスチャの実際の読み込みを、GCD を使用してバックグラウンド スレッドに委譲します。
Appleの 指示に従ってshareGroup
、各バックグラウンド スレッドで、メイン レンダリング コンテキストと同じ新しい EAGLContext を作成して設定します。これにより、バックグラウンド スレッドで作成されたテクスチャやバッファ オブジェクトなどの OpenGL オブジェクトを、メイン スレッドのコンテキストですぐに使用できます。
これは見事にうまくいきました。最近、特定のバッファーのコンテンツのレンダリングに関連する OpenGL の状態をキャッシュする方法として、Vertex Array Objectsについて学びました。見栄えが良く、各メッシュのレンダリングに必要なボイラープレートの状態チェックと設定コードを減らします。さらに、Apple は、Vertex Dataガイドのベスト プラクティスでそれらを使用することも推奨しています。
しかし、VAO を機能させるには深刻な問題がありました。すべての読み込みと同様に、バックグラウンド スレッドでメッシュをファイルからメモリに読み込み、関連するすべての OpenGL オブジェクトを生成します。glDrawElements()
必ず、 VAO を使用して初めて呼び出しを試みたときに、アプリがクラッシュしEXC_BAD_ACCESS
ます。VAO がなければ、問題なくレンダリングされます。
デバッグEXC_BAD_ACCESS
は、特に NSZombies が役に立たない場合 (明らかに役に立たない場合) は苦痛ですが、キャプチャされた OpenGL フレームをしばらく分析した後、バックグラウンド スレッドでの VAO の作成は問題なく行われていることに気付きました (いいえGL_ERROR
、.およびゼロ以外の id)、メイン スレッドで VAO にバインドするときが来ると、存在しない VAO にバインドしようとすると、ドキュメントの状態が発生しGL_INVALID_OPERATION
ます。確かに、レンダリング時に現在のコンテキスト内のすべてのオブジェクトを見ると、単一の VAO は表示されませんが、VAO AT THE SAME TIMEで生成されたすべての VBOが存在します。メイン スレッドに VAO をロードすると、正常に動作します。とてもイライラします。
読み込みコードをよりアトミックな形式に抽出しました。
- (void)generate {
glGenVertexArraysOES(1, &_vao);
glBindVertexArrayOES(_vao);
_vbos = malloc(sizeof(GLuint) * 4);
glGenBuffers(4, vbos);
}
EAGLContext
上記がメイン コンテキストと同じ有効なバックグラウンド スレッドで実行されるとshareGroup
、メイン コンテキストには 4 つの VBO がありますが、VAO はありません。メイン スレッドでメイン コンテキストを使用して実行すると、4 つの VBO と VAO が作成されます。EAGLContext
これにより、VAO を扱う場合の s のオブジェクト共有の性質には奇妙な例外があるという結論に至ります。もしそうなら、私はAppleのドキュメントがどこかにそれを指摘することを本当に期待していたでしょう. そのようなちょっとした情報を手で発見しなければならないのは非常に不便です。これは事実ですか、それとも何か不足していますか?