所以我试图使用openCL实现一个光线/路径跟踪器,它看起来非常简单 - 编写一个跟踪单个光线/像素/等路径的内核,让它在多个光线上并行执行。
但是,在遍历场景时,单个光线可以采用相当多的方向。例如,根据命中对象的材质,光线可以反射或折射。另外,不同的材料需要不同的着色算法。例如,如果一个场景对象需要一个cook-torrance着色器而另一个场景对象需要一个区域各向异性着色器,则需要在内核中调用不同的着色函数。
根据我一直在阅读的内容,不建议在内部使用分支代码,因为它会影响性能。但是,如果我根据每条光线并行化我的代码,这在光线跟踪器中似乎是不可避免的。
所以"分支"代码结构真的对内核性能造成了很大的阻碍吗?如果是这样,我将如何构建我的代码以解决这个问题呢?
答案 0 :(得分:2)
第一次传递(1M射线),无符号字符串数组(甚至打包单个位)
ray 0 ------------------ render end --------------> 0 \
ray 1 ------------------ surface ---------------> 1 \
ray 2 ------------------ surface ---------------> 1 }-- bad for SIMD
ray 3 ------------------ render end --------------> 0 /
ray 4 ------------------ surface ---------------> 1 /
...
...
ray 1M ...
排序(缓存或多路复用,以便重复使用以进行折射和反射) 表面类型(存在/不存在)和表面位置(时间相干)
ray 1 \
ray 2 -------------------- all surfaces --------------> 1 good for simd
ray 4 /
ray 0 \
ray x -------------------- all render end ------------> 0 good for simd
ray 3 /
second pass (refraction) (1M rays)
ray 1 ..................... refract ...................> cast a new ray
ray 2 ..................... refract ...................> cast a new ray
ray 4 ..................... refract ...................> cast a new ray
ray 0 .................... no new ray casting .........> offload some other work/draw
ray x .................... no new ray casting .........> offload some other work/draw
ray 3 .................... no new ray casting .........> offload some other work/draw
third pass (reflection) (1M rays)
ray 1 ..................... reflect...................> cast a new ray
ray 2 ..................... reflect...................> cast a new ray
ray 4 ..................... reflect...................> cast a new ray
ray 0 .................... no new ray casting .........> offload some other work/draw
ray x .................... no new ray casting .........> offload some other work/draw
ray 3 .................... no new ray casting .........> offload some other work/draw
现在有两组1M射线,每次迭代加倍。因此,如果你有256M元素的空间,你应该能够投射光线直到depth7或8.所有这些都可以在一个具有适当索引的数组上完成。