| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> Vulkan_Ray Tracing 01_API基础 -> 正文阅读 |
|
[人工智能]Vulkan_Ray Tracing 01_API基础 |
本专栏我们主要来学一下Vulkan的光线追踪API的具体实现,本章主要是对其光追API拓展的简介,具体参照官网的两篇文章:Ray Tracing In Vulkan与 Vulkan-Guide。 一、Vulkan光追介绍1.1 显卡特性Vulkan光线追踪的版本包括许多Vulkan、SPIR-V和GLSL扩展。 主要的Vulkan扩展是VK_KHR_ray_tracing,它添加了:
Vulkan光追的某些功能是可选的,因此请确保检查驱动程序上支持的功能和属性! 此扩展的特征由VKPhysicalDeviceRacingFeaturesKHR结构描述。结构体如下:
具体光追实现只需要支持rayTracing和rayTracingIndirectTraceRays。还应注意,此扩展需要Vulkan 1.2(或以前版本的扩展)版本中的描述符索引和bufferDeviceAddress功能。 此扩展的可查询属性由vkPhysicalDeviceRacingPropertiesKHR结构描述。这里值得注意的是,着色器头(shaderGroupHandleSize)的大小要求正好为32,而最大递归深度(maxRecursionDepth)仅要求为1。 VK_KHR_ray_tracing依赖于两个额外的扩展,这两个扩展被添加为附加功能的构建块。 这些扩展添加了基础设施,但不能单独启用功能。未来的扩展可能会在API的其他领域建立在这些扩展的基础上,但此时VK_KHR_ray_tracing只允许将此功能用于光线跟踪。 VK_KHR_deferred_host_operations允许将消耗比较大的驱动程序操作在应用程序管理的CPU线程池中执行,从而可以在后台线程上完成工作或跨多个内核并行化。使用光线跟踪,这可以用于光线跟踪管道编译或基于CPU的加速结构构造。 与VK_KHR_ray_tracing扩展一起使用的着色器作为使用两个新SPIR-V扩展的SPIR-V二进制文件提供给API:
开发人员可以使用GLSL或HLSL生成这些二进制文件。对于GLSL,有两个新的GLSL扩展:GLSL_EXT_ray_tracing和GLSL_EXT_ray_query。 HLSL支持也通过DXC(微软的开源HLSL编译器)提供,它允许Vulkan光线跟踪着色器使用微软定义的语法在HLSL中编写,只需稍加修改。 本文档的以下部分将详细介绍光线跟踪功能,包括创建和使用加速结构、主机和延迟操作、光线遍历、光线跟踪管道和光线查询。 1.2 加速结构(Acceleration Structure)为了在复杂的场景中获得高性能,光线跟踪针对在场景信息上构建的优化数据结构(称为加速结构(Acceleration Structure-AS))执行光线相交。加速结构分为两个层次,如下图所示。
建立任何一种加速结构都会在内存中产生不透明的、特定于实现的格式数据。bottom-level加速结构仅被top-level加速结构引用从而被使用,而top-level加速结构是可以被着色器作为描述符绑定的方式来进行访问。 使用vkCreateAccelerationStructureKHR创建加速结构,与Vulkan中的其他对象一样,加速结构的创建仅定义了加速结构的“形状”,必须使用vkBindAccelerationStructureMemoryKHR将内存分配并绑定到加速结构,然后才能进一步使用。不支持稀疏或专用分配。除了查询加速结构分配本身的内存需求之外,vkGetAccelerationStructureMemoryRequirementsKHR还返回在构建和更新过程中所需的辅助缓冲区的大小。 使用vk {Cmd} BuildAccelerationStructureKHR来执行构建。对于bottom-level加速结构,三角形的顶点数据或AABB的范围信息是从缓冲区中提取的。top-level加速结构从缓冲区的结构中提取每个实例的阴影,变换和参考信息。使用具有特殊标志的相同功能执行对加速度结构的更新,以指示需要从现有加速度结构更新位置。 由于加速结构存储器采用特定于实现的不透明格式,因此存在一组对加速结构数据执行操作的函数:vk {Cmd} CopyAccelerationStructureKHR,vk {Cmd} CopyAccelerationStructureToMemoryKHR和vk {Cmd} CopyMemoryToAccelerationStructureKHR。 除了基本的copy操作之外,这些功能还可以执行受限形式的序列化和反序列化,以保存和恢复具有特定版本兼容性要求的加速结构。 加速结构最终可能会占用比它本身所需空间更多的空间,因此对于大型静态加速结构,减少最终使用的空间量可能是有益的。应用程序可以使用vk {Cmd} WriteAccelerationStructuresPropertiesKHR查询最终的压缩大小,然后使用vk {Cmd} CopyAccelerationStructureKHR来压缩加速结构。 1.3 Host Operations(主机端操作-CPU端)Acceleration Structure(加速结构)是非常大的资源,管理它们需要大量的处理工作。 与其他渲染工作一起在设备上安排这项工作可能很棘手,特别是在需要主机Host干预的情况下。 Vulkan提供了加速结构操作的主机Host和设备Device变量,使应用程序可以更好地调度这些工作负载。 设备变量-Device Variants(vkCmdAccelerationStructureKHR)放入命令缓冲区并在设备时间轴上执行,而主机变量-Host Variants(vkAccelerationStructureKHR)直接在主机时间轴上执行。 1.4 Deferred Operations(延迟操作)在CPU上执行加速结构(Acceleration Structure)的构建和更新是相对容易并行化的工作量,我们希望能够在Vulkan中利用它。 应用程序可以在独立的线程上执行独立的命令,但是这种方法要求有足够的命令来充分利用计算机。 这也可能导致负载不平衡,因为某些命令可能要比其他命令花费更长的时间。 为了避免这些麻烦,我们添加了Deferred Operations(延迟操作)以启用命令内的并行性:将单个命令的工作分散到多个CPU内核上。 驱动程序管理的线程池是实现此目的的一种方法,但与Vulkan的低级显式原理不符。 应用程序还运行它们自己的线程池,而且,启用这些线程来执行工作也是一种推荐方案,从而应用程序可以管理驱动程序工作的执行以及其余的负载。 延迟的主机操作是围绕“分工”原则设计的。 应用程序负责的部分如下:
驱动程序部分负责:
这样,应用程序可以控制工作的分配和优先级,但是驱动程序可以管理底层细节。 为了使用延迟操作,应用程序首先构造一个VkDeferredOperationKHR对象,该对象封装了延迟命令的执行状态。 该对象在其整个生命周期中将处于两种状态(“完成”或“待处理”)之一,如下图(延迟操作的状态图)所示。 延迟操作在被构建的时候,是一个"Complete"状态。应用程序通过将新的扩展结构附加到命令参数结构的pNext指针上,从而发出对命令的延迟请求。如果驱动能够支持这个deferred请求,则deferred操作将转换为“Pending”状态。请注意,驱动程序可以随意拒绝该请求,而只需在适当位置执行该命令,即可立即完成该命令。 一旦这个命令被延迟执行后,操作是不会被执行的,直到应用程序通过调用vkDeferredOperationJoinKHR分配线程资源给到这个命令。"join"命令告诉驱动程序使用分配的线程来处理与延迟操作关联在一起的命令。应用程序可以将任意数量的线程加入到延迟的操作中,这样做通常会使命令更快地完成。如果分配的线程中,有一个线程在vkDeferredOperationJoinKHR的调用返回值为VK_SUCCESS时,就说明该操作已经是处于”Complete”状态。 请注意,如果有多个线程加入了延迟操作,当驱动了解到不需要这么多线程时,后加入的线程是可以提早返回的。 1.4.1 Case 1:简化版的压缩技术 (Simplified Compact)压缩对于减少光线跟踪加速结构的内存占用是非常重要的优化。创建具有压缩的加速结构的过程,如下所示:
为了为紧凑的加速结构分配内存,应用程序需要知道其大小。要确定大小,它需要为步骤3和4提交命令缓冲区,并等待其完成。 这个细节使警报铃响在经验丰富的引擎开发人员的脑海中。如果天真地做,这种主机/设备握手会严重降低性能。如果做得好,这将成为复杂性的重要来源,并且可能导致应用程序的设备内存占用量激增,因为紧凑的加速结构需要在设备内存中至少保留一帧。 在Host上构建加速结构使我们可以消除这两个缺点。在Host上构建,我们可以通过在主机上执行初始构建,然后执行从主机内存到设备内存的压缩副本来实现压缩。此副本仍需要监视,以便应用程序可以恢复主机内存,但这是一种更为熟悉的模式,引擎已经实现了这种模式,将纹理和几何数据上传到设备的时候,都是采用类似的方式来处理的。 1.4.1 Case 2:负载均衡(Load Balancing)在Host端来构建加速结构可通过利用闲置的CPU来提高性能。 假定游戏中的配置文件如下图所示(负载平衡:无主机构建): 在图中,加速结构的构造和更新是在设备(Device)上实现的,但是该应用程序有大量的可用CPU时间。 将这些操作移至主机后,CPU便可以与上一帧渲染并行执行下一帧的加速结构工作。 即使CPU需要更多的时钟时间来执行相同的任务,这也可以提高吞吐量,如下图所示(负载平衡:启用主机构建)。 1.5 光线遍历(Ray Traversal)在Vulkan中针对加速结构跟踪射线要经历多个逻辑阶段,从而为如何跟踪射线提供了一定的灵活性。最初仅根据其几何特性找到候选相交-沿射线与加速结构中描述的几何对象是否存在相交? 交汇点测试在Vulkan中是水密的-意味着对于加速结构中描述的单个几何对象,光线无法通过三角形之间的间隙泄漏,并且无法报告同一位置处不同三角形的多次碰撞。这不能保证碰巧邻接的相邻对象,但这意味着单个模型中不会有孔,也不会发生过度着色的情况。 一旦找到候选者,便会在确认交集之前进行一系列剔除操作。这些剔除操作基于用于遍历的标记和加速结构的属性来丢弃候选对象,具体的细节请参考详细的规范。剩余的不透明三角形候选对象被确认为有效交点;而AABB和非透明三角形需要着色器代码以编程方式确定是否发生了击中。 遍历一直进行到找到所有可能的候选对象并被确认或丢弃,然后确定最接近的命中为止。遍历也可以尽早结束以避免不必要的处理。这对于检测遮挡或在某些情况下优化可能很有用。 可以通过Vulkan中的两种机制之一来跟踪光线并获得遍历结果:
射线追踪管道和射线查询如下图所示: 二、Vulkan Ray Tracing API 详述Vulkan API 中对光追提供了一下拓展支持。
额外的 SPIR-V 和 GLSL 扩展还为着色器提供了必要的可编程功能:
2.1 VK_KHR_acceleration_structure加速结构是光线追踪中为了加速光线求交对几何对象进行的一种场景组织形式(可参照:【光线追踪系列十】光追加速结构(BVH树))。通过将对象构建到加速结构中,可以针对已知的数据布局以高效的方式执行光线追踪。VK_KHR_acceleration_structure扩展引入了构建和复制加速结构的功能,以及支持内存序列化的功能。 光线管道 ( VK_KHR_ray_tracing_pipeline) 和光线查询 ( VK_KHR_ray_query)都需要加速结构。 要创建加速结构,需要执行以下的步骤:
2.2 VK_KHR_ray_tracing_pipelineVK_KHR_ray_tracing_pipeline扩展引入了光线追踪管道。这种新形式的渲染管线独立于传统的光栅化管线。光线追踪管线利用一组专用的着色器阶段,不同于传统的顶点/几何/片段着色器。光线追踪管道还利用专用命令来提交渲染工作(vkCmdTraceRaysKHR和vkCmdTraceRaysIndirectKHR)。这些命令与传统光栅化管道(vkCmdDraw和vkCmdDrawIndirect)中的绘图命令类似。 使用追踪光线:
光线追踪管道引入了几个新的着色器域。这些描述如下:
2.3 VK_KHR_ray_queryVK_KHR_ray_query扩展支持跟踪来自所有着色器类型的光线,包括图形、计算和光线跟踪管线。 光线查询要求光线遍历代码明确包含在着色器中。这与光线追踪管道不同,其中光线生成、求交测试和光线几何命中的处理表示为单独的着色器阶段。因此,虽然光线查询允许从更广泛的着色器阶段跟踪光线,但它也限制了 Vulkan 实现可能应用于光线调度和跟踪的优化范围。 该扩展不会引入额外的 API 入口点。它只是为相关的 SPIR-V 和 GLSL 扩展(SPV_KHR_ray_query和 GLSL_EXT_ray_query)提供 API 支持。 提供的功能与提供的功能VK_KHR_ray_query互补VK_KHR_ray_tracing_pipeline,两个扩展可以一起使用。 比如如下代码:
2.4 VK_KHR_pipeline_libraryVK_KHR_pipeline_library主要是介绍管线库。管线库是一种特殊的管线,它可以使用VK_PIPELINE_CREATE_LIBRARY_BIT_KHR 结构体来创建,不能直接绑定和使用。相反,这些管线表示着色器、着色器组和相关状态的集合,可以链接到其他管线。 VK_KHR_pipeline_library没有直接引入任何新的 API 函数,也没有定义如何创建管线库。相反,此功能留给其他使用 VK_KHR_pipeline_library。目前,唯一的例子是VK_KHR_ray_tracing_pipeline。 VK_KHR_pipeline_library被定义为一个单独的扩展,以允许将来在其他扩展中使用相同功能的可能性,而不会引入对光线跟踪扩展的依赖。 要创建光线跟踪管线库,需要执行以下操作:
要将光线追踪管线库链接到一个完整的管线,需要执行:
2.5 VK_KHR_deferred_host_operationsVK_KHR_deferred_host_operations引入了一种跨多个线程分配 CPU 任务的机制。不是在 Vulkan 驱动程序中引入线程池,VK_KHR_deferred_host_operations主要是允许应用程序创建和管理线程。 与VK_KHR_pipeline_library一样,VK_KHR_deferred_host_operations被定义为一个单独的扩展,以允许将来在其他扩展中使用相同功能的可能性,而不会仅依赖于对光线跟踪扩展。 只有特别注明支持延迟的操作才可以延迟。目前支持延迟的操作是vkCreateRayTracingPipelinesKHR, vkBuildAccelerationStructuresKHR,vkCopyAccelerationStructureKHR, vkCopyMemoryToAccelerationStructureKHR,和vkCopyAccelerationStructureToMemoryKHR 请求延迟操作,需要执行以下步骤:
将线程加入延迟操作,并使用 CPU 时间来推进操作:
操作完成后(vkDeferredOperationJoinKHR即已返回 VK_SUCCESS),调用vkGetDeferredOperationResultKHR以获取操作结果。 三、Vulkan光线追踪相关管线3.1 光线追踪管线应用程序可以将特定的着色器与场景中的对象相关联,为这些对象定义诸如材质参数和相交逻辑之类的东西。随着遍历的进行,当光线与对象相交时,实现将自动执行关联的着色器(如下图所示)。 光线跟踪管道与Vulkan中的图形管道相似,但具有增加的功能,可以管理更多的着色器,并将对特定着色器的引用存储到内存中。 使用vkCmdTraceRaysKHR和当前绑定的射线跟踪管道启动射线跟踪管道工作。该命令将调用一组应用程序定义的射线生成线程,这些线程可以从着色器调用traceRaysEXT(),从而开始在指定的加速结构上进行遍历。在遍历期间,如果跟踪和加速结构需要,则相交处的应用程序着色器代码和任何命中着色器都可以控制遍历的方式。遍历完成后,将调用未命中或最接近的命中着色器。 可以使用相同的着色器选择机制来调用可调用着色器,但是要在直接遍历上下文之外。 不同的着色器阶段可以使用所有遍历阶段之间的射线有效载荷结构和遍历控制着色器的射线属性结构来传递参数和结果。 为了使遍历阶段能够知道在给定的遍历步骤之后要调用哪个着色器以控制或响应遍历,该实现使用着色器绑定表。每个着色器条目都包括从实现中查询给定着色器组的着色器组句柄,以及可选的着色器缓冲区记录,应用程序可将其用于实例特定的数据,例如缓冲区设备地址或描述符索引。遍历通过对跟踪射线API调用的参数,对traceRayEXT着色器调用的参数以及存储在加速结构中的信息的组合,通过遍历计算出任何给定着色器的地址。 可以与其他管道类型一样直接创建光线跟踪管道,但是由于光线跟踪管道可以比其他管道类型具有更多数量级的着色器,我们可能要添加着色器,因此扩展添加了另一种机制:管道库(Pipeline libraries)。管道库是一个包括状态和着色器以及其他标志的管道,用来表示那些我们不打算直接绑定到API,而是打算用作要包含在以后的管道中使用的库。管线库可用于多个光线跟踪管线,从而允许在多个管线中重复使用着色器编译。光线跟踪管道创建可能包括创建过程中的一组管道库管道以及一组射线跟踪着色器。每个着色器的所有编译状态必须匹配才能创建兼容的最终管道。除了管道库之外,可以在射线管道构造中使用延迟的主机操作以实现进一步的并行化。 请注意,尽管管道库是作为单独的扩展公开的,但它们仅在当前集成在一起才能与射线跟踪管道一起使用。 Ray Pipeline Shaders (GLSL)示例
3.2 Ray Queries(射线查询)射线查询可用于执行射线遍历并在任何着色器阶段将结果返回。 除了需要加速结构外,仅使用一组新的着色器指令执行射线查询。 射线查询使用加速结构进行初始化,以进行查询,确定遍历属性的射线标志,剔除蒙版以及所跟踪射线的几何描述。 遍历期间,着色器可以访问潜在和已确定的相交的属性以及ray查询本身的属性,从而可以基于要相交的几何图形,如何相交以及在何处进行复杂的决策,如下图: 以下是GLSL中射线查询的不完整示例,说明了着色器如何使用射线查询来检测给定位置是否在阴影中。可以将其添加到片段着色器中,以进行光照计算。大多数射线查询的总体结构通常是相似的-初始化,循环执行,然后进行最终确定。
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 12:31:59- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |