空域AI超分
======

从26.0.0版本开始，新增支持Vulkan协议。

XEngine Kit提供空域AI超分能力，基于单帧图像使用AI推理生成滤波参数进行超采样，通过GPU、NPU协同工作，实现比空域GPU超分更好的画质，建议超分倍率在1.5倍以下时使用。

#### 约束与限制

*   支持的设备类型：Phone，从5.1.0(18)版本开始新增支持Tablet、PC/2in1设备，从5.1.1(19)版本开始新增支持TV设备。
    
*   可通过以下方式查询相关扩展特性是否支持：
    
    *   对于OpenGL ES，使用[HMS\_XEG\_GetString](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_getstring)扩展特性查询接口进行查询。
        
    *   对于Vulkan，使用[HMS\_XEG\_EnumerateDeviceExtensionProperties](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_enumeratedeviceextensionproperties)扩展特性查询接口进行查询。
        
    
    如查询结果包含[XEG\_NEURAL\_UPSCALE\_EXTENSION\_NAME](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#xeg_neural_upscale_extension_name)，则表示支持该特性，若查询结果未包含，则表示不支持该特性。
    

#### 接口说明

以下为空域AI超分特性需要使用的接口，详细说明请参考[接口文档](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine)。

**OpenGL ES接口：**

| 接口名 | 描述 |
| :-- | :-- |
| const GLubyte \* HMS\_XEG\_GetString(GLenum name) | XEngine OpenGL ES扩展特性查询接口。 |
| GL\_APICALL void GL\_APIENTRY HMS\_XEG\_NeuralUpscaleParameter(GLenum pname, GLvoid \*param) | 设置空域AI超分输入参数。 |
| GL\_APICALL void GL\_APIENTRY HMS\_XEG\_RenderNeuralUpscale(GLuint inputTexture) | 执行空域AI超分渲染命令。 |

**Vulkan接口：**

| 接口名 | 描述 |
| :-- | :-- |
| VKAPI\_ATTR VkResult VKAPI\_CALL HMS\_XEG\_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, uint32\_t \*pPropertyCount, XEG\_ExtensionProperties \*pProperties) | XEngine Vulkan扩展特性查询接口。 |
| VKAPI\_ATTR VkResult VKAPI\_CALL HMS\_XEG\_CreateNeuralUpscale(VkDevice device, const XEG\_NeuralUpscaleCreateInfo \*pCreateInfo, XEG\_NeuralUpscale \*pNeuralUpscale) | 创建XEG\_NeuralUpscale对象。 |
| VKAPI\_ATTR VkResult VKAPI\_CALL HMS\_XEG\_CmdRenderNeuralUpscale(VkCommandBuffer commandBuffer, XEG\_NeuralUpscale neuralUpscale, const XEG\_NeuralUpscaleDescription \*pDescription) | 执行空域AI超分渲染命令。 |
| VKAPI\_ATTR void VKAPI\_CALL HMS\_XEG\_DestroyNeuralUpscale(XEG\_NeuralUpscale neuralUpscale) | 销毁XEG\_NeuralUpscale对象。 |

#### 业务流程

*   下面是基于OpenGL ES图形API平台集成空域AI超分的主要业务流程
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/47/v3/Nl4_Ltx-TT-YmAclOMqYug/zh-cn_image_0000002625188397.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073545Z&HW-CC-Expire=86400&HW-CC-Sign=80FFB269C5D1CE139FA6CA8DFAD779DBB66F027D0FAD8188084A2CD2D1F004C1)
    

1.  用户在进入游戏初始化场景时调用HMS\_XEG\_GetString接口查询XEngine支持的特性，当查询接口返回支持的特性列表中包含空域AI超分时代表可以使用此特性。
2.  初始化场景，空域AI超分的输入纹理需要使用OH\_NativeBuffer来创建。
3.  调用HMS\_XEG\_NeuralUpscaleParameter接口配置超分参数，包含超分输入纹理对应的OH\_NativeBuffer句柄。
4.  游戏运行时，每帧先渲染待超分的纹理。
5.  调用HMS\_XEG\_RenderNeuralUpscale接口执行超分，超分结果会写出到当前绑定的帧缓冲。
6.  渲染后续流程，如UI。
7.  当前帧已全部渲染完成，进行送显。
8.  当游戏退出时，释放游戏创建的资源，XEngine内部资源会自行释放。

*   下面是基于Vulkan图形API平台集成空域AI超分的主要业务流程
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/56/v3/OeA1qv7dQbOvEzc6iM8h-w/zh-cn_image_0000002625108541.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073545Z&HW-CC-Expire=86400&HW-CC-Sign=45BD4E702373BDB9C4D86505BC49FF2B04C7C3D045F068A6320E4E2D85EEB4BC)
    

1.  用户在进入游戏初始化场景时调用HMS\_XEG\_EnumerateDeviceExtensionProperties接口查询XEngine支持的特性，当查询接口返回支持的特性列表中包含空域AI超分时代表可以使用此特性。
2.  调用HMS\_XEG\_CreateNeuralUpscale接口创建超分实例。
3.  当游戏运行时，游戏渲染待超分的当前帧纹理。
4.  当待超分纹理渲染完成时，调用HMS\_XEG\_CmdRenderNeuralUpscale接口对待超分的纹理超分。
5.  当超分渲染完成时，游戏渲染剩下的纹理，如UI等。
6.  当前帧已全部渲染完成，进行送显。
7.  当游戏退出时，调用HMS\_XEG\_DestroyNeuralUpscale接口销毁超分实例。

#### 开发步骤

本章以OpenGL ES和Vulkan图像API集成为例，说明XEngine集成操作过程。

#### \[h2\]配置项目

编译HAP时，Native层so编译需要依赖NDK中的libxengine.so。

*   头文件引用
    
    按需引用XEngine的头文件，如使用OpenGL ES空域AI超分。
    
    #include <EGL/egl.h>
    #include <EGL/eglext.h>
    #include <GLES2/gl2.h>
    #include <GLES2/gl2ext.h>
    
    #include <native\_buffer/native\_buffer.h>
    #include <native\_window/external\_window.h>
    #include "xengine/xeg\_gles\_neural\_upscale.h"
    #include "xengine/xeg\_gles\_extension.h"
    
    按需引用XEngine的头文件，如使用Vulkan空域AI超分。
    
    #include "xengine/xeg\_vulkan\_temporal\_upscale.h"
    // ...
    #include "xengine/xeg\_vulkan\_extension.h"
    
*   编写CMakeLists.txt
    
    按需引用XEngine的CMakeLists，如使用OpenGL ES空域AI超分功能，CMakeLists.txt部分示例代码如下，完整示例代码请参见[Demo（GPU加速引擎-GLES）](https://gitcode.com/harmonyos_samples/xengine-samplecode-gles-demo-cpp)。
    
    find\_library(
        # Sets the name of the path variable.
        native-buffer-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        native\_buffer
    )
    
    find\_library(
        # Sets the name of the path variable.
        native-window-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        native\_window
    )
    find\_library(
        # Sets the name of the path variable.
        EGL-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        EGL
    )
    
    find\_library(
        # Sets the name of the path variable.
        GLES-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        GLESv3
    )
    
    find\_library(
       # Sets the name of the path variable.
       xengine-lib
       # Specifies the name of the NDK library that
       # you want CMake to locate.
       xengine
    )
    # ...
    target\_link\_libraries(nativerender PUBLIC
        ${EGL-lib} ${GLES-lib} ${xengine-lib}
        # ...
        ${native-window-lib}
        ${native-buffer-lib}
        )
    
    按需引用XEngine的CMakeLists，如使用Vulkan空域AI超分功能，CMakeLists.txt部分示例代码如下，完整示例代码请参见[Demo（GPU加速引擎-Vulkan）](https://gitcode.com/harmonyos_samples/xengine-samplecode-vulkan-demo-cpp)。
    
    find\_library(
       # Sets the name of the path variable.
       xengine-lib
       # Specifies the name of the NDK library that
       # you want CMake to locate.
       xengine
    )
    # ...
    find\_library(
        # Sets the name of the path variable.
        hilog-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        hilog\_ndk.z
    )
    
    find\_library(
        # Sets the name of the path variable.
        libace-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        ace\_ndk.z
    )
    
    find\_library(
        # Sets the name of the path variable.
        libnapi-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        ace\_napi.z
    )
    
    find\_library(
        # Sets the name of the path variable.
        libuv-lib
        # Specifies the name of the NDK library that
        # you want CMake to locate.
        uv
    )
    
    add\_library(libassimp-shared SHARED IMPORTED)
    set\_target\_properties(
            libassimp-shared
            PROPERTIES
            IMPORTED\_LOCATION
            ${CMAKE\_CURRENT\_SOURCE\_DIR}/libs/arm64-v8a/libassimp.so
    )
    
    target\_link\_libraries(nativerender PUBLIC
        ${EGL-lib} ${GLES-lib} ${xengine-lib}
        ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib} libc++.a librawfile.z.so libassimp-shared libc.so libz.so ${libvsync-lib}
        # ...
        )
    

#### \[h2\]集成XEngine空域AI超分（OpenGL ES）

Native层实现使用OpenGL ES和XEngine图形API搭建图像渲染管线并集成空域AI超分，渲染结果通过[XComponent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-xcomponent)组件显示到屏幕。

本节阐述OpenGL ES图形API的空域AI超分的使用，详细代码请参见[Demo（GPU加速引擎-GLES）](https://gitcode.com/harmonyos_samples/xengine-samplecode-gles-demo-cpp)。

在调用XEngine Kit能力前，需要先通过[Syscap](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/syscap#什么是systemcapabilitysyscap)查询您的目标设备是否支持SystemCapability.Graphic.XEngine系统能力。

1.  调用[HMS\_XEG\_GetString](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_getstring)接口，获取XEngine支持的扩展信息，只有在支持[XEG\_NEURAL\_UPSCALE\_EXTENSION\_NAME](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#xeg_neural_upscale_extension_name)扩展时才可以使用空域AI超分的相关接口。
    
     // 查询XEngine支持的GLES扩展信息
     std::string extensions = (const char\*)HMS\_XEG\_GetString(XEG\_EXTENSIONS);
     LOGI("Model3DSponza support extensions: %{public}s", extensions.c\_str());
     // ...
    // 检查是否支持空域AI超分
     std::string::size\_type neuralIdx = extensions.find(XEG\_NEURAL\_UPSCALE\_EXTENSION\_NAME);
     if (neuralIdx == std::string::npos) {
         isSupportNeural = false;
         LOGE("Model3DSponza not support Neural.");
     }
    
2.  创建输入纹理，并关联一个OH\_NativeBuffer。
    
    // 获取函数指针
    fp\_eglCreateImageKHR = reinterpret\_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
    if (fp\_eglCreateImageKHR == nullptr) {
        LOGE("eglCreateImageKHR not found!");
    }
    fp\_eglDestroyImageKHR = reinterpret\_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
    if (fp\_eglDestroyImageKHR == nullptr) {
        LOGE("eglDestroyImageKHR not found!");
    }
    fp\_glEGLImageTargetTexture2DOES =
        reinterpret\_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
    if (fp\_glEGLImageTargetTexture2DOES == nullptr) {
        LOGE("glEGLImageTargetTexture2DOES not found!");
    }
    // ...
        // 创建OH\_NativeBuffer
        OH\_NativeBuffer\_Config config = {};
        // 渲染宽高和送显宽高均为用户自定义参数
        config.width = width;
        config.height = height;
        config.usage = NATIVEBUFFER\_USAGE\_CPU\_READ | NATIVEBUFFER\_USAGE\_CPU\_READ\_OFTEN | NATIVEBUFFER\_USAGE\_HW\_TEXTURE |
                       NATIVEBUFFER\_USAGE\_HW\_RENDER | NATIVEBUFFER\_USAGE\_ALIGNMENT\_512;
        config.format = NATIVEBUFFER\_PIXEL\_FMT\_RGBA\_8888;
        m\_lightNativeBufferHandle = OH\_NativeBuffer\_Alloc(&config);
        if (m\_lightNativeBufferHandle == nullptr) {
            // 创建失败，用户可自定义错误处理
            LOGE("OH\_NativeBuffer\_Alloc failed, size:(%{public}d, %{public}d) ", width, height);
        }
        m\_nativeWindowBuffer = OH\_NativeWindow\_CreateNativeWindowBufferFromNativeBuffer(m\_lightNativeBufferHandle);
        if (m\_nativeWindowBuffer == nullptr) {
            LOGE("Error to Create nativeWindowBuffer");
        }
        m\_eglImage = fp\_eglCreateImageKHR(eglGetCurrentDisplay(), EGL\_NO\_CONTEXT, EGL\_NATIVE\_BUFFER\_OHOS,
                                          static\_cast<EGLClientBuffer>(m\_nativeWindowBuffer), nullptr);
        if (m\_eglImage == nullptr) {
            LOGE("Error to Create m\_eglImage");
        }
        // 关联超分输入纹理和eglImage
        fp\_glEGLImageTargetTexture2DOES(GL\_TEXTURE\_2D, m\_eglImage);
    
3.  在超分输入纹理上进行渲染。
    
    glViewport(0, 0, renderWidth, renderHeight);
    // ...
    if (glCheckFramebufferStatus(GL\_FRAMEBUFFER) != GL\_FRAMEBUFFER\_COMPLETE) {
        // 创建framebuffer失败，用户可自定义错误处理
        LOGE("Model3DSponza create frameBuffer %{public}s failed", bufferName.c\_str());
    }
    // ...
    unsigned int frameBuffer;
    glGenFramebuffers(1, &frameBuffer);
    glBindFramebuffer(GL\_FRAMEBUFFER, frameBuffer);
    // ...
    glFramebufferTexture2D(GL\_FRAMEBUFFER, index, GL\_TEXTURE\_2D, texture, 0);
    
4.  调用[HMS\_XEG\_NeuralUpscaleParameter](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_neuralupscaleparameter)接口，设置空域AI超分的输入参数。
    
    // m\_sharpness为用户自定义超分锐化参数
    HMS\_XEG\_NeuralUpscaleParameter(XEG\_NEURAL\_UPSCALE\_SHARPNESS, &m\_sharpness);
    // upscaleScissor为超分输入纹理的裁剪窗口参数
    HMS\_XEG\_NeuralUpscaleParameter(XEG\_NEURAL\_UPSCALE\_SCISSOR, upscaleScissor);
    // 设置超分输入纹理对应的OH\_NativeBuffer句柄
    HMS\_XEG\_NeuralUpscaleParameter(XEG\_NEURAL\_UPSCALE\_INPUT\_HANDLE, m\_lightNativeBufferHandle);
    
5.  调用[HMS\_XEG\_RenderNeuralUpscale](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_renderneuralupscale)接口执行空域AI超分。
    
    // 绑定绘制超分结果的帧缓冲，此处使用默认帧缓冲，也可使用用户自定义帧缓冲
    glBindFramebuffer(GL\_FRAMEBUFFER, m\_upscaleFBO);
    glViewport(0, 0, m\_highResWidth, m\_highResHeight);
    // ...
    // 执行空域AI超分
    HMS\_XEG\_RenderNeuralUpscale(m\_lowLightNativeTexture);
    
6.  不需要进行超分渲染时，销毁相关资源。
    
    if (m\_eglImage != nullptr) {
        fp\_eglDestroyImageKHR(eglGetCurrentDisplay(), m\_eglImage);
    }
    
    if (m\_nativeWindowBuffer != nullptr) {
        OH\_NativeWindow\_DestroyNativeWindowBuffer(m\_nativeWindowBuffer);
    }
    
    if (m\_lightNativeBufferHandle != nullptr) {
        OH\_NativeBuffer\_Unreference(m\_lightNativeBufferHandle);
    }
    // ...
    glDeleteFramebuffers(1, &m\_fsrEASUFBO);
    
    glDeleteTextures(1, &m\_gPosition);
    

#### \[h2\]集成XEngine空域AI超分（Vulkan）

使用Vulkan图形API搭建图像渲染管线并集成空域AI超分在Native层实现，渲染结果通过[XComponent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-xcomponent)组件显示到屏幕。

本节阐述Vulkan图形API的空域AI超分使用，详细代码请参见[Demo（GPU加速引擎-Vulkan）](https://gitcode.com/harmonyos_samples/xengine-samplecode-vulkan-demo-cpp)。

在调用XEngine Kit能力前，需要先通过[Syscap](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/syscap#什么是systemcapabilitysyscap)查询您的目标设备是否支持SystemCapability.Graphic.XEngine系统能力。

1.  调用[HMS\_XEG\_EnumerateDeviceExtensionProperties](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_enumeratedeviceextensionproperties)接口，获取XEngine支持的扩展信息，只有在支持XEG\_NEURAL\_UPSCALE\_EXTENSION\_NAME扩展时才可以使用空域AI超分的相关接口。
    
    // 查询XEngine支持的Vulkan扩展列表
    std::vector<std::string> supportedExtensions;
    uint32\_t pPropertyCount;
    // physicalDevice为Vulkan物理设备，用户需进行初始化
    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 (auto ext : pProperties) {
                supportedExtensions.push\_back(ext.extensionName);
            }
        }
    }
    // ...
    if (std::find(supportedExtensions.begin(), supportedExtensions.end(), XEG\_NEURAL\_UPSCALE\_EXTENSION\_NAME) ==
        supportedExtensions.end()) {
        LOGE("XEG\_neural\_upscale not support");
        isSupportNeural = false;
    }
    
2.  声明实例句柄。
    
    XEG\_NeuralUpscale xegNeuralUpscale = nullptr;
    
3.  调用[HMS\_XEG\_CreateNeuralUpscale](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_createneuralupscale)接口，创建超分实例。
    
    // VkRect2D为Vulkan指定的二维区域结构
    // srcRect2D为超分输入纹理区域，用户可自定义
    VkRect2D srcRect2D;
    // srcRect2D.offset.x和srcRect2D.offset.y为原点偏移量
    srcRect2D.offset.x = 0;
    srcRect2D.offset.y = 0;
    // srcRect2D.extent.width与srcRect2D.extent.height为输入纹理采样区域宽高
    srcRect2D.extent.width = lowResWidth;
    srcRect2D.extent.height = lowResHeight;
    
    // dstRect2D为超分输出纹理区域，用户可自定义
    VkRect2D dstRect2D;
    // dstRect2D.offset.x和dstRect2D.offset.y为原点偏移量
    dstRect2D.offset.x = 0;
    dstRect2D.offset.y = 0;
    // dstRect2D.extent.width与dstRect2D.extent.height为超分纹理写入区域宽高
    dstRect2D.extent.width = highResWidth;
    dstRect2D.extent.height = highResHeight;
    
    XEG\_NeuralUpscaleCreateInfo createInfo;
    
    createInfo.sType = XEG\_STRUCTURE\_TYPE\_NEURAL\_UPSCALE\_CREATE\_INFO;
    createInfo.pNext = nullptr;
    createInfo.inputRegion = srcRect2D;
    createInfo.inputSize = {lowResWidth, lowResHeight};
    createInfo.outputSize = {highResWidth, highResHeight};
    createInfo.outputRegion = dstRect2D;
    createInfo.outputFormat = VK\_FORMAT\_R8G8B8A8\_UNORM;
    // device逻辑设备，用户需进行初始化
    VkResult res = HMS\_XEG\_CreateNeuralUpscale(device, &createInfo, &xegNeuralUpscale);
    if (res != VK\_SUCCESS) {
        LOGE("HMS\_XEG\_CreateNeuralUpscale Fatal : VkResult is %d", res);
    } else {
        LOGW("HMS\_XEG\_CreateNeuralUpscale success");
    }
    
4.  调用[HMS\_XEG\_CmdRenderNeuralUpscale](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_cmdrenderneuralupscale)接口下发超分，每帧都需要调用。
    
    XEG\_NeuralUpscaleDescription xegDescription{};
    xegDescription.sType = XEG\_STRUCTURE\_TYPE\_NEURAL\_UPSCALE\_DESCRIPTION;
    xegDescription.pNext = nullptr;
    // sharpness为用户自定义超分锐化参数，此处以参数为0.2f为例
    xegDescription.sharpness = 0.2f;
    // inputImageView为用户创建的超分输入图像的VkImageView
    xegDescription.inputImage = upscaleFrameBuffers.light.color.view;
    // outputImageView为用户创建的超分输出图像的VkImageView
    xegDescription.outputImage = upscaleFrameBuffers.upscale.color.view;
    // drawCmdBuffers\[currentBuffer\]为命令缓冲区，用户需进行初始化
    VkResult result = HMS\_XEG\_CmdRenderNeuralUpscale(drawCmdBuffers\[currentBuffer\], xegNeuralUpscale, &xegDescription);
    if (result != VK\_SUCCESS) {
        LOGE("HMS\_XEG\_CmdRenderNeuralUpscale Fatal : VkResult is %d", result);
    }
    
5.  调用[HMS\_XEG\_DestroyNeuralUpscale](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_destroyneuralupscale)接口销毁实例。
    
    HMS\_XEG\_DestroyNeuralUpscale(xegNeuralUpscale);