将纹理复制到纹理的最佳方法

时间:2014-06-01 14:43:10

标签: opengl copy textures benchmarking fbo

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

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

我找到的可用选项是下一个:

  1. 为源纹理创建fbo并使用glCopyTexSubImage2D()将其复制到目标纹理。
  2. 为源和目标纹理创建fbos并对fbos进行blit。
  3. 为目标纹理创建fbo并将源纹理渲染为fbo。
  4. 您可以忽略创建fbo的成本,因为fbo只会创建一次。

    请不要发布像'取决于'的东西。做你的基准。'。 我不只针对一个GPU。如果有,请,请让我知道它取决于什么。

    此外,由于测量OpenGL调用的时间非常困难,我想知道的不是定量结果。我需要一些关于应该避免哪种方法的建议。

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

    感谢您的阅读。

2 个答案:

答案 0 :(得分:19)

由于我不知道计时器查询,我没想到基准测试。 现在,我可以做自己的基准测试。 我测量了每100次操作的次数并重复了五次。 创建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. 使用简单的passthrough着色器

    创建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(100次操作106.277ms)
    • 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(100次操作118.060ms)
    • 843.303op / s(100次操作118.581ms)
  4. 创建DF和SF并使用glCopyPixels()

    • 525.711op / s(100次操作190.219ms)
    • 523.396op / s(100次操作时为191.060ms)
    • 537.605op / s(100次操作186.010ms)
    • 538.560op / s(100次操作185.680ms)
    • 553.059op / s(100次操作180.813ms)
  5. 绩效比较

    passthrough shader ~ glCopyTexSubImage2D > glBlitFramebuffer >> glCopyPixels
    

    因此,简单的passthrough着色器显示复制纹理的最佳性能。 glCopyTexSubImage2D比passthrough着色器略慢。 fbo-blitting足够快但比着色器和glCopyTexSubImage2D更糟糕。 glCopyPixels,我没有预料到好的结果,表现出最差的表现。

答案 1 :(得分:1)

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

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