0

I follow some common DirectX tutorial on the web which features classes and structuring. I need to allocate memory for XMVECTOR and XMMATRIX because of the specific memory allocation issue.

Now it all works, but I wish to make teh code cleaner. Question is: Is there a way to override new and delete for those structures(so the malloc and pointer conversion details are hidden by the word "new", similarly with the delete) and if so how?

Edit 2014-07-11:

The comments so far suggested two way to workaround the problem by:

1) using a wrapper class for the structures and overloading/overriding delete and new for the wrapper class.

The problem with this is the obvious performance hit and the need to access member structure ever single time (less cleaner code, which defeats the whole purpose).

2) Using XMFLOAT4 and similar structures.

Problem with this is that this makes it easier with memory allocation but adds complications in conversions between types (as XMMATRIX and XMVECTOR are the ones returned by DirectXMath functions). Those conversions also make the code less cleaner so it's like replacing a pile of dog poop with cat poop, it's still poop in the end (yeah, the best comparison I could come up with to convey meaning).

Community
  • 1
  • 1
  • http://www.cprogramming.com/tutorial/operator_new.html – Paweł Stawarz Jul 09 '14 at 23:33
  • @PawełStawarz No, not really. I didn't wrote those structures(obviously) so I have no idea how it all ties in together. The scenario is too specific to to deduce from that general explanation. Are those structures or classes? difference in overriding? Is it even possible for structures? Which one is to be overloaded? Where? etc. etc. etc. – Round Potato Jul 09 '14 at 23:46
  • the link I provided informs you __how__ to overload operators, while the question you linked to, informs __what to do__ inside of the overloaded operators. I would create my own class wrapping the mentionned XMVECTOR and XMMATRIX structs, and overload their operators based on the knowledge from the two links. – Paweł Stawarz Jul 10 '14 at 00:28
  • @PawełStawarz Overridden not overloaded, sorry. And how to do override them in the first place is the question? If you just make a wrapper class overriding methods OF THAT CREATED CLASS then it's the worst solution that immediately comes to mind, it's obvious overhead. Not sure if that was what you were saying though, you wrote create a class and overload(I assume you went override) "their operators"(of the structure), why make the class then. – Round Potato Jul 10 '14 at 01:14
  • You're quite rude for a person who asked for help in the first place. Try being more polite when you're not concrete about what you've already tried and what ideas did you think of yourself. You asked, and I gave you a hint (clearly it isn't an answer, judging by the fact I posted it as a comment) - clean code often comes at a price. And the term is "overload", not "override" - at least in this particular case, when talking about operators. – Paweł Stawarz Jul 10 '14 at 01:31
  • @PawełStawarz It was not in my intentions to be rude, rather to clarify what requires to be done in case you misunderstood me. The term IS override not overload, because it is in the context of overriding operators of specific structs/classes, not overloading global operators to cater for those structs/classes. – Round Potato Jul 10 '14 at 11:42
  • No, it's clearly _overloading_. Read http://en.wikipedia.org/wiki/Operator_overloading, http://wiki.answers.com/Q/Difference_between_overriding_and_overloading and http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence – Paweł Stawarz Jul 10 '14 at 13:33
  • @PawełStawarz not... I wish to override "new XMMATRIX()" , NOT overload "new XMMATRIX(overloadingDifference)". – Round Potato Jul 10 '14 at 15:54
  • Have you even __read__ any of the 4 links I've provided? I guess not. And as such, I'm not going to continue this discussion (since it's pointless anyhow). Wish you best luck with finding someone who would compile them into a single answer tho. – Paweł Stawarz Jul 10 '14 at 16:36
  • `XMVECTOR` and `XMMATRIX` are not intended to be used as storage classes. Instead, you should be using types such as `XMFLOAT4` and `XMFLOAT4X4`. – MooseBoys Jul 10 '14 at 17:19
  • @MooseBoys They are returned from matrix/transformation related functions it's just a struct containing 4 vectors[1] , as such I don't see how your statement is relevant by you simply stating it. Mind providing explanations/fact/sources? [1]http://msdn.microsoft.com/en-us/library/windowsphone/develop/microsoft.directx_sdk.reference.xmmatrix.aspx – Round Potato Jul 10 '14 at 18:36
  • @RoundPotato According to the DirectXMath [type usage guidelines](http://msdn.microsoft.com/en-us/library/windows/desktop/ee418725(v=vs.85).aspx#type_usage_guidelines_), _...often it is easier and more compact to avoid using XMVECTOR or XMMATRIX directly in a class or structure. Instead, make use of the XMFLOAT3, XMFLOAT4, XMFLOAT4X3, XMFLOAT4X4, and so on..._ Also, in general you shouldn't be surprised to see advice without references on SO. A lot of it just comes from first-hand experience. – MooseBoys Jul 10 '14 at 18:46
  • @MooseBoys Thanks for the tips. However, since (as it's re-enforced by what is written following that link) those are indeed "work horses" of DirectXMath, while it might be easier with memory alignment there are complications with conversions/etc between types. So the trade-off doesn't seem beneficial to me. As far as no reference on SO, thanks for the insight, but it's never a good idea to trust/follow blindly what you are told, people advising can also make mistakes. – Round Potato Jul 10 '14 at 23:05
  • @RoundPotato If code simplicity is your main concern, you could look at something like [SimpleMath](http://blogs.msdn.com/b/shawnhar/archive/2013/01/08/simplemath-a-simplified-wrapper-for-directxmath.aspx). Vector math is rarely a performance bottleneck anyway. If you determine through profiling that you really are CPU vector math bottlenecked, then you'll need to evaluate the trade off between clarity and performance (or trusting the compiler to do it for you). – MooseBoys Jul 11 '14 at 00:15
  • @MooseBoys It is main concerns but under the context of incurring minimal to no performance hits(If that is not possible, I'd rather manually allocate "_aligned_malloc(...)" each time). I'm not sure why nobody is replying(maybe my questions isn't clear?), but is there really no way to override new/delete to feature that allocation of the structs directly? – Round Potato Jul 11 '14 at 07:27
  • 1
    @RoundPotato If you're worried about performance, you probably don't want to be overriding the individual new/delete anyway because there's no guarantee of memory adjacency with individual heap allocations. You also pay extra cost on every delete. Instead, I would create an aligned vector/matrix heap and do your own manual heap allocations. This has the added benefit of extremely lightweight allocate/free as usually you do a computation once per frame and can discard the entire custom heap after submitting the work. Naturally, this is way more work for just a slight (potential) perf win. – MooseBoys Jul 11 '14 at 19:55
  • As an alternative, you can also use `#pragma pack` to force alignment of elements in a parent struct. Subsequent elements should be adjacent, but this only works if you know the layout of vectors/matrices you need at compile time. For example, `#pragma pack(push, 16) \ // vector decls \ #pragma pack(pop)`. – MooseBoys Jul 11 '14 at 19:59
  • @MooseBoys If I understood you correctly, you suggest allocating a single aligned block big enough to hold required amount of matrices/vectors and use it for calculations during a frame(thus avoiding new memory reservations each time) and simply ignore the delete procedure and re-use it for the next frame (thus avoiding memory releases), correct? – Round Potato Jul 12 '14 at 00:40
  • @RoundPotato Yes, this is a common technique in 3D engines since they typically work with many similar objects whose lifetimes are all the same - exactly one frame. – MooseBoys Jul 12 '14 at 03:20
  • @MooseBoys Thanks for having the patience with this conversation. That is a great reminder of how to allocate memory for me. Even though the original question is less relevant now, I would still like an answer for cases such as "View*Projection" of a Camera where the camera position/etc. does not move. Thus performance would be less relevant but I would still want clean code. I am surprised that nobody answered yet whether it is possible to override new/delete of a...say XMMATRIX directly(without a wrapper class). – Round Potato Jul 12 '14 at 13:02

1 Answers1

2

The general recommendation is to use the various memory structures (XMFLOAT4, etc.) and Load/Stores. If you were targeting only x64 native, you could use XMVECTOR/XMMATRIX directly since that platform uses 16-byte aligned memory by default.

The overloading new/delete recommendation is not for XMVECTOR or XMMATRIX. Rather you can overload new/delete for your classes that contain these types to use __aligned_malloc( x, 16 ). Global overriding of new/delete is possible, but doing it per-class is actually the recommended solution. See the Scott Meyers "Effective C++" books for detailed discussion of overriding new/delete.

Another approach is to use the pImpl idiom like the DirectX Tool Kit does. The public class is unaligned but the internal class uses __aligned_malloc( x, 16 ). This actually works really well, and both the implementation and the client code doesn't end up looking like "poop".

Finally, you could make use of the SimpleMath wrapper in the DirectX Tool Kit which provides classes that derive from XMFLOAT4, etc. with implicit conversions. It is not as efficient, but it does look clean without worrying about the alignment issues.

BTW, this topic is covered in the DirectXMath Programmer's Guide on MSDN.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81