[.net] Quirks with MDX index buffer

Started by
8 comments, last by MickDuprez 17 years, 9 months ago
Hi all, I've just started using directX with C#, I have a fair grip on C/++/# but I can't find the reason for an exception in my app at - device.indices = ib; If I run it in release it throws the exception, if I continue it paints the form with a white backing with a red X from corner to corner if that's any help. The 'quirky' part is it works on my other machine with the same OS, DX sdk and dev enviroment, only different pcu and video cards which I wouldn't think would make a difference(?) more simple app's were working ok. see code below (from the tutorials at http://www.riemers.net/)-

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
		{
			device.Clear(ClearFlags.Target, Color.Black , 1.0f, 0);
 
			device.BeginScene();
			device.VertexFormat = CustomVertex.PositionColored.Format;
			device.SetStreamSource(0, vb, 0);
			device.Indices = ib;
 

			device.Transform.World = Matrix.Translation(-HEIGHT/2, -WIDTH/2, 0);
			device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, WIDTH*HEIGHT, 0, indices.Length/3);
			device.EndScene();
  
			device.Present();
  
			this.Invalidate();
			angle += 0.05f;
		}
Thanks, Mick.
Advertisement
Are you sure it's the index buffer that's causing the exception? Regardless, you should look at your debug output from Direct3D because the exceptions in MDX are lacking in the worst kind of way. Usually the debug spew will yield greater information. If you already know how to set all this up, then ignore the rest of this message.

In case you don't know how to enable debugging, go to your control panel, click on DirectX and enable the debug runtime on the Direct3D tab, and ensure you have the slider set to maximum. To get the debug spew to appear, run a program called dbmon, included with Visual Studio (<your path to visual studio>\Common7\Tools\Bin\winnt\dbmon.exe). The debug output should appear in this command prompt window.

Thanks Tape_Worm, I wasn't aware of those tools, I'm used to opengl :)

I'll have a play with those settings and tests tonight on my 'problem' machine.

cheers,
Mick.
Feel free to private message me with the debug data, the bare bones exceptions can make using MDX pretty cryptic. Chances are it's a simple thing. But sometimes even a misplaced index in the buffer, or invalid index count (depending on your video driver/card) in your DrawPrimitive call can throw the exact same exception. And yet work beautifully on another machine. In fact, this happened to me some months back where my beastly steriod powered video card let something like this pass, but the cheap ass S3 card on my old work computer would just choke on the exact same code.

Quote:Original post by Tape_Worm
Feel free to private message me with the debug data, the bare bones exceptions can make using MDX pretty cryptic.

To right! cryptic's not the word, I had to track it down using break points which I narrowed down from the debug output. Thanks for the offer, I'll have to brush up on my debugging also, I'm used to using 'console' style debugging dll's in AutoCAD (there are some issues at times with debugging loaded dll's :))



There are some bugs in the IndexBuffer class, which cause problems when the device gets reset (you get memory leaks from nam).

It seems you have to keep your index buffers in the managed memory pool to avoid this, also make sure you use IndexBuffer.SetData(Array, 0, LockFlags.None) when filling the data. The same is true of VertexBuffer, but you can seem to use the default pool without getting memory leaks. Filling the VB is best done with the VertexBuffer.Created event. I did a *lot* of trial and error to find these combinations.

this is the exact code I use (simplified):

ib = new IndexBuffer(device, Allocation.Length, Usage.WriteOnly, Pool.Managed,is32Bit);ib.SetData(Allocation, 0, LockFlags.None);


and for VB:

vb = new VertexBuffer(typeof(byte), Allocation.Length, device, Usage.WriteOnly, VertexFormats.None, Pool.Default);vb.Created += new EventHandler(vbCreated);vbCreated(null, null);


where vbCreated is:

void vbCreated(object sender, EventArgs e){	((VertexBuffer)sender).SetData(Allocation, 0, LockFlags.None);}


This has worked for me.


Also note that when using the debug runtime you may find some of your other games will run very slow (or even crash!) this is because the debug runtime is dealing more heavily with errors the programmer has made instead of just ignoring them. A good example is ragdoll kungfu, which is unplayable with the debug runtime.
Thanks RipTorn, here's my ib and vertices set up -
the vertex buffer -
vb = new VertexBuffer(typeof(CustomVertex.PositionColored),				WIDTH*HEIGHT, device, Usage.Dynamic | Usage.WriteOnly, 				CustomVertex.PositionColored.Format, Pool.Default);


and the index buffer -

ib = new IndexBuffer(typeof(int), (WIDTH-1)*(HEIGHT-1)*6, 				device, Usage.WriteOnly, Pool.Default);


I'm using the SetData() as you describe, can you see anything right/wrong with this type of initialisation ? (apart from what you have already mentioned). I've typed plenty of code in C# but with other lib's so this is all 'very' new to me and I appreciated your good advice as you can't beat experience :)
Cheers,
Mick.
Quote:Original post by RipTorn
There are some bugs in the IndexBuffer class, which cause problems when the device gets reset (you get memory leaks from nam).

It seems you have to keep your index buffers in the managed memory pool to avoid this, also make sure you use IndexBuffer.SetData(Array, 0, LockFlags.None) when filling the data. The same is true of VertexBuffer, but you can seem to use the default pool without getting memory leaks. Filling the VB is best done with the VertexBuffer.Created event. I did a *lot* of trial and error to find these combinations.


Or you can also disable the events for MDX. That works as well. Tom Miller (THE guy for MDX) has written about this on his blog. And this thread even states a performance increase when disabling the events.

I'll look into that :-)

Only events I'm using otherwise are DeviceLost/DeviceReset. This of course can simply be tested prior/after rendering.
Nope, tried everything. There is an error in the device.set_indices method in my OnPaint handler. This code works fine on the other machine!

The debug results -
Quote:
Unhandled Exception: Error in the application.
-2146232832 (Unknown)
at Microsoft.DirectX.Direct3D.Device.set_Indices(IndexBuffer indexData)
at DirectX_Tutorial.WinForm.OnPaint(PaintEventArgs e) in c:\development\d3d dev\d3d1\form1.cs:line 95
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
.......etc.

If I look in the locals int the debugger, the ib is full, has correct count etc???

I'm a bit pissed at this, this is a simple thing that simply shouldn't happen. I consider myself at least 'competent' with C# and with this being a entry level tutorial I'm trying to complete it doesn't look good.
While I like the OOP design of directx (my only reason for changing)I'm already seeing some 'issues' slipping in with versioning. IOW, "are you using the latest release" which is just not good in my opinion, you should be able to build an entry level app with earlier versions.
For instance, the tut I'm doing uses -

vertices[x+y*WIDTH].Position = new Vector3(x, y, 0);

- where as in the version I'm using (9.0b, 1.0.900.0 - which may be the problem??) I have to use -

vertices[x+y*WIDTH].SetPosition(new Vector3(x, y, heightData[x,y]));

- which I can handle but...

It may be back to using opengl where there is only a few basic requirements to set things up, the rest is in your code/algo design.

[/rant]

Thanks for your help Guys, it is appreciated. If this release was known as a 'buggy' release let me know and I'll update and try again.
Cheers,
Mick.

This topic is closed to new replies.

Advertisement