2017-09-07 112 views
2

我初始化SDL与此代码:SDL_RenderPresent()不等待vsync - 如何等待?

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_RENDERER_PRESENTVSYNC添加到SDL_CreateRenderer标志只是使窗口变成空白的白色屏幕。虽然我需要使用SDL_RENDERER_SOFTWARE标志(即使我不使用SDL的软件渲染器来呈现屏幕),否则SDL_RenderPresent()会停顿很长时间,从而导致每秒约1帧。

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

+1

SDL的UpdateWindowSurface似乎没有vsync支持(并且我认为它可能在某些平台上非常困难,而在其他平台上可能不太可能),所以SDL软件渲染器也没有。虽然Vsync在3d API上非常强大,但它可能会更简单地解决您的放缓问题。 – keltar

+0

我不想浪费二进制空间,并依靠GPU API降低兼容性。 – Accumulator

+0

@genpfault是的,谢谢你的注意。我会重新发表评论。 – HolyBlackCat

回答

0

垂直同步是一项硬件功能。当启用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(); 
} 

update的呼叫将仅呈现帧如果至少 15毫秒已经过去了。 15毫秒是60帧/秒帧率所需的时间。

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

编辑

正如评论指出,这不会阻止撕裂,因为您没有同步到VBLANK信号。这个代码只能帮助限制帧速率。据我所知,使用软件渲染器时无法防止撕裂(因为您无法检测到vblank信号)。

+0

vsync不是帧速率。你的代码不会阻止撕裂。帧限制和同步到vblank信号是两个完全不同的事情。 –

+0

这是真的。它不会阻止撕裂,它只能将帧速限制在60FPS。 –