Vulkan 时域 AI 超分多帧信息融合的终极画质方案时域 AI 超分是 XEngine 提供的三种超分方案里效果最好的。它利用历史帧、深度图、运动矢量等多维度信息通过 AI 算法生成高质量的高分辨率画面。在 Vulkan 环境下使用时域超分你需要走创建对象 - 录制命令 - 销毁对象的标准流程。推荐的超分倍率是 1.25 到 2.0 倍。查询扩展支持uint32_tpropertyCount0;HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice,propertyCount,NULL);XEG_ExtensionProperties*propertiesmalloc(sizeof(XEG_ExtensionProperties)*propertyCount);HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice,propertyCount,properties);bool supportedfalse;for(uint32_ti0;ipropertyCount;i){if(strcmp(properties[i].extensionName,XEG_TEMPORAL_UPSCALE_EXTENSION_NAME)0){supportedtrue;break;}}free(properties);XEG_TEMPORAL_UPSCALE_EXTENSION_NAME的值是XEG_temporal_upscale。创建 XEG_TemporalUpscale 对象XEG_TemporalUpscale temporalUpscaleVK_NULL_HANDLE;XEG_TemporalUpscaleCreateInfo createInfo{// ... 创建参数};VkResult resultHMS_XEG_CreateTemporalUpscale(device,createInfo,temporalUpscale);if(result!VK_SUCCESS){// 创建失败return;}HMS_XEG_CreateTemporalUpscale的三个参数deviceVkDevicepTemporalUpscaleInfoXEG_TemporalUpscaleCreateInfo结构体指针不允许为空pTemporalUpscale输出句柄的指针创建参数变化时需要重建对象。对于时域超分来说创建参数通常包括输入输出的分辨率、格式等不常变化的信息。录制超分渲染命令每帧录制超分命令XEG_TemporalUpscaleDescription description{// 输入纹理、深度图、运动矢量、动态遮罩、相机抖动等};HMS_XEG_CmdRenderTemporalUpscale(commandBuffer,temporalUpscale,description);HMS_XEG_CmdRenderTemporalUpscale的三个参数commandBufferVkCommandBuffer需要是Primary 类型。这一点很重要如果你传了 Secondary 类型的命令缓冲可能会出问题temporalUpscale已创建的XEG_TemporalUpscale对象pDescriptionXEG_TemporalUpscaleDescription结构体指针不允许为空XEG_TemporalUpscaleDescription里需要包含和 GLES 版一样的信息输入纹理、深度图、运动矢量、动态遮罩以及相机抖动值。这些信息的具体含义可以参考 GLES 时域超分那篇文章这里不再赘述。销毁对象HMS_XEG_DestroyTemporalUpscale(temporalUpscale);完整流程下面的流程图展示了 Vulkan 时域超分的完整使用流程不支持支持是否查询扩展支持是否支持时域超分?退出或使用其他超分方案创建 XEG_TemporalUpscale 对象每帧准备多维输入数据录入输入纹理/深度图/运动矢量/动态遮罩插入Pipeline Barrier确保写入完成录制超分命令到Primary命令缓冲提交命令缓冲执行场景是否切换?重置历史帧数据或重建对象退出时销毁对象下面的流程图展示了时域超分的输入数据处理流程渲染管线输出颜色纹理深度纹理运动矢量纹理动态遮罩纹理相机抖动值准备XEG_TemporalUpscaleDescription录制超分命令输出高分辨率画面// 1. 查询扩展uint32_tpropertyCount0;HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice,propertyCount,NULL);XEG_ExtensionProperties*propertiesmalloc(sizeof(XEG_ExtensionProperties)*propertyCount);HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice,propertyCount,properties);bool supportedfalse;for(uint32_ti0;ipropertyCount;i){if(strcmp(properties[i].extensionName,XEG_TEMPORAL_UPSCALE_EXTENSION_NAME)0){supportedtrue;break;}}free(properties);if(!supported)return;// 2. 创建对象XEG_TemporalUpscale temporalUpscaleVK_NULL_HANDLE;XEG_TemporalUpscaleCreateInfo createInfo{/* ... */};HMS_XEG_CreateTemporalUpscale(device,createInfo,temporalUpscale);// 3. 每帧准备描述信息并录制命令XEG_TemporalUpscaleDescription desc{// 当前帧的输入纹理、深度图、运动矢量、动态遮罩、抖动值};HMS_XEG_CmdRenderTemporalUpscale(commandBuffer,temporalUpscale,desc);// 4. 提交命令缓冲vkQueueSubmit(queue,1,submitInfo,fence);// 5. 退出时销毁HMS_XEG_DestroyTemporalUpscale(temporalUpscale);Vulkan 版的独特考虑命令缓冲类型HMS_XEG_CmdRenderTemporalUpscale要求命令缓冲是 Primary 类型。如果你的渲染管线用到了 Secondary 命令缓冲比如在 RenderPass 里录制你需要确保超分命令是在 Primary 命令缓冲里录制的。同步问题时域超分需要读取多个输入纹理颜色、深度、运动矢量、动态遮罩。你需要确保在录制超分命令之前这些纹理已经写入完毕。在 Vulkan 里这通常通过 Pipeline Barrier 或者 Semaphore 来实现。一个典型的同步流程是你的渲染管线输出颜色、深度、运动矢量等纹理插入 Pipeline Barrier确保这些纹理的写入完成录制超分命令超分结果可以被后续的后处理步骤读取创建参数 vs 描述信息区分一下哪些信息放在XEG_TemporalUpscaleCreateInfo里、哪些放在XEG_TemporalUpscaleDescription里CreateInfo不常变化的信息比如分辨率、格式。变了就要重建对象Description每帧都可能变化的信息比如具体的纹理 ID、相机抖动值和 GLES 版的对比Vulkan 版的时域超分和 GLES 版在功能上是等价的主要区别在于接口风格方面GLES 版Vulkan 版参数设置HMS_XEG_TemporalUpscaleParameter逐个设置通过XEG_TemporalUpscaleDescription结构体执行方式直接调用录制到命令缓冲命令缓冲类型不适用必须是 Primary 类型同步管理驱动自动处理需要手动管理 Pipeline Barrier使用建议确保输入数据正确运动矢量、动态遮罩的质量直接影响超分效果。运动矢量的计算方式是当前帧NDC的XY - 上一帧NDC的XY。动态遮罩的 R 通道值只能是 0.0静态、0.2运动物体或 1.0特效/半透明。注意同步Vulkan 不会自动帮你做同步。确保输入纹理的写入在超分命令执行之前完成。场景切换时重置和 GLES 版一样切关卡、切视角时要重置历史帧数据。在 Vulkan 里这可能意味着你需要重建对象或者通过描述信息来控制。从稳定等级 0.5 开始如果你在描述信息里有控制稳定等级的字段建议从 0.5 开始根据是否有鬼影或闪烁来微调。时域超分是效果最好的方案但也是接入成本最高的。在 Vulkan 环境下你还需要额外处理好同步问题。不过如果你的引擎已经有 TAA 的基础设施那接入时域超分的边际成本其实不高。