我用以下代码初始化SDL:

SDL_Init(SDL_INIT_VIDEO);

SDL_Window* win = SDL_CreateWindow(
    "SDL Window",
    SDL_WINDOWPOS_UNDEFINED,
    SDL_WINDOWPOS_UNDEFINED,
    WIDTH,
    HEIGHT,
    SDL_WINDOW_SHOWN
);

SDL_Renderer* ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE);
SDL_GL_SetSwapInterval(1); // probably has no effect since it's not using GL

然后,我使用非SDL软件渲染器进行渲染,并使用以下代码将其呈现给窗口:
SDL_UpdateTexture(screenBuffer, NULL, screenData, WIDTH*4);

SDL_RenderClear(ren);
SDL_RenderCopy(ren, screenBuffer, NULL, NULL);
SDL_RenderPresent(ren);

帧速率是完全不受限制的,我不知道为什么。

在SDL_CreateRenderer标志中添加| SDL_RENDERER_PRESENTVSYNC只会使窗口成为空白屏幕。尽管我需要使用SDL_RENDERER_SOFTWARE标志(即使我没有使用SDL的软件渲染器来呈现屏幕),否则SDL_RenderPresent()将停滞很长时间,导致每秒大约1帧。

如何让SDL_RenderPresent()等待vsync,或者自己(准确地)等待它?

最佳答案

VSync是一项硬件功能。启用“垂直同步”后,视频卡将停止渲染器呈现帧,直到来自监视器的指示垂直同步的信号到达为止(这意味着它已完成显示最后一帧)。

如果您使用的是软件渲染器,则由于没有使用视频卡进行渲染,因此无法检测到此信号。由您决定帧速率并等待下一帧。

每秒60帧的示例:

#define TICKS_FOR_NEXT_FRAME (1000 / 60)

int lastTime = 0;

void update() {
    while (lastTime - SDL_GetTicks() < TICKS_FOR_NEXT_FRAME) {
        SDL_Delay(1);
    }

    ... // SDL_RenderCopy...

    SDL_RenderPresent(renderer);
    lastTime = SDL_GetTicks();
}

如果至少经过15毫秒,对update的调用将仅显示该帧。 15 FPS是帧速率为60 FPS所需的时间。

我知道这个问题很旧,但是我决定将答案发布给其他可能需要它的人。

编辑

如注释中所述,这将不会阻止撕裂,因为您没有同步到vblank信号。此代码仅有助于限制帧速率。据我所知,在使用软件渲染器时无法防止撕裂(因为您无法检测到vblank信号)。

关于c++ - SDL_RenderPresent()不等待vsync-如何等待?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46106543/

10-10 13:49
查看更多