I’m currently working on a project that involves setting an enormous amount of vertex data using VertexPositionTextures. This ends up eating up a lot of memory, and while there’s some optimization I can do as far as what is currently in memory and what can be offloaded to the hard-drive, I would like to optimize in every way possible.
My question then: is there a way I can rewrite the VertexPositionTexture struct such that it uses my custom IntVector classes to use less space? Would this require modifications to DrawPrimitives and DrawUserPrimitives as well?
I ask this because I’m not using a texture atlas, so my UV coordinates are always (0,0),(0,1),(1,0),(1,1) which can be represented without floats, and my vertex positions can be easily represented by integers as well.
Yes, you can do this. You just have to define a custom vertex format and XNA will do the rest.
The most important thing to keep in mind is that you are limited to using elements in the available
VertexElementFormats (MSDN) – noting that theHalfVectorformats are not available in theReachprofile (info).You probably don’t need to create your own vector types, because XNA already provides implementations for all usable formats in
Microsoft.Xna.Framework.Graphics.PackedVector(MSDN) or in the main library. If you do want to create your own type, it needs to be astruct(or loose fields in your vertex) that packs in the same way.Finally, it’s worth pointing out that there is no 32-bit
intdata type. And there would be no benefit, either, because afloat(aSingle) is the same size at 32 bits. (And some GPUs operate in single-precision, so you wouldn’t get to keep the extra precision anyway.)So we’re starting with a
VertexPositionTexturecontaining aVector3position (96 bits) and aVector2texture coordinate (64 bits) for a total of 160 bits.Let’s turn that into a custom
IntVertexPositionTexturethat contains aShort4position (64 bits) and aNormalizedShort2texture coordinate (32 bits) for a total of 96 bits (40% size reduction).(If you’re working in 2D, you could use
Short2instead ofShort4and save another 32 bits. There is noShort3.)Here’s the code for this vertex type, which is really just a case of knowing what the API expects:
The important thing when creating a custom vertex type is to make sure the fields match the order and layout that you specify in the
VertexDeclaration(MSDN). How you create yourVertexDeclarationshould be self-explanatory – just have a look at the MSDN page forVertexElement‘s constructor. The offset of each field is specified in bytes.The
elementUsageandusageIndexmatch up to vertex shader semantics in HLSL. So in this custom format we havePOSITION0andTEXCOORD0.The use of
IVertexTypeis optional, as you can also pass aVertexDeclarationdirectly to (for example) aVertexBufferconstructor instead.That should be all the info you need if you want to make a different vertex format to the one I’ve provided. For more info, there is a blog post by Shawn Hargreaves that goes into more detail about the API.