【问题标题】:C++ Opengl Glsl Shader Performance IssueC++ Opengl Glsl 着色器性能问题
【发布时间】:2014-01-14 18:49:55
【问题描述】:

所以最近我一直在我的笔记本电脑上编写一个 fps 游戏,但是当我尝试在我的固定计算机上运行游戏时,它应该表现得更好,它运行得更慢?

这里有几个屏幕截图,比较了有和没有天空盒的简单测试场景。 (固定电脑 - 顶部,笔记本电脑 - 底部)

到目前为止,您可以看到这是我所期望的,但是当我添加相同的天空盒渲染代码 + 着色器代码时(固定计算机 - 顶部,笔记本电脑 - 底部)

正如您现在所看到的,结果完全相反,我不知道为什么如果我在固定计算机上使用天空盒向上或向后看,我会得到大约 5 的 fps。

这是天空盒的着色器代码:

#version 120
varying vec3 pl;
uniform mat4 gWM;
void main()
{
    pl = vec3(gl_Vertex);
    gl_Position = (gWM * gl_Vertex).xyww; // I have also tried with gl_ModelViewProjectionMatrix instead of gWM.
}

片段着色器:

#version 120
varying vec3 pl;
uniform samplerCube cubeMap;
void main()
{
    gl_FragData[1] = textureCube(cubeMap, -pl);
}

实际渲染的网格是一个球体。

另一件事是,我的笔记本电脑还可以处理剩下 100+ fps 的照明计算,但如果我将这些添加到我的固定设备中,我会得到大约 15 个。

如果我的固定装置在开始时表现更差,我不会关心为什么,但因为它并不是我真的想知道 fps 丢失的地方!

固定电脑规格:

CPU:英特尔酷睿 i5 @ 2.80GHz

内存:4,00GB 双通道

显卡:ATI Radeon HD 4800 系列

笔记本电脑规格:

CPU:英特尔酷睿 i7 @2.00GHz

内存:8,00GB 双通道

显卡:英特尔高清显卡 4000

渲染(更新) 对于渲染,我使用这样设置的 G-Buffer(来自延迟照明教程):

        glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);

glGenTextures(ARRAY_ELEMENTS(m_textures), m_textures);
glGenRenderbuffers(1, &m_depthBuffer);
glGenTextures(1, &m_finalTexture);

for(unsigned int i = 0; i < ARRAY_ELEMENTS(m_textures); i++){
    glBindTexture(GL_TEXTURE_2D, m_textures[i]);
    glTexImage2D(GL_TEXTURE_2D, 0, i == 0 ? GL_RGBA32F : GL_RGB8, WindowWidth, WindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i], 0);
}

glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_EXT, WindowWidth, WindowHeight);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);

glBindTexture(GL_TEXTURE_2D, m_finalTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WindowWidth, WindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, m_finalTexture, 0);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE){
    printf("[Error ] Framebuffer status: 0x%x\n", status);
    return false;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mWidth = WindowWidth;
mHeight = WindowHeight;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
return true;

所以我的问题:这可能是什么原因造成的?有没有解决办法?

【问题讨论】:

  • 我怀疑这是填充率问题,除此之外很难说。添加天空盒时是否停止清除颜色/深度缓冲区?很多旧资源会告诉您,这是您可以对天空盒使用的优化,但在现代 GPU(使用缓冲区压缩)上却不是。另外,你渲染天空盒的顺序是什么?为了使填充率最小化,您应该在所有其他不透明几何体之后绘制它。如果您已经采用这种方式进行绘制,则可以先尝试绘制天空盒,以过分强调任何填充率限制以跟踪瓶颈。
  • @AndonM.Coleman 我将所有内容渲染到第二个帧缓冲区中,其中包含位置/漫反射/法线/texcoord 纹理2Ds 和深度+模板纹理,然后在我的光照计算之后,我将最终图像blit 到原始图像帧缓冲区。因此,我在“几何传递”之前清除了最终图像缓冲区一次。但是我只对天空盒使用漫反射纹理,而对于地形我使用其他的。我最后一次渲染天空盒,实际上我尝试先移动它,但它的 fps 更差。
  • 哦,哇。如果您关心性能优化,那么会有很多问题。您可以取消位置 G-Buffer 并从深度重建位置,并且您不希望 blit 帧缓冲区,除非您尝试进行 MSAA 解析。在大多数情况下,绘制带纹理的四边形将比 glBlitFramebuffer (...) 快得多。
  • @AndonM.Coleman 我已经用我用来设置 G 缓冲区的代码更新了我的问题,希望这就是你想要的!
  • 32 位浮点对于除了位置缓冲区之外的所有东西来说都是多余的。更糟糕的是,它使用 32 位 RGB 而不是 RGBA。有些 GPU 无法处理 RGB32F,需要 RGBA32F。驱动程序可能会在内部将这些纹理更改为 RGBA32F,并使A 组件无法使用。知道了这一点,您也许可以将一些额外的数据编码到每个缓冲区的A 组件中,并保存 1 个完整缓冲区的数据。在担心天空盒的性能之前,您应该考虑减少渲染任何东西所需的内存带宽。

标签: c++ performance opengl glsl


【解决方案1】:

当我在使用延迟渲染器时,我只是在 Nividia 560ti 上使用深度纹理和模板开发,我没有任何问题。但是在我的 HD 4650 上,我不会只显示黑屏,所以我切换到RenderBuffers 用于深度和模板,这解决了我的问题。唯一的缺点是它们不能在着色器中采样。我希望这会有所帮助。

【讨论】:

  • 考虑到他的整个引擎是一个延迟着色器,似乎对它们进行采样实际上是一件大事
  • 对于位置和法线和其他属性,是的,它们需要保留纹理,但对于深度和模板,除非您正在做更高级的事情,例如景深和 SSAO,否则不需要。
  • +1,这确实让它表现得更好,所以谢谢你!但是,当您从某些角度(以及整体)查看天空盒渲染时,它会消耗所有 fps,这无济于事。这不会是一个问题,只是没有它现在是 1400 fps,而有了它是 70,从某些角度来看,它会变成 5。
  • 如果您能够以纹理的形式保持深度附件,您甚至不需要位置缓冲区。在大多数情况下,32 位浮点深度足以从深度重建位置。不幸的是,32 位深度 + 模板是一种讨厌的格式:32 位深度 + 8 位模板 + 24 位未使用 = 64 位。如果您合法地需要模板缓冲区,那么您只能通过重建每像素节省 32 位,并且也会增加硬件要求(D32S8X24 不被普遍支持)。
  • 错误,64 位。 (-96 位)用于移除位置缓冲区,(+32 位)用于打包深度+模板。尽管如此,如果您可以在没有模板缓冲区的情况下摆脱困境,那么您可以再节省 32 位。内存带宽是延迟着色的祸根,因此减小 G-Buffer 的大小始终是一个重要目标。
【解决方案2】:

好的,所以我让它工作了,问题很简单,我忘记在球体的渲染代码中除以 sizeof(float),所以它渲染得太多,甚至不应该被渲染!,但它已修复,所以感谢大家帮助我获得更好的表现!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    相关资源
    最近更新 更多