WinRT vector and matrix types in Windows 10


This a follow-up to Win2D integration with Windows 10

Short version

 When you use Win2D on Windows 10, vector and matrix operations work better and run faster!

 

Long version

Last year I wrote about how Win2D includes three different sets of vector and matrix types:

  1. A rich .NET implementation in the namespace System.Numerics
  2. A rich C++ implementation in the header WindowsNumerics.h
  3. A set of plain-data WinRT structs in  the namespace Microsoft.Graphics.Canvas.Numerics

WinRT APIs such as Win2D are implemented using #3, but client application code normally prefers to work with #1 or #2.  These types have conversion operators, so for instance an app could create a System.Numerics.Matrix3x2, assign this to CanvasDrawingSession.Transform (which is of type Microsoft.Graphics.Canvas.Numerics.Matrix3x2), and the data will be automatically converted from one type to the other.

This design mostly worked ok, but people were sometimes confused by the multiple sets of similar looking types, and there are some corner cases (for instance APIs that operate on arrays of vectors rather than single structs) where the type conversion operators do not work automatically.

In Windows 10, all these types have moved out of Win2D into the core Windows platform:

  1. For .NET, System.Numerics is now owned by the .NET CoreFX team and shipped in the NuGet package System.Numerics.Vectors
  2. For C++, WindowsNumerics.h is part of the Windows 10 SDK
  3. The plain-data WinRT structs are added to the operating system in the namespace Windows.Foundation.Numerics

For a developer using Win2D, these changes are mostly transparent.  Regardless of whether you are building for 8.1 or 10, the assembly defining System.Numerics is automatically referenced by .NET apps, and WindowsNumerics.h is automatically made available in your C++ include path.

Now that these types are a core part of the platform, we were able to bake knowledge of them directly into the .NET runtime and C++/CX compiler.  Instead of relying on conversion operators, whenever .NET encounters a Windows.Foundation.Numerics.{Foo}, it will automatically reinterpret this type as a System.Numerics.{Foo}.  The C++ compiler does a similar remapping to the types from WindowsNumerics.h.  Thanks to this specialized projection, Win2D APIs like CanvasDrawingSession.Transform no longer appear merely as a type that is convertible to and from the System.Numerics.Matrix3x2 type that apps are working with – instead they ARE directly of this type!  This has many benefits:

  • No more strange corner cases, for instance array-of-vector parameters now work as expected.
  • Reinterpreting the identity of a type can in some cases generate more efficient code than using conversion operators between two different (although identically laid out) sets of types.
  • The WinRT structs from Windows.Foundation.Numerics are no longer visible to app developers at all.  They are erased by the projection mechanism, removing a possible source of confusion.
  • Basically everything Just Works™, and the plumbing that enables these types in WinRT is properly hidden away where nobody has to worry about it.

Also new in Windows 10 is SIMD optimization of System.Numerics.  These types are implemented in IL, which allows them to be used on older non-SIMD enabled JIT compilers, but key methods are also decorated with a [JitIntrinsic] attribute which is recognized by newer versions of .NET and used to output more efficient SIMD opcodes.  Check out the source code if you are curious how this works (like all of CoreFX, System.Numerics is hosted on GitHub).


Comments (15)

  1. Mansewiz says:

    Nice and useful post!

    On Windows 10, my C# projects are using these types and are nicely compiling.

    However, on the same solution, my C++ Windows Runtime projects are not linking, I am obviously missing to include a library, but which one?

    Error LNK2019 unresolved external symbol "public: __cdecl Windows::Foundation::Numerics::float3x2::float3x2(float,float,float,float,float,float)" (??0float3x2@Numerics@Foundation@Windows@@QAA@MMMMMM@Z) referenced in function "public: virtual class Windows::Foundation::Numerics::float3x2 __cdecl

    1. SimonRev says:

      (Bit late, but in case anyone else has this error). It seemed to be caused when I accessed the Windows::Foundation::Numerics::float3x2 constructor in a header file, but didn’t include the from that same header file (I included from the .cpp file instead).

      I resolved it by including from the header file instead.

  2. Hmm, that's a very odd error!  The C++ numerics implementation is 100% inline in WindowsNumerics.h and WindowsNumerics.inl, so I don't understand how this could be getting a link error.

    I assume you did include that header?  (if you didn't, I'd expect things not to compile at all rather than just failing to link)

    Can you share more info about how this C++ project is set up?

  3. Andrew says:

    Useful post, thanks!

  4. Rico Alexander says:

    Can this library be used for games. If so, any game tutorials available?

  5. Anastasios-Antonios Toulkeridis says:

    Please help!  (I also sent a tweet but I'd like to ask here too).

    I'm trying to submit a universal app that uses Win2D and it fails the Windows App Certification Kit.

    This is the error:

    Supported API test

    FAILED

    Supported APIs

    •Error Found: The supported APIs test detected the following errors:◦API Sleep in kernel32.dll is not supported for this application type. Microsoft.Graphics.Canvas.dll calls this API.

  6. DamyanPepper says:

    @Anastasios – can you confirm which version of Visual Studio (and the app certification kit) you are using?

    Sleep() was previously an unsupported API for Windows Store Apps.  With VS2013 update 4 and the latest version of the Windows App Certification Kit it is now supporeted.

  7. Anastasios-Antonios Toulkeridis says:

    Hello.

    Visual Studio Ultimate 2013 Update 4

    WACT 3.4

    Despite the warning I went ahead and submitted the app to the store and it passed certification!

    This app:

    apps.microsoft.com/…/829b05a3-b10d-4fa1-8c3f-13f1ebc1eca3

    (another app of mine that uses Win2D is this:

    apps.microsoft.com/…/3e7bead2-7e79-4a54-b760-cae233ab6201 )

  8. > WACT 3.4

    This is a very old version – the latest is 10.0.

  9. > Can this library be used for games.

    Do you mean the vector/matrix implementation that this article describes, or Win2D as a whole?

  10. Joe says:

    I have a matrix defined as my "camera" like so:

    this.Transform3x2 =

                   Matrix3x2.CreateTranslation(this.X, this.Y) *

                   Matrix3x2.CreateRotation(this.Rotation) *

                   Matrix3x2.CreateScale(this.Scale) *

                   Matrix3x2.CreateTranslation(this.Size.Width /2, this.Size.Height /2);

    How can I change this so that I can flip an image about the Y-Axis?

    I tried Matrix3x2.CreateScale(-1f,1f) but this also changes where the image is on the screen.

    Would be awesome to have built in support for DrawImage for things like this.

  11. > How can I change this so that I can flip an image about the Y-Axis?

    Use the overload of CreateScale that specifies a center point (microsoft.github.io/…/M_System_Numerics_Matrix3x2_CreateScale_5.htm), and tell it you want to flip around the center of the screen rather than the origin.

  12. Rico Alexander says:

    >Do you mean the vector/matrix implementation that this article describes, or Win2D as a whole?

    Meant win2d as a whole.

  13. Rico,

    Win2D is a graphics API rather than a complete all-in-one game engine, but you could certainly use it to implement the graphics portion of a 2D game, in combination with other APIs for other areas such as input, sound, physics if your game needs that, etc.

    In fact, several of the earliest Win2D apps published in the Store were games…

  14. Rico Alexander says:

    Thanks for the info. Hopefully more tutorial popup focused on using it with to develop games.

Skip to main content