   [.net] [MDX] DrawUserIndexedPrimitives vs. Dynamic Buffers
  Hello world, :)I've recently finished implemented a little particle system for my Managed DirectX graphics engine. Every frame I create an array of CustomVertex.PositionColoredTextured structs and fill them with the updated particles' data.Initially I simply used DrawUserIndexedPrimitives to draw these vertexes, but I decided that it would probably be a good idea to optimize the rendering by using a static index buffer and a dynamic vertex buffer.Strangely this method decreased the render speed to about a quarter of its former value instead of speeding stuff up.Since I need to completely rewrite the vertex buffer every frame - using .Lock(0, LockFlags.Discard); - could it be that DrawUserIndexedPrimitives is generally the more efficient solution for this situation? Should I expect drastically different performance-ratios when testing on other machines?Regards,Bastian   
Quote:Original post by transwarpSince I need to completely rewrite the vertex buffer every frame - using .Lock(0, LockFlags.Discard); - could it be that DrawUserIndexedPrimitives is generally the more efficient solution for this situation? Should I expect drastically different performance-ratios when testing on other machines?Discarding the VB every frame is the problem. The correct way to use a dynamic VB is to create one to contain enough vertices for several (2 - 4) frames of rendering, and lock it in chunks. The first chunk should be locked with the Discard flag, subsequent chunks should be locked with NoOverwrite.Discarding the VB every frame is probably causing the driver to thrash vertex buffers around to do what you want. The best solution would be to use PIX or something to see what's really going on.   ;  Why would this method speed up rendering? Is it possible the graphics driver is still using the old vertex buffer content when I'm already rendering the next frame?   ;  The graphics driver is allowed to buffer up to 3 frames, so if it only has two vertex buffers internally that it's renaming when you use Discard, it'll stall slightly. It's also possible the driver isn't doing buffer renaming at all (I suppose it depends on the size of the VB).Have you tried using a larger vertex buffer and using the NoOverwrite flag to see if it makes a difference?   ;  I've now redesigned the code to do the following:1. Create a VertexBuffer 3x the size of the vertexes I want to store.2. Lock with Discard and use an offset of 0 in the first frame.3. Lock with NoOverwrite and use an offset of "numberOfVerts * StrideSize" in the second frame.4. Lock with NoOverwrite and use an offset of "numberOfVerts * StrideSize * 2" in the third frame5. Start at 2. again.This brought no measurable performance improvement. Am I doing something wrong?Using DrawUserIndexedPrimitives instead of a VertexBuffer gives me a roughly 3x higher framerate.   ;Quote:Original post by transwarpI've now redesigned the code to do the following:1. Create a VertexBuffer 3x the size of the vertexes I want to store.2. Lock with Discard and use an offset of 0 in the first frame.3. Lock with NoOverwrite and use an offset of "numberOfVerts * StrideSize" in the second frame.4. Lock with NoOverwrite and use an offset of "numberOfVerts * StrideSize * 2" in the third frame5. Start at 2. again.This brought no measurable performance improvement. Am I doing something wrong?Using DrawUserIndexedPrimitives instead of a VertexBuffer gives me a roughly 3x higher framerate.Out of curiosity, how are you writing the data into the buffer?  I've actually had a speed increase by using unsafe code to write to the buffer pointer returned by the GraphicsStream object as opposed to writing into the GraphicsStream directly.   ;Quote:Original post by Tape_WormOut of curiosity, how are you writing the data into the buffer?  I've actually had a speed increase by using unsafe code to write to the buffer pointer returned by the GraphicsStream object as opposed to writing into the GraphicsStream directly.private readonly capacity = NumberOfParticles;private int currentVert = -capacity * 4;...renderloop{  ...  currentVert += capacity * 4;  if (currentVert == capacity * 12) currentVert = 0;  using (GraphicsStream stream = vb.Lock(currentVert * PositionColoredTextured.StrideSize,    capacity * 4 * PositionColoredTextured.StrideSize,    currentVert == 0 ? LockFlags.Discard : LockFlags.NoOverwrite))  {    foreach (Particle particle in particleList)    { foreach (PositionColoredTextured vert in particle.GetVerts())   stream.Write(vert);    }    vb.Unlock();  }  ...}It can't really imagine using unsafe code would improve the performance by the factor 3 though.   