kanato's picture

Vertex Buffer Troubles

Hey, I am trying to play around with vertex buffer objects but I keep getting crashes (AccessViolationExceptions) or just garbage, as if the data rendered is completely random. It changes from frame to frame too, even though the geometry rendered/matrices are identical.

My code is setup so that I can just comment out a couple of lines to use vertex arrays instead, and that works fine so I know the geometry is okay, in the client memory at least. But of course I don't want to stick with vertex arrays because of the GC. I have played with various ways to call GL.BufferData, either through the object overload or the IntPtr overload and that doesn't seem to help, although it does not crash at that point. I've also checked that the data was uploaded correctly by calling GL.GetBufferSubData and the retrieved data matches the input data. I have checked GL.GetError after every GL call and no error is ever reported. I've tried both the ARB version and the "standard" version and they give the same results. I must be doing something wrong but I don't see what. Does anyone have any suggestions?

        public override void WriteVertexData(Vector3[] data)
        {
            GL.GenBuffers(1, out vertexBuffer);
            GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);
 
            unsafe
            {
                fixed (Vector3* ptr = data)
                {
                    GL.BufferData(BufferTarget.ArrayBuffer,
                        (IntPtr)(data.Length * Marshal.SizeOf(typeof(Vector3))),
                        (IntPtr)ptr,
                        BufferUsageHint.DynamicCopy);
                }
            }
            vertexCount = data.Length;
 
            mVertexCoords = data;
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        }
 
        public override void Draw()
        {
            mState.SetGLColor(Color.White);
 
            BeginMode beginMode;
            switch (PrimitiveType)
            {
                case PrimitiveType.TriangleList: beginMode = BeginMode.Triangles; break;
                case PrimitiveType.TriangleFan: beginMode = BeginMode.TriangleFan; break;
                case PrimitiveType.TriangleStrip: beginMode = BeginMode.TriangleStrip; break;
 
                default:
                    throw new AgateException(string.Format(
                        "Unsupported PrimitiveType {0}", PrimitiveType));
            }
 
            GL.EnableClientState(EnableCap.VertexArray);
            // Comment out these two lines and uncomment the third to
            // use vertex array instead of VBO.
            GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);
            GL.VertexPointer(3, VertexPointerType.Float, 0, 0);
            //GL.VertexPointer(3, VertexPointerType.Float, Marshal.SizeOf(typeof(Vector3)), mVertexCoords);
 
            GL.DrawArrays(beginMode, 0, vertexCount);
            ErrorCode err = GL.GetError();
 
            if (err != ErrorCode.NoError)
                System.Diagnostics.Debug.Print("Error: {0}", err);
 
        }

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Change:

GL.VertexPointer(3, VertexPointerType.Float, 0, 0);

to:

GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero);

and it should work fine.

Ugly issue that has bitten me more than once. Maybe we should manually add an int overload to this function and cast the int to IntPtr internally.

Edit: Just added these overloads to trunk.

kanato's picture

Yep, that was it. Now I see why it failed.