鸿蒙开发--GraphicsAccelerateKit-AdaptiveBufferResolution-GLES HarmonyOS 图形加速用 ABR 实现自适应稳态渲染什么是 ABR玩游戏的时候你有没有遇到过这种情况场景简单的时候帧率很高很流畅但一到复杂场景比如大量敌人、特效爆炸就开始卡顿这是因为 GPU 的负载在不同场景下是不一样的。ABRAdaptive Buffer Resolution自适应缓冲分辨率就是为了解决这个问题。它的核心思想是在 GPU 负载高的时候自动降低渲染分辨率来保持帧率在 GPU 负载低的时候恢复高分辨率保证画质。打个比方就像开车上坡一样。上坡的时候GPU 负载高你会降档减速降低分辨率来保持动力下坡的时候GPU 负载低你又可以升档加速提高分辨率跑得更快。环境搭建硬件要求设备类型华为手机、平板设备HarmonyOS 系统HarmonyOS 5.0.5 Release 及以上软件要求DevEco Studio 版本DevEco Studio 6.0.0 Release 及以上HarmonyOS SDK 版本HarmonyOS 6.0.0 Release SDK 及以上搭建步骤安装 DevEco Studio去华为开发者官网下载安装配置开发环境确保网络环境正常设备调试使用真机进行调试项目结构这个项目比较特殊因为它涉及到 C 和 ArkTS 的混合开发└── entry/src/main // 代码区 ├── cpp │ ├── types/libentry │ │ └── index.d.ts // native层接口注册文件 │ ├── napi_init.cpp // native api层接口的具体实现函数 │ ├── CMakeLists.txt // native层编译配置 │ ├── include // 头文件 │ ├── source // C代码区 │ │ ├── core.cpp // 核心入口管理生命周期 │ │ ├── renderer.cpp // 渲染管理类的实现 │ │ ├── scene_base.cpp // ABR基类的实现 │ │ ├── scene_abr.cpp // ABR类的实现 │ │ ├── opaque_layer_base.cpp // 场景绘制基类的实现 │ │ ├── opaque_layer.cpp // 场景绘制派生类的实现 │ │ ├── gui.cpp // UI绘制 │ │ └── ... ├── ets │ ├── ability │ │ └── EntryAbility.ts // 程序入口类 │ ├── pages │ │ └── Index.ets // 主界面 └── resources │ ├── base/media // 图片资源 │ │ └── logo.png │ ├── rawfile // 模型和UI资源 │ │ └── ...为什么用 C因为图形渲染对性能要求很高C 能提供更接近硬件的控制能力。ArkTS 负责 UI 界面C 负责底层的图形渲染逻辑。应用架构整个应用分为三部分C 侧实现场景渲染管理 ABR 生命周期ArkTS 侧实现前端界面调用 C 侧的图形渲染方法CMake 编译工具链将 C 侧代码编译成 so 文件提供给 ArkTS 侧使用第一步创建项目使用 Native C 模板创建项目。在 DevEco Studio 中选择 “File New Create Project”然后选择 Native C 模板。第二步添加配置项在module.json5的 module 层级中添加以下配置metadata:[{name:GraphicsAccelerateKit_ABR,value:true}]这个配置告诉系统我们的应用要使用 Graphics Accelerate Kit 的 ABR 功能。第三步引入头文件在 C 代码中引入 ABR 的头文件#includegraphics_game_sdk/abr_gles.h这个头文件包含了所有 ABR 相关的 API。第四步配置 CMakeLists.txt在 CMakeLists.txt 中需要增加对libabr.so的依赖find_library(EGL-lib EGL REQUIRED) find_library(GLES-lib GLESv3 REQUIRED) find_library(ace-lib ace_ndk.z REQUIRED) find_library(hilog-lib hilog_ndk.z REQUIRED) find_library(napi-lib ace_napi.z REQUIRED) find_library(rawfile-lib rawfile.z REQUIRED) find_library(uv-lib uv REQUIRED) find_library(abr-lib libabr.so REQUIRED) set(ADAPTIVEBUFFERRESOLUTION_LINK_LIBRARIES ${EGL-lib} ${GLES-lib} ${ace-lib} ${hilog-lib} ${rawfile-lib} ${napi-lib} ${uv-lib} ${abr-lib} pixelmap_ndk.z image_source_ndk.z libc.a ) target_link_libraries(entry PRIVATE ${ADAPTIVEBUFFERRESOLUTION_LINK_LIBRARIES} )这里做了什么find_library查找需要的库abr-lib libabr.so这是 ABR 的核心库target_link_libraries把所有库链接到我们的项目中第五步ABR 生命周期管理ABR 的生命周期分为三个阶段ABR 初始化创建 ABR 上下文实例配置目标帧率和分辨率因子范围激活 ABR 功能自适应渲染绑定帧缓冲索引动态调整 buffer 的渲染分辨率销毁 ABR 实例销毁 ABR 上下文实例释放内存资源ABR 初始化在 Surface 创建后会触发Core::OnSurfaceCreated()回调函数。在这个函数中完成 ABR 的初始化// 创建ABR上下文帧实例指定图形API类型ABR_Context*context_HMS_ABR_CreateContext(RENDER_API_GLES);if(context_nullptr){GOLOGE(HMS_ABR_CreateContext execution failed.);returnfalse;}// 初始化ABR实例配置ABR的目标帧率属性。例如游戏目标帧率为120fps则配置ABR的目标帧率属性为120fpsABR_ErrorCode errorCodeHMS_ABR_SetTargetFps(context_,120);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_SetTargetFps execution failed, error code: %d.,errorCode);returnfalse;}// 初始化ABR实例配置Buffer分辨率因子范围属性结合具体游戏分辨率、画质设置合适的范围// 例如设置ABR对Buffer分辨率进行0.5~1.0倍的自适应调整errorCodeHMS_ABR_SetScaleRange(context_,0.5f,1.0f);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_SetScaleRange execution failed, error code: %d.,errorCode);returnfalse;}// 激活ABR上下文实例errorCodeHMS_ABR_Activate(context_);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_Activate execution failed, error code: %d.,errorCode);returnfalse;}让我解释一下每个 APIHMS_ABR_CreateContext(RENDER_API_GLES)创建一个 ABR 上下文实例参数RENDER_API_GLES表示使用 OpenGL ES 图形 API返回一个上下文指针后续所有操作都需要用到HMS_ABR_SetTargetFps(context_, 120)设置目标帧率为 120fpsABR 会根据这个目标帧率来调整分辨率如果当前帧率低于目标就降低分辨率如果高于目标就提高分辨率HMS_ABR_SetScaleRange(context_, 0.5f, 1.0f)设置分辨率缩放范围为 0.5 到 1.00.5 表示最低可以降到原始分辨率的 50%1.0 表示最高可以恢复到原始分辨率的 100%这个范围要根据你的应用来设置太低会影响画质HMS_ABR_Activate(context_)激活 ABR 实例激活后ABR 才会在每帧渲染时动态调整分辨率自适应渲染在每帧的渲染循环中ABR 会自动调整分辨率// 更新相机信息floatconstsceneDeltasceneTimer_.DiffTime();sceneTimer_.RestartTimer();camera_.Update(sceneDelta);// 更新视图矩阵和投影矩阵用于场景渲染lastViewProj_camera_.GetViewProjectionMatrix();lastView_camera_.GetViewMatrix();lastProj_camera_.GetProjectionMatrix();// 相机运动数据结构体设置每帧实时相机运动数据ABR_CameraData cameraData;// 相机每帧实时位移数据cameraData.positionstatic_castABR_Vector3(camera_.GetPosition());// 相机每帧实时旋转数据cameraData.rotationstatic_castABR_Vector3(camera_.GetRotation());// 每帧相机运动数据更新ABR_ErrorCode errorCodeHMS_ABR_UpdateCameraData(context_,cameraData);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_UpdateCameraData execution failed, error code: %d.,errorCode);}// 渲染前的准备绑定目标帧缓冲索引清空颜色缓冲renderer_-BeginRenderTarget(fbo,BACKGROUND.x_,BACKGROUND.y_,BACKGROUND.z_,1.0F);// 在Buffer渲染前调用执行失败不影响Buffer正常渲染errorCodeHMS_ABR_MarkFrameBuffer_GLES(context_);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_MarkFrameBuffer_GLES execution failed, error code: %d.,errorCode);}// 调用绘制方法进行渲染opaqueLayer_.Render(sceneDelta,camera_.GetViewMatrix(),lastViewProj_);// 获取每帧的缩放信息floatscale;errorCodeHMS_ABR_GetScale(context_,scale);GOLOGD(Scale is %f.,scale);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_GetScale execution failed, error code: %d.,errorCode);}// 将帧缓冲索引绑定为默认值0renderer_-EndRenderTarget();关键 API 解释HMS_ABR_UpdateCameraData(context_, cameraData)更新相机的位置和旋转信息ABR 需要知道相机的运动状态来预测 GPU 负载比如相机快速移动时可能会看到更多复杂场景HMS_ABR_MarkFrameBuffer_GLES(context_)在渲染前调用告诉 ABR 要调整哪个帧缓冲的分辨率这个函数执行失败不影响正常渲染只是 ABR 功能不生效HMS_ABR_GetScale(context_, scale)获取当前帧的缩放系数可以用来显示调试信息或者做其他处理销毁 ABR 实例在 Surface 销毁时销毁 ABR 实例// 销毁ABR上下文实例并释放内存资源ABR_ErrorCode errorCodeHMS_ABR_DestroyContext(context_);if(errorCode!ABR_SUCCESS){GOLOGE(HMS_ABR_DestroyContext execution failed, error code: %d.,errorCode);returnfalse;}记得在不需要 ABR 的时候销毁它释放内存资源。ABR 的工作原理让我用更通俗的语言解释 ABR 是怎么工作的监控帧率ABR 会持续监控应用的帧率预测负载根据相机运动、场景复杂度等信息预测下一帧的 GPU 负载调整分辨率如果预测到 GPU 负载会很高可能掉帧就降低渲染分辨率如果 GPU 负载很低帧率远超目标就提高渲染分辨率平滑过渡分辨率的变化是渐进的不会突然跳变适用场景ABR 特别适合以下场景3D 游戏场景复杂度变化大的游戏图形渲染应用需要稳定帧率的渲染场景VR/AR 应用对帧率要求极高的场景注意事项分辨率范围设置HMS_ABR_SetScaleRange的参数要根据你的应用来设置。如果最低值设得太低画质会明显下降如果设得太高可能无法有效防止掉帧目标帧率设置要根据你的应用实际需要来设置。比如游戏一般 60fps 或 120fps普通应用 30fps 就够了相机数据更新HMS_ABR_UpdateCameraData要每帧都调用而且数据要准确否则 ABR 的预测会不准确错误处理每个 ABR API 都会返回错误码要检查并处理错误核心流程图ABR 自适应缓冲分辨率的工作原理是否创建 ABR 上下文设置目标帧率设置分辨率缩放范围激活 ABR 实例每帧渲染循环更新相机运动数据标记帧缓冲执行场景渲染获取当前缩放系数GPU 负载是否过高?自动降低渲染分辨率自动提高渲染分辨率ABR 生命周期管理Surface 创建HMS_ABR_CreateContextHMS_ABR_SetTargetFpsHMS_ABR_SetScaleRangeHMS_ABR_Activate进入渲染循环HMS_ABR_UpdateCameraDataHMS_ABR_MarkFrameBuffer_GLES渲染场景HMS_ABR_GetScaleSurface 销毁HMS_ABR_DestroyContext总结ABR 是一个很实用的图形优化技术它能让你的应用在不同负载下都能保持稳定的帧率。核心流程创建 ABR 上下文HMS_ABR_CreateContext设置目标帧率HMS_ABR_SetTargetFps设置分辨率范围HMS_ABR_SetScaleRange激活 ABRHMS_ABR_Activate每帧更新相机数据HMS_ABR_UpdateCameraData每帧标记帧缓冲HMS_ABR_MarkFrameBuffer_GLES获取缩放系数可选HMS_ABR_GetScale销毁上下文HMS_ABR_DestroyContext掌握了这些你就能在 HarmonyOS 应用中实现自适应稳态渲染了。这对于提升用户体验特别是在复杂场景下保持流畅度是非常有帮助的。