   DX9, various VB questions.
  Hi :)I'd like to know a few things about VB's. Nothing too intricate, since most of it is just me looking for confirmation.From what I have gathered, it's best to use a managed VB, since dynamic VB locking is faster than one might think, because the card can cache 2.5frames ahead.(by Evil Steve)Does that mean, that in actual, real applications (none of that demo stuff), vertex transformation is actually more or less CPU bound?Since many DIP calls on a small buffer the hardware transforms many many times are more costly than calculating transforms for each vertex and then additionally copying them into the buffer, yes?That would actually amaze me.A 10mil loop with two multiplications, one division and one power of calculation (integers) easily bogs down frame per frame performance whenever I do it.Granted, 10mils might be non realistic for "actual" render jobs, but I've seen a couple of complex scenes <.<.(That bit is just musing though. I'm a noob with no actual realtime 3d rendering experience.)Also,where should I "put" vertex buffers?In a separate manager?As part of the D3D device?In a mesh?In a sort of unified shader processing unit? (which would either CPU transform vertices, or use shaders)OR a combination of any of the above? <.<I was thinking separate manager.Maybe some sort of object that accepts a transform matrix, vertex data, etc, which the object then batches by filling an internal buffer which it then passes to render unit.Is that a good idea, cause I can't gauge that. :x(The "irrelevant optimization" devil on one shoulder, and the "keep stuff reusable, modular, and generic" devil on the other are clouding my judgment...)I need a little design strategy nudge...Well, cheers :)Edit:I also plan on using a homemade mesh-class, since it's probably a nice learning experience in the end, and because .x seems to be deprecated <.<, hence the desire to know where to put and how to use buffers.   
Quote:Original post by EriusFrom what I have gathered, it's best to use a managed VB, since dynamic VB locking is faster than one might think, because the card can cache 2.5frames ahead.(by Evil Steve)Does that mean, that in actual, real applications (none of that demo stuff), vertex transformation is actually more or less CPU bound?No, why would it be? A managed vb resides on the gpu. Software vertexprocessing would render shaders pretty useless.Quote:Also,where should I "put" vertex buffers?In a separate manager?As part of the D3D device?In a mesh?In a sort of unified shader processing unit? (which would either CPU transform vertices, or use shaders)OR a combination of any of the above?Normally u would use a vertexbuffer and one/several indexbuffers per object/mesh/patch whatever. With a lot of small objects this can become a bottleneck. A solution to that would be instancing. There's plenty of examples for instancing in the d3d sdk.Just one advise: Don't over-engineer your projects. Keep it as simple as possible. Most of the early rendering optimizations are usually a waste of time. Once your project is up and running u can still change the rendering code.   ;Quote:Original post by EriusFrom what I have gathered, it's best to use a managed VB, since dynamic VB locking is faster than one might think, because the card can cache 2.5frames ahead.(by Evil Steve)If your vertex data changes frequently (More than once every second or so), then you should put it in a dynamic vertex buffer. To use a dynamic vertex buffer, the buffer has to be in D3DPOOL_DEFAULT.The GPU is allowed to buffer something like 2.5 frames worth of data for performance reasons, so what you see on screen may be up to 2 frames old.Quote:Original post by EriusDoes that mean, that in actual, real applications (none of that demo stuff), vertex transformation is actually more or less CPU bound?It won't make any difference really - vertex transformation will always happen on the GPU if you're using hardware vertex processing (Which you should be wherever possible). Dynamic buffers will be less optimal than static buffers because they're usually placed in memory that's quick to access by both the CPU and GPU, instead of being VRAM resident like static buffers will be (Although it ultimately depends on the driver). Dynamic resources are still very quick - every game has dynamic resources, so drivers are optimised to handle them well.Quote:Original post by EriusSince many DIP calls on a small buffer the hardware transforms many many times are more costly than calculating transforms for each vertex and then additionally copying them into the buffer, yes?Yes and no. Lots of DIP calls mean lots of transitions to kernel mode to actually make the call, so they're slow to do. Vertex shaders usually operate very quickly; unless you have a horribly complicated vertex shader, you're unlikely to be vertex shader bound (That is, you can usually consider vertex transforms "free" if you're using hardware vertex processing).Quote:Original post by EriusThat would actually amaze me.A 10mil loop with two multiplications, one division and one power of calculation (integers) easily bogs down frame per frame performance whenever I do it.Granted, 10mils might be non realistic for "actual" render jobs, but I've seen a couple of complex scenes <.<.(That bit is just musing though. I'm a noob with no actual realtime 3d rendering experience.)The GPU is extremely parallelised; modern CPUs can execute something like 32 or 64 vertex or pixel shaders at once, and the chip is designed specifically for doing processing on vectors (SIMD-style). The CPU is more general purpose and will never be able to out-perform a GPU at what the GPU does best.Quote:Original post by EriusAlso,where should I "put" vertex buffers?In a separate manager?As part of the D3D device?In a mesh?In a sort of unified shader processing unit? (which would either CPU transform vertices, or use shaders)OR a combination of any of the above? <.<That depends on your engine and whether they're static or dynamic. It's common to have them as part of the mesh for simplicity, since the mesh "owns" its vertices.In theory, it's better to put the vertices for as many meshes as possible (Especially static meshes / vertices) into as single vertex buffer. That means that you can draw the most triangles in a single DrawPrimitive or DrawIndexedPrimitive call (In theory).Quote:Original post by EriusI was thinking separate manager.Maybe some sort of object that accepts a transform matrix, vertex data, etc, which the object then batches by filling an internal buffer which it then passes to render unit.Is that a good idea, cause I can't gauge that. :x(The "irrelevant optimization" devil on one shoulder, and the "keep stuff reusable, modular, and generic" devil on the other are clouding my judgment...)That sounds reasonable (Similar to the second option, above). Although unless you're trying to make a very high performance engine, it may just end up overcomplicating things - your engine should try to reduce the number of meshes drawn as much as possible anyway.   ;Preface: damn you Steve! [grin]Quote:From what I have gathered, it's best to use a managed VB, since dynamic VB locking is faster than one might think, because the card can cache 2.5frames ahead.It depends... most specifically what you mean by managed [smile] If you mean creating a buffer in the managed pool, then generally speaking you'd be right that it's often the best choice, but a managed buffer does not necessarily mean it's also dynamic. More details on locking and dynamic buffers can be found over here. Creating a buffer in the managed pool on the other hand means that DirectX will take more care of the resources for you, such as keeping a copy around on the CPU to re-upload to the GPU when the device was lost or the resource was evicted from GPU memory to free up space. It's mainly a usability thing that may or may not have performance consequences for locking. I can think of some scenarios where either the managed or the default pool would be a better fit, but in general I think it's difficult to give a rule of thumb for this choice.Quote:Does that mean, that in actual, real applications (none of that demo stuff), vertex transformation is actually more or less CPU bound?I'm no expert on actual real applications but I guess it's safe to say that this statement doesn't hold in general. CPU/GPU synchronization is a tricky subject and the only blanket advice that holds is to try and avoid stalls (here's a great resource). On the subject of vertex transformations, modern GPUs can easily deal with typical workload there. In fact most integrated cards (Intel laptop GPUs) transparently leave vertex transformations to the CPU, since the brunt of the workload lies with pixel shading.Quote:Since many DIP calls on a small buffer the hardware transforms many many times are more costly than calculating transforms for each vertex and then additionally copying them into the buffer, yes?No... Maybe [smile] The point here is that the DIP calls themselves are expensive, not necessarily the vertex transformation (see here). There may be some rare scenario's where transforming the vertices on the CPU may be beneficial, but in general it's always faster to do this on the GPU. After all, locking is expensive too and in most typical scenarios you need different transforms each frame, so there is no value in keeping old result around. Rather than doing stuff on the CPU, the typical way to address the problem of having too many DIP calls is to batch small buffers into bigger ones (see here).Quote:A 10mil loop with two multiplications, one division and one power of calculation (integers) easily bogs down frame per frame performance whenever I do it.For an interesting treatise, go here. You simply can't judge actual performance by looking at some unrelated calculations. Most notably, the hardware uses floats instead of integers and you can't perfectly simulate the asynchronous operation of the CUP & GPU.Quote:where should I "put" vertex buffers?Wherever you like [smile] I'd personally go with the mesh approach, if you don't foresee using 1000+ DIP calls per frame. Batching can be important, but I'd start worrying about that once you really need it. There's no use in complicating your first 3D rendering experience to the point you feel like giving up.Quote:I also plan on using a homemade mesh-class, since it's probably a nice learning experience in the end, and because .x seems to be deprecated <.<, hence the desire to know where to put and how to use buffers.Continuing on the last tangent, yes .x is deprecated but it will still give you a good feel of what you actually need. And it will get you started faster. Results matter [smile];Quote:Original post by Evil SteveIt won't make any difference really - vertex transformation will always happen on the GPU if you're using hardware vertex processing (Which you should be wherever possible).Ah, hm.I must be understanding some of my resources incorrectly then, like.http://www.gamedev.net/community/forums/topic.asp?topic_id=505926Specifically:Quote:Original post by GekkoSo instead of drawing one box and using transforms to the same quad all over the screen, would I calculate the actual position of the vertices depending on the position of the quad, the scale, etc., and input those actual positions into the vertex buffer?Made me think otherwise, since from what I have gathered, transformations, as well as shaders, are only applied during a DrawPrimitive call and to avoid many of those, the vertices have to be transformed elsewhere.But both of your replies are making me doubt that, especially the bit about the parallel nature of shaders.I'm actually kind of sorry for being so dense, but I really am confused by the relationship of reducing drawing calls by batching and the usage of dynamic buffers which are refilled often.Is the following way of thinking more sound then?Each subset of a mesh is a drawing call, anyway?It's not uncommon for a static buffer to be 'the victim' of many DP calls, since the vertices in it can be parts of many 'logically' separate meshes?And since they're static, the only transformation possible is via DP calls anyway?AndDynamic VBs don't have as much to do with storing pre-transformed vertices, but more like, acting as a chunk/region for the card to render geometry in pieces, since the whole source might not fit in? (let's say 16gb ram full of geometry data, something most chips probably don't have onboard...)But all the transforms are still done via DP calls?So pre-transforming geometry is a waste, beyond maybe a handful of GUI vertices?Those questions might look naive or obvious, but that obsession with batching and saving DP calls is what keeps me from being able to plan/design anything...In short.Did I misunderstand batching?Was I distracted by transforms, and instead batching focuses more on keeping state switches low? (That DX FAQ remigius linked to seems to reinforce this one.)And that is where dynamic buffers shine, since they can be filled more quickly, with set of data that is similar, reducing texture and state switches, but not necessarily drawing calls?As in taking the example of having to draw 100 different quadsIf they all shared the same texture, and no state changes are required, I would still have to do 100 draw call, since that's where their transforms kick in, since you both said that transformation isn't CPU bound?Then how is it possible to draw them all in one go?Well, I think that's enough questions for one post.I'm going to look for more resources on my own as well, but I'm still very interested in replies, of course.And, about overengineering. I'll keep it in mind.I'm just worried that I might mess up things in a way that makes extending functionality a chore.Well, thanks for your time, and cheers. :)Edit:Ah, thank you as well, remigius. I'm heading over to those links right now and read up.And yes, results matter, I can't believe I'm having such a hard time letting go...Thanks again :)   ;Quote:Original post by EriusEach subset of a mesh is a drawing call, anyway?It's not uncommon for a static buffer to be 'the victim' of many DP calls, since the vertices in it can be parts of many 'logically' separate meshes?And since they're static, the only transformation possible is via DP calls anyway?Each subset of a mesh is one draw call, yes (As an aside, "Subset" is really just a term used by ID3DXMesh). When you call DrawSubset, the mesh sets up that material and then draws all faces using that material in a single DrawIndexedPrimitive() call.The vertex transformation is never actually done at DrawPrimitive() time. All DrawPrimitive does is adds an entry to the driver's command buffer. The GPU is always reading from this queue, and when it reads the DP() command, it'll go through each triangle to be rendered in turn, and run the vertex shader on the vertices for that triangle to transform them. The GPU has an internal cache it uses to store transformed vertices, so it can avoid transforming the same vertex several times if it's accessed in quick succession (ID3DXMesh::Optimize will re-order the vertex / index buffer so that vertices are recycled as frequently as possible to keep them in the GPU's cache).The exact size of the cache (And even it's presence) depends on the graphics card and driver version.Quote:Original post by EriusDynamic VBs don't have as much to do with storing pre-transformed vertices, but more like, acting as a chunk/region for the card to render geometry in pieces, since the whole source might not fit in? (let's say 16gb ram full of geometry data, something most chips probably don't have onboard...)But all the transforms are still done via DP calls?So pre-transforming geometry is a waste, beyond maybe a handful of GUI vertices?For the first part, yes. If you're animating an arm bending at the elbow, you wouldn't add vertices for every single position the vertices could be in over the 90 degree or so arc, you'd add them once and then update them each frame depending on what angle the arm is bent at. So you'd have the arm vertices in a dynamic vertex buffer, and update their positions every frame on the CPU, before rendering them.As I mentioned earlier in this post, DP doesn't do any vertex transforms. Because the vertices are transformed at render time, if they're pre-transformed, you can save a small amount of vertex shader time, but it's not generally that useful to do (Someone feel free to correct me if I'm wrong here...)Quote:Original post by EriusDid I misunderstand batching?Was I distracted by transforms, and instead batching focuses more on keeping state switches low? (That DX FAQ remigius linked to seems to reinforce this one.)Nope, that's correct - a batch is essentially one DP() call. You can have 50 SetRenderState() calls between two DrawPrimitive() calls, the driver should combine them into one "Change device state" command (Having said that, don't go changing every render state every time if you can help it).Quote:Original post by EriusAnd that is where dynamic buffers shine, since they can be filled more quickly, with set of data that is similar, reducing texture and state switches, but not necessarily drawing calls?Dynamic resources aren't about reducing draw calls, they're about getting the data (vertices, texel data, etc) modified on the CPU and then thrown at the GPU in the quickest way possible.Quote:Original post by EriusAs in taking the example of having to draw 100 different quadsIf they all shared the same texture, and no state changes are required, I would still have to do 100 draw call, since that's where their transforms kick in, since you both said that transformation isn't CPU bound?Then how is it possible to draw them all in one go?If you had 100 quads sharing one texture, then you can draw them in two ways:1. 100 matrix changes, SetTransform() calls and DrawPrimitive() calls.2. Put them in a dynamic vertex buffer, update their positions when they change, then make 1 DrawPrimitive() call.Usually, #2 is the better option because lots of batches are A Bad Thing with Direct3D.That's what ID3DXSprite does internally - it puts all sprites into a vertex buffer, and when you call Flush() or End(), it sorts them, puts them into the vertex buffer, then calls DrawIndexedPrimitive() to draw all sprites sharing the same texture in one go.   ;  @Evil SteveHm. I see...however...some things still look contradictory to me.To my question "   Does that mean, that in actual, real applications (none of that demo stuff), vertex transformation is actually more or less CPU bound?"I gotQuote:No, why would it be? A managed vb resides on the gpu. Software vertexprocessing would render shaders pretty useless.Quote:It won't make any difference really - vertex transformation will always happen on the GPU if you're using hardware vertex processing (Which you should be wherever possible).But then you wrote:Quote:So you'd have the arm vertices in a dynamic vertex buffer, and update their positions every frame on the CPU, before rendering them.andQuote:2. Put them in a dynamic vertex buffer, update their positions when they change, then make 1 DrawPrimitive() call.So vertices have to be transformed on the CPU ,after all?Is shader use implied here? Do they change something I'm not aware of?Cause I seriously do not see how I would be able to transform the vertices into the final state which would be fed into the buffer and be 'rendered' in one DP call, without the CPU.Is there a diagram I can Google or something, cause I'm feeling rather hot and embarrassed here :PMaybe it's because I'm thinking fixed function pipeline, which I remember to work like this.vertex data -> set transform -> draw primitive -> device processes each vertex specified.just like you said.So how am I supposed to skip vertex data -> set transform -> draw primitive -> processingin that chain ?Lets take that 100 quad example again, no let's make it 1000, or more. (Should be scalable, yes?)On each frame, every quad changes it's position and scaling according to an unique animation, so no generic random jitter function or anything.They're all unique, save the fact that they all use the same texture, and drawing any of those quads doesn't require any change of lighting, or whatever.I only have one that one DP call to render them.How do I pull that one single call off without processing the vertices on the CPU?That's what confused the hell out of me, do shaders really change so many things about all this?Cause I have no clue about shaders...yet.;Quote:Original post by Erius[snip]So vertices have to be transformed on the CPU ,after all?Is shader use implied here? Do they change something I'm not aware of?Cause I seriously do not see how I would be able to transform the vertices into the final state which would be fed into the buffer and be 'rendered' in one DP call, without the CPU.There's two types of transform we're talking about here:1. Changing the vertices in local space (E.g. updating the arm vertices in my example)2. Transforming the local space vertices into pixel coordinates ready for interpolation for the pixel shaderThe first one can be done by CPU or GPU, it depends how you're doing the animation. Skinned animation is usually done on the GPU unless it's too complicated (As in, the vertex shader would exceed the instruction limit), in which case it can be done on the CPU. More complicated animation such as inverse kinematics would likely be done on the CPU.The second one is almost always done by the GPU; you pass in the world, view and projection matrices and the vertices (implied by the DrawPrimitive() call), and the shader then transforms each vertex by the world*view*projection matrix and then adjusts for the viewport.Quote:Original post by EriusIs there a diagram I can Google or something, cause I'm feeling rather hot and embarrassed here :PMaybe it's because I'm thinking fixed function pipeline, which I remember to work like this.vertex data -> set transform -> draw primitive -> device processes each vertex specified.just like you said.The fixed function pipeline behaves in exactly the same way (On modern cards, the fixed function pipeline is emulated with shaders internally).Quote:Original post by EriusSo how am I supposed to skip vertex data -> set transform -> draw primitive -> processingin that chain ?Lets take that 100 quad example again, no let's make it 1000, or more. (Should be scalable, yes?)On each frame, every quad changes it's position and scaling according to an unique animation, so no generic random jitter function or anything.They're all unique, save the fact that they all use the same texture, and drawing any of those quads doesn't require any change of lighting, or whatever.I only have one that one DP call to render them.How do I pull that one single call off without processing the vertices on the CPU?In that case, where the animation is too complex to do on the GPU, you'd do the transformation (Step 1 of it, above) on the CPU. This is what ID3DXSprite does.It all boils down to what you can and can't do on the GPU. Basic animation can be done with the vertex shader, but more complicated animation needs done on the CPU.When you do animation on the CPU, you still (usually) work in local space, so all vertex positions are relative to the model origin, not the world - the transformation from model local space to world space to screen coordinates is still almost always done by the vertex shader.;  Ah, of course. I was pretty much only talking about the first kind of transform, sorry for the confusion because I wasn't specific enough.I feel much more sane again, that really did get me...Thank you very much indeed for your time, as trivial seeming as this turned out to be, it kept me in a complete lockdown.I seriously appreciate it.Time to flesh out something simple...Cheers!   