Opengl glReadPixels()消耗单个内核的所有CPU周期
我有一个带有OpenGL窗口的SDL2应用程序,它表现良好:当它运行时,应用程序与我的60Hz显示器同步,我看到应用程序的CPU使用率为12% 到目前为止还不错。 但是,当我通过从深度缓冲区(绘制后)读取单个(!)深度值来添加3D拾取时,会发生以下情况:Opengl glReadPixels()消耗单个内核的所有CPU周期,opengl,nvidia,cpu-usage,sdl-2,glreadpixels,Opengl,Nvidia,Cpu Usage,Sdl 2,Glreadpixels,我有一个带有OpenGL窗口的SDL2应用程序,它表现良好:当它运行时,应用程序与我的60Hz显示器同步,我看到应用程序的CPU使用率为12% 到目前为止还不错。 但是,当我通过从深度缓冲区(绘制后)读取单个(!)深度值来添加3D拾取时,会发生以下情况: FPS仍为60 主线程的CPU使用率达到100% 如果不使用glReadPixels,CPU使用率将再次下降到12%。为什么从深度缓冲区读取单个值会导致CPU耗尽所有周期 我的窗口是通过以下方式创建的: SDL_GL_SetAttribut
- FPS仍为60
- 主线程的CPU使用率达到100%
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, use_aa ? 1 : 0 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, use_aa ? 4 : 0 );
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow
(
"Fragger",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
fbw, fbh,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI
);
我的画的结论是:
SDL_GL_SwapWindow( window );
我的深度读取是通过以下方式执行的:
float depth;
glReadPixels( scrx, scry, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
我的显示同步使用以下配置:
int rv = SDL_GL_SetSwapInterval( -1 );
if ( rv < 0 )
{
LOGI( "Late swap tearing not available. Using hard v-sync with display." );
rv = SDL_GL_SetSwapInterval( 1 );
if ( rv < 0 ) LOGE( "SDL_GL_SetSwapInterval() failed." );
}
else
{
LOGI( "Can use late vsync swap." );
}
int rv=SDL\u GL\u SetSwapInterval(-1);
如果(rv<0)
{
LOGI(“延迟交换不可用。使用与显示器的硬v同步”);
rv=SDL_GL_SetSwapInterval(1);
如果(rv<0)LOGE(“SDL_GL_SetSwapInterval()失败”);
}
其他的
{
LOGI(“可以使用后期vsync交换”);
}
使用“perf”进行的调查显示,nVidia的驱动程序会不断地进行系统调用,其中一个是sys_clock_gettime(),如下所示:
我尝试了一些变体,通过读取GL_BACK或GL_FRONT,得到了相同的结果。
我还试着在换窗前后阅读。
但CPU使用率始终处于100%的水平
- 平台:Ubuntu 18.04.1
- SDL:2.0.8版
- CPU:Intel Haswell
- GPU:nVidia GTX750Ti
- GL_版本:3.2.0 NVIDIA 390.87
我也尝试过(像素缓冲区对象),但这只适用于RGBA值,而不适用于深度值。如何/何时读取深度?从哪个缓冲区?当你这么做的时候,怎么没有vsync的FPS掉下来?看起来您强制驱动程序进行同步,因为请求的深度尚未渲染。从逻辑上讲,您可能需要上一帧的深度,而不是当前渲染的深度。@keltar谢谢。我用GL_FRONT和GL_BACK尝试了glReadBuffer(),结果相同。100%的CPU使用率。没有VSYNC到300 FPS,但仍然有很多循环被烧毁,所有都在GLADEXPLICALL()中。英伟达驱动程序在使用CPU-GPU同步时使用繁忙等待。事实上,这并没有什么错,因为这是最有效的选择。真正的问题是,您正在强制执行同步,而您应该执行的当然是异步回读。绝对没有理由不使用深度缓冲区内容,您应该真正修复代码。@derhass我认为我的代码是正确的:我在读取RGBA时获得非阻塞readpixels,而不是读取深度时。代码如下: