我正在编写一个C++/SDL/OpenGL应用程序,我遇到了最奇怪的错误.通过简单的可变时间步长,游戏似乎运行良好.但随后FPS开始表现得很奇怪.我发现Sleep(1)和SDL_Delay(1)都需要15 ms才能完成.
在0-15之间的任何输入都需要15ms来完成,将FPS锁定在大约64.如果我将其设置为16,则需要30 MS OO
我不知道为什么会这样.这是我遇到过的最奇怪的错误.
我的循环看起来像这样:
while (1){
GLuint t = SDL_GetTicks();
Sleep(1); //or SDL_Delay(1)
cout << SDL_GetTicks() - t << endl; //outputs 15
}
Run Code Online (Sandbox Code Playgroud)
它应该很少花费1ms,但大部分时间需要15ms.
我的操作系统是Windows 8.1.CPU是intel i7.我正在使用SDL2.任何想法都会受到赞赏,因为我一无所知.
rcg*_*ldr 12
股票代码默认为64赫兹,或15.625毫秒/滴答.您需要使用timeBeginPeriod(1)将其更改为1000hz == 1ms.MSDN文章:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624(v=vs.85).aspx
如果这里的目标是获得固定频率序列,则应该使用更高分辨率的计时器,但遗憾的是这些只能被轮询,因此需要轮询和休眠的组合以减少CPU开销.示例代码,假设Sleep(1)可能需要几乎2毫秒(在Windows XP中会发生这种情况,但在Windows的更高版本中不会发生).
/* code for a thread to run at fixed frequency */
#define FREQ 400 /* frequency */
typedef unsigned long long UI64; /* unsigned 64 bit int */
LARGE_INTEGER liPerfFreq; /* used for frequency */
LARGE_INTEGER liPerfTemp; /* used for query */
UI64 uFreq = FREQ; /* process frequency */
UI64 uOrig; /* original tick */
UI64 uWait; /* tick rate / freq */
UI64 uRem = 0; /* tick rate % freq */
UI64 uPrev; /* previous tick based on original tick */
UI64 uDelta; /* current tick - previous */
UI64 u2ms; /* 2ms of ticks */
#if 0 /* for optional error check */
static DWORD dwLateStep = 0;
#endif
/* get frequency */
QueryPerformanceFrequency(&liPerfFreq);
u2ms = ((UI64)(liPerfFreq.QuadPart)+499) / ((UI64)500);
/* wait for some event to start this thread code */
timeBeginPeriod(1); /* set period to 1ms */
Sleep(128); /* wait for it to stabilize */
QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
uOrig = uPrev = liPerfTemp.QuadPart;
while(1){
/* update uWait and uRem based on uRem */
uWait = ((UI64)(liPerfFreq.QuadPart) + uRem) / uFreq;
uRem = ((UI64)(liPerfFreq.QuadPart) + uRem) % uFreq;
/* wait for uWait ticks */
while(1){
QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
uDelta = (UI64)(liPerfTemp.QuadPart - uPrev);
if(uDelta >= uWait)
break;
if((uWait - uDelta) > u2ms)
Sleep(1);
}
#if 0 /* optional error check */
if(uDelta >= (uWait*2))
dwLateStep += 1;
#endif
uPrev += uWait;
/* fixed frequency code goes here */
/* along with some type of break when done */
}
timeEndPeriod(1); /* restore period */
Run Code Online (Sandbox Code Playgroud)