Nic*_*las 12
每个着色器阶段都有自己的调用频率.我将使用OpenGL术语,但D3D以相同的方式工作(因为它们都建模相同的硬件关系).
这是第二个最复杂的.它们为每个输入顶点执行一次......有点.如果使用非索引渲染,则比率恰好为1:1.每个输入顶点都将在单独的顶点着色器实例上执行.
如果您使用索引渲染,那么它会变得复杂.它或多或少是1:1,每个顶点都有自己的VS调用.但是,由于后T&L缓存,每个输入顶点可以执行少于一次的顶点着色器.
请参阅,假设顶点着色器的执行在输入顶点数据和输出顶点数据之间创建1:1映射.这意味着如果将相同的输入数据传递给顶点着色器(在同一渲染命令中),则需要生成相同的输出数据.因此,如果硬件可以检测到它将要在先前使用的相同输入数据上执行顶点着色器,则它可以跳过该执行并简单地使用先前执行的输出.
硬件通过使用顶点的索引来检测到这一点(这就是为什么它不适用于非索引渲染).如果向顶点着色器提供相同的索引,则假定着色器将获得所有相同的输入值,因此将生成相同的输出值.因此硬件将根据索引缓存输出值.如果索引位于T&L后缓存中,则硬件将跳过VS的执行并仅使用输出值.
实例化只会稍微使后T&L缓存稍微复杂化.它不是仅仅根据顶点索引进行缓存,而是根据索引和实例 ID进行缓存.因此,如果两个值相同,它仅使用缓存的数据.
所以一般来说,VS为每个顶点执行一次,但是如果用索引数据优化几何,它可以执行更少的次数.有时会少得多,具体取决于你的工作方式.
或者用D3D说法的船体着色器.
在这方面,TCS非常简单.它将在渲染命令的每个补丁中为每个顶点执行一次.这里没有进行缓存或其他优化.
或D3D用法中的域着色器.
在曲面细分基元生成器生成新顶点之后执行TES.因此,它的执行频率显然取决于您的镶嵌参数.
TES采用曲面细分生成的顶点并输出顶点.它以1:1的比例进行.
但与顶点着色器类似,每个输出基元中的每个顶点不一定是1:1.与VS一样,假设TES在曲面细分的基元和输出参数中的位置之间提供直接的1:1映射.因此,如果您使用相同的修补程序位置多次调用TES,则应该输出相同的值.
因此,如果生成的图元共享顶点,则通常仅针对这样的共享顶点调用TES一次.与顶点着色器不同,您无法控制硬件将使用多少.您可以做的最好的事情是希望生成算法足够智能,以最大限度地减少调用TES的频率.
对于每个点,线或三角形图元,将为渲染命令直接给出或由曲面细分器生成一个几何着色器.因此,如果将6个顶点渲染为未连接的线,则您的GS将被正确调用3次.
每个GS调用都可以生成零个或多个基元作为输出.
GS可以在内部使用实例化(在OpenGL 4.0或Direct3D 11中).这意味着,对于到达GS的每个基元,GS将被调用X次,其中X是GS实例的数量.每个这样的调用将获得相同的输入原始数据(具有用于区分这些实例的特殊输入值).这对于更有效地将基元定向到分层帧缓冲器的不同层是有用的.
或者像D3D那样的像素着色器.即使它们不是像素,也可能不会成为像素,并且它们可以针对同一像素执行多次;)
在调用频率方面,这些是最复杂的.他们执行的频率取决于很多事情.
对于原始光栅化的每个像素大小的区域,FS必须至少执行一次.但他们的执行可能不止于此.
为了计算纹理函数的导数,一个FS调用通常会借用其相邻调用之一的值.如果没有这样的调用,如果邻居落在被光栅化的图元的边界之外,则这是有问题的.
在这种情况下,仍然会有相邻的FS调用.即使它不产生实际数据,它仍然存在并仍然有效.好的部分是这些帮助程序调用不会损害性能.它们基本上耗尽了着色器资源,否则这些资源就会被淘汰.此外,系统将忽略此类帮助程序调用实际输出数据的任何尝试.
但它们在技术上仍然存在.
一个不太透明的问题围绕多重采样.请参阅,多重采样实现(特别是在OpenGL中)允许自己决定要发出多少FS调用.虽然有多种方法可以强制多重采样渲染为每个样本创建FS调用,但无法保证实现只会在这些情况之外的每个覆盖像素执行一次FS.
例如,如果我没记错的话,如果您在某些NVIDIA硬件(8到16或类似的东西)上创建具有高样本数的多重采样图像,则硬件可能决定多次执行FS.每个样品不一定一次,但每4个样品一次.
那你有多少FS调用?对于由基元覆盖的每个像素大小的区域,至少有一个被光栅化.如果您正在进行多重采样渲染,可能会更多.
您指定的确切调用数.也就是说,您发送的工作组数量*CS指定的每个组的调用次数(您的本地组计数).不多也不少.
归档时间: |
|
查看次数: |
582 次 |
最近记录: |