【问题标题】:Best method to copy texture to texture将纹理复制到纹理的最佳方法
【发布时间】:2014-07-21 18:33:09
【问题描述】:

将像素从纹理复制到纹理的最佳方法是什么?

我找到了一些方法来实现这一点。 例如,有一个方法glCopyImageSubData(),但我的目标版本是OpenGL 2.1,所以我不能使用它。 此外,由于性能非常重要,glGetTexImage2D() 不是一个选项。 由于我将视频帧作为纹理处理,因此我必须每秒复制大约 30~60 次。

我找到的可用选项如下:

  1. 为源纹理创建 fbo 并使用 glCopyTexSubImage2D() 将其复制到目标纹理。
  2. 为源纹理和目标纹理创建 fbo 并对 fbo 进行 blit。
  3. 为目标纹理创建 fbo 并将源纹理渲染到 fbo。

您可以忽略创建 fbo 的成本,因为 fbo 只会创建一次。

请不要张贴诸如“视情况而定”之类的内容。做你的基准。 我不仅仅针对一个 GPU。如果取决于,请告诉我它是如何取决于什么的。

此外,因为很难测量 OpenGL 调用的时间,所以我想知道它不是一个定量的结果。我需要一些关于应该避免使用哪种方法的建议。

如果你知道更好的复制纹理的方法,也请告诉我。

感谢您的阅读。

【问题讨论】:

  • 我认为给予 GL2.1 限制(FBO 也不是核心功能,但可能作为扩展广泛使用),除了您列出的那些之外,没有其他好的替代品。我还认为所有 3 个选项之间的性能差异会很小。
  • 在现代 GL 中计时 GL 调用实际上是简单。如果您的驱动程序支持计时器查询(大多数 2.1 实现不支持),您可以在命令之前将查询插入命令队列并在命令之后完成查询。等待几帧以获得该查询的结果,您将非常准确地测量它所花费的时间。您不能在较旧的驱动程序上使用它,但如果您只是想大致了解使用现代实现的每次调用之间的性能差异,这可能会有所帮助。
  • 如果需要,您可以立即获得计时器查询的结果……但这会强制管道停止。因此,从长远来看,这取决于您使用计时器查询的目的。如果您想在对运行时性能影响最小的情况下进行性能测量,请仅在结果之后查询它变得可用。如果您想立即知道命令的成本,请继续获取结果而不在它可用时进行其他工作(换句话说,强制 CPU/GPU 同步)。在您的情况下,我认为第二种方法可以正常工作。
  • @derhass 很高兴知道我找到了所有方法!谢谢。
  • @AndonM.Coleman 我不知道。事实上,我正在使用 Qt,而 Qt 已经为此提供了一个包装类!我现在正在测试它。我稍后会更新结果。谢谢。

标签: opengl copy textures benchmarking fbo


【解决方案1】:

由于我不知道那个计时器查询,所以我没有想到基准测试。 现在,我可以做自己的基准测试了。 我测量了每 100 次操作的 tming 并重复了五次。 不包括创建 FBO 的成本。

- S=source texture, D=destination texture, SF=FBO of S, DF=FBO of D
- operation=copying texture to texture
- op/s = how many operations for one second(average), larger is better
  1. 使用简单的直通着色器创建 DF 并将 S 渲染到 DF

    • 945.656op/s(100 次操作为 105.747ms)
    • 947.293op/s(100 次操作为 105.564ms)
    • 949.099op/s(100 次操作为 105.363ms)
    • 949.324op/s(100 次操作为 105.338ms)
    • 948.215op/s(100 次操作为 105.461ms)
  2. 创建 SF 并将 glCopyTexSubImage2D() 用于 D

    • 937.263op/s(100 次操作为 106.694ms)
    • 940.941op/s(106.277ms,100 次操作)
    • 941.722op/s(100 次操作为 106.188ms)
    • 941.145op/s(100 次操作为 106.254ms)
    • 940.997op/s(100 次操作为 106.270ms)
  3. 创建DF和SF并使用glBlitFramebuffer()

    • 828.172op/s(100 次操作为 120.748ms)
    • 843.612op/s(100 次操作为 118.538ms)
    • 845.377op/s(100 次操作为 118.290ms)
    • 847.024op/s(118.060ms 100 次操作)
    • 843.303op/s(100 次操作为 118.581ms)
  4. 创建 DF 和 SF 并使用 glCopyPixels()

    • 525.711op/s(190.219ms,100 次操作)
    • 523.396op/s(100 次操作为 191.060ms)
    • 537.605op/s(100 次操作为 186.010ms)
    • 538.560op/s(100 次操作为 185.680ms)
    • 553.059op/s(100 次操作为 180.813ms)

性能对比

passthrough shader ~ glCopyTexSubImage2D > glBlitFramebuffer >> glCopyPixels

因此,简单的直通着色器显示了复制纹理的最佳性能。 glCopyTexSubImage2D 比直通着色器稍慢。 fbo-blitting 足够快,但比着色器和 glCopyTexSubImage2D 差。 glCopyPixels,我没有预料到好的结果,显示出我预期的最差的性能。

【讨论】:

  • 复制深度附件怎么样?
  • 您使用哪种硬件?
【解决方案2】:

我们最终将四边形渲染到目标中;当使用最小着色器时,使用 GPU 执行 blit 的不同方法之间的性能差异很小,这种方法提供了最大的灵活性。

但是,如果您能找到一种方法来避免完全复制的操作 - 如果您可以将一个将您的副本变异的操作更改为读取原始副本的操作,则应用变异并一次生成一个新副本 - 当然会快得多。

【讨论】:

  • 我不确定我是否理解您的回答。在第一段中,我是否认为您的意思是使用最少着色器的第三个选项最灵活且易于使用?
猜你喜欢
  • 2011-03-16
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多