在glsl中使用实例化时,为什么纹理缓冲比顶点输入快?

Mar*_*nDo 5 c++ opengl performance glsl opengl-4

我正在编写自己的渲染引擎。目前,我正在地形上。我使用渲染地形glDrawArraysInstanced。地形由许多“块”组成。每个块都是一个四边形,这也是绘制调用的一个实例。然后,在四边形着色器中对每个四边形进行四边形细分。对于我的着色器输入,我使用VBO实例化VBO(使用顶点属性除数)和纹理缓冲区。这是我的一个着色器的一个简单示例:

#version 410 core

layout (location = 0) in vec3 perVertexVector; // VBO attribute  
layout (location = 1) in vec3 perInstanceVector; // VBO instanced attribute
uniform samplerBuffer someTextureBuffer; // texture buffer
out vec3 outputVector;

void main()
{
    // some processing of the inputs;
    outputVector = something...whatever...;
} 
Run Code Online (Sandbox Code Playgroud)

一切正常,我没有任何错误。它的渲染速度约为60-70 FPS。但是今天,我做了一些更改,不得不将所有实例化的VBO更改为纹理缓冲区。由于某种原因,性能提高了一倍,并以120-160 FPS的速度运行(有时甚至更多!)我没有做任何其他更改,只是创建了更多的纹理缓冲区并使用了它们而不是所有实例化属性。

这是我用于为着色器创建实例属性的代码(简化为可读版本):

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribDivisor(0, 1); // this makes the buffer instanced
Run Code Online (Sandbox Code Playgroud)

这是我创建纹理缓冲区的简化代码:

glBindTexture(GL_TEXTURE_BUFFER, textureVBO);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, VBO);
Run Code Online (Sandbox Code Playgroud)

我认为我没有做错任何事情,因为一切正常。这只是性能...我认为属性比纹理要快,但是结果却相反,我对纹理缓冲区比属性快两倍以上的事实感到非常惊讶。

但是还有一件事我不理解。

实际上,我glDrawArraysInstanced两次调用了地形()的render函数。第一次是渲染地形,第二次是使用不同的变换矩阵将其渲染到FBO以进行水反射。当我仅渲染一次(不使用反射)并且使用实例化属性时,我得到大约90 FPS,因此比我之前提到的60 FPS快一点。

但!当我仅渲染一次并且使用纹理缓冲区时,差异确实很小。它的运行速度与我渲染两次(大约120-150 fps)时一样快!

我想知道它是否使用某种缓存或某种方式,但是对我来说没有任何意义,因为两个渲染调用中的每个顶点都使用不同的矩阵进行了转换,因此着色器输出的结果完全不同。


我真的很感谢对此问题的一些解释:

为什么纹理缓冲区比实例属性快?


编辑:

以下是我的问题的摘要,以便更好地理解:

我唯一要做的就是更改我的glsl代码中的这些行:

layout (location = 1) in vec3 perInstanceVector; // VBO instanced attribute
outputVector = perInstanceVector;
Run Code Online (Sandbox Code Playgroud)

对此:

uniform samplerBuffer textureBuffer; // texture buffer which has the same data as the previous VBO instanced attribute
outputVector = texelFetch(textureBuffer, gl_InstanceID).xyz
Run Code Online (Sandbox Code Playgroud)

一切工作都像以前一样,但是在性能方面要快两倍。

Que*_*and 0

我看到 3 个可能的原因:

  1. 由于寄存器的使用不同,着色器可能有不同的占用,因此性能会有很大不同
  2. 在属性之间,获取不是以相同的方式实现的,调度程序可以在着色器中比在输入汇编器中进行更好的等待处理
  3. 也许第二个的驱动程序开销更少

您是否尝试过使用不同数量的原语?或者尝试使用计时器?