HarmonyOS GPU 超分 Vulkan 版:低分辨率变高分辨率
HarmonyOS GPU 超分 Vulkan 版:低分辨率变高分辨率
什么是 GPU 超分
上一篇我们介绍了用 OpenGL ES 实现 GPU 超分,这篇来看看用 Vulkan 怎么做。功能是一样的:把低分辨率图像"重建"成高分辨率图像,但 Vulkan 版本通常性能更好。
简单回顾一下:GPU 超分不是简单地拉伸像素,而是通过算法智能补充细节。就像一个画家看到模糊的小照片,然后凭技巧画出清晰的大画。
环境搭建
硬件要求
- 设备类型:请参考 XEngine 开发指南的硬件要求
软件要求
- DevEco Studio 版本:DevEco Studio 6.0.0 Release 及以上
- HarmonyOS SDK 版本:HarmonyOS 6.0.0 Release SDK 及以上
搭建步骤
- 安装 DevEco Studio:去华为开发者官网下载安装
- 配置开发环境:确保网络环境正常
- 设备调试:使用真机进行调试
项目结构
├── entry/src/main // 代码区 │ ├── cpp │ │ ├── types │ │ │ ├── libnativerender │ │ │ └── index.d.ts // native层接口注册文件 │ │ │── napi_init.cpp // native api层接口的具体实现函数 │ │ │── CMakeLists.txt // native层编译配置 │ │ │── 3rdParty // 三方件 │ │ │── common // 通用接口 │ │ │── file // 文件管理 │ │ │── libs // 三方动态库 │ │ │── manager // native&arkts交互 │ │ │── render // 渲染 │ │ │── vulkanbase // vulkan基础能力封装 │ ├── ets │ │ ├── entryability │ │ │ └── EntryAbility.ts // 程序入口类 │ │ ├── pages │ │ │ └── index.ets // 主界面展示类 │ ├── resources // 资源文件目录 │ │ ├── base │ │ │ ├── media │ │ │ └── icon.png // 图片资源 │ │ ├── rawfile │ │ │ ├── Sponza │ │ │ └── sponza.obj // 模型资源第一步:引入头文件
#include<string>#include<vector>#include<algorithm>#include<xengine/xeg_vulkan_extension.h>#include<xengine/xeg_vulkan_spatial_upscale.h>和 OpenGL ES 版本类似,但用的是 Vulkan 版本的头文件。
第二步:配置 CMakeLists.txt
find_library( xengine-lib xengine ) find_library( EGL-lib EGL ) find_library( Vulkan-lib vulkan ) target_link_libraries(nativerender PUBLIC ${EGL-lib} ${Vulkan-lib} ${xengine-lib})链接了xengine、EGL和vulkan三个库。
第三步:查询设备是否支持超分
VkPhysicalDevice physicalDevice;std::vector<std::string>supportedExtensions;uint32_tpPropertyCount;HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice,&pPropertyCount,nullptr);if(pPropertyCount>0){std::vector<XEG_ExtensionProperties>pProperties(pPropertyCount);if(HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice,&pPropertyCount,&pProperties.front())==VK_SUCCESS){for(autoext:pProperties){supportedExtensions.push_back(ext.extensionName);}}}if(std::find(supportedExtensions.begin(),supportedExtensions.end(),XEG_SPATIAL_UPSCALE_EXTENSION_NAME)==supportedExtensions.end()){exit(1);// return error}和 OpenGL ES 版本一样,先查询设备支持的扩展,然后检查是否支持空域超分。Vulkan 的查询方式是"先问数量,再取数据"的两步式调用。
第四步:创建超分实例
XEG_SpatialUpscale xegSpatialUpscale;声明一个超分实例句柄,就像一个"遥控器"。
uint32_tm_renderWidth=800;uint32_tm_renderHeight=600;uint32_tm_upscaleWidth=1200;uint32_tm_upscaleHeight=900;VkDevice device;定义渲染分辨率(800x600)和超分后的目标分辨率(1200x900)。
VkRect2D srcRect2D;srcRect2D.offset.x=0;srcRect2D.offset.y=0;srcRect2D.extent.width=m_renderWidth;srcRect2D.extent.height=m_renderHeight;设置输入区域。srcRect2D定义了从哪里读取原始图像:
offset:起始偏移,从 (0, 0) 开始extent:大小,等于原始渲染分辨率
VkRect2D dstRect2D;dstRect2D.offset.x=0;dstRect2D.offset.y=0;dstRect2D.extent.width=m_upscaleWidth;dstRect2D.extent.height=m_upscaleHeight;设置输出区域。dstRect2D定义了超分结果写到哪里:
offset:起始偏移,从 (0, 0) 开始extent:大小,等于超分后的目标分辨率
XEG_SpatialUpscaleCreateInfo createInfo;createInfo.format=VK_FORMAT_R8G8B8A8_UNORM;createInfo.sharpness=0.3f;createInfo.outputSize=dstRect2D.extent;createInfo.inputRegion=srcRect2D;createInfo.outputRegion=dstRect2D;createInfo.inputSize=srcRect2D.extent;配置创建参数:
format:图像格式,VK_FORMAT_R8G8B8A8_UNORM表示 RGBA 四通道,每个通道 8 位sharpness:锐化参数,0.3 是一个平衡值outputSize:输出尺寸inputRegion:输入区域outputRegion:输出区域inputSize:输入尺寸
HMS_XEG_CreateSpatialUpscale(device,&createInfo,&xegSpatialUpscale);调用HMS_XEG_CreateSpatialUpscale创建超分实例。
第五步:执行超分
VkImageView inputImageView=VK_NULL_HANDLE;VkImageView outputImageView;VkCommandBuffer cmdBuff=VK_NULL_HANDLE;定义输入和输出的图像视图,以及命令缓冲区:
inputImageView:原始低分辨率图像outputImageView:超分后的高分辨率图像cmdBuff:Vulkan 命令缓冲区
XEG_SpatialUpscaleDescription xegDescription;xegDescription.inputImage=inputImageView;xegDescription.outputImage=outputImageView;HMS_XEG_CmdRenderSpatialUpscale(cmdBuff,xegSpatialUpscale,&xegDescription);设置输入输出图像,然后调用HMS_XEG_CmdRenderSpatialUpscale执行超分。这个命令会被记录到命令缓冲区里,等 GPU 执行时才会真正运行。
第六步:销毁实例
HMS_XEG_DestroySpatialUpscale(xegSpatialUpscale);不需要超分功能时,销毁实例,释放内存资源。
OpenGL ES 版和 Vulkan 版的区别
你可能会问:既然功能一样,为什么要有两个版本?主要区别在于:
- 性能:Vulkan 通常性能更好,因为它的底层控制更精细
- 复杂度:Vulkan 的代码更复杂,需要手动管理很多东西
- 兼容性:OpenGL ES 兼容性更好,几乎所有设备都支持
选择哪个版本取决于你的需求:
- 如果追求性能,选 Vulkan
- 如果追求开发效率,选 OpenGL ES
Vulkan 版 GPU 超分的整体工作流程如下:
OpenGL ES 版与 Vulkan 版的选择决策:
适用场景
GPU 超分特别适合以下场景:
- 游戏渲染:先用低分辨率渲染(性能好),再超分到高分辨率(画质好)
- 视频播放:把低分辨率视频超分到高分辨率显示
- 图片查看:放大图片时保持清晰度
注意事项
- 设备支持:不是所有设备都支持 GPU 超分,一定要先查询扩展
- 锐化参数:
sharpness要根据实际效果来调整 - 分辨率比例:超分的倍率不宜过大,一般 1.5 到 2 倍比较合适
- 性能开销:超分本身有性能开销,要权衡画质提升和性能损失
总结
Vulkan 版本的 GPU 超分和 OpenGL ES 版本功能相同,核心流程:
- 查询设备是否支持超分
- 创建超分实例,配置参数(锐化度、输入输出区域)
- 调用
HMS_XEG_CmdRenderSpatialUpscale执行超分 - 销毁实例
如果你的应用已经在用 Vulkan,那直接用 Vulkan 版本的超分会更方便。如果用的是 OpenGL ES,就用 OpenGL ES 版本。
