c++ - 为什么添加颜色附件会导致速度降低 3 倍?

标签 c++ opengl framebuffer fbo

我像这样渲染一些模型的深度:

m_fbo = new globjects::Framebuffer();
depthBuffer = globjects::Texture::createDefault();
depthBuffer->storage2D(1, GL_DEPTH_COMPONENT32F, size, size);
m_fbo->attachTexture(GL_DEPTH_ATTACHMENT, depthBuffer);

m_fbo->bind();
... draw all the things

现在,当我像这样向它添加颜色附件时:

m_fbo = new globjects::Framebuffer();
depthBuffer = globjects::Texture::createDefault();
depthBuffer->storage2D(1, GL_DEPTH_COMPONENT32F, size, size);
m_fbo->attachTexture(GL_DEPTH_ATTACHMENT, depthBuffer);

attributeBuffer = globjects::Texture::createDefault();
attributeBuffer->storage2D(1, <format>, size, size);
m_fbo->attachTexture(GL_COLOR_ATTACHMENT0, attributeBuffer);

m_fbo->bind();
... draw all the things

根据属性缓冲区的格式,渲染时间从 2.6 毫秒变为 5 毫秒(R8、RG8)、8.5 毫秒(RGB8、RGBA8、R32F)或 14.5 毫秒(RG32F、RGBA32F)(使用 opengl 计时器查询测量) .

我什至没有更改片段着色器,所以我没有计算任何额外的值来写入该颜色缓冲区。如果我注释掉 attachTexture 行,渲染时间会再次下降。

手边的纹理是一个 2Kx2K 的阴影贴图集。我使用的程序镶嵌模型,将每个三角形转换为一个点,并将 gl_PointSize = 1 的点渲染到该图集内随机选择的 64x64 瓦片中。曲面 segmentation 和几何着色器非常繁重,所以我不认为这是带宽或填充率限制。如果我渲染成一个大阴影贴图而不是多个小阴影贴图,这种减速会小得多(1.9 到 2.1 毫秒)。

如果我在几何着色器中使用 imageStore 手动将属性写入纹理并且不使用颜色附件,那么减速也是合理的(1.9 到 2.3 毫秒)

此外,当我开始使用 nsight 进行跟踪时,这种减速神秘地消失了,这使得无法对此进行分析。

知道为什么会发生这种情况吗?

我使用的是 750 Ti。

最佳答案

与大多数 OpenGL 性能问题一样,它们取决于实现。因此我们只能猜测,除非我们知道实际的实现是如何工作的。

  1. GPU 通常针对深度渲染进行了优化。由于您正在添加颜色附件,因此您不再进行仅深度渲染。
  2. 您的颜色附件格式是 GL_R32F。这种格式的渲染速度很可能比常规的旧 GL_RGBA8 格式慢。
  3. 如果每次切换到随机选择的 64x64 阴影贴图时都更改渲染目标,这真的很慢。更改渲染目标是一项非常昂贵的操作,但有一些方法可以解决它。请参阅本演示文稿的第 29 页:http://http.download.nvidia.com/developer/presentations/2005/GDC/OpenGL_Day/OpenGL_FrameBuffer_Object.pdf
  4. 如果我没理解错的话,您正在渲染许多 1 像素的三角形。这很慢。这是因为 GPU 以 2x2 像素为一组对像素进行光栅化。即使只渲染一个像素,硬件仍会运行着色器 4 次,然后仅丢弃 3 个像素。如果您渲染的只是 1 个像素的三角形,那么您实际上浪费了 3/4 的光栅化性能。

请问您为什么使用深度附件格式 GL_DEPTH_COMPONENT32F?大多数 GPU 甚至不支持 32 位深度缓冲区。通常为 24 位。您是否尝试过使用 GL_DEPTH_COMPONENT24GL_DEPTH_COMPONENT32

虽然这是一个非常特殊的问题。您是否尝试更新您的 GPU 驱动程序?

关于c++ - 为什么添加颜色附件会导致速度降低 3 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38504139/

相关文章:

c++ - 关于long long和long double

c++ - 在 C++ 中使用 reinterpret_cast 向下转型

c - KHR 平台标题在做什么?

c++ - 为什么无法从我的光照着色器访问 G-Buffer?

c++ - 如何在 PHP 扩展中实例化全局 C++ 类?

c++ - 如果 operator= 函数未在 C++ 类中实现,执行将如何工作

java - 用 lwjgl 绘制玩家(一个简单的矩形)没有什么作用

c++ - 在 Qt 中使用 SOIL 库时出错

opengl - 何时调用 glEnable(GL_FRAMEBUFFER_SRGB)?

android - glCheckFramebufferStatus 返回 36054 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT