ANGLEとは
ANGLE(Almost Native Graphics Layer Engine)は、OpenGL ES API呼び出しを各プラットフォームで利用可能なハードウェアでサポートされたAPIの1つに変換してくれる。最初はWindowsでWebGLレンダリングする方法として始まったらしい。現在のサポートはこちらで確認できる。
目標
Windowsで、OpenGL ESをそのままVulkanで実行できるようにしたい。
必要なツール(2021年8月時点)
VisualStudio 2019、Windows 10SDK、Python3.9、GLFW、ANGLE、chromiumのdepot_tools
導入手順
1 gclientやGN、ninjaが使えるように、depot_toolsをこちらからダウンロードする
2 depot_toolsへのパスを通す(※ここではPythonのパスより前に設定する)
3 VisualStudio 2019、Windows 10 SDKが利用可能か確認
4 ソースを取得する
set DEPOT_TOOLS_WIN_TOOLCHAIN=0 git clone https://chromium.googlesource.com/angle/angle cd angle python scripts/bootstrap.py gclient sync git checkout master
5 ninjaビルド用のディレクトリを作成する
gn gen out/Debug
ここではビルド前に様々なビルドオプションを設定することが可能。
6 ninjaでビルドする(時間がかかります)
autoninja -C out/Debug
ここではVisual Studioソリューション生成して、ビルドすることも可能。
7 out/Debugに以下のライブラリが生成されていることを確認
libEGL.dll
libEGL.dll.lib
libGLESv2.dll
libGLESv2.dll.lib
8 GLFWをダウンロード
ドキュメントによると、ANGLEのバックエンドをVulkanに変更するにはEGL拡張のEGL_ANGLE_platform_angleを使えばよい。eglGetPlatformDisplayEXT(EGLenum platform, void native_display, const EGLint attrib_list) のようにして設定することが可能で、ANGLE内にサンプルコードもある。しかしGLFWを使っている場合は初期化の前に以下のように設定するだけで簡単にバックエンドを変更できる。
glfwInitHint(GLFW_ANGLE_PLATFORM_TYPE, GLFW_ANGLE_PLATFORM_TYPE_VULKAN);
参考
自分が確認したところ、GLFWのWindowsパッケージではANGLEがサポートされていないようだったので、GLFWのmain branchから直接cloneしてコンパイルした。
9 Visual Studio 2019でプロジェクト作成&ANGLEから必要なものを持ってくる。自分は以下のように配置した
AngleTest └main.cpp .sln lib ├GLES2 ├include └ANGLEのincludeの中身 └lib └x64 └libGLESv2.dll.lib、libEGL.dll.lib └GLFW x64 └Debug └.exe
アプリケーションと同じ階層に以下の.dllファイルを配置する
libEGL.dll
libGLESv2.dll
absl.dll
libc++.dll
VkLayer_khronos_validation.dll
vulkan-1.dll
zlib.dll
10 Additional Include/Library Directory と Additional Dependenciesを以下のように設定する
Additional Include Directories
..\lib\GLFW\include
..\lib\GLES2\include
Additional Library Directories
..\lib\GLFW\lib
..\lib\GLES2\lib\x64
Additional Dpendencies
glfw3.lib
libEGL.dll.lib
libGLESv2.dll.lib
11 テスト用のOpenGL ESは以下の通り
#include <iostream> #define GLFW_INCLUDE_ES3 #define GL_GLEXT_PROTOTYPES #include "GLFW/glfw3.h" int main(){ int Width = 800; int Height = 600; //バックエンドにVulkanを選択 glfwInitHint(GLFW_ANGLE_PLATFORM_TYPE, GLFW_ANGLE_PLATFORM_TYPE_VULKAN); if (glfwInit() == GL_FALSE) { throw std::runtime_error("failed to init GLFW"); } glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); auto window = glfwCreateWindow(Width, Height, "App", nullptr, nullptr); if (!window) { throw std::runtime_error("failed to create Window"); } glfwMakeContextCurrent(window); glfwSwapInterval(1); while (glfwWindowShouldClose(window) == GL_FALSE) { glfwPostEmptyEvent(); glViewport(0, 0, Width, Height); glClear(GL_COLOR_BUFFER_BIT); glClearColor(0.f, 0.f, 0.5f, 1.f); glfwSwapBuffers(window); glfwWaitEvents(); } glfwDestroyWindow(window); glfwTerminate(); return -1; }
12 Vulkanで動いているか確認したいのでRenderDocを使う
デフォルトではOpenGL ESエミュレータのフックが有効でキャプチャできないので、以下のように無効にしておく。
set RENDERDOC_HOOK_EGL=0
参考
13 実行結果
備考
- 元々OpenGLのプロジェクトを無理やりOpenGL ESにしようとしたとき、GLEWを使っていると初期化に失敗するので、GLES2/gl2.h、GLES2/gl2ext.hから直接OpenGL ESの関数を呼び出した。
参考
- 何か間違い、気になる箇所等あれば言って下さると嬉しいです