I'm surprised the debug runtime didn't catch this...

Started by
4 comments, last by Evil Steve 19 years, 2 months ago
I just spent 2 hours pulling my hair out trying to find the cause of this bug. I'm making a bomberman clone, and I tried to "start a new game". This involves deleting my CMap and re-creating it with new. So, I thought that'd flush out any bad data. Apparently not. When I started the game again, only 1 frame in 3 was valid - the other 2 were magenta or green (meaning that DrawPrimitive() was failing). I checked and re-checked that the VB was getting filled and rendered correctly, and it was. And I just discovered the cause. The cause was my IDirect3DDevice wrapper. It wraps calls like SetStreamSource(), so I don't end up calling IDirect3DDevice::SetStreamSource() every frame when the source vertex buffer hasn't changed. When I deleted my CMap, I deleted the vertex buffer - but I forgot to set the stream source to NULL. Then, the map was re-created, and the stream source was still pointing at the old vertex buffer. In the render loop, I called my wrapper SetStreamSource(), which did nothing, because the address of the new VB was the same as the currently set stream (Thanks to the debug CRT). Then, it went and rendered from that. My map's VB is a dynamic one, with enough space for 3 frames. So, for one frame, Direct3D was able to render what I put in the VB at the last lock(), and for the other 2, the data was gibberish. Now, what I'd like to know is why the debug runtime didn't catch this? First, Stream 0 was pointing at a release()d vertex buffer, and second, DrawPrimitive wasn't failing - even on the frames where it drew nothing... The only reason I can think was that the vertex buffer wasn't completely released - but I checked in the debugger, and the vtable of the IDirect3DVertexBuffer9 gets set to 0xfeeefeee, and Release() returned 0...
Advertisement
Weird, the vertex buffer definitely gets destroyed, but this code doesn't crash, doesn't give any debug output, and all the function return D3D_OK:
CDynamicVertexBuffer* pVB = CD3DDevice::Get().CreateDynamicVertexBuffer(9,sizeof(TLVertex),FVF_TLVERTEX);CD3DDevice::Get().SetStreamSource(0,pVB,0);pVB->Release();CD3DDevice::Get().GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST,0,3);
1) What was the D3D output then?
2) Have you #defined D3D_DEBUG_INFO? (if you haven't, the D3D output will tell you how..)
3) What is the level of your Debug output? Maybe you should check some unchecked options..
Quote:Original post by Pipo DeClown
1) What was the D3D output then?
2) Have you #defined D3D_DEBUG_INFO? (if you haven't, the D3D output will tell you how..)
3) What is the level of your Debug output? Maybe you should check some unchecked options..

1) There wasn't anything mentioned about this in the output. The last line was: D3DX: Unicode support: 1
2) Yup, the members of the IDirect3DVertexBuffer9 are all set to 0xfeeefeee when Release() is called.
3) Maximum.

There's pleanty of other debug output - For example, I set all renderstates to a set value just to be sure, so there's a crapload of Direct3D9: (WARN) :Ignoring redundant SetRenderState - 209 lines, with various numbers there.
For debug builds try using software vertex processing and ensure your device isn't PURE.

1. In the main, hardware display devices are single direction - you send them stuff, they render it. They don't really have a way of complaining or providing feedback if what you send to them is bad. Their usual "response" to bad input data is to either not draw it, draw garbage, draw it black or white, or draw it in some obvious colour.

Although the D3D runtime and the device driver will do *some* checking of parameters etc, they won't do things like check all the data in your hardware index buffers for correctness because it would affect performance. Using software vertex processing with the debug D3D runtime _will_ perform extra checking on your data so it'll often catch things that "seem ok" with hardware.


2. As you know, PURE devices bypass most of the help & checking the D3D runtime provides and sends the data you pass in straight to the display driver.


3. There's "magic" that happens behind the scenes in the driver and the D3D runtime - if the buffer is required by the hardware, even though the interface structure you have a pointer to may be released, it's likely the resource will be around somewhere the driver/D3D can get to it until it really can be free'd

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

Thanks for the reply Simon.
I didn't know about the software vertex processing and pure debive thing, I've changed my code appropriately. Still nothing in the debug output though.

I never really thought about how the driver will probably keep the buffer around internally, I suppose that makes sense now.

Thanks for the replies,
Steve

This topic is closed to new replies.

Advertisement