HIP RT v2.1 介绍 - 批量几何体构建、变换查询函数等

首次发布:
最后更新:
Daniel Meister's avatar
Daniel Meister

我们非常激动地宣布 HIP RT v2.1 发布。在本篇博文中,我们将讨论新的功能和相应的 API 更改。

批量构建

在之前的版本中,底部几何体是逐个构建的,这对于大量小型几何体来说可能效率低下。我们引入了针对小型几何体的批量构建功能,允许我们在一次内核启动中高效地构建许多小型几何体。我们添加了以下函数:

hiprtError hiprtCreateGeometries(...);
hiprtError hiprtDestroyGeometries(...);
hiprtError hiprtBuildGeometries(...);
hiprtError hiprtGetGeometriesBuildTemporaryBufferSize(...);

这些函数执行与相应的单几何体变体相同的操作,一次处理多个几何体。例如,hiprtCreateGeometries 接受多个构建输入,通过一次 malloc 调用高效地创建多个几何体。同样,hiprtDestroyGeometries 一次销毁多个几何体。对于构建本身,hiprtBuildGeometries 接受多个构建输入并一次构建多个几何体。小型几何体(最多 512 个几何图元)将在一次内核启动中构建,而较大的几何体将使用指定的质量构建进行逐个处理。请注意,HIP RT 内部会分离小型和大型几何体,因此用户无需显式进行此操作。小型几何体的最大大小(即图元数量小于或等于此值的几何体将通过批量构建进行处理)可以在构建选项中指定。

struct hiprtBuildOptions
{
hiprtBuildFlags buildFlags;
u32 batchBuildMaxPrimCount;
};

如果 batchBuildMaxPrimCount == 0,则禁用批量构建,所有几何体将按顺序处理。需要注意的是,批量构建内部使用修改版的快速构建,这可能会对加速结构和光线追踪性能的质量产生轻微的负面影响。尽管如此,我们认为这种负面影响微不足道,因为几何体非常小。

全局和动态堆栈

全局堆栈有效地结合了共享内存和全局内存。虽然共享缓冲区分配相对简单,但确定全局缓冲区的大小却相当复杂。我们决定更改 API 以使分配更加用户友好。我们引入了两个新的结构来表示这两种缓冲区类型:

struct hiprtGlobalStackBuffer
{
u32 stackSize;
u32 stackCount;
void* stackData;
};
struct hiprtSharedStackBuffer
{
u32 stackSize;
void* stackData;
};

这两个结构都封装了缓冲区地址和堆栈大小。全局缓冲区堆栈还有一个堆栈计数,定义了我们需要的堆栈数量(通常每个计划的线程一个)。全局缓冲区可以通过以下函数创建/销毁:

hiprtError hiprtCreateGlobalStackBuffer(hiprtContext context, const hiprtGlobalStackBufferInput& input, hiprtGlobalStackBuffer* stackBufferOut);
hiprtError hiprtDestroyGlobalStackBuffer(hiprtContext context, hiprtGlobalStackBuffer stackBuffer);
struct hiprtGlobalStackBufferInput
{
hiprtStackType type = hiprtStackTypeGlobal;
u32 stackSize;
u32 threadCount;
};

除了类型(我们将在下文讨论)之外,我们仅定义了堆栈大小和计划线程的数量。在分配了这两个缓冲区后,我们最终可以创建一个堆栈对象:

hiprtGlobalStackBuffer globalStackBuffer = ...;
hiprtSharedStackBuffer sharedStackBuffer = ...;
hiprtGlobalStack stack(globalStackBuffer, sharedStackBuffer);

全局堆栈缓冲区包含所有计划线程的堆栈,这可能是一种浪费,因为只有一小部分线程正在并发执行。我们引入了动态堆栈,该堆栈仅为活动线程分配堆栈,并在需要时动态地将堆栈分配给线程。HIP RT 在堆栈构造函数中内部处理整个过程。动态堆栈的创建方式与全局堆栈相同;我们需要将 hiprtGlobalStackBufferInput 中的类型更改为 hiprtStackTypeDynamic(我们无需设置 threadCount):

hiprtDynamicStack stack(globalStackBuffer, sharedStackBuffer);

当然,这会带来一些额外的开销,略微增加寄存器使用量。我们为内存有限的系统提供了动态堆栈选项。

变换查询函数

对于某些着色计算,我们需要从/到对象空间进行变换。我们可以将这些变换显式地存储在单独的缓冲区中,但这很浪费,因为 hiprtScene 已经包含了变换数据。我们提供了允许从场景对象查询这些变换的函数:

hiprtFrameSRT hiprtGetObjectToWorldFrameSRT(hiprtScene scene, u32 instanceID, float time);
hiprtFrameSRT hiprtGetWorldToObjectFrameSRT(hiprtScene scene, u32 instanceID, float time);
hiprtFrameMatrix hiprtGetObjectToWorldFrameMatrix(hiprtScene scene, u32 instanceID, float time);
hiprtFrameMatrix hiprtGetWorldToObjectFrameMatrix(hiprtScene scene, u32 instanceID, float time);

请注意,这些函数接受时间参数。这对于运动模糊尤其有用,因为 HIP RT 内部可以正确地插值变换。

其他功能

  • 我们优化了 Orochi 中的基数排序。这提高了快速构建和平衡构建的速度(这两种构建都依赖于基数排序)。
  • 我们在顶级场景对象中使用了更紧密的变换实例框,从而提高了光线追踪性能。
  • 我们修复了几何体 IO 函数(hiprtSaveGeometryhiprtLoadGeometry)。请注意,场景 IO 函数仍然无法正常工作。
  • 我们在 hiprtBuildTraceKernelshiprtBuildTraceKernelsFromBitcode 中添加了一个选项来启用/禁用编译后的追踪内核的缓存。

立即下载

HIP RT v2.1 的下载链接可在 HIP RT 页面上找到。

如果您正在寻找有关开始使用 HIPRT 的指南,请查看 HIP RT SDK 教程存储库HIP RT 文档页面

Daniel Meister's avatar

Daniel Meister

Daniel Meister 是 AMD 的一名研究员和软件工程师。他的研究兴趣包括实时光线追踪、加速数据结构、全局照明、GPGPU 和用于渲染的机器学习。

相关新闻和技术文章

© . This site is unofficial and not affiliated with AMD.