GeForce/RADEON で OpenGL ES 2.0 を動かす

OpenGL ES 2.0 を使う機会が増えています。
iOS や Android 等のモバイル機器をはじめ、デスクトップ環境でもサポートが始まりました。
これまでモバイル向けに書いたコードを PC 上で走らせる場合 2つの選択肢がありました。

 (1) GPU / OS が提供する OpenGL ES 2.0 エミュレータ
 (2) 自分で OpenGL との相互変換を行う

ここに新たに 3番目

 (3) デスクトップ GPU の OpenGL ES 2.0 プロファイル

が加わります。

● (1) GPU / OS の OpenGL ES 2.0 エミュレータ

多くの場合 OS や GPU 毎にツールとして EGL/GLES2.0 エミュレーション用の
互換ライブラリが提供されています。

OpenGL ES 2.0 Emulator

テクスチャフォーマットなど特殊な機能にも対応しており、ターゲットが一致して
いれば高い互換性が保てます。
あくまでエミュレーション用なのでそれ以上の用途には向きません。
開発ツールで利用していてもパフォーマンス不足を感じたり、プラグインから
呼び出す場合 64bit 非対応が問題になったりします。
デスクトップ GPU のドライバとの相性もあります。

● (2) 自分で OpenGL との変換を行う

OpenGL 自体もともと互換性が高いので、OpenGL と OpenGL ES の違いはそれほど
大きくありません。
うまくライブラリを作れば、比較的薄いレイヤーで両者の違いを吸収することができます。
完全に同じ API ではないので保守性は落ちます。
例えばシェーダーも GL 用と GLES 用 2セット管理することになります。

● (3) デスクトップ GPU の OpenGL ES 2.0 プロファイル

OpenGL 4.1 では公式に OpenGL ES 2.0 プロファイルに対応しました。
ドライバが対応していればそのまま OpenGL ES 2.0 API を用いることが可能です。

NVIDIA GeForce GTX 400 シリーズは 4.1 対応ドライバを公開しており
「GL_ARB_ES2_compatibility」が含まれています。

OpenGL 4.1 Driver

GeForce GTX460 に対応ドライバを入れて GLES/gl2.h ヘッダのみで描画できることを
一応確認しました。

 ・EGL は無いので WGL をそのまま使う
 ・拡張 API 同様に必要な API の関数アドレスを自分で取り出す

GLES 2.0 のヘッダ gl2.h はそのままプロトタイプ宣言が記述されていて、
関数ポインタ型の定義が無い点は注意が必要です。
この辺の関数宣言ヘッダを自分で用意する必要があります。
GL1.1 gl/gl.h はそのまま使えるため、存在しない API のみ取り出すことになります。
シェーダー周りなどはまだ詳しく調べていません。

同じように AMD/ATI RADEON も Catalyst 10.8 より OpenGL ES 2.0 に対応しています。
OpenGL 4.1 プロファイルではなく独自に API エントリを求める仕様となっているようです。

OpenGL ES 2.0 Coming to a Desktop Near You

上のサンプルを見ると、最初に dll から EGL を取り出し、さらに eglGetProcAddress()
を使って OpenGL ES 2.0 API アドレスを読みだしています。

 ・EGL が用意されており、専用の EGL API を用いる
 ・使用する API の関数ポインタをすべて取得する

こちらも関数のヘッダ定義を自分で用意する必要があります。
gl2.h のプロトタイプ宣言と衝突する可能性があります。

今まで各種 GPU の GL ES2.0 Emulator や NetWalker 等で共通に走らせていた
EGL + GLES2.0 のコードがそのまま走りました。使用したのは RADEON HD 5850

GL_VERSION: OpenGL ES 2.0 10151 Release
GL_RENDERER: ATI Radeon HD 5800 Series 
GL_VENDOR: Advanced Micro Devices, Inc.
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 1.0.17

気がついたことなど

・eglGetDisplay() は EGL_DEFAULT_DISPLAY を渡す
・eglCreateWindowSurface() を複数作れないなど EGL の実装の制限がある

eglGetDisplay() は実装により HDC を用いるものと EGL_DEFAULT_DISPLAY (NULL)
が必要なものと二通りあります。今回は後者で、これらの動きは以前公開されていた
ATI 版の OpenGL ES 2.0 Emulator によく似ています。

参考にしたサンプルでは “atioglxx.dll” をロードしていますが、そのままでは
x64 で動作しません。64bit の場合 “atio6axx.dll” にします。

それぞれ GL ES 2.0 が走りました。
ドライバが標準対応することで扱いは容易になるはずですが使い方がばらばらです。
最終的には 4.1 での統一が望まれます。

関連エントリ
OpenGL 4.1 GeForce GTX 460
NetWalker PC-Z1 のその後と OpenGL ES 2.0 Emulator
OpenGL ES 2.0 Emulator
OpenGL ES 2.0 まとめ