Cursor lag in DX9

BlitzMax Forums/BlitzMax Programming/Cursor lag in DX9

Grey Alien(Posted 2011) [#1]
I felt that the cursor lagged more in DX9 than DX7 in my match-3 game, so I switched on the system cursor and verified that the in-game cursor does indeed lag more in DX9.

Does anyone know why this is and if there are any workarounds? I'm guessing that there must be some kind of delay in rendering with DX9. Years ago we had a big Cursor Lag issue in DX7 and that was resolved by tweaking the way DX7 drew in the module (by cleaning out any old screens to be rendered in the buffer and staying up to date). Does DX9 need something like that or is it a no hoper?

Or perhaps there's a lag in reading the coordinates? But I doubt that would vary depending on DX use.

Last edited 2011


Tommo(Posted 2011) [#2]
Does this happen in window mode or in fullscreen mode?
Maybe you can try something below:
* always use vsync.
* use maxgui + CanvasGraphics for window mode
* don't use brl.timer to trigger rendering


JazzieB(Posted 2011) [#3]
I can confirm that this happens in both windowed and fullscreen mode. It's for this reason that I'm still using DX7 in my current project. I also found that keyboard response didn't seem as good either - I was a worse player under DX9 than I was in DX7 ... go figure!

Anyhow, the lag is worse with vsync on. When off, it's not so bad, but obviously dependant on how fast your system is. The faster, the better, but this is not good if you're writing for the casual games market.

It does need fixing and I'm surprised it hasn't been yet, because of the same issue we had in DX7.


Grey Alien(Posted 2011) [#4]
Yes it happens in both mode here too. I recently changed to DX9 because I discovered the SetVirtualResolution() didn't work with DX9 on netbooks with small screens. But I've realised that there is a cursor lag. I use Vsync on as it makes the games look a lot smoother but some players are reporting bad cursor lag.


ImaginaryHuman(Posted 2011) [#5]
maybe it's to do with how many extra backbuffers there are which it cycles between when you flip the display? does the old mouse hack (grab a pixmap pixel) work?


Grey Alien(Posted 2011) [#6]
Haven't tried that. Perhaps I should. Yeah it feels like there are too many backbuffers or something like that.


col(Posted 2011) [#7]
Hey guys, there is still only 1 backbuffer being used in the standard Bmax DX9 setup.
It must be something else.

I vaguely remember there was an issue a looong time ago with mouse input and keyboard input, I can't even remember what that issue was, something along the lines of input buffers ?? I cant remember, but Mark resorted back to using the system input instead if DirectX input. Maybe its the same issue popped up again ?
Although I'm sure Bmax Dx uses standard input.

Last edited 2011


Kryzon(Posted 2011) [#8]
Can anyone code a simple demo? maybe even post in the bug reports.


Grey Alien(Posted 2011) [#9]
I'll see what I can do this coming week. I'd like to get this fixed if possible as it's hurting sales of my game.


Gabriel(Posted 2011) [#10]
Yeah, there's a well-known bug with DX9 and (I think) Nvidia cards which needs to be fixed. It's a bit tricky, and IIRC the solution is to write to a (very small) rendertexture every frame. Here's the class I used in Star Sentinel Tactics. It uses TV3D, but converting to DX9 shouldn't be too tricky.

You call Init() once and Update() every frame.

Type StratosMouseLagFixer
	
	Global Surfaces:CTVRenderSurface[]
	Global Textures:Int[]
	
	Global Frame:Int
	
	Function Init()
		Surfaces = New CTVRenderSurface[2]
		Textures = New Int[2]
		Surfaces[0] = TVGameEngine.CreateRenderSurface(2, 2)
		Surfaces[1] = TVGameEngine.CreateRenderSurface(2, 2)
		Surfaces[0].SetSystemMemCopy(True, True)
		Surfaces[1].SetSystemMemCopy(True, True)
		Textures[0] = Surfaces[0].GetTexture()
		Textures[1] = Surfaces[1].GetTexture()
	End Function
	
	Function Update()
		
		If StratosGameSettings.IsMouseLagFixEnabled()
			
			Frame:+1
			If Frame > 2
				Frame = 1
			End If
			
			Select Frame
				Case 1
					RenderATriangleToTexture(0)
					LockAndReadTexture(1)
				Case 2
					RenderATriangleToTexture(1)
					LockAndReadTexture(0)
					
			End Select
		
		End If
		
	End Function
	
	Function RenderATriangleToTexture(Index:Int)
		Surfaces[Index].StartRender()
		TVGameEngine.TVScreen2D.Draw_Triangle(0, 0, 1, 1, 0, 1, $FFFFFFFF)
		Surfaces[Index].EndRender()
	End Function
	
	Function LockAndReadTexture(Index:Int)
		Local LockedTex:Int = TVGameEngine.TVTextureFactory.LockTexture(Textures[Index], True)
		TVGameEngine.TVTextureFactory.GetPixel(LockedTex, 0, 0)
		TVGameEngine.TVTextureFactory.UnlockTexture(Textures[Index], False)
	End Function
	
	Function Shutdown()
		Surfaces[0].Destroy()
		Surfaces[0] = Null
		Surfaces[1].Destroy()
		Surfaces[1] = Null
	End Function
	
End Type



therevills(Posted 2011) [#11]
Does the hardware cursor lag in DX9?


Gabriel(Posted 2011) [#12]
I honestly can't remember. Sorry. The link to the problem on Nvidia's forum that I buried in my code comments is now a dead link, so I don't have a reference any more.


Grey Alien(Posted 2011) [#13]
@Gabriel. Interesting thanks, I'll see if I can get this to work. DX9 in BMax has way less stuff exposed so may require module tweaks and I'm a noob on most internal BMax stuff.

@therevills: the windows mouse cursor doesn't lag, but if I show my in-game one at the same time, the lag is obvious. There's still a lag in DX7 but it's less bad. OpenGL also has a lag.


GfK(Posted 2011) [#14]
Surely this lag is down to the fact that the Windows cursor updates itself independently of your game timing?


therevills(Posted 2011) [#15]
Temp Solution: Add an option to display only the OS mouse cursor


Grey Alien(Posted 2011) [#16]
Yeah I added that option. Anything you pickup in game that attaches to cursor, like a powerup, lags behind.


col(Posted 2011) [#17]
I know this sounds rather bizarre, and a long shot... but have you tried ( just as a test on your own machine ) to lower the mouse sensitivity ??

After digging around the net.....

Quote :-
"It seems the input systems ( whether using the hardware DX or System mouse ) when used with DirectX can get overloaded with trying to catch up with the thousands of mouse messages sent through the system which can then cause stalls - up to 3 or 4 frames.
You may find its not usually noticeable when VSYNC is OFF because of the fast refresh speeds, and more noticeable with the SYNC on."


Aparently even the top AAA games have had some complaints on some systems using Dx9, worse on Dx10 and Dx11.

They seem to work around it by adjusting mouse sensitivity in the game itself, but maybe reducing it at the source would help ?

Another thing you could test for yourself, if you don't mind playing in the BRL files is...

Goto
(V1.42)

brl.mod/dxgraphics.mod/d3d9graphics.bmx

line 72 ( or thereabouts :) ) reads..

pp.PresentationInterval=D3DPRESENT_INTERVAL_ONE

you could try changing it to

pp.PresentationInterval=D3DPRESENT_INTERVAL_IMMEDIATE

just to see if it makes any difference.
EDIT:- It appears Mark decided to leave out that Constant so here it is
Const D3DPRESENT_INTERVAL_IMMEDIATE = $80000000

You could just use
pp.PresentationInterval = $80000000

just to test it - don't forget to 'Rebuild Modules' after you've made changes.

EDIT2 :-
Also make sure DirectX is always up to date by downloading the latest version from MS. It doesnt always mean updates to Dx11 etc, it also updates fixes in older versions too.

There are more things to try but it means more modifying to the BRL files. Some people dont like doing that. One of the reasons I created a whole 'complete' D3D9 driver as Mark has left some of it out. It's seems he's only included what was needed to get what he wanted done.

There is a function in there for setting the mouse cursor and using an immediate flag. Again this would mean modifying BRL and testing to see if makes any differences, it usually performs better when this flag is OFF anyway, but it may be worth testing.
If you don't mind going down that route, let me know.

Last edited 2011


Grey Alien(Posted 2011) [#18]
@Col Thanks for all this info! I only just saw you added all this extra stuff. I'll try that mod tweak out and see what happens.

I have also discovered that there's a general input lag, so even when I press keys I see an input lag. If I switch to DX7 the lag is reduced. This is a real bummer for DX9 games, and we should get it sorted out for everyone who uses Blitz.

I tried this possible fix from CyBeRGoth and it works in full-screen mode DX9 but not windowed mode.

Local MouseHack:TPixmap
MouseHack = GrabPixmap(1, 1, 1, 1)


Last edited 2011


Grey Alien(Posted 2011) [#19]
This was the old DX7 lag fix that BRL eventually implemented. Could something like this work for DX9?

		If TD3D7Max2DDriver(_max2dDriver)
			Local sdesc:DDSurfaceDesc2 = New DDSurfaceDesc2
			sdesc.dwSize = SizeOf(sdesc)
			Local res:Int = PrimaryDevice.backbuffer.Lock(Null,sdesc,DDLOCK_WAIT|DDLOCK_READONLY,Null)
			PrimaryDevice.backbuffer.unlock(Null)
			Return res
		EndIf



col(Posted 2011) [#20]
Hey Grey Alien.

I agree we ( the community ) should make it a priority to get this fixed or at least reduced to a barely noticeable level.

Do you have some sample source code that you know suffers from the lag that I could use for testing?


Grey Alien(Posted 2011) [#21]
I'll make some. Stay tuned.


col(Posted 2011) [#22]
This thread is continued here