【发布时间】:2012-09-16 22:40:50
【问题描述】:
我在 FBO 中渲染到浮点纹理,并且需要 CPU 上该纹理的所有像素的平均值。所以我认为使用 mipmapping 将平均值计算为 1x1 mipmap 非常方便,因为我节省了 CPU 计算时间,我只需将 1 个像素传输到 CPU,而不是假设 1024x1024 像素。
所以我用这条线:
glGetTexImage(GL_TEXTURE_2D, variableHighestMipMapLevel, GL_RGBA, GL_FLOAT, fPixel);
但尽管我只特别要求最高级别的 mipmap,其大小始终为 1x1 像素,但完成该行代码所需的时间取决于纹理的级别 0 mipmap 的大小。这对我来说毫无意义。例如,在我的测试中,1024x1024 基础纹理的这条线比 32x32 基础纹理花费的时间大约长 12 倍。
fPixel 中的结果是正确的,只包含想要的像素,但是时间清楚地表明整个纹理集被转移,这对我来说是主要的原因,因为转移到 CPU 显然是我的瓶颈。
我使用 Win7 和 opengl,并在 ATI Radeon HD 4800 和 GeForce 8800 GTS 上进行了测试。
有人知道这个问题,或者有聪明的方法只将最高 mipmap 的一个像素传输到 CPU 吗?
【问题讨论】:
-
如何生成mipmap?
glGenerateMipmap,我猜? -
"完成该行代码所需的时间取决于纹理的 0 级 mipmap 的大小。"您如何测量它?
-
@ChristianRau:是的,我在 glGetTexImage 之前使用 glGenerateMipmap。
-
@NicolBolas:我使用 boost::timer 类来测量线路何时完成。这并不完全准确,每次测试的时间略有不同,但因为它慢了 12 倍,所以我并不真正关心精度。
glGenerateMipmap( GL_TEXTURE_2D ); float *fPixel = new float[4]; Timer.resume(); glGetTexImage(GL_TEXTURE_2D, highestMipMapLevel, GL_RGBA, GL_FLOAT, fPixel); Timer.stop(); -
@lenn 由于 GPU 操作的异步性,您的时间测量很可能完全是垃圾。您可能正在测量
glGenerateMipmaps(或一系列其他先前的操作),一旦CPU 调用glGenerateMipmaps返回,就不必完成这些操作。尝试在glGetTexImage(或简单的glFinish)之前插入一个栅栏事件点,以等待任何先前GPU操作完成以实际测量glGetTexImage(当然仅用于测量目的,请勿在生产代码)。
标签: opengl gpu gpgpu render-to-texture