游戏里需要 GPU 排序?试试 XEngine 高性能着色器(HPS)

你有没有遇到过这种场景:你的游戏里有大量的粒子、精灵或者透明物体,需要按照深度排序才能正确渲染。在 CPU 上排序当然可以,但数据要来回搬运,性能不好。如果能在 GPU 上直接排序,省去了数据搬运的开销,那该多好。

XEngine 的 HPS(High Performance Shader,高性能着色器)特性就是做这个的。它提供了一个 GPU 端的基数排序(Radix Sort)能力,让你可以在 Vulkan 命令缓冲里直接录制排序命令,由 GPU 高效完成排序。

什么是基数排序

下面是 HPS 基数排序的整体使用流程:

查询设备是否支持 HPS 扩展

支持?

退出或使用 CPU 排序

创建 XEG_HPS 对象

上传待排序数据到 GPU 内存

录制排序命令到命令缓冲

提交命令缓冲执行排序

排序结果留在 GPU 内存

直接用于后续渲染步骤

退出时销毁 HPS 对象

基数排序是一种非比较排序算法。简单说,它不是通过比较元素大小来排序,而是按照每个元素的"位"(从低位到高位)逐轮分配和收集。基数排序的时间复杂度是 O(nk),其中 n 是元素数量,k 是位数。对于 32 位整数来说,k=32,所以效率很高。

GPU 上的基数排序特别适合大规模数据的排序,因为 GPU 有大量的并行计算单元,可以同时处理很多数据。

查询支持

HPS 基数排序需要通过扩展查询接口确认设备支持:

uint32_t propertyCount = 0;
HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice, &propertyCount, NULL);

XEG_ExtensionProperties* properties = malloc(sizeof(XEG_ExtensionProperties) * propertyCount);
HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice, &propertyCount, properties);

bool supported = false;
for (uint32_t i = 0; i < propertyCount; i++) {
    if (strcmp(properties[i].extensionName, XEG_HPS_RADIX_SORT_EXTENSION_NAME) == 0) {
        supported = true;
        break;
    }
}
free(properties);
if (!supported) return;

XEG_HPS_RADIX_SORT_EXTENSION_NAME 的值是 "XEG_hps_radix_sort"。这个特性起始版本是 6.0.0(20)。

创建 XEG_HPS 对象

确认支持之后,创建 HPS 对象:

XEG_HPS hps = VK_NULL_HANDLE;

XEG_HPSCreateInfo createInfo = {
    // 创建参数
};

VkResult result = HMS_XEG_CreateHPS(device, &createInfo, &hps);
if (result != VK_SUCCESS) {
    // 创建失败
    return;
}

HMS_XEG_CreateHPS 的三个参数:

  • deviceVkDevice
  • pCreateInfoXEG_HPSCreateInfo 结构体指针,不允许为空
  • pHps:输出句柄的指针

返回 VK_SUCCESS 表示创建成功。

录制排序命令

有了 HPS 对象之后,你可以在命令缓冲里录制基数排序命令:

XEG_HPSRadixSortDescription description = {
    // 排序的输入输出信息
};

VkResult result = HMS_XEG_CmdRadixSortHPS(commandBuffer, hps, &description);
if (result != VK_SUCCESS) {
    // 命令录制失败
}

HMS_XEG_CmdRadixSortHPS 的三个参数:

  • commandBufferVkCommandBuffer
  • hps:已创建的 XEG_HPS 对象
  • pDescriptionXEG_HPSRadixSortDescription 结构体指针,不允许为空

返回 VK_SUCCESS 表示命令录制成功。

XEG_HPSRadixSortDescription 描述了排序的具体信息:要排序的数据在哪里、排序结果写到哪里、排序的 key 是什么等等。这些信息的具体字段需要参考结构体的定义。

销毁对象

用完之后记得销毁:

HMS_XEG_DestroyHPS(hps);

完整流程

// 1. 查询扩展
uint32_t propertyCount = 0;
HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice, &propertyCount, NULL);
XEG_ExtensionProperties* properties = malloc(sizeof(XEG_ExtensionProperties) * propertyCount);
HMS_XEG_EnumerateDeviceExtensionProperties(physicalDevice, &propertyCount, properties);

bool supported = false;
for (uint32_t i = 0; i < propertyCount; i++) {
    if (strcmp(properties[i].extensionName, XEG_HPS_RADIX_SORT_EXTENSION_NAME) == 0) {
        supported = true;
        break;
    }
}
free(properties);
if (!supported) return;

// 2. 创建 HPS 对象
XEG_HPS hps = VK_NULL_HANDLE;
XEG_HPSCreateInfo createInfo = { /* ... */ };
HMS_XEG_CreateHPS(device, &createInfo, &hps);

// 3. 每帧:录制排序命令
XEG_HPSRadixSortDescription desc = { /* 当前帧的排序参数 */ };
HMS_XEG_CmdRadixSortHPS(commandBuffer, hps, &desc);

// 4. 提交命令缓冲
vkQueueSubmit(queue, 1, &submitInfo, fence);

// 5. 排序结果在 GPU 内存里,可以直接用于后续的渲染步骤

// 6. 退出时销毁
HMS_XEG_DestroyHPS(hps);

和 XEG_StructureType 的关系

HPS 使用了 XEG_StructureType 枚举里的三个值:

  • XEG_STRUCTURE_TYPE_HPS_CREATE_INFO = 1001
  • XEG_STRUCTURE_TYPE_HPS_RADIX_SORT = 1002
  • XEG_STRUCTURE_TYPE_HPS_RADIX_SORT_DESCRIPTION = 1003

如果你的结构体需要设置 sType 字段,记得用对应的枚举值。

实际应用场景

GPU 排序和 CPU 排序的对比:

少量数据

大量数据且在 GPU 渲染链中

需要对大量数据排序

数据量和性能要求?

CPU 排序即可

使用 HPS GPU 排序

数据无需搬运 开销低

数据已在 GPU 避免回读

GPU 并行计算效率高

排序结果无缝衔接渲染管线

  1. 粒子系统排序:大量透明粒子需要按照深度排序才能正确渲染。在 GPU 上排序避免了数据回读到 CPU 的开销。

  2. 精灵渲染:2D 游戏里大量的精灵需要按层级排序。GPU 排序可以让这个过程更快。

  3. 光线追踪加速结构:有些光线追踪算法需要对图元进行空间排序来构建加速结构。

  4. 物理模拟:碰撞检测中经常需要对物体按空间位置排序。

使用建议

  1. 数据要提前上传到 GPU:基数排序是在 GPU 上执行的,所以待排序的数据必须在 GPU 内存里。如果你的数据在 CPU 上,需要先上传。

  2. 排序结果也在 GPU 上:排序完成后,结果直接存在 GPU 内存里,可以无缝用于后续的渲染步骤。如果你需要在 CPU 上使用排序结果,需要回读。

  3. 命令录制而非立即执行HMS_XEG_CmdRadixSortHPS 只是把排序命令录制到命令缓冲里,不会立即执行。你需要提交命令缓冲之后排序才会真正运行。

  4. 检查返回值:创建和录制命令都有返回值,记得检查是否为 VK_SUCCESS

HPS 是一个很实用的 GPU 计算工具。虽然它目前只提供了基数排序能力,但这个能力在游戏开发中用得非常多。如果你的游戏有大量的排序需求,HPS 可以帮你省下不少 CPU 时间。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐