为什么OpenGL双缓冲似乎在性能方面不一致?

Par*_*emp 2 opengl macos frame-rate objective-c double-buffering

我在OSX上制作一个简单的图形应用程序.我刚开始通过检查帧之间系统时间的差异来监视帧速率.它似乎每隔几帧悬挂一下.

该应用程序在NSTimer对象上运行,目前设置为200 fps(5毫秒帧).为了确保它不仅仅是我的主代码很慢,我注释掉了整个主循环,除了[self.context flushBuffer]; (当然还有帧率采样代码).即使重复这一次调用,也会导致它一次挂起几帧.这是我的控制台输出的示例:

4
5
6
10
5
5
5
4
6
10
5
5
5
5
5
5
20
4
5
6
20
5
5
5
Run Code Online (Sandbox Code Playgroud)

这是每次循环迭代之间的时间(以毫秒为单位).在200帧/秒时,每帧应该约为5毫秒,但它会反复挂起10,15甚至20毫秒.正如你在-initOpenGL函数中看到的那样,Vsyncing被禁用了.

-(void)initOpenGL{
    NSOpenGLPixelFormatAttribute attributes[] = {NSOpenGLPFADoubleBuffer, 0};
    NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes: attributes];
    self.context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
    [self.context setView:[self.window contentView]];
    [self.context makeCurrentContext];

    //Disable Vsync
    int temp = 0;
    [self.context setValues: &temp forParameter: NSOpenGLCPSwapInterval];

    glViewport(0, 0, windowWidth, windowHeight);
    glMatrixMode(GL_PROJECTION);
    glOrtho(0, windowWidth, 0, windowHeight, -1, 100);

    //Flip all textures right side up
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glScalef(1.0f, -1.0f, 1.0f);

    glMatrixMode(GL_MODELVIEW);

    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }
Run Code Online (Sandbox Code Playgroud)

编辑,新信息:我可以确认这与双缓冲与单一有关.当我初始化没有DoubleBuffer属性的NSOpenGLPixelFormat时,它以200 fps完美运行.鉴于该属性,我继续得到口吃.

Dam*_*mon 5

在不知道实际渲染代码(未发布)的情况下,一个非常可能的原因是首先使用NSTimerfor frame rate control并不是一个好主意.请参阅文档(重点添加):

计时器不是实时机制 ; 只有当添加了计时器的其中一个运行循环模式正在运行并且能够检查计时器的触发时间是否已经过去时,它才会触发.由于典型的运行循环管理各种输入源,因此定时器的时间间隔的有效分辨率被限制在50-100毫秒的量级.

因此,期望在5毫秒之内使用计时器从根本上是有缺陷的.

除此之外,可能还有其他效果(进程调度,纹理上传和OpenGL中的停顿等),这将使帧时间不是100%不变.虽然由这些引起的抖动通常会小得多.