鸿蒙(API 12 Beta6版)图形加速【Vulkan平台】超帧功能开发

业务流程

基于Vulkan图形API平台,集成超帧内插模式的主要业务流程如下:

  1. 用户进入超帧适用的游戏场景。
  2. 游戏应用调用[HMS_FG_CreateContext_VK]接口创建超帧上下文实例。
  3. 游戏应用调用接口配置超帧实例属性。包括调用[HMS_FG_SetAlgorithmMode_VK](必选)设置超帧算法模式并选择内插模式;调用[HMS_FG_SetResolution_VK](必选)设置超帧输入输出图像分辨率;调用[HMS_FG_SetCvvZSemantic_VK](可选)设置齐次裁剪空间Z/W范围及深度测试函数;调用[HMS_FG_SetImageFormat_VK](可选)设置超帧输入输出图像格式;如果颜色缓冲区相对深度模板缓冲区基于y轴翻转180度,则调用[HMS_FG_SetDepthStencilYDirectionInverted_VK](可选)设置翻转状态。
  4. 游戏应用调用[HMS_FG_Activate_VK])接口激活超帧上下文实例。
  5. 游戏应用调用[HMS_FG_CreateImage_VK]接口创建真实渲染帧颜色缓冲区图像实例、深度模板缓冲区图像实例、预测帧缓冲区图像实例。该接口将游戏应用中的VkImage、VkImageView图像资源和超帧算法实现之间建立关联。
  6. 游戏应用调用[HMS_FG_Dispatch_VK]接口并传入历史真实渲染帧颜色信息、深度信息、相机矩阵信息,生成预测帧,并更新预测帧缓冲区。
  7. 预测帧绘制UI并送显。
  8. 绘制缓存中的上一帧真实渲染帧,并绘制UI。
  9. 上一帧真实渲染帧送显。
  10. 渲染游戏场景获取真实渲染帧,缓存真实渲染帧颜色信息、深度信息、相机矩阵等信息,用于后续超帧预测。由于内插模式真实帧需要等待前一帧预测帧绘制并送显后再送显,因此此处缓存一帧真实帧信息。跳转至序号5继续执行,直到退出游戏场景。
  11. 用户退出超帧适用的游戏场景。
  12. 游戏应用调用[HMS_FG_DestroyContext_VK]接口销毁超帧上下文实例并释放内存资源。

开发步骤

本节阐述基于Vulkan图形API平台的超帧调用示例。

  1. 引用Graphics Accelerate Kit超帧头文件:frame_generation_vk.h。

    // 引用超帧frame_generation_vk.h头文件
    #include <graphics_game_sdk/frame_generation_vk.h>

  2. 编写CMakeLists.txt。

    find_library(
    # Sets the name of the path variable.
    framegeneration-lib
    # Specifies the name of the NDK library that you want CMake to locate.
    libframegeneration.so
    )
    find_library(
    # Sets the name of the path variable.
    vulkan-lib
    # Specifies the name of the NDK library that you want CMake to locate.
    vulkan
    )

    target_link_libraries(entry PUBLIC
    ${framegeneration-lib} ${vulkan-lib}
    )

  3. 调用[HMS_FG_CreateContext_VK]接口创建超帧上下文实例。

    // 变量声明
    VkInstance vkInstance = VK_NULL_HANDLE;
    VkPhysicalDevice vkPhysicalDevice = VK_NULL_HANDLE;
    VkDevice vkDevice = VK_NULL_HANDLE;

    // 创建超帧上下文实例
    FG_ContextDescription_VK contextDescription{};
    contextDescription.vkInstance = vkInstance;
    contextDescription.vkPhysicalDevice = vkPhysicalDevice;
    contextDescription.vkDevice = vkDevice;
    contextDescription.framesInFlight = 1;
    contextDescription.fnVulkanLoaderFunction = vkGetInstanceProcAddr;
    FG_Context_VK* m_context = HMS_FG_CreateContext_VK(&contextDescription);
    if (m_context == nullptr) {
    return;
    }

  4. 调用超帧实例属性配置接口,超帧算法模式选择内插模式。

    // 初始化超帧接口调用错误码
    FG_ErrorCode errorCode = FG_SUCCESS;

    // 超帧算法模式
    FG_AlgorithmModeInfo aInfo{};
    aInfo.predictionMode = FG_PREDICTION_MODE_INTERPOLATION; // 内插模式
    aInfo.meMode = FG_ME_MODE_BASIC; // 运动估计基础模式
    errorCode = HMS_FG_SetAlgorithmMode_VK(m_context, &aInfo); // [必选] 设置超帧算法模式
    if (errorCode != FG_SUCCESS) {
    return;
    }

    // 真实帧颜色缓冲区分辨率
    FG_Dimension2D inputColorResolution{};
    inputColorResolution.width = 1280; // 真实帧颜色缓冲区图像宽度
    inputColorResolution.height = 720; // 真实帧颜色缓冲区图像高度
    // 真实帧深度模板缓冲区分辨率
    FG_Dimension2D inputDepthStencilResolution{};
    inputDepthStencilResolution.width = 1280; // 真实帧深度模板缓冲区图像宽度
    inputDepthStencilResolution.height = 720; // 真实帧深度模板缓冲区图像高度
    // 预测帧分辨率
    FG_Dimension2D outputColorResolution{};
    outputColorResolution.width = 1280; // 预测帧图像宽度
    outputColorResolution.height = 720; // 预测帧图像高度
    // 超帧输入输出图像分辨率
    FG_ResolutionInfo rInfo{};
    rInfo.inputColorResolution = inputColorResolution;
    rInfo.inputDepthStencilResolution = inputDepthStencilResolution;
    rInfo.outputColorResolution = outputColorResolution;
    errorCode = HMS_FG_SetResolution_VK(m_context, &rInfo); // [必选] 设置超帧输入输出图像分辨率
    if (errorCode != FG_SUCCESS) {
    return;
    }

    // [可选] 设置齐次裁剪空间Z/W范围及深度测试模式,接口不调用时默认为FG_CVV_Z_SEMANTIC_ZERO_TO_ONE_FORWARD_Z
    errorCode = HMS_FG_SetCvvZSemantic_VK(m_context, FG_CVV_Z_SEMANTIC_ZERO_TO_ONE_FORWARD_Z);
    if (errorCode != FG_SUCCESS) {
    return;
    }

    // [可选] 设置超帧输入输出图像格式
    FG_ImageFormat_VK imageFormat{};
    imageFormat.inputColorFormat = VK_FORMAT_R8G8B8A8_UNORM;
    imageFormat.inputDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
    imageFormat.outputColorFormat = VK_FORMAT_R8G8B8A8_UNORM;
    errorCode = HMS_FG_SetImageFormat_VK(m_context, &imageFormat);
    if (errorCode != FG_SUCCESS) {
    return;
    }

    // [可选] 当颜色缓冲区相对深度模板缓冲区基于y轴翻转180度时,设置第二个参数为true,接口不调用时默认为false
    errorCode = HMS_FG_SetDepthStencilYDirectionInverted_VK(m_context, true);
    if (errorCode != FG_SUCCESS) {
    return;
    }

  5. 调用[HMS_FG_Activate_VK]接口激活超帧上下文实例。

    // 激活超帧上下文实例
    errorCode = HMS_FG_Activate_VK(m_context);
    if (errorCode != FG_SUCCESS) {
    return;
    }

  6. 调用[HMS_FG_CreateImage_VK]接口创建真实渲染帧颜色缓冲区图像实例、深度模板缓冲区图像实例、预测帧缓冲区图像实例。

    // 变量声明
    VkImage inputColorImage = VK_NULL_HANDLE;
    VkImageView inputColorImageView = VK_NULL_HANDLE;
    VkImage inputDepthStencilImage = VK_NULL_HANDLE;
    VkImageView inputDepthStencilImageView = VK_NULL_HANDLE;
    VkImage outputColorImage = VK_NULL_HANDLE;
    VkImageView outputColorImageView = VK_NULL_HANDLE;

    // 创建真实帧颜色缓冲区图像实例
    FG_Image_VK* inputColor = HMS_FG_CreateImage_VK(m_context, inputColorImage, inputColorImageView);
    if (!inputColor) {
    return;
    }
    // 创建真实帧深度模板缓冲区图像实例
    FG_Image_VK* inputDepthStencil = HMS_FG_CreateImage_VK(m_context, inputDepthStencilImage, inputDepthStencilImageView);
    if (!inputDepthStencil) {
    return;
    }
    // 创建预测帧缓冲区图像实例
    FG_Image_VK* outputColor = HMS_FG_CreateImage_VK(m_context, outputColorImage, outputColorImageView);
    if (!outputColor) {
    return;
    }

  7. 游戏运行中,真实帧和预测帧交替渲染并送显。渲染真实帧时,缓存颜色信息、深度信息和相机矩阵等属性信息。渲染预测帧时,需调用[HMS_FG_Dispatch_VK]接口并传入上一帧真实帧属性信息,指定预测帧缓冲区索引,生成预测帧,最终更新预测帧缓冲区内存。

    // 帧计数
    uint32_t frameNum = 0;

    // 帧循环
    while (true) {
    frameNum += 1;
    if ((frameNum & 1) != 0) { // 预测帧渲染阶段
    // 设置预测帧生成前真实帧颜色缓冲区同步状态
    FG_ImageSync_VK inputColorInitImageSync{};
    inputColorInitImageSync.stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    inputColorInitImageSync.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    inputColorInitImageSync.accessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

         // 设置预测帧生成后真实帧颜色缓冲区同步状态
         FG_ImageSync_VK inputColorFinalImageSync{};
         inputColorFinalImageSync.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
         inputColorFinalImageSync.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
         inputColorFinalImageSync.accessMask = VK_ACCESS_TRANSFER_READ_BIT;
    
         // 创建真实帧颜色缓冲区图像属性实例
         FG_ImageInfo_VK inputColorImageInfo{};
         inputColorImageInfo.image = inputColor;
         inputColorImageInfo.initialSync = inputColorInitImageSync;
         inputColorImageInfo.finalSync = inputColorFinalImageSync;
    
         // 设置预测帧生成前深度模板缓冲区同步状态
         FG_ImageSync_VK depthInitImageSync{};
         depthInitImageSync.stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
         depthInitImageSync.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
         depthInitImageSync.accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    
         // 设置预测帧生成后深度模板缓冲区同步状态
         FG_ImageSync_VK depthFinalImageSync{};
         depthFinalImageSync.stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
         depthFinalImageSync.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
         depthFinalImageSync.accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
    
         // 创建真实帧深度模板缓冲区图像属性实例
         FG_ImageInfo_VK depthImageInfo{};
         depthImageInfo.image = inputDepthStencil;
         depthImageInfo.initialSync = depthInitImageSync;
         depthImageInfo.finalSync = depthFinalImageSync;
    
         // 设置预测帧生成前预测帧缓冲区同步状态
         FG_ImageSync_VK outputColorInitImageSync{};
         outputColorInitImageSync.stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
         outputColorInitImageSync.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
         outputColorInitImageSync.accessMask = VK_ACCESS_SHADER_WRITE_BIT;
    
         // 设置预测帧生成后预测帧缓冲区同步状态
         FG_ImageSync_VK outputColorFinalImageSync{};
         outputColorFinalImageSync.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
         outputColorFinalImageSync.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
         outputColorFinalImageSync.accessMask = VK_ACCESS_TRANSFER_READ_BIT;
    
         // 创建预测帧缓冲区图像属性实例
         FG_ImageInfo_VK outputColorImageInfo{};
         outputColorImageInfo.image = outputColor;
         outputColorImageInfo.initialSync = outputColorInitImageSync;
         outputColorImageInfo.finalSync = outputColorFinalImageSync;
    
         // 帧生成属性配置结构体
         FG_DispatchDescription_VK dispatchDescription{};
         // 传入真实渲染帧颜色缓冲区属性信息
         dispatchDescription.inputColorInfo = inputColorImageInfo;
         // 传入真实渲染帧深度模板缓冲区属性信息
         dispatchDescription.inputDepthStencilInfo = depthImageInfo;
         // 传入预测帧缓冲区属性信息
         dispatchDescription.outputColorInfo = outputColorImageInfo;
    
         // 变量声明
         FG_Mat4x4 preViewProj;
         FG_Mat4x4 preInvViewProj;
         VkCommandBuffer vkCommandBuffer = VK_NULL_HANDLE;
    
         // 传入上一帧真实渲染帧视图投影矩阵
         dispatchDescription.viewProj = preViewProj;
         // 传入上一帧真实渲染帧视图投影逆矩阵
         dispatchDescription.invViewProj = preInvViewProj;
         // 传入用于录入超帧绘制指令的命令缓冲区句柄
         dispatchDescription.vkCommandBuffer = vkCommandBuffer;
         // 传入当前帧序号
         dispatchDescription.frameIdx = 0;
    
         // 生成预测帧,更新预测帧缓冲区的内存
         errorCode = HMS_FG_Dispatch_VK(m_context, &dispatchDescription);
         if (errorCode != FG_SUCCESS) {
             return;
         }
         switch (errorCode) {
             case FG_SUCCESS: { // 生成预测帧成功
                 // 绘制预测帧
                 // ...
    
                 // 绘制UI
                 // ...
    
                 // 预测帧送显
                 // ...
                 break;
             }
             case FG_COLLECTING_PREVIOUS_FRAMES:
                 // 传入真实帧数量未达到固定阈值,无预测帧生成,内插模式传入真实帧数量<3时返回该状态码,此时不要将预测帧送显
                 break;
             default:
                 // 预测帧生成失败
                 return;
         }
     } else { // 真实帧渲染阶段            
         // 绘制缓存中的上一帧真实帧
         // ...
    
         // 绘制UI
         // ...
         
         // 渲染当前帧渲染画面,缓存颜色、深度、相机矩阵等信息,用于下一帧预测帧生成
         // ...
        
         // 送显缓存中的上一帧真实帧
         // ...
     }
    

    }

  8. 调用[HMS_FG_DestroyContext_VK]接口销毁超帧实例,释放内存资源。

    // 销毁超帧上下文实例并释放内存资源
    errorCode = HMS_FG_DestroyContext_VK(&m_context);
    if (errorCode != FG_SUCCESS) {
    return;
    }

最后呢

很多开发朋友不知道需要学习那些鸿蒙技术?鸿蒙开发岗位需要掌握那些核心技术点?为此鸿蒙的开发学习必须要系统性的进行。

而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档 》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。

针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细鸿蒙(OpenHarmony )手册(共计1236页)与鸿蒙(OpenHarmony )开发入门视频,帮助大家在技术的道路上更进一步。

  • 《鸿蒙 (OpenHarmony)开发学习视频》
  • 《鸿蒙生态应用开发V2.0白皮书》
  • 《鸿蒙 (OpenHarmony)开发基础到实战手册》
  • OpenHarmony北向、南向开发环境搭建
  • 《鸿蒙开发基础》
  • 《鸿蒙开发进阶》
  • 《鸿蒙开发实战》

总结

鸿蒙---作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。

并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行! 自↓↓↓拿

相关推荐
小冷爱学习!8 小时前
华为动态路由-OSPF-完全末梢区域
服务器·网络·华为
2501_904447749 小时前
华为发力中端,上半年nova14下半年nova15,大力普及原生鸿蒙
华为·智能手机·django·scikit-learn·pygame
MarkHD9 小时前
第十八天 WebView深度优化指南
华为·harmonyos
塞尔维亚大汉10 小时前
OpenHarmony(鸿蒙南向)——平台驱动开发【MIPI CSI】
harmonyos·领域驱动设计
别说我什么都不会10 小时前
鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP
操作系统·harmonyos
feiniao865111 小时前
2025年华为手机解锁BL的方法
华为·智能手机
塞尔维亚大汉12 小时前
OpenHarmony(鸿蒙南向)——平台驱动开发【I3C】
harmonyos·领域驱动设计
VVVVWeiYee12 小时前
BGP配置华为——路径优选验证
运维·网络·华为·信息与通信
今阳14 小时前
鸿蒙开发笔记-6-装饰器之@Require装饰器,@Reusable装饰器
android·app·harmonyos
余多多_zZ15 小时前
鸿蒙初学者学习手册(HarmonyOSNext_API14)_组件截图(@ohos.arkui.componentSnapshot (组件截图) )
学习·华为·harmonyos·鸿蒙·鸿蒙系统