OpenGL异步渲染场景需要花费几秒钟

时间:2019-03-04 14:12:35

标签: c++ opengl wxwidgets

我已经使用wxWidgets和OpenGL实现了Mandelbrot分形生成器。计算是在片段着色器内部执行的,而我正在使用wxGLCanvas小部件显示结果。它工作正常,但是当我要进行高分辨率导出时,线程锁定了几秒钟,从而冻结了UI。

最初,我尝试将所有渲染代码(和上下文创建)移到一个单独的渲染线程中,但是我发现,不仅锁定了渲染线程,还发现了所有线程。这可以通过在执行仅在循环中将消息打印到stdout的渲染之前生成一个新线程来容易地演示。在冻结之前,它最多可以打印1条消息,然后在渲染完成后恢复。

要执行文件导出,首先渲染为纹理,然后使用glGetTexImage将像素读入主存储器。渲染与您期望的异步进行,但是glGetTexImage函数将阻止(再次达到预期)。因此,我尝试将glFenceSync与glGetSynciv结合使用,仅在达到围栏指示已完成渲染时才调用glGetTexImage。

我可以确认绘图调用立即返回,但是当我返回到wxWidgets事件循环以等待渲染完成时,应用程序中的所有线程将冻结。我认为wxWidgets可能正在进行强制进行同步的OpenGL调用(wxGLCanvas中可能有问题)-我相当确定这不是我的代码中的问题。

我不确定为什么所有线程都阻塞在glGetTexImage调用上,而不仅仅是渲染线程。我以为这可能是我的设置(硬件,驱动程序,操作系统等)的怪胎,但在完全不同的平台上得到了相同的结果。

我能想到的唯一剩下的选择是在具有自己的OpenGL上下文的另一个进程中进行导出渲染。如果仍要使用wxGLCanvas设置上下文,则可能需要在屏幕上显示一个可见窗口,这并不理想。另外,如果用户在渲染期间尝试关闭窗口,则该窗口将无响应。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

与其说是解决方案,不如说是一种解决方法(由注释中的derhass建议)是将渲染分为几个较小的渲染。我将图像绘制成水平条纹,每个条纹高10像素,并在每个条纹之间调用wxSafeYield(),以使UI保持一定的响应速度(如果绘制时间太长,用户可以中止渲染)。

另一个优点是,GPU过载的危险较小。在执行此操作之前,我曾经启动过长时间的渲染,这导致我的显示器关闭,我不得不进行强制重启。