9

次の関数は、opengl32.dll と gdi32.dll の間で重複しています。

[opengl32.dll]         / [gdi32.dll]
wglChoosePixelFormat   / ChoosePixelFormat
wglDescribePixelFormat / DescribePixelFormat
wglGetPixelFormat      / GetPixelFormat
wglSetPixelFormat      / SetPixelFormat
wglSwapBuffers         / SwapBuffers

私は長い間答えを探してきましたが、それがなぜなのか、正確な違いは何かという具体的な情報を誰も持っていないようです.

OpenGL FAQのセクション 5.190 は、これらの関数が機能的に同一ではないことを示唆しています。

OpenGL が正しく動作するようにするには、相当する wgl の wglChoosePixelformat、wglDescribePixelformat、wglGetPixelformat、wglSetPixelformat、および wglSwapBuffers の代わりに、ChoosePixelformat、DescribePixelformat、GetPixelformat、SetPixelformat、および SwapBuffers を使用します。それ以外の場合はすべて、可能な場合は wgl 関数を使用します。5 つの wgl 関数の使用は、OpenGL ドライバーにランタイム リンクする開発者にとってのみ重要です。

「OpenGL ドライバーへのランタイム リンク」は、opengl32.dll をバイパスして ICD を直接ロードすることを意味しますか?

"Mesa3D does not like my context creation code"という名前のスタック オーバーフロー スレッドは、これを強化しているようです。

C# では失敗するがマネージ C++ では失敗する wglCreateContextという名前の別のスタック オーバーフロー スレッドは、GDI 関数を使用するときに gdi32.dll の前に opengl32.dll をロードする必要があることを示唆しています。

私自身のテストでは、これらの関数の opengl32/wgl バージョンが呼び出されると、一部のシステム (Nvidia、ただし Intel または Parallels VM ではない)で「エラー: 2000」が発生することが示されています。GDI バージョンに変更すると、この問題は解消されますが、LoadLibrary("opengl32.dll") を使用しても何も変わらないようです。

これらの WGL 関数と GDI 関数の違いを調査した人はいますか? なんらかの違いがあることは明らかです。どのバージョンをどの状況で使用する必要があるか、間違ったバージョンを使用した場合の潜在的な落とし穴は何かを理解しようとしています。

編集: wayback machineは、ICD の直接読み込みがどのように機能するかを説明する Web ページを表示します。これは、2D アクセラレータと 3D アクセラレータが別々の ICD (通常の opengl32.dll+ICD メカニズムでは処理できない) を備えた 2 つの異なるハードウェアであった Voodoo 1/2 時代に明らかに必要でした。これが直接のICDです。

ただし、以下の投稿は、AMD ICD が wgl バリアントをエクスポートしないことを示しており、この考えと矛盾しています。

この知識の鍵を握っている誰かまたはどこかがそこにいるに違いありません。

編集 2: 上記の Web ページから、これまでで最も明確な提案が得られました。

「したがって、opengl32.dll という名前の OpenGL ドライバーを使用している場合は 、GDI 関数を呼び出す必要があります。opengl32.dll という名前のドライバーを使用していない場合は、GDI 関数を呼び出してはなりません。」

しかし、これは、AMD ICD が wgl 関数をエクスポートしないという事実とどのように適合するのでしょうか?

編集 2: ここで見られるように、明らかに Mesa3d は WGL シンボルをエクスポートします: http://cgit.freedesktop.org/mesa/mesa/tree/src/mesa/drivers/windows/gdi

Mesa3d は ICD として使用することを想定していないため、これは理にかなっています。これは、上にリンクされた Mesa3d スレッドのパターンに適合します。これらの呼び出しは Microsoft の opengl32.dll を介してルーティングされていないため、gdi 関数は失敗しますが、Mesa3d は wgl* 関数をエクスポートしているため、これらは引き続き機能します。ただし、これは Mesa3d に固有のものです。AMD の ICD を直接使用しようとすると、その方法は失敗します。

4

1 に答える 1

8

大きな違いがあります。つまり、WGL 関数のプロトタイプはどのシステム ヘッダーにも定義されていません。opengl32.dllはシンボルをエクスポートしますが、関数を手動でインポートしない限り、これを知ることはできません。

ただし、WGL Installable Client Drivers (ICD) が実装する関数には、実際には次のようなプレフィックスが付けられてDrvSwapBuffers (...)DrvSetPixelFormat (...)ますDrvGetProcAddress (...):wglChoosePixelFormat (...)ChoosePixelFormat (...)

opengl32.dll は基本的に Microsoft の OpenGL の GDI 実装であり、ICD のラッパーです。Mesaを見ると、ICD の実装がどのように見えるかを確認することもできます。どの関数にも接頭辞が付いていないことに注意してwglください。ICD は wgl プレフィックス付きシンボルをエクスポートしません。実装する WGL 関数はすべて拡張機能 ( wglSwapIntervalEXT (...)、など) であり、またはwglChoosePixelFormatARB (...)を使用してのみロードできます。wglGetProcAddress (...)DrvGetProcAddress (...)


AMD の OpenGL ICD を見てみましょう。

        ICD輸出

AMD が実際に EGL API を ICD に完全に実装していることに気付くでしょう (また、AMD ハードウェアで EGL を使用するために必要なヘッダーをここで取得できます) が、WGL シンボルはエクスポートされません。


アップデート:

コメントで説明されているように、gdi32.dllは実際に呼び出しwglChoosePixelFormat (...)たときに呼び出されますChoosePixelFormat (...)。関数が最初に行うことは、opengl32.dllを試してロードし、次のように呼び出すことwglChoosePixelFormat (...)です。

.text:4D579CAC ; int __stdcall ChoosePixelFormat(HDC,const PIXELFORMATDESCRIPTOR *)
.text:4D579CAC                 public _ChoosePixelFormat@8
.text:4D579CAC _ChoosePixelFormat@8 proc near
.text:4D579CAC
.text:4D579CAC hLibModule      = dword ptr -4
.text:4D579CAC arg_0           = dword ptr  8
.text:4D579CAC arg_4           = dword ptr  0Ch
.text:4D579CAC
.text:4D579CAC                 mov     edi, edi
.text:4D579CAE                 push    ebp
.text:4D579CAF                 mov     ebp, esp
.text:4D579CB1                 push    ecx
.text:4D579CB2                 push    esi
.text:4D579CB3                 lea     eax, [ebp+hLibModule]
.text:4D579CB6                 push    eax             ; int
.text:4D579CB7                 push    offset aWglchoosepixel ; "wglChoosePixelFormat"
.text:4D579CBC                 call    _GetAPI@12      ; GetAPI(x,x,x)
.text:4D579CC1                 xor     esi, esi
.text:4D579CC3                 test    eax, eax
.text:4D579CC5                 jz      short loc_4D579CD1
.text:4D579CC7                 push    [ebp+arg_4]
.text:4D579CCA                 push    [ebp+arg_0]
.text:4D579CCD                 call    eax
.text:4D579CCF                 mov     esi, eax

これは次のとおりです( opengl32.dllGetAPIをロードして、そこから名前付き関数をインポートするだけです):

                               GetAPI - gdi32.dll

ChoosePixelFormat (...)現在、ICD はすべての実装で機能的に同一であるため、実際には を実装していません。シンプルなパターンマッチング機能です。実行時にopengl32.dllがその関数の 1 つを ICD にディスパッチする方法を確認したい場合は、次wgl...の制御フローを参照してwglSwapBuffersください。

  wglSwapBuffers - opengl32.dll

赤い左側のブランチは ICD がインストールされたときに発生するもので、緑色の右側のブランチは のデフォルトの GDI 実装ですwglSwapBuffers。興味深いことに、GDI の実装には完全なglFinish (...). ほとんどのハードウェア ドライバーは、バッファーをスワップするときに終了するのではなく、コマンド キューをフラッシュする傾向があります。これにより、CPU/GPU の並列処理が向上します。

于 2013-12-17T23:18:03.037 に答える