从 Android 10 开始,Android 允许用户为指定进程设置 GPU Debug Layer,指定 Debug Layer 后,所有 OpenGL ES 或 Vulkan 的调用都会先经过调试层,然后再调用平台厂商开发的 GPU Library 接口。调试层对于性能和图形工作者有比较大的作用,通过调试层,我们可以做很多事情,如:
- 观察接口调用的顺序、接口传入的参数值,用以分析图形显示相关的问题
- 在接口调用的地方新增
trace监控,结合perfetto等工具,分析性能相关问题 - 在调试层中对某些有调用顺序的接口做顺序校验,不按顺序调用可以直接
crash,提前发现问题 - 在每个调用中增加
checkError,定位精准的出错点 - ...
由于 gl 和 egl 接口非常多,手动编写 layer function 非常繁琐,所以本项目通过 opengl-es-debug-layer-generator 生成了所有的 layer 函数,然后通过 app 模块生成了调试层的 apk
环境设置:
# 打开调试层
adb shell settings put global enable_gpu_debug_layers 1
# 设置想要调试的目标应用
adb shell settings put global gpu_debug_app com.android.settings
# 安装调试层 apk
adb install layer-debug.apk
# 设置调试层 apk 包名
adb shell settings put global gpu_debug_layer_app site.hanschen.gpu
# 设置调试层 so 名
adb shell settings put global gpu_debug_layers_gles libGLESDebugLayer.so设置完之后, 重启想要调试的目标进程即可,在 layer-debug.apk 中,默认实现了 logcat 输出以及 trace 跟踪
环境恢复:
adb shell settings delete global enable_gpu_debug_layers
adb shell settings delete global gpu_debug_app
adb shell settings delete global gpu_debug_layers_gles
adb shell settings delete global gpu_debug_layer_app由于 native 进程如 surfaceflinger 不会读取 global settings 进行初始化,可以通过以下命令进行全局设置(其实应用也可以用这种方式生效)
adb shell setprop debug.gles.layers libGLESDebugLayer.so
adb push lib/arm64-v8a/libGLESDebugLayer.so /data/local/debug/gles/
adb shell stop && adb shell start# 配置是否在 gl 命令前面添加 index 前缀
[debug.gpu.enable_index]: [1]
# 配置是否输出 logcat
[debug.gpu.enable_log]: [1]
# 配置是否添加 trace 监控
[debug.gpu.enable_trace]: [1]
# 配置是否输出参数值
[debug.gpu.log_params]: [1]
# 配置生效的进程,默认不配置则所有进程都生效
[debug.gpu.cmdline]: [/system/bin/surfaceflinger]
# 对每一条 GL 指令执行 glFinish,默认为 0
[debug.gpu.enable_gl_finish]: [1]