为什么片段着色器比渲染纹理更快?

Use*_*ted 0 c++ opengl glsl

我检查了一些内容,得到了关于 C++ & OpenGL & GLSL 性能的奇怪结果。

在第一个程序中,我使用片段着色器将像素绘制到纹理,然后渲染纹理。纹理的 mag\min 为GL_NEAREST

在第二个程序中,我使用片段着色器并直接渲染到屏幕上。

为什么第二个程序更快?渲染纹理不是比重复相同的动作更快吗?

这就像拍摄 AAA 游戏的视频,然后在同一台计算机上显示它,并随着视频获得较低的 FPS。

片段着色器是:

uniform int mx,my;

void main(void) {
    vec2 p=gl_FragCoord.xy;
    p-=vec2(mx,my);
    if (p.x<0.0)
        p.x=-p.x;
    if (p.y<0.0)
        p.y=-p.y;
    float dis=sqrt(p.x*p.x+p.y*p.y);
    dis+=(abs(p.x)+abs(p.y))-(abs(p.x)-abs(p.y));
    p.x/=dis;
    p.y/=dis;
    gl_FragColor=vec4(p.x,p.y,0.0,1.0);
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 6

与通常的性能问题一样,真正确定的唯一方法是使用分析器。

也就是说,我的猜测是,这主要是处理带宽与内存带宽的问题。为了渲染纹理,处理器必须从内存的一部分读取数据,并将相同的数据写回到内存的另一部分。

要直接从着色器渲染,处理器只需将输出写入内存,而不必从内存读取数据。

因此,问题是哪个更快:从内存中读取特定数据,还是使用处理单元生成它?着色器中的数学非常简单(本质上唯一复杂的部分是)sqrt- 因此至少对于您的特定硬件,计算结果似乎比从内存中读取结果要快一些(至少给定其他内存访问同时进行,等等)

请注意,两者(着色器与纹理)具有完全不同的特征。读取纹理的速度几乎是恒定的,无论创建纹理时涉及的计算有多简单或多复杂。不言而喻,如果计算很简单,着色器将运行得很快,但如果计算变得复杂,则着色器会减慢(可能很多)。在您提到的 AAA 游戏中,可以公平地猜测,至少某些着色器使用足够复杂的计算,几乎肯定会比纹理读取慢。在相反的极端情况下,一个非常简单的着色器(例如,仅将片段颜色从输入传递到输出的着色器)可能比从纹理读取快得多。