为什么即使只请求1x1 mipmap级别,glGetTexImage也会传输所有mipmap纹理?

时间:2012-09-25 11:59:46

标签: opengl gpu gpgpu render-to-texture

我渲染到FBO中的浮点纹理,需要CPU上该纹理的所有像素的平均值。所以我认为使用mipmapping来计算1x1 mipmap的平均值是非常方便的,因为我节省了CPU计算时间,我只需要将1个像素传输到CPU instad,比如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?

1 个答案:

答案 0 :(得分:3)

glGenerateMipmap( GL_TEXTURE_2D );
float *fPixel = new float[4];
Timer.resume();
glGetTexImage(GL_TEXTURE_2D, highestMipMapLevel, GL_RGBA, GL_FLOAT, fPixel);
Timer.stop();

让这成为您的一课:始终提供完整的信息。

它需要12倍的原因是因为您正在测量生成 mipmap所需的时间,而不是将mipmap传输到CPU所需的时间。与大多数渲染命令一样,glGenerateMipmap在返回时实际上不会完成。事实上,甚至启动的可能性都很大。这很好,因为allows OpenGL to run independently of the CPU. You issue a rendering command, and it completes sometime later.

然而,当你开始从该纹理中读取时,OpenGL必须停止CPU并等待所有将触及该纹理的内容完成。因此,您的计时是测量对纹理执行所有操作所花费的时间以及传输数据的时间。

如果您想要更准确的衡量标准,请在之前发出glFinish ,然后启动计时器。

更重要的是,如果你想对像素数据执行异步读取,你需要do the read into a buffer object.这允许OpenGL避免CPU停顿,但只有你有其他工作可以做才有用与此同时。

例如,如果你这样做是为了找出HDR色调映射的场景的整体照明,你应该为前一帧的场景数据而不是当前场景数据做这个。没有人会注意到。因此,您渲染场景,生成mipmaps,读入缓冲区对象,然后渲染下一帧的场景,生成mipmap,读入不同的缓冲区对象,然后从前一场景的缓冲区开始读取。

这样,当你开始阅读上一个读取的结果时,它们实际上会在那里,并且不会发生CPU停止。