查看完整版本: [-- 奇怪的处理落? --]

-> 同人游戏创作/Doujin Games Workshop -> 奇怪的处理落? [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

mk124 2009-03-26 03:14

奇怪的处理落?

现在我的程序是自己处理Sleep时间控制帧数的,不过貌似偶尔有卡帧的处理落问题……
我去掉了我的帧率控制代码,开启了垂直更新同步,结果还是有古怪的处理落卡帧问题= =

结果我将进程的优先级改为实时后,问题解决……
为啥会这样呢= =?我明明已经将游戏的主线程的优先级设为最高了啊……貌似这样:
  1.     HANDLE currentThread = GetCurrentThread();
        SetThreadPriority(currentThread, THREAD_PRIORITY_TIME_CRITICAL);

而且我的东西占用CPU也只是4-8%左右而已,想不通为啥会处理落……
求助……

绯想の夜 2009-03-26 06:06
其实应该用游戏时间来控制。。。。

mk124 2009-03-26 07:05
就是拿timeGetTime(精度:1ms)获得的实际时间来控制的啊= =

littlewater 2009-03-26 10:17
瞬间CPU占用过高的关系吧?

看看每一次帧渲染的时间间隔,如果起伏变化很大的话……

建议试试D3D多缓冲……

h5nc 2009-03-26 10:27
所以说请用orz……
没有比orz再优的办法了。。。
然后intel分析之。。

补充:orz
莫要挖坟
http://bbs.thproject.org/read.php?tid=26160&fpage=16

littlewater 2009-03-26 20:05
不一定的,找到问题根源动手解决之,知道问题所在以后,
方法并不一定只有一二种^^

求每帧描绘MS统计~♪

mk124 2009-03-26 21:19
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=14, realSleepTime=14, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=2


精度=timeGetTime()精度=1ms;
renderTime = 逻辑运算时间+图形渲染时间;


已经看了AVC大的ORZ,其实想法还不错,不过有好多层古怪的API封装= =
其实也就是跟目标时间相差大的时候Sleep()挂起线程,相差小就循环抢CPU卡准确时间~
那啥= = 暂时没考虑过用这个方法呢 虽然并不难用~

littlewater 2009-03-27 09:34
=3= 从你这输出上看,那不就是很流畅了嘛……
你确定以上输出的数据中有至少一次处理落么 OTL

另外我很难相信这是真的,请求的时间和SLEEP的时间居然那么准……
也许机器比较准?水水自己的机器SLEEP都不准的……

求含此输出的EXE程序,想自己跑一跑确认出现30FPS的时候是否还是对的……

----------------------------------

再去跑了几趟游戏,发现运动中并且挂的时候,机箱有时候会有鸣叫,于是又
看了一下LZ的API调用,发现并未使用DINPUT,也不是WIN32API的GetAsyncKeyState,而是用的是回调的WM_KEYDOWN和WM_KEYUP
通常不应该也不建议使用消息循环回调来处理人物运行,推荐是放到帧循环中每帧轮询吧……

不过实测不按键也会偶尔有卡住现象……问题依然迷茫= =

h5nc 2009-03-27 15:04
私以为调用机箱鸣叫很有嫌疑。。。那是中弹。。

Advance 2009-03-27 15:39
timeGetTime的精度取决于所有进程调用timeBeginPeriod的最小值,在NT4.0以上的系统中默认值是5ms
Sleep的精度同上,当然真要准的话除非优先级特别高……

THREAD_PRIORITY_TIME_CRITICAL优先级不应在一般的应用程序中使用

关于瞬间FPS低下,关闭GC试试。相应的tracer需要准备一个

mk124 2009-03-27 15:41
至少有一个处理落啊|||
我在感到有轻微卡帧现象的时候就立即停止执行的呢……
咩= =中弹已经不用Beep()乱叫了,所以肯定不是这个问题呐|||
只是所有残机用完的时候才Beep() 一次……

好吧……样本上传了= =
用了OutputDebugString()输出~拖进调试器里就能看到了。

mk124 2009-03-27 15:52
使用THREAD_PRIORITY_TIME_CRITICAL应该没啥问题吧= =,至少不陷入死循环就不会有问题……(默|||)
还有,啥是GC呢?= =

littlewater 2009-03-27 18:02
水水自己跑了一次,你可以看一下这两段比较明显的时间间隔:
第一处,最大真实时间间隔有90ms+
00000774    13.08438396    [832] destSleepTime=14, realSleepTime=14, renderTime=1    
00000775    13.10101509    [832] destSleepTime=16, realSleepTime=17, renderTime=1    <---- start
00000776    13.19690228    [832] destSleepTime=15, realSleepTime=15, renderTime=2    <---- stop
00000777    13.19899559    [832] destSleepTime=14, realSleepTime=15, renderTime=51    
00000778    13.20046902    [832] destSleepTime=0, realSleepTime=1, renderTime=31    
00000779    13.21989250    [832] destSleepTime=0, realSleepTime=0, renderTime=1    
第二处,最大真实时间间隔有100ms+
00001548    26.19770050    [832] destSleepTime=13, realSleepTime=13, renderTime=1    <---- start
00001549    26.30513191    [832] destSleepTime=16, realSleepTime=17, renderTime=1    <---- stop
00001550    26.30688667    [832] destSleepTime=15, realSleepTime=16, renderTime=54    
00001551    26.31012535    [832] destSleepTime=0, realSleepTime=0, renderTime=39    
其他也存在一些,至于为什么描绘并没有跳变,因为后面被你用数个destSleepTime=0覆盖了漏洞
不过这只是我自己机器上跑的结果……附上完整的文件~
顺便,我的本子只能跑到25FPS,哭啊,看来显卡太烂、显存太小=3=~

--------------------
自己的一点点(微不足道)的说法,所谓FPS=60或者多少,并不是为了尽可能去达到它(除非你做3D那肯定不应该锁定),
我不清楚一次处理是否等同于一次真实的渲染(我这里假定处理和绘制是同一个概念,即同一个线程,事实上大多程序也这么做),
FPS的存在意义,是让它真实的反应描绘速率,如果慢了发生掉帧,那就应该让它掉,而不是去补回来,因为在同一个16~17ms之间绘制多少次
意义几乎不大(夸张点想象0ms的间隔),绘制多少次,差不多等于只绘制了一次罢了……请勿为了追求60FPS而去弄60FPS。

我自己也没做过很高深的STG,以上言论也可以无视之~♪

mk124 2009-03-27 18:14
控制帧率算法有严重问题么|||
我去检查下……

谢谢~!

mk124 2009-03-27 18:22
貌似很诡异呢= =我没有去刻意保持60FPS啊= =
更没有destSleepTime=0达到加速补帧的行为……

以下测试为:
我开启了游戏,故意去点游戏的标题栏,达到卡帧的目的,然后发现FPS的确下降了啊……
乃的问题……莫非timeGetTime()抽风了?-_____-

destSleepTime=14, realSleepTime=14, renderTime=5
destSleepTime=12, realSleepTime=12, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=188    <-Click
destSleepTime=0, realSleepTime=0, renderTime=5
destSleepTime=11, realSleepTime=12, renderTime=3
destSleepTime=13, realSleepTime=14, renderTime=5
destSleepTime=11, realSleepTime=11, renderTime=3

destSleepTime=11, realSleepTime=11, renderTime=3
destSleepTime=13, realSleepTime=14, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=2
destSleepTime=15, realSleepTime=15, renderTime=89    <-Click
destSleepTime=0, realSleepTime=0, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=4
destSleepTime=12, realSleepTime=12, renderTime=2
destSleepTime=15, realSleepTime=16, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=2


-------------------------------------------------------------------------------- 附上后来测试的明显有处理落的调试数据:
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=6
destSleepTime=11, realSleepTime=11, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=11       <
destSleepTime=5, realSleepTime=5, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=5
destSleepTime=11, realSleepTime=11, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=4
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=20       <
destSleepTime=0, realSleepTime=0, renderTime=7
destSleepTime=9, realSleepTime=9, renderTime=18       <
destSleepTime=0, realSleepTime=0, renderTime=3
destSleepTime=14, realSleepTime=15, renderTime=4
destSleepTime=11, realSleepTime=11, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=3
destSleepTime=13, realSleepTime=13, renderTime=3
destSleepTime=14, realSleepTime=14, renderTime=3


-------------------------------------------------------------------------------- 后来继续发现= =
系统空载或将进程设置为实时的时候,renderTime稳定在1~2ms
执行了比较多程序的时候……(见上面的调试信息)
destSleepTime==realSleepTime,不过renderTime时间非常不稳定,在1-10MS之间飘~

Advance 2009-03-27 19:31
跑了5分钟没有发现任何问题......

mk124 2009-03-27 19:33
timeGetTime()不太可能抽风吧= =
是不是你的调试器有延迟了……?

littlewater 2009-03-27 20:41
那就直接和系统有关了吧^^
毕竟WIN不是实时的,估计这问题一下子也搞不定咯~♪

作罢

mk124 2009-03-27 21:40
郁闷死了= =
不能作罢啊|||||||

littlewater 2009-03-28 08:08
象AVC大这样的机器自然就米问题了,我觉得这没啥办法啊,本来不是实时系统的东西
要不你就做缓冲,多开几个缓冲试试……

水月 2009-03-29 14:06
用QueryPerformanceFrequency
和QueryPerformanceCounter可以取得纳秒级的精确分辨率,这个和硬件有关,最差386机器上也有微妙级的分辨率
然后如果是多核CPU请设置SetThreadAffinityMask线程对CPU的亲和力,防止跨CPU调用
此外sleep精度是16毫秒级的,还有sleep还有线程切换问题
解决办法是
判断剩余时间是否与大16毫秒。如果大于16就休眠大于部分。剩下时间用忙等待来精确休眠。这样即使sleep发生偏差,忙等待也会纠正过来。

littlewater 2009-03-29 19:21
但是在水水机器上根本没有时间在一个17MS内完成
结果处理逻很正常不是?

Advance 2009-03-29 20:02
结果只有0.xx ms可以休息么(1000/60=...)

啊,纯水是不好的,所以补充点有用的东西吧

TO 20楼:

我想有些地方你的理解似乎不太正确,这里正好有篇中文的:
http://www.cnblogs.com/dksoft/archive/2008/05/25/1207093.html
http://blog.csdn.net/axx1611/archive/2007/09/15/1786599.aspx

比如我的主板PIT就是8254.2

  1. text:800125D1                 call    _HalpAcquireSystemHardwareSpinLock@0 ; HalpAcquireSystemHardwareSpinLock()
    .text:800125D6                 mov     al, 0
    .text:800125D8                 out     43h, al         ; Timer 8253-5 (AT: 8254.2).
    .text:800125DA                 pushfw
    .text:800125DC                 popfw
    .text:800125DE                 jmp     short $+2
    .text:800125E0                 in      al, 40h         ; Timer 8253-5 (AT: 8254.2).
    .text:800125E2                 pushfw
    .text:800125E4                 popfw
    .text:800125E6                 jmp     short $+2
    .text:800125E8                 movzx   edx, al
    .text:800125EB                 in      al, 40h         ; Timer 8253-5 (AT: 8254.2).

littlewater 2009-03-29 21:09
QueryPerformanceFrequency这个函数好像在不同的机器上得到的值意义不同,有的机器(很多是老P4的)
返回的是3.5M晶振,而很多新的双核四核返回的直接是主频……不知道是什么原因?

PIT嗯呢?
说起来可能会偏差话题了……

mk124 2009-03-29 22:10
早就调用SetThreadAffinityMask绑到第一个处理器上了,还提高线程到最高优先了|||
还有,AVC大大好像说过……Sleep精度还决定于timeBeginPeriod()和线程优先度呢

苍穹的巨熊 2009-04-04 10:52
完全看不懂

biilibili 2013-09-30 17:01
真心强大!!就是看不懂


查看完整版本: [-- 奇怪的处理落? --] [-- top --]


Powered by phpwind v8.7 Code ©2003-2011 phpwind
Time 0.044427 second(s),query:2 Gzip enabled