Skip to content

Add Simd matrix types and use them to bind native Simd matrices. Fixes #58599 - #2571

Merged
rolfbjarne merged 17 commits into
dotnet:xcode9from
rolfbjarne:xcode9-matrix
Sep 5, 2017
Merged

Add Simd matrix types and use them to bind native Simd matrices. Fixes #58599#2571
rolfbjarne merged 17 commits into
dotnet:xcode9from
rolfbjarne:xcode9-matrix

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

The OpenTK matrices (Matrix2/3/4) has a different memory layout than Apple's
matrix_float2x2/matrix_float3x3/matrix_float4x4 matrices: the OpenTK versions
are row-major, while Apple's versions are column-major.

This means that when blitting memory from one to the other, the matrix will
appear to have been transposed.

See bug #58599 for an example.

Unfortunately we've already bound several API with Apple's matrix_floatXxX
matrices using OpenTK's matrices, and although they're bound wrong, and the
matrices appear transposed on input/output, we can't change the behavior
because we have to maintain compatibility.

This means we have to introduce new API, and then also just define new matrix
types with the right memory layout (column-major). Additionally, in the future
we might be able to mark these matrices as Simd-matrixes, so that the JIT/AOT
compiler can generate the correct alignment for them, avoiding having to
define a native conversion method (using the [MarshalDirective] hack).

The matrices have been designed to match API-wise the matrices in the
System.Numerics.Vectors namespace 1, but for the moment with only a few
basic operations implemented (Determinant/Transpose/Multiply) defined (we can
always add more later if we want to).

In addition explicit conversion operators to and from the corresponding
OpenTK.MatrixX are implemented, which means any operation defined in the
OpenTK matrices can be used by converting back and forth.

Also add a new xtro check that verifies that we bind things correctly from now
on + that all simd API have [MarshalDirective] attributes.

The OpenTK matrices (Matrix2/3/4) has a different memory layout than Apple's
matrix_float2x2/matrix_float3x3/matrix_float4x4 matrices: the OpenTK versions
are row-major, while Apple's versions are column-major.

This means that when blitting memory from one to the other, the matrix will
appear to have been transposed.

See bug #[58599][2] for an example.

Unfortunately we've already bound several API with Apple's matrix_floatXxX
matrices using OpenTK's matrices, and although they're bound wrong, and the
matrices appear transposed on input/output, we can't change the behavior
because we have to maintain compatibility.

This means we have to introduce new API, and then also just define new matrix
types with the right memory layout (column-major). Additionally, in the future
we might be able to mark these matrices as Simd-matrixes, so that the JIT/AOT
compiler can generate the correct alignment for them, avoiding having to
define a native conversion method (using the [MarshalDirective] hack).

The matrices have been designed to match API-wise the matrices in the
System.Numerics.Vectors namespace [1], but for the moment with only a few
basic operations implemented (Determinant/Transpose/Multiply) defined (we can
always add more later if we want to).

In addition explicit conversion operators to and from the corresponding
OpenTK.MatrixX are implemented, which means any operation defined in the
OpenTK matrices can be used by converting back and forth.

[1]: https://msdn.microsoft.com/en-us/library/system.numerics.matrix4x4(v=vs.111).aspx
[2]: https://bugzilla.xamarin.com/show_bug.cgi?id=58599
@rolfbjarne

Copy link
Copy Markdown
Member Author

A question that remains is whether we should add corresponding Simd vector types too. Especially Vector3 is troublesome, because the native simd version is 16 bytes, since there's 4 bytes of padding at the end (but if we do one, I'd say we do all, just to be consistent).

The padding in the native Vector3 type leads to easy-to-make mistakes such as this: PR #2565.

One option is to add Simd vector types and only use them in any new frameworks (ARKit/Vision).

return !left.Equals (right);
}

public static explicit operator global::OpenTK.Matrix2 (MatrixFloat2x2 value)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: should this be an implicit operator instead? The conversion is lossless (it's just transposing the matrix), but it could also lead to slow code (it would be very easy to write code that does a lot of conversions, which would slow it down).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's too easy to hide the performance cost. The overuse of the explicit one should be spotted in code reviews as a potential "non-free" issue.

@monojenkins

Copy link
Copy Markdown
Contributor

Build failure

@spouliot spouliot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to read it again (lots of stuff) but tests makes me feel better. There's a few things in xtro that needs to be consistent with the existing tests.

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated

if (contains_simd_types && very_strict) {
// We can't map this method to a native function.
Console.WriteLine ($"!simd-can't-map-managed! {method}");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start with either !unknown- or !wrong- so it gets sorted along other important/critical logs

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not important/critical, so I didn't change it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does sounds like an unknown that requires investigation (like an API that won't work) unlike missing that have not indirect impact (i.e. what we ship is correct but incomplete)

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated
ManagedSimdInfo existing;
if (managed_methods.TryGetValue (key, out existing)) {
if (very_strict)
Console.WriteLine ($"!simd-double-mapping! same key '{key}' for both '{existing.Method}' and '{method}'");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start with either !unknown- or !wrong- so it gets sorted along other important/critical logs

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not important/critical, so I didn't change it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's reuse existing tags so they are grouped together, e.g. !duplicate-simd-mapping

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated
var typeName = type.ToString ();

if (!rv && typeName.Contains ("simd"))
Console.WriteLine ($"!simd-unknown-type! Could not detect that {typeName} is a Simd type, but its name contains 'simd'.");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start with either !unknown- or !wrong- so it gets sorted along other important/critical logs

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated
}

if (IsExtVector (type, ref simd_type))
Console.WriteLine ($"!simd-unmapped-type! The Simd type {simd_type} does not have a mapping. Please add one in SimdCheck.cs");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start with either !unknown- or !wrong- so it gets sorted along other important/critical logs

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated
if (!anyCalls)
return;

Console.WriteLine ($"!simd-missing-marshaldirective! {method}: simd type: {simd_type}");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start with either !unknown- or !wrong- so it gets sorted along other important/critical logs

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated
return;
if (!strict)
return;
Console.WriteLine ($"!simd-can't-map-native! {decl}: could not find a managed method (selector: {decl.Selector} name: {decl.GetName ()}. Found the simd type '{simd_type}' in the native signature.");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

start with either !unknown- or !wrong- so it gets sorted along other important/critical logs

CheckMarshalDirective (method, simd_type);

// We have a potentially broken managed method. This needs fixing/investigation.
Console.WriteLine ($"!unknown-simd-type-in-signature! {method}: the native signature has a simd type ({simd_type}), while the corresponding managed method is using an incorrect (non-simd) type.");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was unintentional 😄

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must have been a natural choice :)

@monojenkins

Copy link
Copy Markdown
Contributor

Build failure

…raries.

Fixes this build problem for framework-test:

	clang: error: linker command failed with exit code 1 (use -v to see invocation)
	MTOUCH: error MT5212: Native linking failed, duplicate symbol: '_x_mdltransform_get_rotation_matrix'.
	MTOUCH: error MT5213: Duplicate symbol in: /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/framework-test/obj/iPhoneSimulator/Debug-unified/mtouch-cache/XStaticObjectTest.framework/XStaticObjectTest (Location related to previous error)
	MTOUCH: error MT5213: Duplicate symbol in: /Users/builder/jenkins/workspace/xamarin-macios-pr-builder/tests/framework-test/obj/iPhoneSimulator/Debug-unified/mtouch-cache/XStaticArTest.framework/XStaticArTest(libtest-ar.x86_64.o) (Location related to previous error)
	MTOUCH: error MT5212: Native linking failed, duplicate symbol: '_x_mdltransformcomponent_get_local_transform'.
	MTOUCH: error MT5212: Native linking failed, duplicate symbol: '_x_mdltransform_create_global_transform'.
	MTOUCH: error MT5212: Native linking failed, duplicate symbol: '_x_get_matrix_float4x4'.
	MTOUCH: error MT5212: Native linking failed, duplicate symbol: '_x_get_matrix_float3x3'.
	MTOUCH: error MT5212: Native linking failed, duplicate symbol: '_x_get_matrix_float2x2'.
	MTOUCH: error MT5209: Native linking error: 6 duplicate symbols for architecture x86_64
	MTOUCH: error MT5202: Native linking failed. Please review the build log.
…d ignore the right simd matrix types.

Fixes this introspection/Mac problem:

    ***** ApiSignatureTest.NativeSignatures
    Selector: uniformWithName:matrixFloat2x2: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat2x2, nothing encoded
    Selector: uniformWithName:matrixFloat3x3: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat3x3, nothing encoded
    Selector: uniformWithName:matrixFloat4x4: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat4x4, nothing encoded
    Selector: setMatrixFloat2x2Value: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat2x2, nothing encoded
    Selector: setMatrixFloat3x3Value: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat3x3, nothing encoded
    Selector: setMatrixFloat4x4Value: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat4x4, nothing encoded
    Selector: initWithName:matrixFloat2x2: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat2x2, nothing encoded
    Selector: initWithName:matrixFloat3x3: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat3x3, nothing encoded
    Selector: initWithName:matrixFloat4x4: on type SpriteKit.SKUniform, Type: Simd.MatrixFloat4x4, nothing encoded
… build work.

Fixes this:

    Simd/MatrixFloat4x4Test.cs(28,12): error CS0117: 'Asserts' does not contain a definition for 'AreEqual'
    Simd/MatrixFloat4x4Test.cs(29,12): error CS0117: 'Asserts' does not contain a definition for 'AreEqual'
    Simd/MatrixFloat4x4Test.cs(37,12): error CS0117: 'Asserts' does not contain a definition for 'AreEqual'
    Simd/MatrixFloat4x4Test.cs(48,12): error CS0117: 'Asserts' does not contain a definition for 'AreEqual'
    [...]
…xammac tests.

Exclude code that requires the test binding project from xammac tests because
there's currently no XM version of the test binding project.

Fixes this:

    tests/monotouch-test/SpriteKit/UniformTest.cs(20,7): error CS0246: The type or namespace name 'Bindings' could not be found (are you missing a using directive or an assembly reference?)
    tests/monotouch-test/ModelIO/MDLMaterialProperty.cs(37,7): error CS0246: The type or namespace name 'Bindings' could not be found (are you missing a using directive or an assembly reference?)
    tests/monotouch-test/ModelIO/MDLTransform.cs(34,7): error CS0246: The type or namespace name 'Bindings' could not be found (are you missing a using directive or an assembly reference?)

@rolfbjarne rolfbjarne left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spouliot I've fixed some of the xtro messages, but not those I didn't consider important/critical (so that they're not sorted with the important/critical logs).

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated

if (contains_simd_types && very_strict) {
// We can't map this method to a native function.
Console.WriteLine ($"!simd-can't-map-managed! {method}");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not important/critical, so I didn't change it.

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated
ManagedSimdInfo existing;
if (managed_methods.TryGetValue (key, out existing)) {
if (very_strict)
Console.WriteLine ($"!simd-double-mapping! same key '{key}' for both '{existing.Method}' and '{method}'");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not important/critical, so I didn't change it.

CheckMarshalDirective (method, simd_type);

// We have a potentially broken managed method. This needs fixing/investigation.
Console.WriteLine ($"!unknown-simd-type-in-signature! {method}: the native signature has a simd type ({simd_type}), while the corresponding managed method is using an incorrect (non-simd) type.");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was unintentional 😄

@monojenkins

Copy link
Copy Markdown
Contributor

Build success

@rolfbjarne

Copy link
Copy Markdown
Member Author

@spouliot I've fixed all the xtro messages now.

@spouliot spouliot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Introspection tests needs to be adjusted (failures due to unencoded simd types).

  • SKTransformNode is a new type and should not add an obsolete API

	[Obsolete ("Use 'RotationMatrix3x3' instead.")]
	public virtual OpenTK.Matrix3 RotationMatrix { get; set; }

Comment thread tests/xtro-sharpie/SimdCheck.cs Outdated

if (contains_simd_types && very_strict) {
// We can't map this method to a native function.
Console.WriteLine ($"!simd-can't-map-managed! {method}");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does sounds like an unknown that requires investigation (like an API that won't work) unlike missing that have not indirect impact (i.e. what we ship is correct but incomplete)

@monojenkins

Copy link
Copy Markdown
Contributor

Build success

@spouliot

spouliot commented Sep 1, 2017

Copy link
Copy Markdown
Contributor

intro ran fine on the last build
only the SKTransformNode issue remains

…broken (and obsolete) non-simd version of RotationMatrix.
@monojenkins

Copy link
Copy Markdown
Contributor

Build success

@dalexsoto dalexsoto left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants