angle折腾笔记
时隔多年重新编译angle,主要是为了PC上能模拟ES3.1,特别是最好能支持VT相关操作。本来不抱希望,毕竟angle文档上写的很清楚,目前GL/GLES/Vulkan Backend都只支持到ES 3.1,ES 3.2还处于in progress。
但是突然发现EXT_copy_image
这个扩展在Vulkan Backend上已经被支持Vulkan: Add support for EXT_copy_image,瞬间觉得有戏就折腾了下。
Compile Angle
DevSetup里描述的还是比较清晰的,这里只记录下有坑的地方。
Proxy
由于大家都知道的国情,记得给git和gclient都打开代理,避免烦恼
git config --global http.proxy "127.0.0.1:1087" |
Error Code 9009
拉取仓库完成之后,gclient会自动调用脚本设置一些东西,然后我就遇到一个非常奇怪的错误
python3 third_party\depot_tools\update_depot_tools_toggle.py --disable |
看了下这个脚本非常简单,直接运行了下也没出错——搜了下9009这个错误编码是和VS有关,但是我还没到这一步呢orz
最后突然发现我本地测试犯傻了,顺手就是调用的python
…改成python3
之后弹出了Microsoft Store,好吧又是老问题了,修改下环境变量里的PATH即可(具体可参考解决 win10 命令行下运行 python 弹出 Windows 应用商店)。
Windows SDK
这个问题说实话是我一开始万万没想到这么坑的… angle编译需要Windows SDK 10.0.20348.0及对应的Debugger Tool
for debug_file, is_optional in debug_files: |
咱就跟着版本来一个呗,万万没想到VS Installer提示安装成功但是实际安装失败…遇事不决就手动,运行vcvarsall.bat amd64 10.0.20348.0
结果提示SDK incomplete。网上查了圈还真有类似问题,Visual Studio Installer does not provide SDK 10.0.20348.0/Not able to install any previous version of VS. Download fails because on invalid signature,简直了emmm
然后我自作聪明了一发——那要不试试我本地已有的Windows SDK?当然事后发现就是自己坑自己 修改了下setup_toolchain.py
强行指定老版本
args.append('10.0.19041.0') |
这样之后就可以成功生成工程gn gen out/Debug --sln=angle-debug --ide=vs2019
。然而下一个暴击就是编译出错
1>..\..\third_party\llvm-build\Release+Asserts\bin\clang-cl.exe /c ../../src/libEGL/egl_loader_autogen.cpp /Foobj/libEGL_egl_loader/egl_loader_autogen.obj /nologo /showIncludes:user "-imsvcC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\ATLMFC\include" "-imsvcC:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include" "-imsvcC:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\ucrt" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\um" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\winrt" "-imsvcC:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\cppwinrt" -DUSE_AURA=1 -D_HAS_NODISCARD -D_CRT_NONSTDC_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS "-DCR_CLANG_REVISION=\"llvmorg-15-init-9074-gc62b014d-1\"" -DCOMPONENT_BUILD -D_LIBCPP_ABI_UNSTABLE -D_LIBCPP_ENABLE_NODISCARD -D_LIBCPP_NO_AUTO_LINK -D__STD_C -D_CRT_RAND_S -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_ATL_NO_OPENGL -D_WINDOWS -DCERT_CHAIN_PARA_HAS_EXTRA_FIELDS -DPSAPI_VERSION=2 -DWIN32 -D_SECURE_ATL -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_UNICODE -DUNICODE -DNTDDI_VERSION=NTDDI_WIN10_FE -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00 -D_DEBUG -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DANGLE_IS_WIN -DANGLE_USE_EGL_LOADER -DGL_GLES_PROTOTYPES=1 -DEGL_EGL_PROTOTYPES=1 -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -I../../buildtools/third_party/libc++ -I../../include -I../../src /W4 -Wimplicit-fallthrough -Wunreachable-code-aggressive -Wthread-safety /WX -Wno-missing-field-initializers -Wno-unused-parameter -Wloop-analysis -Wno-unneeded-internal-declaration -Wno-nonportable-include-path -Wno-null-pointer-subtraction -Wenum-compare-conditional -Wno-psabi -Wno-ignored-pragma-optimize -Wno-unqualified-std-cast-call -Xclang -no-opaque-pointers -Wmax-tokens -Wshadow -fno-delete-null-pointer-checks -fno-ident -fcolor-diagnostics -fmerge-all-constants -fcrash-diagnostics-dir=../../tools/clang/crashreports -mllvm -instcombine-lower-dbg-declare=0 /clang:-ffp-contract=off -fcomplete-member-pointers /Gy /FS /bigobj /utf-8 /Zc:twoPhase /Zc:sizedDealloc- /D__WRL_ENABLE_FUNCTION_STATICS__ -fmsc-version=1916 /Zc:dllexportInlines- -m64 -msse3 /Brepro -Wno-builtin-macro-redefined -D__DATE__= -D__TIME__= -D__TIMESTAMP__= -ffile-compilation-dir=. -no-canonical-prefixes -ftrivial-auto-var-init=pattern /Od /Ob0 /GF /Z7 -gcodeview-ghash -Xclang -fuse-ctor-homing /guard:cf,nochecks /MDd -Wheader-hygiene -Wstring-conversion -Wtautological-overlap-compare -Wexit-time-destructors -Wglobal-constructors /we4244 /we4312 /we4456 /we4458 /we4715 /we4800 /we4838 -Wbad-function-cast -Wconditional-uninitialized -Wextra-semi-stmt -Wfloat-conversion -Winconsistent-missing-destructor-override -Wmissing-field-initializers -Wnewline-eof -Wnon-virtual-dtor -Wredundant-parens -Wreturn-std-move -Wshadow -Wshadow-field -Wtautological-type-limit-compare -Wundefined-reinterpret-cast -Wunneeded-internal-declaration -Wunused-but-set-variable -Wsuggest-destructor-override -Wsuggest-override -Wparentheses -Wrange-loop-analysis -Wstrict-prototypes -Wunreachable-code-aggressive -Wshorten-64-to-32 -Wno-undefined-bool-conversion -Wno-tautological-undefined-compare /std:c++17 -Wno-trigraphs /Zc:alignedNew- /TP /GR- -I../../buildtools/third_party/libc++/trunk/include /Fd"obj/libEGL_egl_loader_cc.pdb" |
稍微看了下minwinbase.h
里FILE_INFO_BY_HANDLE_CLASS
的定义,发现是编译参数里的-DNTDDI_VERSION=NTDDI_WIN10_FE
这个宏不存在导致的…好吧好吧,那看来还真是不能用老版本的Windows SDK。
在M$官网扒拉到了Windows SDK and emulator archive,发现下下来已经是Windows SDK 10.0.20348.1了,不管了先装为敬——emmm为啥安装文件夹是对应到10.0.20348.0? 把前面修改的setup_toolchain.py
回退之后重新生成工程,终于编译成功~
Compile Option
编译出来的libGLESv2.dll
和libEGL.dll
覆盖回去之后发现启动失败,LoadLibrary
对应Error code 126,这种情况赌五毛肯定是有依赖库丢了…用Dependencies验证了下确实。那么用gn args out/Debug
修改一下编译设置,第三方库强制static link就好了。
is_component_build = false |
ps. 最后打包应该使用Release版本,直接用gn gen out/Release --sln=angle-release --ide=vs2019
配合gn args out/Release
is_component_build = false |
GLES Runtime
这里主要参考了EGLWindow.cpp,主要涉及两个细节:
- 强制打开ES 3.1,这里和PVR有所不同,如果不指定
EGL_CONTEXT_MINOR_VERSION_KHR
,那么默认是走的3.0EGLint ContextAttributes[] =
{
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
EGL_CONTEXT_MINOR_VERSION_KHR, 1,
EGL_NONE
}
EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, ContextAttributes); - 使用Vulkan Backend
EGLAttrib DisplayAttributes[] =
{
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE,
EGL_NONE
};
EglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, hDC, DisplayAttributes);
别的没啥要改的了,一把梭使用glCopyImageSubDataEXT
就都没问题了。比较遗憾的是PC上依然只支持BC系列,不能使用ETC(完美模拟手机计划失败)。看了下代码,其实是这个条件还没实现完整导致的orz
angle::Result ImageHelper::CopyImageSubData(const gl::Context *context, |
Conclusion
后来顺手测试了下PVR版本的libGLESv2.dll
,才发现其实也有EXT_copy_image
支持,所以VT的效果也是对的。
但是折腾了这么一大圈还是有价值的: 一方面使用起来的体验天差地别,angle vulkan backend能稳定跑到60fps,而angle dx11 backend只有50fps同时没有copy_image,pvr则只有可怜的10fps不到。另一个非常大的收益在于方便调试,毕竟有对应PDB和源代码之后,可以一路F11进去看各种GL_ERROR
的原因,特别关注ValidateXXX
函数里面的检查: