9
$\begingroup$

Say I have a model made up of vertices, each with position, normal, tangent, and texcoord attributes, where triangles are specified by index triples.

If we just focus on the vertex attributes, I'm aware of two broad strategies: the structure of arrays, and the array of structures. I've also heard that the array of structures is preferred because it increases the memory locality (and therefore cache locality) of the attributes for a given vertex.

Is it really the case that this improves performance? The main way I could think that this would come about is by vertex indices that require the rasterizer to acquire vertex data that has long since been evicted from cache. If vertex data access is random like this, then keeping all the attributes for a vertex on the same cache line would certainly make things faster, but is this not an issue that could be mostly mitigated by optimizing the order of triangle specification?

Furthermore, it's my understanding that modern GPUs may be better at unpacking long vectors of the same type, than vectors of structures of many types. Would it then be possible for a structure-of-arrays layout to consistently outperform an array-of-structures layout of the same vertex data, if the index order is optimized?

$\endgroup$
4
  • 4
    $\begingroup$ Couldn't you simply try it out and see which is fastest for your case? $\endgroup$ Commented Mar 19, 2018 at 2:20
  • $\begingroup$ I would have thought for indexed meshes that array-of-structures would be more efficient as the vertex shader will be fed all vertex attributes so having them grouped together in memory is going to be cache friendlier. $\endgroup$
    – PaulHK
    Commented Jan 11, 2019 at 7:33
  • $\begingroup$ Depending on the data types in structure, vec4s and floats pack together nicely, other types not so well $\endgroup$
    – PaulHK
    Commented Jan 11, 2019 at 7:41
  • 2
    $\begingroup$ @user1118321 While individual benchmarking experiments are a commendable practice, there certainly is more long-term value in a broader theoretical discussion and maybe resulting establishment of general practices based on how vertex pulling hardware works. $\endgroup$ Commented Feb 26, 2019 at 9:31

2 Answers 2

2
$\begingroup$

Apologies, I was going to add a comment to your question thread but found I ended up elaborating too much. My development experience is from a DX 11 perspective so some of this may not hold in OpenGL

The memory locality of the data does certainly play a major part. But there is a few other items that do play into this, the width of the data as you know. I've had a few GPUs and have had a stark performance hit on some based upon certain tipping points. That is the for example, on my old AMD r290 if I recall, you could basically pass up to 4 float4s through to the vertex buffer with no additional cost over 1, but once I posted > 4 then there was a measurable drop (in frame rate). This is purely off my recollection and so is anecdotal as best. But it holds that GPU architecture is changing all the time, and what niche techniques that give you a performance edge today maybe the bane of your performance tomorrow. I've tried myself to stick to the advised known best on the assumption that hardware vendors will build their GPUs to the most common techniques of passing payloads via VB (obviously with some looks from constant buffers).

Having said that, you have asked the question about ordering the vertices, and certainly that will help marginally. The performance gain is when you combine this with index buffers which then allows the hardware to optimise and cache already calculated vertices. You certainly may get even more gains from Triangle strips etc which specifically ordered as per your thoughts. Most of model rendering I do is indice/vertex based optimised models with instancing, I use a small amount of lookups for cyclic motion effects (tree branches for example), in these cases the entire branch of the tree is looking up the same value. So caching can be taken advantage of here also.

All I can say in summary from myself is:

  • Try not to overthink optimisation at the start, while your still developing your game/application try not to prematurely optimise. If you need to come back and add new capabilities, you might lose all the effort. You have my habit maybe ><, love trying to get the best performance and techniques
  • GPU architectures are varied, and strengths of one can reflect weaknesses in another. AMD and Nvidia are famous for getting devs to optimise games to their architecture, for a reason, each has advantages/disadvantages. Taking the middle road on development might be the best place, don't use any hardware vendor based features (opinion here). (add to that, some packed formats only exist in AMD).

These are just a few thoughts and experiences I have had. There are a lots books out there that you should get your hands on around these very topics. I've not seen to many prescribe what you're proposing, but that doesn't mean its wrong. Good luck.

$\endgroup$
1
$\begingroup$

This may depend on target hardware and the API you are going to use. Can you provide more info? Here's some (very broad and general) best practices for OpenGL. https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices

Also, do you have a performance problem? Or are you just curious.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.