Software Development

Correcting The Future

DirectX: D3D Mouse Lag

I've been trying to solve this problem for ages. I knew it was common, but didn't understand why it was happening. Finally, I have solved it. This problem happens in many commercial games and professional products alike. Although less noticeable on faster machines, it can still happen there especially if the CPU is as fast or faster than the GPU.

What can happen is one of two things:

1. The mouse seems to move behind where you expect it to be even though the game runs at acceptable speeds. It'll feel like your mouse is gliding on ice. This can also be delayed character movements, etc. but the game and character runs at full speed.
2. The mouse moves fine, but the display is behind by up to a second or more.

I was getting #2 because I use the default Windows mouse cursor.

So what is going on here? Why would this happen?


What is actually happening is that the fill rate is being used up while the command buffer isn't. Huh? Let me explain.

Suppose you want to draw a simple texture that fills the screen. This is TWO triangles (D3D only works on triangles), but you have millions of pixels. Now consider the case where you would move the texture to where the mouse pointer is. What you MIGHT get is a delay in where the texture is drawn. The texture could be drawn where the mouse pointer was up to a second ago. So the texture is lagging behind. If you have a super fast card, the fill rate (maximum pixels drawn per second) won't be used up, so the lag might not even exist. But for complex games, it can be. On older cards, the fill rate will be used up quite easily.

The problem with D3D is that you can queue multiple frames until the command buffer is filled up. The more frames you queue up, the larger the lag. And game programmers will do everything they can to reduce the number of state changes, compounding the problem.

What you really want is to have only one or two frames in the command buffer. Some might think that the Present() call will force the command buffer to be flushed out. But this is not true. It can return with a positive result, and what it really did was simply to queue the Present command into the command buffer. So while you're waiting for a frame to render, you have tons of frames queued in your command buffer that were computed in under one or two millisecond. When they get rendered, they will look identical since not much can happen in that short a time.

Storing commands is quick.
Rendering them is another story all together.

In essence what is happening is that I'm computing 100 frames worth of commands in 1 millisecond which fills up my command buffer. But the video card would take 1000 milliseconds to render those 100 frames @ 10 ms each which is rather good frame rate (100 fps). And this is how you get a top speed frame rate while having lag. Every frame you render from then on will be 1 second old because that's how long a frame takes to go from the back of the command buffer to the front. The extra 99 frames in your command buffer is what is causing the lag. (These numbers are examples only).

How to fix this?

If you're using DirectX 9, you can use an occlusion query. Make sure that the request ends AFTER the Present() call. When the query returns data, then you know that the frame has been displayed. You can now move on to rendering the next frame. I had tried to end the query before the Present() call, thinking that Present() flushes the command buffer, and it did not work.

With DX8 and before, you can try to lock the backbuffer and read a pixel. This has varying degrees of success from what I've heard. Locking will cause your thread to pause until the command buffer is done. So you might need to use threading and other tools to get your program to work correctly.

If you want to render 2 or 3 frames ahead (needed to take advantage of multi GPU cards), you can always use multiple queries. When the second or third one returns data respectively, you can draw the next frame. Make sure to rotate your query indices.

Anyways, I'm glad I've finally fixed this problem. In Project V, when you drag components around, they now stay relatively close to the mouse pointer. There is a one frame delay because of double buffering, but it's not really noticeable. So if anyone else ever gets this problem, even on faster cards, this is how you fix it.

Project V Hack: Flawed Design?Project V: Implementing Event Systems

Comments

Unregistered user Monday, June 22, 2009 7:24:14 PM

the one who asks the question writes: i have a question, all my games, whenever i play, when i move my mouse, the game lag's like crazy, iv never had this problem before, the pc im using is very slow compared to what we have these days, but im playing the same games i played before, and recently, it started lagging without a reason, i have reformatted the HD, iv reinstalled windows, iv reinstalled my video driver, and im still getting this annoying lag, could this help me? or could u help me out plz? thx

Vorlath Monday, June 22, 2009 11:51:37 PM

What I mention in the article is on the programmer side. If you didn't have this problem before, then something else is likely going on.

Not sure if this is anything, but when you move a window around, can you see the screen redraw itself, or does the window move really fast with the white areas left behind draw itself really fast as well? If it redraws slowly, it means your video driver hasn't been activated. This can happen with older cards. Does your screen ever freeze and then come back? If so, that's a problem with settings on your video card. Oh, make sure you don't have antialiasing and that kind of stuff turned on.

I don't know. It could be a lot of things. What kind of video card do you have? Make sure hardware acceleration is set to full in your display properties/Settings/Advanced/Troubleshoot menu. Also make sure to enable write combining. If you have an old AGP video card, you can try setting the aperture size to 0 or 4MB (which will turn it off). Set your AGP speed to max (4x or 8x if you have it). If your AGP card is really old, try turning off AGP read and AGP writes (otherwise known as AGP texture acceleration).

Run dxdiag. You may find something there. Also, your audio drivers can actually cause lag in certain cases. Disable hardware acceleration on your audio (or disable your audio driver) and see if that does something. To fix it, turn AGP texture acceleration off if you have it, or reinstall your audio drivers.

Like I said, it could be anything. With newer cards, you should try getting the newest drivers. That's almost always the answer. If you have an older ATI card (or even a newer one), may I suggest trying the Omega drivers (there is a version available for older cards and it works great). They are far better than the official drivers.

One last thing that may be happening is that you had an older version of DirectX 9b installed at one point and you installed 9c over top. That version 9b is almost impossible to remove and will cause issues EVEN if you reinstall Windows. You'll need to find a tool somewhere that will completely remove DirectX. Make sure to completely remove your video drivers too. And then install DX 9c from scratch. And then install your video drivers. Only do all this if that is actually the problem. It's a pain to do correctly and takes a full day if you're lucky.

Something else that could happen is that the video card has been dislodged a little bit from its socket and is drawing too much power and is acting up. Also, your power supply may be nearing the end of its life. If your screen has ever gone bezerk, your power supply is likely ready to give up. This will definitely cause lag. Do any textures ever show up weird and with animated random noise? If so, that's your power supply.

Good luck.

Unregistered user Monday, June 29, 2009 6:34:10 AM

the one who asked the question writes: Thx alot, i found out it was the sound card, cause when i disable it, i dont get mouse lag, thx a bunch ill try out ur solution and ill tell u how it goes thx

Vorlath Monday, June 29, 2009 12:44:13 PM

Awesome news. Thanks for reporting back.

Sound card issues are usually very easy to fix. Also, if you still have problems after reinstalling drivers and have an actual sound card (not a built in one), you can try plugging it in a different slot. Try moving it closer to the power supply if you can. And if you have both a sound card and a built in one, make sure to disable the onboard card in your bios to avoid contention.

Also check if your game plays music from the HD. If you turn off music and lag disappears, then your HD is too fragmented. Defrag and you should be good to go. While you're at it, you should probably check that UDMA is enabled on your hard drive controllers. The option is in the control panel/System/Hardware Tab/Device Manager/IDE ATA Controllers/Select Primary IDE Controller (and check secondary as well)/Properties/Advanced Settings and make sure DMA is selected if you have it.

Offering some possible tips just in case.

Unregistered user Wednesday, October 21, 2009 10:39:50 AM

Anonymous writes: Hey im having the same problem i think. My mouse feels like its moving on a soapy surface. hard to describe, i cant aim properly etc. Im not really a techhead so i dunno how to do the things you said to do. im using dx10 would you be able to explain it for me? thanks.

Vorlath Wednesday, October 21, 2009 9:36:35 PM

I've never used dx10. With dx10, your video card would be newer. So it's likely a programming issue. Does this only happen in particular programs and not others? If so, then it's a programming issue and you have to wait for a patch (or get a different video card which can be hit or miss).

If you have a control panel for your video card, you could try forcing vsync. This can stall the video card on each frame. It has a downside, but if your card is fast enough, you should notice a difference.

Other than that, not much you can do other than to turn down rendering effects to low.

Unregistered user Wednesday, October 21, 2009 11:20:46 PM

Anonymous writes: It happens in both 3d games (Counterstrike source, Company of heroes) and 2d games (soldat. everything seems fine like you said. It's just the mouse movement and i have a decent computer (dual core, 4gb RAM, nvidia 9800gt) So im guessing thats not the problem. I have tried changing gfx cards (ATI radeon 3850) but the same thing. I remmeber that it was all fine at one point then i tried to change some settings because of some very minor fps lag when i died on soldat (worst decision) and now i have this problem. thanks for your quick reply :)

Vorlath Thursday, October 22, 2009 1:17:10 AM

If it was fine at one point, then it's definitely NOT your video card or machine. It's a setting or driver issue. Have you tried installing new drivers?

Also thy the other stuff I've mentioned. Disable your audio card in the device manager and see if it still lags. If it doesn't, then you need to get new drivers for your audio card. Also check vsync and double or triple buffering.

Unregistered user Friday, October 23, 2009 1:33:59 AM

Anonymous writes: What kind of drivers Should i install? like motherboard? Im not getting any lag as such, it just feels like my mouse moves like its a on a soapy surface, its just weird and by looking at it u couldnt tell the difference.

Vorlath Friday, October 23, 2009 9:16:33 PM

Drivers for your video card.

Unregistered user Friday, October 23, 2009 11:25:55 PM

Anonymous writes: Drivers for video card are up to date.

Unregistered user Tuesday, January 19, 2010 8:39:43 PM

PC GAMER IN TROUBLE writes: I installed COMPANY OF HEROES for the 2nd time .the 1st time it installed with no problems. 5 months later I reinstalled & it installed fine.. but i noticed i can't see the MOUSE CURSOR, making it very hard to navigate. i am going NUTS! =(

Vorlath Tuesday, January 19, 2010 9:12:10 PM

Dunno about that one.

Unregistered user Sunday, March 7, 2010 12:46:10 AM

Anonym writes: Thanks for the research, just fixed this for Freelancer by hooking into the Direct3D pipeline! greets w0dk4

Unregistered user Friday, January 13, 2012 12:34:24 AM

Steve writes: Hi! Any chance of a code sample of this fix? Thanks!

Unregistered user Friday, January 13, 2012 3:50:06 AM

Jake Birkett writes: Yeah a code sample would be great because we are suffering the same issue with DX9 when using VSync. I'm using the lock backbuffer plus read a pixel technique which seemed to work fine but some people have reported halving of framerate, which obviously sucks.

Write a comment

New comments have been disabled for this post.

May 2013
S M T W T F S
April 2013June 2013
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31