How to find the cause of framedrops

Started by
16 comments, last by Paulpetk123 8 years, 1 month ago
I'm experiencing odd framedrops in our live DirectX9 game and have difficulty figuring out why they happen. If I play a match then occasionally for a few seconds roughly one in every 10 frames is dropped (not with a regular pattern though). I've logged frame timings and the framedrops turn out to be caused by the swap call (which also waits for VSync if enabled):
direct3DDevice9->Present(NULL, NULL, NULL, NULL);
Nothing else on the CPU side is taking long enough to cause the framedrops. In other words: I am somehow giving the videocard too much work to do to finish within the 16ms needed for 60fps.
The odd thing is: the frames around it are all rendered faster and I am not aware of anything special being rendered during the framedrops. I've tried doing a PIX capture but nothing special seems to happen in those frames.
It gets even stranger: if I turn off VSync I run at around 200fps. I see the same pattern of framedrops, but the drops are from taking 5ms for normal frames and 6ms during those longer frames. So I get a pattern of frame durations in ms like this: 5ms-5-5-5-5-5-6-5-5-5-5-6-5-5-5-5-5-5-5-5-5-6-5 etc. This is far below the duration needed to achieve 60fps with VSync enabled, so it makes no sense to me that with VSync on I am still seeing framedrops.
One thing I've noticed is that this happens more if I move quickly. Could it be that using a texture that hasn't been used for 10 seconds is slow in DirectX9? Seems odd since I never heard of this kind of behaviour.
Note that I am running these test on a Geforce GTX 560 Ti on 1920*1080 on Windows 7.
I'm out of ideas on what to try next. How can I find the cause for this?

My dev blog
Ronimo Games (my game dev company)
Awesomenauts (2D MOBA for Steam/PS4/PS3/360)
Swords & Soldiers (2D RTS for Wii/PS3/Steam/mobile)

Swords & Soldiers 2 (WiiU)
Proun (abstract racing game for PC/iOS/3DS)
Cello Fortress (live performance game controlled by cello)

Advertisement

Are you using D3DPRESENT_INTERVAL_DEFAULT to enable vsync? If so, try D3DPRESENT_INTERVAL_ONE instead. (See remarks here for more info.)

Otherwise look for anything else that may be dependent on timer resolution, because that's almost certainly what's causing your problem.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Just checked, I was already doing D3DPRESENT_INTERVAL_ONE.

My dev blog
Ronimo Games (my game dev company)
Awesomenauts (2D MOBA for Steam/PS4/PS3/360)
Swords & Soldiers (2D RTS for Wii/PS3/Steam/mobile)

Swords & Soldiers 2 (WiiU)
Proun (abstract racing game for PC/iOS/3DS)
Cello Fortress (live performance game controlled by cello)

Have you run your program through a CPU profiler and a GPU profiler yet?

Try both, try to duplicate the frame drops and see if it highlights the problem.

Profilers are your friends! :D

Hope this helps!

do you experience any of the framedrops if nothing changes? (I mean, if you draw exactly the same every frame)


In other words: I am somehow giving the videocard too much work to do to finish within the 16ms needed for 60fps.

yet there's nothing unusual about those particular frames, eh?

where are your assets? always in memory? paged from disk? possible asset cache miss due to occasional thrashing when you momentarily hit that Nth asset you have to draw simultaneously? too many textures oncard, GPU must occasionally fetch from sysmem?

fix your timestep, framerate limiter, vsync limited, or unlimited framerate? which algo are you using?

you mentioned moving fast, that causes a high delta in your scene. paged (from disk or sysmem) asset not ready would be a typical cause.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

... GPU profiler yet? ...

The only DX9 GPU profiler I know is PIX and I don't think PIX can be used to effectively capture detailed performance data for a longer capture. I can get all the detail for a single frame but I don't have a clear reproduction case so it's very unpredictable when the framedrops will happen.

... where are your assets? ... too many textures oncard, GPU must occasionally fetch from sysmem? ...

We don't do any of that kind of streaming of textures or meshes at all.

What I can imagine might be happening is that the driver is moving textures between system RAM and GPU memory. However, the videocard drivers report 1024mb dedicated video memory and the game uses less than half of that, so swapping between system RAM and video RAM only makes sense if something else in Windows is grabbing a lot of that memory. Is there any way to monitor this kind of behaviour?

By the way, the textures are loaded during the loading screen, not during gameplay, like this:

D3DXCreateTextureFromFileInMemoryEx(device, fileBuffer, imageSize, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_NONE, 0, NULL, NULL, &resultTexture);

do you experience any of the framedrops if nothing changes? (I mean, if you draw exactly the same every frame)

Just tried this and I do see occasional framedrops when I do this, but very rare and not in the kind of pattern I see during normal gameplay.

My dev blog
Ronimo Games (my game dev company)
Awesomenauts (2D MOBA for Steam/PS4/PS3/360)
Swords & Soldiers (2D RTS for Wii/PS3/Steam/mobile)

Swords & Soldiers 2 (WiiU)
Proun (abstract racing game for PC/iOS/3DS)
Cello Fortress (live performance game controlled by cello)


However, the videocard drivers report 1024mb dedicated video memory and the game uses less than half of that, so swapping between system RAM and video RAM only makes sense if something else in Windows is grabbing a lot of that memory. Is there any way to monitor this kind of behaviour?

ending all possible background processes before running the game can eliminate potential interference from background processes. but only something like a stand alone vid capture util would grab vidram. you running video chat in the background or something? <g>.

NONPOW2 is the only potential slowdown i see in your texture loading.

let me see how the call compares to mine....

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

no image filtering, box filtering for mipmaps:

h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,D3DX_DEFAULT, // widtth
D3DX_DEFAULT, // height
D3DX_DEFAULT, // miplvls ( default = complete chain )
0, // usage (0=not render & not dynamic)
D3DFMT_A8R8G8B8,mempool,
D3DX_FILTER_NONE, // image filter ( default = tri + dither )
D3DX_DEFAULT, // mip filter ( default = box )
0, // color key (0=none)
NULL,NULL,&(Ztex[numtextures].tex));
load sprite texture (DDS file). no image filtering, point filtering for mipmaps:
h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,
D3DX_DEFAULT,D3DX_DEFAULT, // width,height
0, // mip lvls. 0 or default = full chain, 1= no mip maps.
0, // usage: not dynamic, not render tgt.
D3DFMT_A8R8G8B8,mempool,
D3DX_FILTER_NONE, // image filter
D3DX_FILTER_POINT, // mip filter. none=vanishing mipmaps problem. point=wrap problems.
// linear,tri,and box blend the keycolor into the edges of the image (dark edges problem).
// no mips causes sparkle problem.
0, // 0XFF000000, color key
NULL,NULL,&(Ztex[numtextures].tex));
load sprite texture (DDS file). no image filtering, point filtering for mipmaps, 5 mipmap levels:
h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,
D3DX_DEFAULT,D3DX_DEFAULT, // width,height
5, // NO MIP MAPS //mip lvls. 0 or default = full chain, 1= no mip maps.
0, // usage not dynamic not render tgt
D3DFMT_A8R8G8B8,mempool,
D3DX_FILTER_NONE, // image filter
D3DX_FILTER_POINT, // mip filter. none=vanishing mipmaps problem. point=wrap problems.
// linear,tri,and box blend the keycolor into the edges of the image (dark edges problem).
// no mips causes sparkle problem.
0, //0XFF000000, // color key
NULL,NULL,&(Ztex[numtextures].tex));
load color keyed sprite texture. no image filtering, point filtering for mipmaps:
h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,
D3DX_DEFAULT,D3DX_DEFAULT, // width,height
0, // mip lvls. 0 or default = full chain, 1= no mip maps.
0, // usage: not dynamic, not render tgt.
D3DFMT_A8R8G8B8,mempool,
D3DX_FILTER_NONE, // image filter
D3DX_FILTER_POINT, // mip filter. none=vanishing mipmaps problem. point=wrap problems.
// linear,tri,and box blend the keycolor into the edges of the image (dark edges problem).
// no mips causes sparkle problem.
0xFF000000, // 0XFF000000, color key
NULL,NULL,&(Ztex[numtextures].tex));

load bitmap. no filtering, no mipmaps:

h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,D3DX_DEFAULT,D3DX_DEFAULT,1,0,D3DFMT_A8R8G8B8,mempool,D3DX_FILTER_NONE,D3DX_FILTER_NONE,0,NULL,NULL,&(Ztex[numtextures].tex));
load dynamic bitmap: (looks to be no filtering and no mipmaps)
h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,D3DX_DEFAULT,D3DX_DEFAULT,1,D3DUSAGE_DYNAMIC,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,D3DX_FILTER_NONE,D3DX_FILTER_NONE,0,NULL,NULL,&(Ztex[numtextures].tex));
load color keyed sprite, no filtering, no mipmaps:
h=D3DXCreateTextureFromFileExA(Zd3d_device_ptr,s,D3DX_DEFAULT,D3DX_DEFAULT,1,0,D3DFMT_A8R8G8B8,mempool,D3DX_FILTER_NONE,D3DX_FILTER_NONE,0XFF000000,NULL,NULL,&(Ztex[numtextures].tex));

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

You can use Renderdoc, INtel GPA, AMD codeXL or NVidia Nsight for GPU profiling. They all give you GPU timings, some will give you more info than others depending on the hardware you run it on. Renderdoc doesnt do DX9 though although I never checked this.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

This topic is closed to new replies.

Advertisement