3

There are two types of overloads of DrawUserIndexedPrimitive: Those accepting 16-bit indices and those accepting 32-bit indices.

When using 16-bit indices, everything works fine. When using 32-bit indices, I get an InvalidOperationException with the "helpful" error text An unexpected error has occurred (no inner exceptions) when DrawUserIndexedPrimitive is called. When I enable "Unmanaged Code Debugging" in the project properties, I get the lines

First-chance exception at 0x75a5b9bc in DrawUserPrimitives.exe: Microsoft C++ exception: long at memory location 0x0032e6b4..
First-chance exception at 0x75a5b9bc in DrawUserPrimitives.exe: Microsoft C++ exception: long at memory location 0x0032e728..

in the debug window right before the exception is thrown.

Why does this happen? Since both overloads are available, I would imagine that both would work (or at least throw a meaningful exception if only one of them is supported). Here's a complete minimal sample program that can be used to reproduce this issue. I'm using XNA 3.0.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

public class GameTest : Microsoft.Xna.Framework.Game
{
    static void Main(string[] args)
    {
        using (var game = new GameTest())
        {
            game.Run();
        }
    }

    GraphicsDeviceManager manager;

    public GameTest() { manager = new GraphicsDeviceManager(this); }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.SteelBlue);
        GraphicsDevice.VertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);

        var basicEffect = new BasicEffect(GraphicsDevice, null);
        basicEffect.VertexColorEnabled = true;
        basicEffect.View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up);
        basicEffect.Projection = Matrix.CreateOrthographicOffCenter(-1, 2, 2, -1, 1.0f, 1000.0f);

        // two simple points
        var pointList = new VertexPositionColor[] {
            new VertexPositionColor(new Vector3(0,0,0), Color.White),
            new VertexPositionColor(new Vector3(0,1,0), Color.White)
        };

        // one simple line between those two points
        var lineListIndices = new short[] { 0, 1 };      // works fine
        // var lineListIndices = new int[] { 0, 1 };     // causes exception below

        basicEffect.Begin();
        foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
        {
            pass.Begin();
            GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
                PrimitiveType.LineList, pointList, 0, 2, 
                lineListIndices, 0, 1);  // exception occurs here
            pass.End();
        }
        basicEffect.End();

        base.Draw(gameTime);
    }
}
pinckerman
  • 4,115
  • 6
  • 33
  • 42
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • Are you perhaps using 64bit machine? – Jethro Aug 17 '11 at 09:53
  • @Jethro: Yes, but I'm compiling the project to 32 bit. Anyway, in C#, `short` is *always* 16 bit and `int` is *always* 32 bit. – Heinzi Aug 17 '11 at 10:08
  • Try declaring your array as Int32[] lineListIndices = new Int32[] { 0, 1} and see if that works. I'd be surprised, but maybe there's some compiler confusion since you're using var to declare the variable? – Dave Carlile Aug 17 '11 at 16:18
  • @Crappy: Well, that would be quite a serious bug in the compiler. ;-) But no, I tried it and it didn't make a difference. – Heinzi Aug 17 '11 at 16:36
  • Yeah, this is an odd one - sure seems like what you have should work. If you haven't already, maybe try asking this over on the XNA forums as well - maybe one of the framework devs will chime in. – Dave Carlile Aug 17 '11 at 18:43
  • A couple of quick points: You shouldn't be creating a new `VertexDeclaration` each frame. It should be reused (same goes for the other reference-type objects you are creating - like the arrays). And as a wild guess: XNA 4.0 only supports 32-bit indices on the HiDef profile. In XNA 3.0 you need to check the device capabilities. It is possible your graphics device does not support 32-bit indices. (Is there a particular reason for not using XNA 4.0?) – Andrew Russell Aug 18 '11 at 04:19
  • @Andrew: Thank, I know, this is just (short) sample code to reproduce the issue. We're not using XNA 4.0, since I don't want to force our customers to upgrade from .net FW 3.5SP1 to 4.0 without a good reason -- I use XNA for 3D visualization in a line-of-business application that currently requires .net FW 3.5SP1. Thanks for the hint with the capabilities, I'll check that. (If that's the case, why can't XNA simply throw a 32BitIndicesNotSupportedException? Oh, now that you mention it, the XNA 4.0 version does support such an exception...) – Heinzi Aug 18 '11 at 07:37

1 Answers1

2

The cryptic error message seems to be a bug in XNA 3.0 (thanks Andrew for the hint). Running the code (slightly modified) in XNA 4.0 yields a more useful error message (NotSupportedException):

XNA Framework Reach profile does not support 32 bit indices. Use IndexElementSize.SixteenBits or a type that has a size of two bytes.

That make sense, since my graphics card does not seem to support the HiDef profile, which would support 32 bit indices.

Heinzi
  • 167,459
  • 57
  • 363
  • 519