Sleep(1)和SDL_Delay(1)需要15毫秒 [英] Sleep(1) and SDL_Delay(1) takes 15 ms

查看:706
本文介绍了Sleep(1)和SDL_Delay(1)需要15毫秒的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写C ++/SDL/OpenGL应用程序,并且遇到了最奇怪的错误.通过简单的可变时间步长,游戏似乎运行良好.但是随后FPS开始表现异常.我发现Sleep(1)和SDL_Delay(1)都需要15毫秒才能完成.

I am writing a C++/SDL/OpenGL application, and I have had the most peculiar bug. The game seemed to be working fine with a simple variable timestep. But then the FPS started behaving strangely. I figured out that both Sleep(1) and SDL_Delay(1) take 15 ms to complete.

在0到15之间对这些函数的任何输入都需要15毫秒才能完成,将FPS锁定在大约64.如果将其设置为16,则需要30 MS O.O

Any input into those functions between 0-15 takes 15ms to complete, locking FPS at about 64. If I set it to 16, it takes 30 MS O.O

我不知道为什么会这样.这是我遇到过的最奇怪的错误.

I have NO idea why this is happening. This is the strangest bug I have ever encountered.

我的循环如下:

while (1){
    GLuint t = SDL_GetTicks();
    Sleep(1); //or SDL_Delay(1)
    cout << SDL_GetTicks() - t << endl; //outputs 15
}

它很少会像预期的那样花费1毫秒的时间,但大多数情况下会花费15毫秒的时间.

It will very rarely take 1ms as it is supposed to, but the majority of the time it takes 15ms.

我的操作系统是Windows 8.1. CPU是Intel i7.我正在使用SDL2.因为我一无所知,所以任何想法都会受到赞赏.

My OS is windows 8.1. CPU is an intel i7. I am using SDL2. Any ideas would be appreciated, since I am clueless.

推荐答案

股票代码默认为64 hz,即15.625 ms/tick.您需要使用timeBeginPeriod(1)将其更改为1000hz == 1ms. MSDN文章:

The ticker defaults to 64 hz, or 15.625 ms / tick. You need to change this to 1000hz == 1ms with timeBeginPeriod(1). MSDN article:

http://msdn.microsoft.com/zh-CN/library/windows/desktop/dd757624(v=vs.85).aspx

如果此处的目标是获得固定的频率序列,则应使用更高分辨率的计时器,但不幸的是,这些计时器只能轮询,因此需要将轮询和睡眠结合使用以减少cpu开销.示例代码假设一个Sleep(1)可能要花费将近2毫秒的时间(在Windows XP中会发生这种情况,但在更高版本的Windows中不会发生).

If the goal here is to get a fixed frequency sequence, you should use a higher resolution timer, but unfortunately these can only be polled, so a combination of polling and sleep to reduce cpu overhead is needed. Example code, which assumes that a Sleep(1) could take up to almost 2 ms (which does happen with Windows XP, but not with later versions of 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 */

这篇关于Sleep(1)和SDL_Delay(1)需要15毫秒的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆