Opengl 渲染命令中着色器调用的频率

Opengl 渲染命令中着色器调用的频率,opengl,opengl-es,glsl,shader,direct3d,Opengl,Opengl Es,Glsl,Shader,Direct3d,着色器有调用,每个调用(通常)都有一组唯一的输入数据,每个调用(通常)都写入各自的单独输出数据。发出渲染命令时,每个着色器会被调用多少次?每个着色器阶段都有自己的调用频率。我将使用OpenGL术语,但D3D的工作方式是相同的(因为它们都建模相同的硬件关系) 顶点着色 这些是第二复杂的。它们对每个输入顶点执行一次。。。有点。如果使用的是非索引渲染,则比例正好为1:1。每个输入顶点将在单独的顶点着色器实例上执行 如果使用索引渲染,则会变得复杂。它或多或少是1:1,每个顶点都有自己的VS调用。但是,由

着色器有调用,每个调用(通常)都有一组唯一的输入数据,每个调用(通常)都写入各自的单独输出数据。发出渲染命令时,每个着色器会被调用多少次?

每个着色器阶段都有自己的调用频率。我将使用OpenGL术语,但D3D的工作方式是相同的(因为它们都建模相同的硬件关系)

顶点着色 这些是第二复杂的。它们对每个输入顶点执行一次。。。有点。如果使用的是非索引渲染,则比例正好为1:1。每个输入顶点将在单独的顶点着色器实例上执行

如果使用索引渲染,则会变得复杂。它或多或少是1:1,每个顶点都有自己的VS调用。但是,由于,每个输入顶点执行顶点着色器的次数可能少于一次

请参见,假设顶点着色器的执行在输入顶点数据和输出顶点数据之间创建1:1映射。这意味着,如果将相同的输入数据传递给顶点着色器(在相同的渲染命令中),则预期VS将生成相同的输出数据。因此,如果硬件可以检测到它将要对它以前使用过的相同输入数据执行顶点着色器,它可以跳过该执行,只使用以前执行的输出。假设它周围有这些值,比如缓存中的值

硬件通过使用顶点的索引来检测这一点(这就是为什么它不适用于非索引渲染)。如果向顶点着色器提供相同的索引,则假定该着色器将获得所有相同的输入值,因此将生成相同的输出值。因此,硬件将根据索引缓存输出值。如果索引在后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