睡眠(1)和SDL_Delay(1)需要15毫秒
Sleep(1) and SDL_Delay(1) takes 15 ms
我正在编写一个C++/SDL/OpenGL应用程序,我遇到了最特殊的错误。通过一个简单的可变时间步长,游戏似乎运行得很好。但随后FPS开始表现怪异。我发现Sleep(1)和SDL_Delay(1)都需要15毫秒才能完成。
在0-15之间对这些功能的任何输入都需要15毫秒才能完成,将FPS锁定在大约64。如果我把它设置为16,它需要30毫秒O.O
我的循环如下:
while (1){
GLuint t = SDL_GetTicks();
Sleep(1); //or SDL_Delay(1)
cout << SDL_GetTicks() - t << endl; //outputs 15
}
它很少会像预期的那样需要1毫秒,但大多数时间都需要15毫秒。
我的操作系统是windows 8.1。CPU是英特尔i7。我正在使用SDL2。
股票代码默认为64赫兹,即15.625毫秒/分。您需要将其更改为1000hz==1ms,时间为BeginPeriod(1)。MSDN文章:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624(v=vs.85).aspx
如果这里的目标是获得固定的频率序列,则应该使用更高分辨率的计时器,但不幸的是,这些计时器只能轮询,因此需要将轮询和睡眠相结合来减少cpu开销。示例代码,假设睡眠(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 */
看起来15毫秒是操作系统将提供给您的最小切片。我不确定你的具体框架,但睡眠通常能保证最短的睡眠时间。(即,它将睡眠至少1ms。)
SDL_Delay()/Sleep()在时间低于10-15毫秒时无法可靠使用。CPU滴答声的注册速度不够快,无法检测到1毫秒的差异。
请参阅此处的SDL文档。
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- std::原子加载和存储都需要吗
- 需要帮助设置在C++中使用的Potrace
- 是否需要删除包含对象的"pair"?
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- C++我需要了解在哪里使用指针和双指针
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 我需要将多个函数组合为一个函数
- 概念中的cv限定符需要表达式参数列表
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 需要从 istream 和 ostream 派生 iostream
- 需要帮助了解C++中"15 Puzzle Game"的某些部分
- 为什么保存 IP 的字符串需要 15 字节,而大小只有 4
- Windows 8(1)比需要多睡1毫秒
- 如何获得比Windows XP上的计时器滴答(15毫秒)更高精度的时间
- 睡眠(1)和SDL_Delay(1)需要15毫秒