简体   繁体   English

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

[英]OpenGL asynchronous render of scene that takes several seconds

I've implemented a Mandelbrot fractal generator using wxWidgets and OpenGL. 我已经使用wxWidgets和OpenGL实现了Mandelbrot分形生成器。 The computation is performed inside a fragment shader, and I'm using a wxGLCanvas widget to display the result. 计算是在片段着色器内部执行的,而我正在使用wxGLCanvas小部件显示结果。 It's working well, but when I want to do a high-res export, the thread locks up for a few seconds which freezes the UI. 它运行良好,但是当我要执行高分辨率导出时,线程锁定了几秒钟,这冻结了UI。

Initially I tried moving all rendering code (and context creation) into a separate render thread, but what I found was that it wasn't just the render thread that would lock up, but ALL threads. 最初,我尝试将所有渲染代码(和上下文创建)移到一个单独的渲染线程中,但是我发现,锁定的不仅仅是渲染线程,而是所有线程。 This could be easily demonstrated by spawning a new thread prior to doing the render that just prints a message to stdout in a loop. 这可以通过在执行仅在循环中将消息打印到stdout的渲染之前生成一个新线程来容易地演示。 It would get as far as printing 1 message before freezing, then resuming once the render was complete. 在冻结之前,它将打印多达1条消息,然后在渲染完成后恢复。

To perform the file export, I first render to a texture, then I read the pixels into main memory with glGetTexImage. 为了执行文件导出,我首先渲染为纹理,然后使用glGetTexImage将像素读入主存储器。 The render occurs asynchronously as you would expect, but the glGetTexImage function will block (again, that's expected). 渲染与您期望的异步进行,但是glGetTexImage函数将阻止(再次达到预期)。 I therefore tried using glFenceSync in combination with glGetSynciv to only call glGetTexImage once the fence had been reached indicating a completed render. 因此,我尝试将glFenceSync与glGetSynciv结合使用,仅在达到围栏指示已完成渲染时才调用glGetTexImage。

I could confirm the draw call was returning immediately, but the moment I returned to the wxWidgets event loop to wait for the render to finish, all threads in the application would freeze. 我可以确认绘图调用立即返回,但是当我返回到wxWidgets事件循环以等待渲染完成时,应用程序中的所有线程都将冻结。 I figure maybe wxWidgets is making an OpenGL call that's forcing a sync (prob something in wxGLCanvas) - I'm fairly sure it wasn't something in my code. 我认为wxWidgets正在进行强制进行同步的OpenGL调用(wxGLCanvas中可能有问题)-我相当确定这不是我的代码中的问题。

I'm not sure why all threads were blocking on the glGetTexImage call, rather than just the render thread. 我不确定为什么所有线程都阻塞glGetTexImage调用,而不仅仅是渲染线程。 I thought it might be a quirk of my setup (hardware, driver, OS, etc.), but got the same result on a completely different platform. 我以为这可能是我的设置(硬件,驱动程序,操作系统等)的怪癖,但在完全不同的平台上却得到了相同的结果。

The only remaining option I can think of is to do the export render in another process with its own OpenGL context. 我能想到的唯一剩下的选择是使用自己的OpenGL上下文在另一个进程中进行导出渲染。 If I'm still to use wxGLCanvas to set up the context I would probably need a visible window on the screen, which isn't ideal. 如果仍要使用wxGLCanvas设置上下文,则可能需要在屏幕上显示一个可见窗口,这并不理想。 Also, if the user tries to close the window during the render, it would be unresponsive. 同样,如果用户在渲染过程中尝试关闭窗口,它将无响应。

Any ideas? 有任何想法吗?

Not so much a solution, but a workaround (suggested by derhass in the comments) is to split the render into several smaller renders. 与其说是解决方案,不如说是一种解决方法(由注释中的derhass建议)是将渲染分为几个较小的渲染。 I'm drawing the image in horizontal strips, each 10 pixels high, and calling wxSafeYield() between each one so the UI remains somewhat responsive (and the user can abort the render if it's taking too long). 我将图像绘制成水平条纹,每个条纹高10像素,并在每个条纹之间调用wxSafeYield(),以使UI保持一定的响应速度(如果绘制时间太长,用户可以中止渲染)。

An additional advantage is that there's less danger of overloading the GPU. 另一个好处是,GPU过载的危险较小。 Prior to implementing this I once kicked off a long render that caused my displays to shut off and I had to do a hard reboot. 在执行此操作之前,我曾经启动过长时间的渲染,导致显示器关闭,因此必须进行强制重启。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM