HLSL中的流控制

问题描述 投票:0回答:1

[我最近阅读了有关射线云的论文(请谨慎阅读,如果您不想要它,则为PDF:http://www.diva-portal.org/smash/get/diva2:1223894/FULLTEXT01.pdf),作者继续进行优化(第22ff页)。通过重投影算法。他指出,通过每帧仅对所有像素的1/16进行光线转换(所选像素在4x4网格中跳动)并重新投影其余像素,他的性能提高了约10倍。

我现在也尝试在Unreal Engine 4(自定义HLSL着色器)中实现这一点,并且现在进行了raymarching和重投影。但是,我坚持只在必要的像素上运行光线行进。据我所知,HLSL中的任何分支都将计算出该分支的两边,然后将其扔掉。因此,我不能在像素着色器中执行以下伪代码操作:if(!PixelReprojection){返回0;}否则{return Raymarch(...); }因为它将为甚至重新投影的像素计算Raymarch。

我看不到任何其他方式来归档此文件...HLSL中是否有任何分支机构允许这样做?由于经过光线转换和重新投影的像素每帧都会发生变化,因此它不能是静态的。据我所知,我真的对任何想法都感到好奇,因为在他也在GPU上编写代码时,作者如何能将性能提高十倍。

在这里,我将不胜感激。

关于,foodius

hlsl unreal-engine4 fragment-shader flow-control
1个回答
0
投票

TLDR:在if语句前使用属性[branch]


据我所知,HLSL中的任何分支都将计算出该分支的两侧,并且将其中一个扔掉

这实际上并不完全正确。是的,分支可以展平,这意味着双方都按照您的描述进行了计算,但是也可以not展平(称为动态分支)。

现在,不扁平化分支有一些缺点:如果同一wave中的两个线程在分支中采用不同的路径,则必须产生第二个wave,因为wave中的所有线程都必须运行相同的代码(因此某些线程将移至新产生的wave)。因此,在这种情况下,许多线程被“禁用”(这意味着它们与wave中的其他线程运行相同的代码,但实际上未将任何内容写入内存)。尽管如此,这种动态分支仍可能比在分支的两侧运行都快,但这取决于实际代码。

甚至可以通过智能着色器设计消除这一缺点(即,确保分支一侧的线程在同一波中,因此在波内不会发生差异。但是,这需要对基础知识有一些了解。硬件,例如波形大小等)

在任何情况下:如果没有另外说明,HLSL编译器将自行决定是使用动态分支还是将分支展平。但是,可以通过adding an attribute将两种方式之一强制执行if语句,例如:

//Enforce dynamic branching:
[branch] 
if (...) { ... }
else { ... }

//Enforce flattening of the branch:
[flatten]
if (...) { ... }
else { ... }
© www.soinside.com 2019 - 2024. All rights reserved.