多个OpenGL上下文,多个窗口,多线程和vsync
我正在使用OpenGL创建一个图形用户界面应用程序,其中可以有任意数量的窗口 – “多文档界面”样式.
如果有一个窗口,主循环可能如下所示: >处理事件 但是当有3个窗口时,请考虑主循环: >每个窗口处理事件 糟糕…现在渲染一帧的应用程序发生在正确的帧率的1/3. 解决方法:实用程序窗口 一个解决方法是只有其中一个窗口与vsync打开,其余的与vsync关闭.首先在vsync窗口上调用swapBuffers(),然后绘制一个,然后在每个窗口上绘制其余的窗口和swapBuffers(). 这个解决方法大概可能看起来很好,但这不是没有问题: 有一个窗口是特别的,这是不合适的 解决方法:每个窗口一个线程 因为每个线程可以有一个OpenGL上下文绑定,也许答案是每个窗口有一个线程. 我仍然希望GUI是单线程的,但是,3窗口情况的主循环如下所示: (每个窗口) >锁定全局互斥体 这个工作吗这个other question表示不会:
为了调查此声明,我创建了一个simple test program.该程序创建N个窗口和N个线程,每个线程绑定一个窗口,请求每个窗口启用vsync,然后报告帧速率.到目前为止,结果如下: > Linux,X11,4.4.0 NVIDIA 346.47(2015-04-13) >帧速率为60fps,无论打开多少个窗口. > OSX 10.9.5(2015-04-13) 帧速率没有上限;交换缓冲区不阻塞. 解决方法:只有一个上下文,一个大的帧缓冲区 我想到的另一个想法是:只有一个OpenGL上下文,一个大的framebuffer,所有窗口的大小放在一起. 每个框架,每个窗口调用glViewport在绘制之前设置它们各自的framebuffer矩形. 所有绘图完成后,swapBuffers()在唯一的OpenGL上下文中. 我即将调查此解决方法是否可行.我有一些问题是: >有没有这么大的帧缓冲区可以吗? Camilla Berglund,GLFW的维护者说:
解决方法:只有一个上下文 This question表示该算法可能工作: Activate OpenGL context on window 1 Draw scene in to window 1 Activate OpenGL context on window 2 Draw scene in to window 2 Activate OpenGL context on window 3 Draw scene in to window 3 For all Windows SwapBuffers 根据问题提问者,
看起来他们只是在Microsoft Windows上进行了测试,而且这个解决方案将无处不在. 还有很多来源告诉我,makeContextCurrent()在draw()例程中太慢了. 它也看起来不符合EGL规范.为了允许另一个线程eglSwapBuffers(),你必须eglMakeCurrent(NULL)这意味着你的eglSwapBuffers现在应该返回EGL_BAD_CONTEXT. 问题 所以,我的问题是:解决使用vsync打开多窗口应用程序的最佳方法是什么?这似乎是一个常见的问题,但我还没有看到一个令人满意的解决方案. 类似的问题 类似于这个问题:Synchronizing multiple OpenGL windows to vsync但是我想要一个平台无关的解决方案 – 至少是每一个平台的解决方案. 而这个问题:Using SwapBuffers() with multiple OpenGL canvases and vertical sync?但是真的这个问题与Python无关. 解决方法
不,它不阻止.缓冲区交换调用立即返回,不会阻塞.然而,它是插入同步点,以便任何改变后台缓冲区的命令都会被延迟,直到发生缓冲区交换. OpenGL命令队列的长度有限,使程序块成为可能. 缓冲区交换也不是OpenGL操作.它是一个图形/窗口系统级操作,独立于OpenGL上下文.只看一下缓冲区交换功能:它们唯一的参数是drawable(= window)的句柄.实际上即使你有多个OpenGL上下文在一个drawable上运行,你只需要将缓冲区交换一次;你可以在没有OpenGL上下文的情况下使用drawable. 所以通常的做法是: ' first do all the drawing operations foreach w in windows: foreach ctx in w.contexts: ctx.make_current(w) do_opengl_stuff() glFlush() ' with all the drawing commands issued ' loop over all the windows and issue ' the buffer swaps. foreach w in windows: w.swap_buffers() 由于缓冲区交换不会阻塞,您可以为所有的窗口发出所有缓冲区交换,而不会被V-Sync延迟.然而,下一个解决用于交换的后台缓冲区的OpenGL绘图命令可能会停止. 解决方法是使用实??际绘图发生的FBO,并将其与在交换缓冲区循环之前执行FBO blit循环到后台缓冲区进行组合: ' first do all the drawing operations foreach w in windows: foreach ctx in w.contexts: ctx.make_current(w) glBindFramebuffer(GL_DRAW_BUFFER,ctx.master_fbo) do_opengl_stuff() glFlush() ' blit the FBOs' renderbuffers to the main back buffer foreach w in windows: foreach ctx in w.contexts: ctx.make_current(w) glBindFramebuffer(GL_DRAW_BUFFER,0) blit_renderbuffer_to_backbuffer(ctx.master_renderbuffer) glFlush() ' with all the drawing commands issued ' loop over all the windows and issue ' the buffer swaps. foreach w in windows: w.swap_buffers() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |