2 Feb 2008

D3D Debugging

I just spent a bit of time debugging the D3D9 specific code. Running the test viewer under the D3D debug runtime and with the warning level to highest reveals 2 warnings:
  • redundant render state switches (which I'm ignoring for now, the frame shader system already helps to reduce redundant state switches a lot, and fixing the remaining state switch warnings would involve implementing a D3DXEffectStateManager, but before I do this I want to make sure that my own redundant state switch detection would actually be faster then D3D's)
  • more serious is the second warning: "render target was detected as bound, but couldn't detect if texture was actually used in rendering". This is only a real problem if you want to read from the same render target you're currently rendering to, which isn't happening anywhere in Nebula3 (unless you screw up the frame-shaders). I fixed the warning by adding a "UnbindD3D9Resources()" method to the D3D9RenderDevice, which is called at the end of a rendering pass, and before the D3D9 device is shut down. The method simply sets the texture stages, vertex buffer and index buffer of the device to NULL.
The most serious problem though was that Direct3D reported memory leaks when shutting down the application. Finding a D3D9 memory leak can be tricky, but thankfully Direct3D has a nice mechanism built into its debug runtime to find the allocation which causes the memory leak: on shutdown D3D writes a memleak log to debug-out, where each memory leak is given an unique id. The problem is, that even one forgotten Release() call can generate hundreds of memory leaks because of D3D's many internal dependencies. The most interesting leak however is usually the last reported, at the bottom of the leak-report. To find the offending allocation, open the DirectX Control Panel, go to the Direct3D 9 tab, and enter the last reported AllocID into the "Break On AllocID" field. Run the application in the debugger, and it should break at the allocation call in question. Turns out I forgot 3 Release() calls: one in D3D9RenderTarget::BeginPass() after obtaining the backbuffer surface from the D3D9 device, one in D3D9RenderTarget::EndPass() after a GetSurfaceLevel(), and after another GetSurfaceLevel() call in D3D9RenderDevice::SaveScreenShot().

The moral of the story: read the D3D9 docs carefully even for "uninteresting" functions, and run the application through the debug runtime after each change to the rendering code, to prevent such bugs from piling up to unmanageable levels.

I wanted to get this stuff fixed before the January SDK release, so this will come next week as time permits. Drakensang bugfixing and optimization has full priority for me at the moment.

Completely unrelated:
  • Watched Death Proof yesterday, and I was a little bit disappointed. The first half was outright boring, then 10 seconds with (probably) the most spectacular (and gory) car crash in movie history. The second half with the "new girls" was actually really good, but the car-chase at the end and the finale was quite a letdown as well, guess I was hoping to see Kurt Russel die in a more spectacular way hehe...
  • RezHD on XBLA is ... wow.


Assassin said...

Floh,please re-upload first nebula 3 sdk(27-Mar-2007
First Nebula3 Snapshot For Download).
Pleaseeee...... ))

Floh said...

Uh... that could be tricky, I didn't specifically store it somewhere I think. Why do you need that specific version? If it's important and I can't find a backup somewhere I could probably build a new one from the state of the CVS at that date.

Anonymous said...

I've uploaded the first sdk to rapidshare. (http://rapidshare.com/files/88873087/Nebula3SDK-26.03.2007.exe.html)

floh: "Attila said...
Thanks for the answer. Can you estimate when will the Nebula3 (PC) be ready to use in projects?"

Assassin said...

Floh, very interesting engine architecture.
Ignacio, thanks.

Gabriel Hasbun-Comandari said...

Mr. Floh, I've been admiring your work since nebula 2 without Mangalore. I've always been updating myself with the Nebula 3 engine progress, and I think the same mistakes as in Nebula 2 must not be made once again. Nebula 3 needs good documentation. We could really start thinking of documenting the most possible and perhaps build a book out of it. We can create tutorials and make diagrams, explain to 10 year old assumption, etc. I think this is the best to attract more programmers toward this wonderful engine of yours, I can be totally commited on starting documentation on Nebula 3 with your help of course(Note, I am a python, C, C++ developer, although not a guru)

Assassin said...

I join to Gabriel Hasbun-Comandari.