The locking mechanism seems to be one of the most misunderstood calls in Direct3D, particularly in Managed DirectX. How to do the locks, and do them fast seems to be a particularly tough question for people to grasp. Before we get to that, though, what exactly is "locking" the buffer? It is simply the act of allowing your CPU to access a range of data in your resource. Since you cannot talk directly to the graphics hardware, there needs to be a way to allow you to manipulate vertex data from your application, and the locking mechanism is it. Look at the various lock overloads that exist for our vertex and index buffers (they take the same parameters): public System.Array Lock ( System.Int32 offsetToLock , Microsoft.DirectX.Direct3D.LockFlags flags ) public System.Array Lock ( System.Int32 offsetToLock , System.Type typeVertex , Microsoft.DirectX.Direct3D.LockFlags flags , params int[] ranks ) public Microsoft.DirectX.Direct3D.GraphicsStream Lock ( System.Int32 offsetToLock , System.Int32 sizeToLock , Microsoft.DirectX.Direct3D.LockFlags flags ) As you can see, there are three overloads available when attempting to lock our buffers. We should start with the first one, since it is the simplest. This overload is only available if you created your buffer via the constructor that takes a System.Type and a number of vertices or indices. In actuality, this overload really just calls the next overload with the data you passed in from the constructor. The next two overloads are where things get interesting. The first parameter of each is the offset (in bytes) at which you want to start the lock. If you wish to lock the entire buffer, you will naturally want to start this member at zero. You'll notice the first two overloads each return an array, which can be extremely useful since it will return the data to you in an easy-to-use form. In the second overload, the second parameter is the base type of the array you wish to be returned. The last parameter is used to determine the size of the array that is returned. This "ranks" parameter seems to throw everyone for a loop for some reason, so let's look at it in depth for a moment. Let's assume you had a vertex buffer that had nothing but position data in it (Vector3), and it had 1,200 vertices in it. If you wanted to lock this buffer into a Vector3 array of 1,200 items, the lock call would look like this: Vector3[] data = (Vector3[])vb.Lock(0, typeof(Vector3), LockFlags.None, 1200); This call will result in a single dimension array of 1,200 Vector3s. Now let's say for some reason you wanted to have a two-dimensional array of 600 vertices each. That lock call would look like Vector3[,] data = (Vector3[,])vb.Lock(0, typeof(Vector3), LockFlags.None, 600, 600); Notice the extra parameter? The ranks parameter is actually a parameter array. It can and will create up to a three-dimensional array of data to return back to you. You should use this parameter to specify exactly how large of an array you wish to get back.
|