Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos 同步两个NSOpenGLView的flushBuffer_Macos_Opengl_Flush_Nsopenglview - Fatal编程技术网

Macos 同步两个NSOpenGLView的flushBuffer

Macos 同步两个NSOpenGLView的flushBuffer,macos,opengl,flush,nsopenglview,Macos,Opengl,Flush,Nsopenglview,我正在开发一个OSX应用程序,它由两个nsopenggleviews(leftGLView和rightlview)组成,并排放置在NSWindow contentView中。 这两个视图不共享NSOpenGLContext,但都是双缓冲的,并将缓冲区交换与监视器回程同步 设置CVDisplayLink并将其链接到第一个NSOpenGLView的NSOpenGLContext和NSOpenGLPixelFormat(如左侧) 在CVDisplayLink回调中,我使用以下代码绘制两个视图: -(C

我正在开发一个OSX应用程序,它由两个
nsopenggleview
s(
leftGLView
rightlview
)组成,并排放置在NSWindow contentView中。 这两个视图不共享
NSOpenGLContext
,但都是双缓冲的,并将缓冲区交换与监视器回程同步

设置
CVDisplayLink
并将其链接到第一个
NSOpenGLView
NSOpenGLContext
NSOpenGLPixelFormat
(如左侧)

在CVDisplayLink回调中,我使用以下代码绘制两个视图:

-(CVReturn)draw {

     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

     CGLLockContext([[leftGLView openGLContext] CGLContextObj]);
     [[leftGLView openGLContext] makeCurrentContext];
     ... draw code ...
     [[leftGLView openGLContext] flushBuffer];
     CGLUnlockContext([[leftGLView openGLContext] CGLContextObj]);

     CGLLockContext([[rightGLView openGLContext] CGLContextObj]);
     [[rightGLView openGLContext] makeCurrentContext];
     ... draw code ...
     [[rightGLView openGLContext] flushBuffer];
     CGLUnlockContext([[rightGLView openGLContext] CGLContextObj]);

     [pool release];
     return kCVReturnSuccess;
}
这种方法的问题是,两个
flushBuffer
并不总是同步的。右侧NSOpenGLView的更新有时晚于左侧(可能在下次监视器刷新期间)。 这并非完全出乎意料,因为苹果关于
-flushBuffer
的文档中指出:

根据交换间隔上下文属性(请参见 NSOpenGLCPSwapInterval),可在垂直 返回监视器,而不是在刷新缓冲区后立即返回 打电话。隐式glFlush在返回之前由flushBuffer完成。 为了获得最佳性能,应用程序不应调用glFlush 在调用flushBuffer之前后续OpenGL命令可以 在调用flushBuffer后立即发出,但不执行 直到缓冲区复制完成。

但是,在这种情况下,我有两个不同的
NSOpenGLContext
,因此可以同时刷新两个缓冲区

为了进一步研究这一点,我假设
-flushBuffer
仅在交换(或复制)缓冲区后返回,并且由于这仅与监视器回溯同步发生,因此对flushBuffer的第二次调用将太晚,无法在该回溯上发生。这可以解释我观察到的行为。 因此,我尝试分离一个辅助线程来执行flushBuffer调用,但没有任何区别

我终于尝试使用两种不同的
CVDisplayLink
s,一种用于左侧GLView,另一种用于右侧GLView。然而,这种技术似乎也不能解决问题,并且增加了保持两个CVDisplayLink线程同步的额外复杂性


有没有办法让两个NSOpenGLView之间的两个
flushBuffer
同步进行?

在交换之前将每个上下文设置为不同线程的当前上下文。否则,启用VSYNC后,您的帧速率将不必要地减少一半。@AndonM.Coleman:谢谢您的回复。当我尝试使用两个线程(每个视图一个)时,我只是这样做了,这改善了情况,但并没有完全解决问题。在我发布的示例中,我只使用了一个线程,但帧速率仍然是60fps。我不明白如何将帧速率减半。如果使用VSYNC,则每次交换都将在VBLANK之后完成。使用VSYNC进行缓冲区交换最简单的实现是交换操作本身阻塞,直到VBLANK(监视器的垂直回溯间隔)滚动。因此,在最坏的情况下(假设刷新率为60 Hz),两次背对背交换将需要33.33334 ms。在最好的情况下,它们将需要略高于16.66667的时间。无论在何种情况下,除非您从两个单独的线程驱动交换链,否则您的一个窗口将始终落后于另一个窗口。@AndonM.Coleman:谢谢,我现在明白了。你知道为什么有时候即使我从两个独立的线程驱动交换,一个视图仍然落后一帧吗?这比使用单个线程要好得多,但仍然不够完美。仍然不能保证两个线程能够提前足够长的时间交换缓冲区,以便在VBLANK之前完成。即使在单窗口应用程序中也可以看到这一点,如果它们在VBLANK之前约1ms交换缓冲区,则帧可能无法及时完成,最终结果是显示2帧的旧帧,而新帧稍微延迟。你可以考虑的一件事实际上是在一个线程中完成这一切,但是只在一个窗口上使用VSyc。假设第一个块的缓冲区交换直到VBLANK,并且您可以及时完成第二个窗口的帧,这可能会起作用