web-dev-qa-db-ja.com

OpenGLの設計は悪いですか?

私はOpenGLとOpenGL ESを長い間使用しており、それらをかなりよく知っています。また、使用するのが非常に面倒であり、これがどこで議論されているのか、私は実際に見たことがありません。ここに私が気づいた悪いデザインのいくつかの例があります:

  • どこでもグローバルな状態。すべての機能には状態があり、多くの場合、暗黙的で、時には非表示になります。ドキュメントを詳細に読まなければ、どの値がどの州に合法であり、何がそれに影響を与えるかを理解するのは困難です。これらはグローバルであるため、シングルスレッドプログラムであってもデバッグするのは悪夢です。
  • エラー処理は、おそらく私がこれまでにどのフレームワークでも見た中で最悪のものです。エラーは手動でハードウェアの制限をチェックする必要があるという事実を考慮して、スライドさせてみましょう。ただし、エラーフラグは2つしかありません。これらのフラグは、多くの場合、単一の関数のコンテキスト内で複数回使用されてさまざまなことを示し、その理由を推測する以外に選択肢はありません。エラーの「スロット」は1つしかないので、すべての関数の後でチェックしないと、チェックの前にエラーが複数あるとエラーが失われるため、関数の最後まで正しく到達することはありません。
  • 関数のシグネチャは直感に反して誤解を招くことがよくあります。任意の数を取る引数ですが、実際には有効な値は2つだけです。有効な値が1つしかない列挙型引数(glTexImage2Dのborder = 0など)があるため、なぜそこにあるのか疑問に思います(APIの将来のバージョンとの互換性?いいえ、他の値を受け入れるように変更されることはありません)。いずれにせよ、1種類の値しか処理できない関数が受け入れる冗長な列挙型(3Dテクスチャでのみ機能する関数のGL_TEXTURE_3Dなど)。
  • ほとんどすべてを行うために必要な拡張機能。サポートされている拡張機能についてGPUにクエリを実行するのは非常に困難です。
  • GlGenTextures/glCreateTexturesなど、実際には非常に異なる機能を実行する関数の誤解を招くような類似の関数名
  • フレームバッファの完全性に関する曖昧で難解なルール(たとえば、テクスチャにレンダリングする場合など)。ドキュメンテーションを詳細に読まないと、フレームバッファが不完全であると考えられる理由を理解できない状況に日常的に遭遇します。これは、前述のエラー処理がひどいことであり、エラーコードはさまざまなエラーによって共有されるため、さらに悪化します。添付ファイルの完全性ルールを読んで、badがどのようになっているかを理解してください。また、どのフレームバッファアタッチメントが悪いのかについてのフィードバックもありません。
  • 固定機能パイプラインは、シェーダーを備えた新しいパイプラインと混合でき、巨大な混乱につながる
  • コンパイル時にエラーの種類をチェックすることは絶対にありませんが、ほとんどの場合、これはハードウェアに依存していると思います
  • 冗長な機能がたくさんあります(glUniformまたはglGetのバリエーションがいくつあるか見てください)

これらすべて、および他の多くの欠陥により、OpenGLは問題ないようです。それは非常に人気があり、モバイルデバイスを支配し、活発な開発が行われており、あらゆる種類のGPUでサポートされています。どうして?なぜこれがすべて許容されるのか、そして最も重要なのはなぜこのように設計されたのか? GPUは非常に特殊なデバイスであり、CPU、GPU、メモリなどの間の通信には一定の制約が必要であることは知っていますが、ほとんどの場合、回避できる設計の誤りが原因であるようです。

2
nukeop

それは非常に人気があり、モバイルデバイスを支配し、活発な開発が行われており、あらゆる種類のGPUでサポートされています。どうして?

さて...あなたの代わりは何ですか?

Vulkanを無視して、モバイルデバイス用のクロスプラットフォームアプリケーションを作成し、ハードウェア3Dを使用したい場合、正確に何を使用しますかexceptOpenGL ES?

OpenGLが賢明でよく設計されたAPIであると(少なくとも最近は)誰も主張していません。しかしそれは機能します;それは仕事を成し遂げ、広く利用可能なクロスプラットフォームの代替手段はもうありません。


そして、いくつかの事実確認のために:

エラーの「スロット」は1つしかないので、すべての関数の後でチェックしないと、チェックの前にエラーが複数あるとエラーが失われるため、関数の最後まで正しく到達することはありません。

それは誤りです。 OpenGLのエラーはqueuedです。 glGetErrorを呼び出すたびに、キューに最後に追加されたエラーが返されます 。 OpenGLエラーはOpenGLで失われません。

妥当な頻度でエラーをチェックしないことの問題は、チェックしないと、どの関数がどのエラーの原因であるかを知ることが難しいことです。

glTexImage2Dのborder = 0など

これは、GL 3.1より前のテクスチャがボーダーテクセルを持つ可能性があるために存在します。しかし、コンシューマーグレードのハードウェアはボーダーテクセルをサポートしていないため、3.1でコアOpenGLから削除されました。ただし、関数からパラメーターを単に削除することはできません。それはあちこちでABIを壊します。したがって、彼らは最小の抵抗の経路をたどりました:パラメータを保持しますが、それがゼロであることを要求しました。

ESは、デスクトップOpenGLとのAPI互換性を維持するためにそれを保持しました。

一般に、OpenGL APIのほとんどすべての煩わしさは、最終的にはある程度の「下位互換性があるため」になります。

コンパイル時にあらゆる種類のエラーをチェックすることは絶対にありません

OpenGLはC APIです。 Cには、コンパイル時の検証を行う余地があまりありません。

5
Nicol Bolas