高性能GPU排序
========

从6.0.0(20) 版本开始，新增高性能GPU排序特性。

XEngine Kit HPS(High Performance Sorting)特性提供高性能GPU排序能力。相比于其它排序能力，该能力依托于华为Maleoon GPU的软硬结合优化，效率更高。

#### 约束与限制

可通过以下方式查询相关扩展特性是否支持：

对于Vulkan，使用[HMS\_XEG\_EnumerateDeviceExtensionProperties](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_enumeratedeviceextensionproperties)扩展特性查询接口进行查询，如查询结果包含XEG\_HPS\_RADIX\_SORT\_EXTENSION\_NAME，则表示支持该特性，若查询结果未包含，则表示不支持该特性。

#### 接口说明

以下接口为使用高性能GPU排序所需要使用的接口，关于这些接口的详细说明见[接口文档](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine)。

| 接口名 | 描述 |
| :-- | :-- |
| VKAPI\_ATTR VkResult VKAPI\_CALL HMS\_XEG\_CreateHPS (VkDevice device, const XEG\_HPSCreateInfo \*pCreateInfo, XEG\_HPS \*pHps) | 创建XEG\_HPS对象。 |
| VKAPI\_ATTR void VKAPI\_CALL HMS\_XEG\_DestroyHPS (XEG\_HPS hps) | 销毁XEG\_HPS对象。 |
| VKAPI\_ATTR VkResult VKAPI\_CALL HMS\_XEG\_CmdRadixSortHPS (VkCommandBuffer commandBuffer, XEG\_HPS hps, const XEG\_HPSRadixSortDescription \*pDescription) | 录制HPS排序命令，使用此接口前需要通过HMS\_XEG\_EnumerateDeviceExtensionProperties接口查询是否支持XEG\_HPS\_RADIX\_SORT\_EXTENSION\_NAME扩展。 |

#### 业务流程

*   下面是以Vulkan应用程序渲染为例，说明使用高性能GPU排序的的主要业务流程
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c6/v3/r_uuJzrjQP-0Nq3tFTglYQ/zh-cn_image_0000002594828956.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073546Z&HW-CC-Expire=86400&HW-CC-Sign=3049E5144B9D1D7C9E232153E0DB512AF441288EE473F6F025CBAC69F9FD8D49)
    

1.  应用调用[HMS\_XEG\_EnumerateDeviceExtensionProperties](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_enumeratedeviceextensionproperties)接口获取扩展属性列表。如果在列表中未找到[XEG\_HPS\_RADIX\_SORT\_EXTENSION\_NAME](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#xeg_hps_radix_sort_extension_name)，说明当前设备不支持高性能GPU排序。
2.  应用调用[HMS\_XEG\_CmdRadixSortHPS](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_cmdradixsorthps)录制排序命令。
3.  XEngine Kit返回一个command buffer。
4.  应用调用vkQueueSubmit接口将排序命令提交到GPU队列执行，GPU并行完成高性能排序。
5.  XEngine Kit返回排序结果。
6.  应用调用[HMS\_XEG\_DestroyHPS](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_destroyhps)接口销毁HPS实例，释放全部GPU资源。销毁后HPS句柄失效，不可再使用。

#### 开发步骤

本章以在Vulkan应用程序渲染为例，说明使用高性能GPU排序的开发步骤。

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

编译HAP时，Native层so需要依赖NDK中的XEngine相关库和头文件。

*   头文件引用
    
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <xengine/xeg\_vulkan\_hps.h>
    #include <xengine/xeg\_vulkan\_extension.h>
    #include <xengine/xeg\_extension\_defs.h>
    
*   CMakeLists.txt添加库依赖
    
    CMakeLists.txt中添加对XEngine动态链接库依赖的代码如下。
    
    find\_library(
        # 设置路径变量的名称。
        xengine-lib
        # 指定希望CMake定位的NDK库的名称。
        xengine
    )
    target\_link\_libraries(nativerender PUBLIC
        // 其他库文件
        // ...
        ${xengine-lib})
    

#### \[h2\]集成高性能GPU排序（Vulkan）

XEngine 高性能GPU排序可以独立使用。相关代码在Native层实现。

在调用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\_HPS\_RADIX\_SORT\_EXTENSION\_NAME扩展时才可以使用高性能GPU排序接口。
    
    VkPhysicalDevice physicalDevice;
    std::vector<std::string> supportedExtensions;
    uint32\_t propertyCount;
    HMS\_XEG\_EnumerateDeviceExtensionProperties(physicalDevice, &propertyCount, nullptr);
    if (propertyCount > 0) {
        std::vector<XEG\_ExtensionProperties> properties(propertyCount);
        if (HMS\_XEG\_EnumerateDeviceExtensionProperties(physicalDevice, &propertyCount, &properties.front()) ==
            VK\_SUCCESS) {
            for (auto ext : properties) {
                supportedExtensions.push\_back(ext.extensionName);
            }
        }
    }
    if (std::find(supportedExtensions.begin(), supportedExtensions.end(), XEG\_HPS\_RADIX\_SORT\_EXTENSION\_NAME) ==
        supportedExtensions.end()) {
        exit(1);
    }
    
2.  准备HPS相关资源。
    
    VkDevice device;
    VkCommandBuffer cmdBuffer;
    VkQueue queue;
    // 要被排序的key
    VkBuffer keyBuffer;
    // 与key对应的value
    VkBuffer indexBuffer;
    // 排序量
    VkBuffer sortCount;
    
3.  声明实例句柄。
    
    XEG\_HPS xegHPS { VK\_NULL\_HANDLE };
    
4.  调用[HMS\_XEG\_CreateHPS](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_createhps)接口，实例化句柄。
    
    // 构造输入描述符
    XEG\_HPSRadixSort sorInfo{
        XEG\_STRUCTURE\_TYPE\_HPS\_RADIX\_SORT,
        nullptr
    };
    
    XEG\_HPSCreateInfo info {
        XEG\_STRUCTURE\_TYPE\_HPS\_CREATE\_INFO,
        &sorInfo
    };
    // 实例化句柄
    HMS\_XEG\_CreateHPS(device, &info, &xegHPS);
    
5.  构造排序描述符，调用[HMS\_XEG\_CmdRadixSortHPS](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/xengine-kit-xengine#hms_xeg_cmdradixsorthps)接口录制排序命令。
    
    VkCommandBufferBeginInfo cmdBufferBeginInfo {};
    cmdBufferBeginInfo.sType = VK\_STRUCTURE\_TYPE\_COMMAND\_BUFFER\_BEGIN\_INFO;
    
    // 录制排序命令
    vkBeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo);
    XEG\_HPSRadixSortDescription sortDescription{
        XEG\_STRUCTURE\_TYPE\_HPS\_RADIX\_SORT\_DESCRIPTION,
        nullptr,
        sortCount,
        keyBuffer,
        indexBuffer
    };
    HMS\_XEG\_CmdRadixSortHPS(cmdBuffer, xegHPS, &sortDescription);
    vkEndCommandBuffer(cmdBuffer);
    
6.  提交排序命令。
    
    // 提交command buffer
    VkResult res;
    {
        VkSubmitInfo submitInfo{};
        submitInfo.sType = VK\_STRUCTURE\_TYPE\_SUBMIT\_INFO;
        submitInfo.waitSemaphoreCount = 0;
        submitInfo.signalSemaphoreCount = 0;
        submitInfo.pSignalSemaphores = nullptr;
        submitInfo.commandBufferCount = 1;
        submitInfo.pCommandBuffers = &cmdBuffer;
        submitInfo.pWaitSemaphores = nullptr;
        res = vkQueueSubmit(queue, 1, &submitInfo, nullptr);
    }
    // 等待结束
    vkDeviceWaitIdle(device);
    
7.  销毁HPS对象。
    
    if(xegHPS){
        HMS\_XEG\_DestroyHPS(xegHPS);
    }