-
Notifications
You must be signed in to change notification settings - Fork 0
/
ShaderBindingTable.rst
286 lines (193 loc) · 12.9 KB
/
ShaderBindingTable.rst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
着色器绑定表
===========================
.. dropdown:: 更新记录
:color: muted
:icon: history
* 2023/9/14 增加该扩展文档
* 2023/9/14 增加 ``光追管线和着色器组结构`` 章节
* 2023/9/14 增加 ``VkRayTracingShaderGroupCreateInfoKHR`` 章节
* 2023/9/14 增加 ``一个简单的着色器绑定表示意图`` 章节
* 2023/9/14 增加 ``着色器绑定表的分类`` 章节
* 2023/9/14 增加 ``光线生成着色器组`` 章节
* 2023/9/14 增加 ``命中组`` 章节
* 2023/9/14 增加 ``未命中组`` 章节
* 2023/9/14 增加 ``着色器绑定表的拷贝`` 章节
* 2023/9/14 增加 ``着色器绑定表`` 章节
* 2023/9/15 重命名 ``光线生成着色器组`` 为 ``生成组``
* 2023/9/15 更新 ``生成组`` 章节
* 2023/9/15 更新 ``一个简单的着色器绑定表示意图`` 章节
* 2023/9/15 更新 ``未命中组`` 章节
* 2023/9/15 重命名 ``着色器绑定表的分类`` 章节为 ``着色器组``
* 2023/9/15 更新 ``着色器组`` 章节
* 2023/9/15 更新 ``命中组`` 章节
* 2023/9/15 更新 ``未命中组`` 章节
* 2023/9/15 增加 ``着色器绑定表的构成`` 章节
* 2023/9/15 增加 ``光线生成着色器绑定表`` 章节
* 2023/9/15 增加 ``综上`` 章节
* 2023/9/15 更新 ``着色器绑定表的拷贝`` 章节
* 2023/9/15 增加 ``光追调度着色器绑定表寻址`` 章节
* 2023/9/15 增加 ``命中着色器绑定表寻址`` 章节
`文献源`_
.. _文献源: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap40.html#shader-binding-table
着色器绑定表
#####################################
* 着色器绑定表是一种用于将光追管线和加速结构联系起来的一种资源。
* 其指定了加速结构中每一个几何上要操作的着色器。
* 此外还包含每一个着色器要访问的资源,包括纹理索引,缓存地址和常量。
* 应用通过 ``VkBuffer`` 来分配和管理着色绑定表。
* 着色器绑定表作为光追管线的 ``vkCmdTraceRaysNV`` , ``vkCmdTraceRaysKHR`` 或者 ``vkCmdTraceRaysIndirectKHR`` 光追调度指令的参数使用。
光追管线和着色器组结构
#####################################
.. figure:: ../../_static/vkRayTracingShaderGroupCreateInfo.svg
光追管线和着色器组结构示意图
VkRayTracingShaderGroupCreateInfoKHR
********************************************
`VkRayTracingShaderGroupCreateInfoKHR <./VK_KHR_ray_tracing_pipeline.html#vkraytracingshadergroupcreateinfokhr>`_
一个简单的着色器绑定表示意图
#####################################
.. figure:: ../../_static/sbt_struct_sample.svg
一个简单的着色器绑定表示意图
在创建光线追踪管线时需要通过指定 ``VkRayTracingShaderGroupCreateInfoKHR`` 来设置该管线中的着色器组。在光追光线创建时,驱动会根据用户 ``VkRayTracingPipelineCreateInfoKHR::pGroups`` 指定的着色器组创建相应着色器组句柄。在光追管线构建成功后,就可以
通过 ``vkGetRayTracingShaderGroupHandlesKHR`` 获取相应的着色器组句柄(示意图中的 ``Handle``)。
``Handle`` 是一个类型为 ``uint8_t`` 的数组,实际上就是一段连续的内存,用于存储着色器组对应的句柄(其中 :bdg-secondary:`VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleSize` 就是单个句柄的比特大小,本机为 ``32``)。该数组就是通过 ``vkGetRayTracingShaderGroupHandlesKHR`` 获取得到的相应着色器句柄数据。
之后就需要创建一个 ``Buffer`` 缓存(上图的 ``Group``)用于存放( ``Handle`` 拷贝到 ``Buffer`` 中)这些着色器组句柄,该 ``Buffer`` 就是传说中的着色器绑定表。
着色器组
********************************************
着色器组分为三种:
生成组
--------------------
生成组只能由一个光线生成着色器构成,用于生成光线。每一次光追调度只能执行一个光线生成着色器,也就是每一次光追调度只能有一个生成组。
如上图中的 ``RG`` 就是由一个光线生成着色器构成的生成组。
命中组
--------------------
命中组是由相交着色器、任意命中着色器和最近命中着色器,单一或两两或三三不重复构成的,比如:
* 单个相交着色器或单个任意命中着色器或单个最近命中着色器,可以构成一个命中组
* 一个任意命中着色器和一个最近命中着色器,可以构成一个命中组
* 一个任意命中着色器和一个最近命中着色器,可以构成一个命中组
* 一个相交着色器和一个任意命中着色器和一个最近命中着色器,可以构成一个命中组
如上图中的 ``Hit`` 就是由一个最近命中着色器构成的命中组。
未命中组
--------------------
当对场景中的某一几何物体光线相交查询失败时会调用。一次光追调度可以执行多个未命中着色器。
未命中组只能由一个未命中着色器构成。
如上图中的 ``Miss`` 和 ``Miss Shadow`` 就是各自由一个未命中着色器构成的未命中组。
可调用组
--------------------
可调用着色器是通过光追着色器请求执行的,一次光追调度可能会执行多次可调用着色器。
一个可调用组由一个可调用着色器构成。
.. note:: 着色器绑定表示意图中没有用到可调用着色器,也就没有可调用组。
着色器绑定表的构成
********************************************
与着色器组分类对应,着色器绑定表由三类着色器绑定表构成:
光线生成着色器绑定表
-----------------------
由一个生成组构成。
如上图的 ``RG`` 就是使用一个生成组构成一个光线生成着色器绑定表。
命中着色器绑定表
-----------------------
由多个命中组构成。
如上图的 ``Hit`` 就是使用一个命中组构成一个命中着色器绑定表。
未命中着色器绑定表
-----------------------
由多个未命中组构成。
如上图的 ``Miss`` 和 ``Miss Shadow`` 就是使用两个未命中组构成一个未命中着色器绑定表。
可调用着色器绑定表
-----------------------
由多个可调用组构成。
.. note:: 着色器绑定表示意图中没有用到可调用组,也就没有可调用着色器绑定表。
综上
-----------------------
着色器绑定表是由光线生成着色器绑定表、命中着色器绑定表、未命中着色器绑定表和可调用着色器绑定表组成的一张大表。
在使用 ``vkCmdTraceRaysKHR`` 光追调度时:
.. code:: c++
// 由 VK_KHR_ray_tracing_pipeline 提供
void vkCmdTraceRaysKHR(
VkCommandBuffer commandBuffer,
const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
uint32_t width,
uint32_t height,
uint32_t depth);
其中:
* :bdg-secondary:`pRaygenShaderBindingTable` 对应着光线生成着色器绑定表。
* :bdg-secondary:`pMissShaderBindingTable` 对应着未命中着色器绑定表。
* :bdg-secondary:`pHitShaderBindingTable` 对应着命中着色器绑定表。
* :bdg-secondary:`pCallableShaderBindingTable` 对应着可调用着色器绑定表。
而 ``VkStridedDeviceAddressRegionKHR`` 定义如下:
.. code:: c++
// 由 VK_KHR_ray_tracing_pipeline 提供
typedef struct VkStridedDeviceAddressRegionKHR {
VkDeviceAddress deviceAddress;
VkDeviceSize stride;
VkDeviceSize size;
} VkStridedDeviceAddressRegionKHR;
* :bdg-secondary:`deviceAddress` 对应着色器绑定表那张大表中该类型的绑定表的起始偏移地址。
* :bdg-secondary:`stride` 对应着该类型的绑定表中组句柄的大小。
* :bdg-secondary:`size` 对应着该类型的绑定表的大小。
各类型 ``VkStridedDeviceAddressRegionKHR`` 与示意图中着色器绑定表的对应结构示意图如下:
.. figure:: ../../_static/SBTAddressRegion.svg
着色器绑定表的拷贝
********************************************
就是将各类着色器绑定表拷贝至由 ``VkBuffer`` 构成的着色器绑定表的大表中。
在将 ``Handle`` 拷贝到 ``Buffer`` 中时需要满足如下条件:
* :bdg-secondary:`VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleSize` 单个着色器组句柄的大小。
* :bdg-secondary:`VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleAlignment` 单个着色器组句柄的对齐大小。
* :bdg-secondary:`VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupBaseAlignment` 不同着色器组句柄的对齐大小。
* 光线生成着色器绑定表的 ``pRaygenShaderBindingTable->stride`` 是不使用的且必须等于 ``pRaygenShaderBindingTable->size``
光追调度着色器绑定表寻址
#####################################
在使用 ``vkCmdTraceRaysKHR`` 光追调度时, ``GPU`` 首先会去调用 ``光线生成着色器绑定表`` 中绑定的光线生成着色器生成光线并进行光线追踪。
光线生成着色器绑定表寻址
********************************************
该寻址比较简单,由于 ``pRaygenShaderBindingTable`` 中的 ``stride`` 和 ``size`` 是固定的,且相同, ``GPU`` 可直接通过 ``pRaygenShaderBindingTable`` 寻址到光线生成着色器。
自后,在光追着色器中使用 ``traceRayEXT`` 函数进行光线追踪。
.. code:: glsl
void traceRayEXT(
accelerationStructureEXT topLevel,
uint rayFlags,
uint cullMask,
uint sbtRecordOffset,
uint sbtRecordStride,
uint missIndex,
vec3 origin,
float Tmin,
vec3 direction,
float Tmax,
int payload
);
* :bdg-secondary:`topLevel` 为顶层加速结构。
* :bdg-secondary:`rayFlags` 为追踪标志位。
* :bdg-secondary:`cullMask` 为剔除遮罩。
* :bdg-secondary:`sbtRecordOffset` 为命中着色器绑定表记录偏移。
* :bdg-secondary:`sbtRecordStride` 为命中着色器绑定表记录跨度。
* :bdg-secondary:`missIndex` 为未命中着色器绑定表引用。
* :bdg-secondary:`origin` 为追踪的光线起点。
* :bdg-secondary:`Tmin` 为追踪的光线长度的最小值。
* :bdg-secondary:`direction` 为追踪的光线的方向。
* :bdg-secondary:`Tmax` 为追踪的光线长度的最大值。
* :bdg-secondary:`payload` 为负载引用。
当调用 ``traceRayEXT`` 时需要设置 ``sbtRecordOffset`` 、 ``sbtRecordStride`` 和 ``missIndex`` 用于告诉 ``GPU`` ,当该追踪该光线时如果发生了命中或未命中, ``GPU`` 会根据这些设置去着色器绑定表中进行寻址,找到对应命中着色器绑定表和未命中绑定表中的光追着色器,进而进行调用。其中:
命中着色器绑定表寻址
********************************************
``sbtRecordOffset`` 和 ``sbtRecordStride`` 用于寻址命中着色器绑定表中的命中组。该寻址与创建实体( ``VkAccelerationStructureInstanceKHR`` )时设置的 ``instanceShaderBingdingTableRecordOffset`` 进行配合寻址。
``instanceShaderBingdingTableRecordOffset`` 用于记录命中着色器绑定表中的其实位置。 ``sbtRecordOffset`` 、 ``sbtRecordStride`` 和 ``instanceShaderBingdingTableRecordOffset`` 最终的寻址结果会加到 ``pHitShaderBindingTable->deviceAddress`` 中。
对于 ``traceRayEXT`` 完整的命中着色器绑定表寻址计算为:
.. math::
pHitShaderBindingTable->deviceAddress+pHitShaderBindingTable->stride\times(instanceShaderBindingTableRecordOffset+geometryIndex \times sbtRecordStride+sbtRecordOffset)
.. note:: 其中 ``geometryIndex`` 为实体中的相交的几何体索引值
未命中着色器绑定表寻址
********************************************
``missIndex`` 用于寻址未命中着色器绑定表中的未命中组。进而找到对应的未命中着色器。
对于 ``traceRayEXT`` 完整的未命中着色器绑定表寻址计算为:
.. math::
pMissShaderBindingTable->deviceAddress + pMissShaderBindingTable->stride \times missIndex
可调用着色器绑定表寻址
********************************************
通过在主色器中调用 ``executeCallableEXT`` 函数传入 ``sbtRecordIndex`` 参数进行可调用着色器绑定表寻址:
.. code:: glsl
void executeCallableEXT(uint sbtRecordIndex, int callable);
对于 ``executeCallableEXT`` 完整的可调用着色器绑定表寻址算法为:
.. math::
pCallableShaderBindingTable->deviceAddress + pCallableShaderBindingTable->stride \times sbtRecordIndex