From a3314bc2edff1ae54069facaf96214371a859bac Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 18 Aug 2017 17:25:14 +0200 Subject: [PATCH 01/17] [xtro-sharpie] Add a Simd check class to verify signatures with Simd types. --- tests/xtro-sharpie/Helpers.cs | 42 +++ tests/xtro-sharpie/Runner.cs | 1 + tests/xtro-sharpie/SimdCheck.cs | 382 +++++++++++++++++++++++++ tests/xtro-sharpie/common.ignore | 41 +++ tests/xtro-sharpie/xtro-sharpie.csproj | 1 + 5 files changed, 467 insertions(+) create mode 100644 tests/xtro-sharpie/SimdCheck.cs diff --git a/tests/xtro-sharpie/Helpers.cs b/tests/xtro-sharpie/Helpers.cs index cb1bfb5e09c5..fa980fbc6947 100644 --- a/tests/xtro-sharpie/Helpers.cs +++ b/tests/xtro-sharpie/Helpers.cs @@ -247,5 +247,47 @@ public static string GetSelector (this ObjCMethodDecl self) { return self.Selector.ToString () ?? (self.IsPropertyAccessor ? self.Name : null); } + + public static bool IsObsolete (this ICustomAttributeProvider provider) + { + if (provider.HasCustomAttributes) { + foreach (var attrib in provider.CustomAttributes) { + var attribType = attrib.Constructor.DeclaringType; + if (attribType.Namespace == "System" && attribType.Name == "ObsoleteAttribute") + return true; + } + } + + // If we're a property accessor, check the property as well. + var prop = FindProperty (provider as MethodReference); + if (prop != null) + return IsObsolete (prop); + + return false; + } + + public static PropertyDefinition FindProperty (this MethodReference method) + { + var def = method?.Resolve (); + if (def == null) + return null; + + if (!def.IsSpecialName) + return null; + + if (!def.DeclaringType.HasProperties) + return null; + + if (!method.Name.StartsWith ("get_", StringComparison.Ordinal) && !method.Name.StartsWith ("set_", StringComparison.Ordinal)) + return null; + + var propName = method.Name.Substring (4); + foreach (var prop in def.DeclaringType.Properties) { + if (prop.Name == propName) + return prop; + } + + return null; + } } } \ No newline at end of file diff --git a/tests/xtro-sharpie/Runner.cs b/tests/xtro-sharpie/Runner.cs index ba556849b596..44fff6c68a72 100644 --- a/tests/xtro-sharpie/Runner.cs +++ b/tests/xtro-sharpie/Runner.cs @@ -25,6 +25,7 @@ public void Execute (string pchFile, IEnumerable assemblyNames) new ObjCInterfaceCheck (), new ObjCProtocolCheck (), new SelectorCheck (), + new SimdCheck (), // new ListNative (), // for debug }; foreach (var assemblyName in assemblyNames) { diff --git a/tests/xtro-sharpie/SimdCheck.cs b/tests/xtro-sharpie/SimdCheck.cs new file mode 100644 index 000000000000..f52485e7e602 --- /dev/null +++ b/tests/xtro-sharpie/SimdCheck.cs @@ -0,0 +1,382 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +using Mono.Cecil; + +using Clang.Ast; + +namespace Extrospection +{ + + class SimdCheck : BaseVisitor + { + bool very_strict = false; + bool strict = false; + + // A dictionary of native type -> managed type mapping. + class NativeSimdInfo + { + public string Managed; + public string InvalidManaged; + } + + static Dictionary type_mapping = new Dictionary () { + { "matrix_double2x2", new NativeSimdInfo { Managed ="MatrixDouble2x2", InvalidManaged = "Matrix2d" }}, + { "matrix_double3x3", new NativeSimdInfo { Managed = "MatrixDouble3x3", InvalidManaged = "Matrix3d" }}, + { "matrix_double4x4", new NativeSimdInfo { Managed = "MatrixDouble4x4", InvalidManaged = "Matrix4d" }}, + { "matrix_float2x2", new NativeSimdInfo { Managed = "MatrixFloat2x2", InvalidManaged = "Matrix2", }}, + { "matrix_float3x3", new NativeSimdInfo { Managed = "MatrixFloat3x3", InvalidManaged = "Matrix3", }}, + { "matrix_float4x3", new NativeSimdInfo { Managed = "MatrixFloat4x3", }}, + { "matrix_float4x4", new NativeSimdInfo { Managed = "MatrixFloat4x4", InvalidManaged = "Matrix4", }}, + { "simd_quatd", new NativeSimdInfo { Managed = "Quaternion4d", }}, + { "simd_quatf", new NativeSimdInfo { Managed = "Quaternion4", }}, + { "vector_double2", new NativeSimdInfo { Managed = "Vector2d", }}, + { "vector_double3", new NativeSimdInfo { Managed = "Vector3d", }}, + { "vector_double4", new NativeSimdInfo { Managed = "Vector4d", }}, + { "vector_float2", new NativeSimdInfo { Managed = "Vector2", }}, + { "vector_float3", new NativeSimdInfo { Managed = "Vector3", }}, + { "vector_float4", new NativeSimdInfo { Managed = "Vector4", }}, + { "vector_int2", new NativeSimdInfo { Managed = "Vector2i", }}, + { "vector_int3", new NativeSimdInfo { Managed = "Vector3i", }}, + { "vector_int4", new NativeSimdInfo { Managed = "Vector4i", }}, + { "vector_uint2", new NativeSimdInfo { Managed = "Vector2i", }}, + { "vector_uint3", new NativeSimdInfo { Managed = "Vector3i", }}, + { "vector_uint4", new NativeSimdInfo { Managed = "Vector4i", }}, + // simd_floatX is typedefed to vector_floatX + { "simd_float2", new NativeSimdInfo { Managed = "Vector2" }}, + { "simd_float3", new NativeSimdInfo { Managed = "Vector3" }}, + { "simd_float4", new NativeSimdInfo { Managed = "Vector4" }}, + { "simd_float4x4", new NativeSimdInfo { Managed = "MatrixFloat4x4", InvalidManaged = "Matrix4" }}, + // The native definition is two 'vector_float2' fields. + // The managed definition matches this (two 'Vector2' fields), and should work fine. + { "GKQuad", new NativeSimdInfo { Managed = "GKQuad" }}, + // The native definition is two 'vector_float3' fields. + // In this case each element uses 16 bytes (4 floats) due to padding. + // The managed definition is two Vector3 fields, and does *not* + // match the native definition (missing the padding). + // It still works because we're marshalling this struct manually ([MarshalDirective]). + { "GKBox", new NativeSimdInfo { Managed = "GKBox", }}, + // The native definition is 'vector_float3 points[3]' - an array of three vector_float3. + // In this case each element uses 16 bytes (4 floats) due to padding. + // The managed definition is just an array of Vector3, but luckily + // it's a private field, so we might be able to improve this later. Right now we're marshalling + // this struct manually ([MarshalDirective]), so managed code should get correct + // results. + { "GKTriangle", new NativeSimdInfo { Managed = "GKTriangle", }}, + // This is a 'vector_int4, represented by a Vector4i in managed code, + // which means it's matching the native definition. + { "MDLVoxelIndex", new NativeSimdInfo { Managed = "MDLVoxelIndex" }}, + // In managed code this is struct of two Vector4, so it's matching the native definition. + { "MDLVoxelIndexExtent", new NativeSimdInfo { Managed = "MDLVoxelIndexExtent" }}, + // In managed code this is a struct of two Vector3, so it's *not* matching + // the native definition. However, since we're manually marshalling this type + // (using [MarshalDirective]), managed code doesn't get incorrect results. + { "MDLAxisAlignedBoundingBox", new NativeSimdInfo { Managed = "MDLAxisAlignedBoundingBox", }}, + // The managed definition is identical to the native definition + { "MPSImageHistogramInfo", new NativeSimdInfo { Managed = "MPSImageHistogramInfo" }}, + }; + + static Dictionary managed_simd_types; // bool: invalid_for_simd + + static SimdCheck () + { + managed_simd_types = new Dictionary (); + foreach (var kvp in type_mapping) { + managed_simd_types [kvp.Value.Managed] = false; + if (!string.IsNullOrEmpty (kvp.Value.InvalidManaged)) + managed_simd_types [kvp.Value.InvalidManaged] = true; + } + } + + class ManagedSimdInfo + { + public MethodDefinition Method; + public bool ContainsInvalidMappingForSimd; + } + Dictionary managed_methods = new Dictionary (); + + public override void VisitManagedMethod (MethodDefinition method) + { + var type = method.DeclaringType; + + if (!type.IsNested && type.IsNotPublic) + return; + + if (type.IsNested && (type.IsNestedPrivate || type.IsNestedAssembly || type.IsNestedFamilyAndAssembly)) + return; + + if (method.IsPrivate || method.IsAssembly || method.IsFamilyAndAssembly) + return; // Don't care about non-visible types + + if (type.Namespace == "Simd" || type.Namespace.StartsWith ("OpenTK", StringComparison.Ordinal)) + return; // We're assuming everything in the Simd and OpenTK namespaces can be ignored (the former because it's correctly written, the latter because it doesn't map to native simd types). + + if (method.HasCustomAttributes && method.CustomAttributes.Where ((v) => v.Constructor.DeclaringType.Name == "ExtensionAttribute").Any ()) + return; // Extension methods can't be mapped. + + var invalid_simd_type = false; + var contains_simd_types = ContainsSimdTypes (method, ref invalid_simd_type); + + var key = method.GetName (); + if (key == null) { + if (method.IsObsolete ()) + return; // Don't care about obsolete API. + + if (contains_simd_types && very_strict) { + // We can't map this method to a native function. + Console.WriteLine ($"!simd-can't-map-managed! {method}"); + } + return; + } + + 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}'"); + } else { + managed_methods [key] = new ManagedSimdInfo { + Method = method, ContainsInvalidMappingForSimd = invalid_simd_type + }; + } + } + + bool ContainsSimdTypes (MethodDefinition method, ref bool invalid_for_simd) + { + if (IsSimdType (method.ReturnType, ref invalid_for_simd)) + return true; + + if (method.HasParameters) { + foreach (var param in method.Parameters) + if (IsSimdType (param.ParameterType, ref invalid_for_simd)) + return true; + } + + return false; + } + + bool IsSimdType (TypeReference td, ref bool invalid_for_simd) + { + return managed_simd_types.TryGetValue (td.Name, out invalid_for_simd); + } + + bool ContainsSimdTypes (ObjCMethodDecl decl, ref string simd_type, ref bool requires_marshal_directive) + { + if (IsSimdType (decl.ReturnQualType, ref simd_type, ref requires_marshal_directive)) + return true; + + var is_simd_type = false; + foreach (var param in decl.Parameters) + is_simd_type |= IsSimdType (param.QualType, ref simd_type, ref requires_marshal_directive); + + return is_simd_type; + } + + bool IsExtVector (QualType type, ref string simd_type) + { + var rv = false; + var t = type.CanonicalQualType.Type; + + // Unpoint the type + var pointerType = t as Clang.Ast.PointerType; + if (pointerType != null) + t = pointerType.PointeeQualType.Type; + + if (t.Kind == TypeKind.ExtVector) { + rv = true; + } else { + var r = (t as RecordType)?.Decl; + if (r != null) { + foreach (var f in r.Fields) { + var qt = f.QualType.CanonicalQualType.Type; + if (qt.Kind == TypeKind.ExtVector) { + rv = true; + break; + } + var at = qt as ConstantArrayType; + if (at != null) { + if (at.ElementType.Type.Kind == TypeKind.ExtVector) { + rv = true; + break; + } + } + } + } + } + + 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'."); + + if (rv) + simd_type = typeName; + + return rv; + } + + bool IsSimdType (QualType type, ref string simd_type, ref bool requires_marshal_directive) + { + var str = Undecorate (type.ToString ()); + + if (type_mapping.TryGetValue (str, out var info)) { + requires_marshal_directive = true; + simd_type = str; + return true; + } + + 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"); + + return false; + } + + string Undecorate (string native_name) + { + if (native_name.StartsWith ("const ", StringComparison.Ordinal)) + return Undecorate (native_name.Substring ("const ".Length)); + + if (native_name.StartsWith ("struct ", StringComparison.Ordinal)) + return Undecorate (native_name.Substring ("struct ".Length)); + + const string _Nonnull = " _Nonnull"; + if (native_name.EndsWith (_Nonnull, StringComparison.Ordinal)) + return Undecorate (native_name.Substring (0, native_name.Length - _Nonnull.Length)); + + const string _Nullable = " _Nullable"; + if (native_name.EndsWith (_Nullable, StringComparison.Ordinal)) + return Undecorate (native_name.Substring (0, native_name.Length - _Nullable.Length)); + + const string _star = " *"; + if (native_name.EndsWith (_star, StringComparison.Ordinal)) + return Undecorate (native_name.Substring (0, native_name.Length - _star.Length)); + + return native_name; + } + + bool HasMarshalDirective (ICustomAttributeProvider provider) + { + if (provider?.HasCustomAttributes != true) + return false; + + foreach (var ca in provider.CustomAttributes) + if (ca.Constructor.DeclaringType.Name == "MarshalDirective") + return true; + + return false; + } + + void CheckMarshalDirective (MethodDefinition method, string simd_type) + { + if (!method.HasBody) + return; + + // The [MarshalDirective] attribute isn't copied to the generated code, + // so instead apply some heuristics and detect calls to the xamarin_simd__ P/Invoke, + // and if there are any, then assume the method binding has a [MarshalDirective]. + var body = method.Body; + var anyCalls = false; + foreach (var i in body.Instructions) { + switch (i.OpCode.Code) { + case Mono.Cecil.Cil.Code.Call: + case Mono.Cecil.Cil.Code.Calli: + case Mono.Cecil.Cil.Code.Callvirt: + var mr = i.Operand as MethodReference; + if (mr != null) { + if (mr.Name.StartsWith ("xamarin_simd__", StringComparison.Ordinal)) + return; + if (mr.Name.StartsWith ("xamarin_vector_float3__", StringComparison.Ordinal)) + return; + } + anyCalls = true; + break; + default: + break; + } + } + + // If the method doesn't call anywhere, it can't be broken. + // For instance if the method just throws an exception. + if (!anyCalls) + return; + + Console.WriteLine ($"!simd-missing-marshaldirective! {method}: simd type: {simd_type}"); + } + + public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKind) + { + if (visitKind != VisitKind.Enter) + return; + + // don't process methods (or types) that are unavailable for the current platform + if (!decl.IsAvailable () || !(decl.DeclContext as Decl).IsAvailable ()) + return; + + var simd_type = string.Empty; + var requires_marshal_directive = false; + var native_simd = ContainsSimdTypes (decl, ref simd_type, ref requires_marshal_directive); + + ManagedSimdInfo info; + managed_methods.TryGetValue (decl.GetName (), out info); + var method = info?.Method; + + if (!native_simd) { + if (method != null) { + // The managed method uses types that were incorrectly used in place of the correct Simd types, + // but the native method doesn't use the native Simd types. This means the binding is correct. + } else { + // Neither the managed nor the native method have anything to do with Simd types. + } + return; + } + + if (method == null) { + // Could not map the native method to a managed method. + // This needs investigation, to see why the native method couldn't be mapped. + + // Check if this is new API, in which case it probably couldn't be mapped because we haven't bound it. + var is_new = false; + var attrs = decl.Attrs.ToList (); + var parentClass = decl.DeclContext as Decl; + if (parentClass != null) + attrs.AddRange (parentClass.Attrs); + + foreach (var attr in attrs) { + var av_attr = attr as AvailabilityAttr; + if (av_attr == null) + continue; + if (av_attr.Platform.Name != "ios") + continue; + if (av_attr.Introduced.Major >= 11) { + is_new = true; + break; + } + } + if (is_new && !very_strict) + 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."); + return; + } + + if (!info.ContainsInvalidMappingForSimd) { + // The managed method does not have any types that are incorrect for Simd. + if (requires_marshal_directive) + CheckMarshalDirective (method, simd_type); + return; + } + + if (method.IsObsolete ()) { + // We have a potentially broken managed method, but it's obsolete. That's fine. + return; + } + + if (requires_marshal_directive) + 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."); + } + } +} \ No newline at end of file diff --git a/tests/xtro-sharpie/common.ignore b/tests/xtro-sharpie/common.ignore index 9cd34f89a6cc..ac09bc6c59d9 100644 --- a/tests/xtro-sharpie/common.ignore +++ b/tests/xtro-sharpie/common.ignore @@ -1,3 +1,8 @@ +# ARKit + +## This method is manually bound. +!simd-missing-marshaldirective! System.IntPtr ARKit.ARPointCloud::GetRawPoints(): simd type: vector_float3 + # AVFoundation ## We only bind "finished" as we cannot use [Bind] here as it would break compatibility with iOS 6.x @@ -68,6 +73,10 @@ ## part of category GKScore_Deprecated !missing-selector! GKScore::playerID not bound +# GameplayKit + +# Bound as GKAgent3D.Rotation3x3 +!simd-can't-map-native! GKAgent3D::rotation: could not find a managed method (selector: name: GKAgent3D::. Found the simd type 'matrix_float3x3' in the native signature.' # Intents @@ -175,6 +184,38 @@ !incorrect-protocol-member! MDLMeshBufferZone::allocator is REQUIRED and should be abstract !incorrect-protocol-member! MDLMeshBufferZone::capacity is REQUIRED and should be abstract +## MDLTransformComponent is a protocol, which makes mapping non-trivial because the only place that has the required information is in the protocol's ProtocolMember attributes. + +## This selector does not have a fixed version with the correct +## Simd matrix, because it's a static member in a protocol, so creating an +## extension method doesn't make much sense. +!simd-can't-map-native! MDLTransformComponent::globalTransformWithObject:atTime:: could not find a managed method (selector: globalTransformWithObject:atTime: name: +MDLTransformComponent::globalTransformWithObject:atTime:. Found the simd type 'matrix_float4x4' in the native signature. + +## A Simd-fixed version exists as an extension method in the protocol interface (MDLTransformComponent_Extensions.GetLocalTransform4x4) +!simd-can't-map-native! MDLTransformComponent::localTransformAtTime:: could not find a managed method (selector: localTransformAtTime: name: MDLTransformComponent::localTransformAtTime:. Found the simd type 'matrix_float4x4' in the native signature. + +## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.GetMatrix4x4 +!simd-can't-map-native! MDLTransformComponent::matrix: could not find a managed method (selector: name: MDLTransformComponent::matrix. Found the simd type 'matrix_float4x4' in the native signature. + +## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.SetMatrix4x4 +!simd-can't-map-native! MDLTransformComponent::setMatrix:: could not find a managed method (selector: setMatrix: name: MDLTransformComponent::setMatrix:. Found the simd type 'matrix_float4x4' in the native signature. + +## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.SetLocalTransform +!simd-can't-map-native! MDLTransformComponent::setLocalTransform:: could not find a managed method (selector: setLocalTransform: name: MDLTransformComponent::setLocalTransform:. Found the simd type 'matrix_float4x4' in the native signature. + +## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.SetLocalTransform +!simd-can't-map-native! MDLTransformComponent::setLocalTransform:forTime:: could not find a managed method (selector: setLocalTransform:forTime: name: MDLTransformComponent::setLocalTransform:forTime:. Found the simd type 'matrix_float4x4' in the native signature. + +## All the MDLMesh constructors below are bound as internal functions. +!simd-can't-map-native! MDLMesh::initBoxWithExtent:segments:inwardNormals:geometryType:allocator:: could not find a managed method (selector: initBoxWithExtent:segments:inwardNormals:geometryType:allocator: name: Generators::initBoxWithExtent:segments:inwardNormals:geometryType:allocator:. Found the simd type 'vector_uint3' in the native signature. +!simd-can't-map-native! MDLMesh::initCapsuleWithExtent:cylinderSegments:hemisphereSegments:inwardNormals:geometryType:allocator:: could not find a managed method (selector: initCapsuleWithExtent:cylinderSegments:hemisphereSegments:inwardNormals:geometryType:allocator: name: Generators::initCapsuleWithExtent:cylinderSegments:hemisphereSegments:inwardNormals:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. +!simd-can't-map-native! MDLMesh::initConeWithExtent:segments:inwardNormals:cap:geometryType:allocator:: could not find a managed method (selector: initConeWithExtent:segments:inwardNormals:cap:geometryType:allocator: name: Generators::initConeWithExtent:segments:inwardNormals:cap:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. +!simd-can't-map-native! MDLMesh::initCylinderWithExtent:segments:inwardNormals:topCap:bottomCap:geometryType:allocator:: could not find a managed method (selector: initCylinderWithExtent:segments:inwardNormals:topCap:bottomCap:geometryType:allocator: name: Generators::initCylinderWithExtent:segments:inwardNormals:topCap:bottomCap:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. +!simd-can't-map-native! MDLMesh::initHemisphereWithExtent:segments:inwardNormals:cap:geometryType:allocator:: could not find a managed method (selector: initHemisphereWithExtent:segments:inwardNormals:cap:geometryType:allocator: name: Generators::initHemisphereWithExtent:segments:inwardNormals:cap:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. +!simd-can't-map-native! MDLMesh::initPlaneWithExtent:segments:geometryType:allocator:: could not find a managed method (selector: initPlaneWithExtent:segments:geometryType:allocator: name: Generators::initPlaneWithExtent:segments:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. +!simd-can't-map-native! MDLMesh::initSphereWithExtent:segments:inwardNormals:geometryType:allocator:: could not find a managed method (selector: initSphereWithExtent:segments:inwardNormals:geometryType:allocator: name: Generators::initSphereWithExtent:segments:inwardNormals:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. +!simd-can't-map-native! MDLMesh::newBoxWithDimensions:segments:geometryType:inwardNormals:allocator:: could not find a managed method (selector: newBoxWithDimensions:segments:geometryType:inwardNormals:allocator: name: +Generators::newBoxWithDimensions:segments:geometryType:inwardNormals:allocator:. Found the simd type 'vector_uint3' in the native signature. +!simd-can't-map-native! MDLMesh::newPlaneWithDimensions:segments:geometryType:allocator:: could not find a managed method (selector: newPlaneWithDimensions:segments:geometryType:allocator: name: +Generators::newPlaneWithDimensions:segments:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. # Security diff --git a/tests/xtro-sharpie/xtro-sharpie.csproj b/tests/xtro-sharpie/xtro-sharpie.csproj index 856440adb129..d4e3c4ad5a7a 100644 --- a/tests/xtro-sharpie/xtro-sharpie.csproj +++ b/tests/xtro-sharpie/xtro-sharpie.csproj @@ -71,6 +71,7 @@ + From 7647972e55f7037957da334e5872c44626aa196a Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 18 Aug 2017 17:28:48 +0200 Subject: [PATCH 02/17] [Simd] Add simd matrix types. 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 --- src/Simd/MatrixFloat2x2.cs | 146 ++++++++ src/Simd/MatrixFloat3x3.cs | 207 +++++++++++ src/Simd/MatrixFloat4x4.cs | 240 ++++++++++++ src/frameworks.sources | 3 + tests/monotouch-test/Asserts.cs | 205 +++++++++++ .../monotouch-test/Simd/MatrixFloat2x2Test.cs | 315 ++++++++++++++++ .../monotouch-test/Simd/MatrixFloat3x3Test.cs | 333 +++++++++++++++++ .../monotouch-test/Simd/MatrixFloat4x4Test.cs | 348 ++++++++++++++++++ tests/monotouch-test/monotouch-test.csproj | 4 + 9 files changed, 1801 insertions(+) create mode 100644 src/Simd/MatrixFloat2x2.cs create mode 100644 src/Simd/MatrixFloat3x3.cs create mode 100644 src/Simd/MatrixFloat4x4.cs create mode 100644 tests/monotouch-test/Simd/MatrixFloat2x2Test.cs create mode 100644 tests/monotouch-test/Simd/MatrixFloat3x3Test.cs create mode 100644 tests/monotouch-test/Simd/MatrixFloat4x4Test.cs diff --git a/src/Simd/MatrixFloat2x2.cs b/src/Simd/MatrixFloat2x2.cs new file mode 100644 index 000000000000..1057118d1ed5 --- /dev/null +++ b/src/Simd/MatrixFloat2x2.cs @@ -0,0 +1,146 @@ +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2017 Microsoft Inc +// + +// +// This represents the native matrix_float2x2 type, which has a column-major layout +// (as opposed to OpenTK.Matrix2, which has a row-major layout). +// + +using System; +using System.Runtime.InteropServices; + +using VectorFloat2=global::OpenTK.Vector2; + +namespace Simd +{ + [StructLayout (LayoutKind.Sequential)] + public struct MatrixFloat2x2 : IEquatable + { + public float M11; + public float M21; + public float M12; + public float M22; + + public readonly static MatrixFloat2x2 Identity = new MatrixFloat2x2 ( + 1, 0, + 0, 1); + + public MatrixFloat2x2 (VectorFloat2 column0, VectorFloat2 column1) + { + M11 = column0.X; + M21 = column0.Y; + M12 = column1.X; + M22 = column1.Y; + } + + public MatrixFloat2x2 ( + float m11, float m12, + float m21, float m22) + { + M11 = m11; + M21 = m21; + M12 = m12; + M22 = m22; + } + + public float Determinant { + get { + return M11 * M22 - M21 * M12; + } + } + + public void Transpose () + { + this = Transpose (this); + } + + public static MatrixFloat2x2 Transpose (MatrixFloat2x2 mat) + { + return new MatrixFloat2x2 (mat.M11, mat.M21, mat.M12, mat.M22); + } + + public static void Transpose (ref MatrixFloat2x2 mat, out MatrixFloat2x2 result) + { + result.M11 = mat.M11; + result.M12 = mat.M21; + result.M21 = mat.M12; + result.M22 = mat.M22; + } + + public static MatrixFloat2x2 Multiply (MatrixFloat2x2 left, MatrixFloat2x2 right) + { + MatrixFloat2x2 result; + Multiply (ref left, ref right, out result); + return result; + } + + public static void Multiply (ref MatrixFloat2x2 left, ref MatrixFloat2x2 right, out MatrixFloat2x2 result) + { + result.M11 = left.M11 * right.M11 + left.M12 * right.M21; + result.M12 = left.M11 * right.M12 + left.M12 * right.M22; + + result.M21 = left.M21 * right.M11 + left.M22 * right.M21; + result.M22 = left.M21 * right.M12 + left.M22 * right.M22; + } + + public static MatrixFloat2x2 operator * (MatrixFloat2x2 left, MatrixFloat2x2 right) + { + return Multiply (left, right); + } + + public static bool operator == (MatrixFloat2x2 left, MatrixFloat2x2 right) + { + return left.Equals (right); + } + + public static bool operator != (MatrixFloat2x2 left, MatrixFloat2x2 right) + { + return !left.Equals (right); + } + + public static explicit operator global::OpenTK.Matrix2 (MatrixFloat2x2 value) + { + return new global::OpenTK.Matrix2 ( + value.M11, value.M12, + value.M21, value.M22); + } + + public static explicit operator MatrixFloat2x2 (global::OpenTK.Matrix2 value) + { + return new MatrixFloat2x2 ( + value.R0C0, value.R0C1, + value.R1C0, value.R1C1); + } + + public override string ToString () + { + return $"({M11}, {M12})\n({M21}, {M22})"; + } + + public override int GetHashCode () + { + return M11.GetHashCode () ^ M12.GetHashCode () ^ M21.GetHashCode () ^ M22.GetHashCode (); + } + + public override bool Equals (object obj) + { + if (!(obj is MatrixFloat2x2)) + return false; + + return Equals ((MatrixFloat2x2) obj); + } + + public bool Equals (MatrixFloat2x2 other) + { + return + M11 == other.M11 && + M12 == other.M12 && + M21 == other.M21 && + M22 == other.M22; + } + } +} diff --git a/src/Simd/MatrixFloat3x3.cs b/src/Simd/MatrixFloat3x3.cs new file mode 100644 index 000000000000..74739b84398e --- /dev/null +++ b/src/Simd/MatrixFloat3x3.cs @@ -0,0 +1,207 @@ +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2017 Microsoft Inc +// + +// +// This represents the native matrix_float3x3 type, which has a column-major layout +// (as opposed to OpenTK.Matrix3, which has a row-major layout). +// + +using System; +using System.Runtime.InteropServices; + +using VectorFloat3=global::OpenTK.Vector3; + +namespace Simd +{ + [StructLayout (LayoutKind.Sequential)] + public struct MatrixFloat3x3 : IEquatable + { + /* Due to memory alignment, vectors of length 3 are + * represented as vectors of length 4, so we pad here + * with dummy fields. + * See top of /usr/include/simd/matrix_types.h for more information. */ + public float M11; + public float M21; + public float M31; + float dummy0; + public float M12; + public float M22; + public float M32; + float dummy1; + public float M13; + public float M23; + public float M33; + float dummy2; + + public readonly static MatrixFloat3x3 Identity = new MatrixFloat3x3 + { + M11 = 1f, + M22 = 1f, + M33 = 1f, + }; + + public MatrixFloat3x3 (VectorFloat3 column0, VectorFloat3 column1, VectorFloat3 column2) + { + M11 = column0.X; + M21 = column0.Y; + M31 = column0.Z; + M12 = column1.X; + M22 = column1.Y; + M32 = column1.Z; + M13 = column2.X; + M23 = column2.Y; + M33 = column2.Z; + dummy0 = 0; + dummy1 = 0; + dummy2 = 0; + } + + public MatrixFloat3x3 ( + float m11, float m12, float m13, + float m21, float m22, float m23, + float m31, float m32, float m33) + { + M11 = m11; + M21 = m21; + M31 = m31; + M12 = m12; + M22 = m22; + M32 = m32; + M13 = m13; + M23 = m23; + M33 = m33; + dummy0 = 0; + dummy1 = 0; + dummy2 = 0; + } + + public float Determinant { + get { + return + M11 * (M22 * M33 - M23 * M32) - + M12 * (M21 * M33 - M23 * M31) + + M13 * (M21 * M32 - M22 * M31); + } + } + + public void Transpose () + { + this = Transpose (this); + } + + public static MatrixFloat3x3 Transpose (MatrixFloat3x3 mat) + { + MatrixFloat3x3 result = new MatrixFloat3x3 (); + Transpose (ref mat, out result); + return result; + } + + public static void Transpose (ref MatrixFloat3x3 mat, out MatrixFloat3x3 result) + { + result.M11 = mat.M11; + result.M21 = mat.M12; + result.M31 = mat.M13; + result.M12 = mat.M21; + result.M22 = mat.M22; + result.M32 = mat.M23; + result.M13 = mat.M31; + result.M23 = mat.M32; + result.M33 = mat.M33; + result.dummy0 = 0; + result.dummy1 = 0; + result.dummy2 = 0; + } + + public static MatrixFloat3x3 Multiply (MatrixFloat3x3 left, MatrixFloat3x3 right) + { + MatrixFloat3x3 result; + Multiply (ref left, ref right, out result); + return result; + } + + public static void Multiply (ref MatrixFloat3x3 left, ref MatrixFloat3x3 right, out MatrixFloat3x3 result) + { + result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31; + result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32; + result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33; + result.dummy0 = 0; + + result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31; + result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32; + result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33; + result.dummy1 = 0; + + result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31; + result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32; + result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33; + result.dummy2 = 0; + } + + public static MatrixFloat3x3 operator * (MatrixFloat3x3 left, MatrixFloat3x3 right) + { + return Multiply (left, right); + } + + public static bool operator == (MatrixFloat3x3 left, MatrixFloat3x3 right) + { + return left.Equals (right); + } + + public static bool operator != (MatrixFloat3x3 left, MatrixFloat3x3 right) + { + return !left.Equals (right); + } + + public static explicit operator global::OpenTK.Matrix3 (MatrixFloat3x3 value) + { + return new global::OpenTK.Matrix3 ( + value.M11, value.M12, value.M13, + value.M21, value.M22, value.M23, + value.M31, value.M32, value.M33); + } + + public static explicit operator MatrixFloat3x3 (global::OpenTK.Matrix3 value) + { + return new MatrixFloat3x3 ( + value.R0C0, value.R0C1, value.R0C2, + value.R1C0, value.R1C1, value.R1C2, + value.R2C0, value.R2C1, value.R2C2); + } + + public override string ToString () + { + return + $"({M11}, {M12}, {M13})\n" + + $"({M21}, {M22}, {M23})\n" + + $"({M31}, {M32}, {M33})"; + } + + public override int GetHashCode () + { + return + M11.GetHashCode () ^ M12.GetHashCode () ^ M13.GetHashCode () ^ + M21.GetHashCode () ^ M22.GetHashCode () ^ M23.GetHashCode () ^ + M31.GetHashCode () ^ M32.GetHashCode () ^ M33.GetHashCode (); + } + + public override bool Equals (object obj) + { + if (!(obj is MatrixFloat3x3)) + return false; + + return Equals ((MatrixFloat3x3) obj); + } + + public bool Equals (MatrixFloat3x3 other) + { + return + M11 == other.M11 && M12 == other.M12 && M13 == other.M13 && + M21 == other.M21 && M22 == other.M22 && M23 == other.M23 && + M31 == other.M31 && M32 == other.M32 && M33 == other.M33; + } + } +} diff --git a/src/Simd/MatrixFloat4x4.cs b/src/Simd/MatrixFloat4x4.cs new file mode 100644 index 000000000000..b7ac7a548833 --- /dev/null +++ b/src/Simd/MatrixFloat4x4.cs @@ -0,0 +1,240 @@ +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright (c) 2017 Microsoft Inc +// + +// +// This represents the native matrix_float4x4 type, which has a column-major layout +// (as opposed to OpenTK.Matrix4, which has a row-major layout). +// + +using System; +using System.Runtime.InteropServices; + +using VectorFloat4=global::OpenTK.Vector4; + +namespace Simd +{ + [StructLayout (LayoutKind.Sequential)] + public struct MatrixFloat4x4 : IEquatable + { + public float M11; + public float M21; + public float M31; + public float M41; + + public float M12; + public float M22; + public float M32; + public float M42; + + public float M13; + public float M23; + public float M33; + public float M43; + + public float M14; + public float M24; + public float M34; + public float M44; + + public readonly static MatrixFloat4x4 Identity = new MatrixFloat4x4 { + M11 = 1f, + M22 = 1f, + M33 = 1f, + M44 = 1f, + }; + + public MatrixFloat4x4 (VectorFloat4 column0, VectorFloat4 column1, VectorFloat4 column2, VectorFloat4 column3) + { + M11 = column0.X; + M21 = column0.Y; + M31 = column0.Z; + M41 = column0.W; + M12 = column1.X; + M22 = column1.Y; + M32 = column1.Z; + M42 = column1.W; + M13 = column2.X; + M23 = column2.Y; + M33 = column2.Z; + M43 = column2.W; + M14 = column3.X; + M24 = column3.Y; + M34 = column3.Z; + M44 = column3.W; + } + + public MatrixFloat4x4 ( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44) + { + M11 = m11; + M21 = m21; + M31 = m31; + M41 = m41; + M12 = m12; + M22 = m22; + M32 = m32; + M42 = m42; + M13 = m13; + M23 = m23; + M33 = m33; + M43 = m43; + M14 = m14; + M24 = m24; + M34 = m34; + M44 = m44; + } + + public float Determinant { + get { + float a = M33 * M44 - M34 * M43; + float b = M32 * M44 - M34 * M42; + float c = M32 * M43 - M33 * M42; + float d = M31 * M44 - M34 * M41; + float e = M31 * M43 - M33 * M41; + float f = M31 * M42 - M32 * M41; + + return + M11 * (M22 * a - M23 * b + M24 * c) - + M12 * (M21 * a - M23 * d + M24 * e) + + M13 * (M21 * b - M22 * d + M24 * f) - + M14 * (M21 * c - M22 * e + M23 * f); + } + } + + public void Transpose () + { + this = Transpose (this); + } + + public static MatrixFloat4x4 Transpose (MatrixFloat4x4 mat) + { + MatrixFloat4x4 result; + Transpose (ref mat, out result); + return result; + } + + public static void Transpose (ref MatrixFloat4x4 mat, out MatrixFloat4x4 result) + { + result.M11 = mat.M11; + result.M21 = mat.M12; + result.M31 = mat.M13; + result.M41 = mat.M14; + + result.M12 = mat.M21; + result.M22 = mat.M22; + result.M32 = mat.M23; + result.M42 = mat.M24; + + result.M13 = mat.M31; + result.M23 = mat.M32; + result.M33 = mat.M33; + result.M43 = mat.M34; + + result.M14 = mat.M41; + result.M24 = mat.M42; + result.M34 = mat.M43; + result.M44 = mat.M44; + } + + public static MatrixFloat4x4 Multiply (MatrixFloat4x4 left, MatrixFloat4x4 right) + { + MatrixFloat4x4 result; + Multiply (ref left, ref right, out result); + return result; + } + + public static void Multiply (ref MatrixFloat4x4 left, ref MatrixFloat4x4 right, out MatrixFloat4x4 result) + { + result.M11 = left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31 + left.M14 * right.M41; + result.M12 = left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32 + left.M14 * right.M42; + result.M13 = left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33 + left.M14 * right.M43; + result.M14 = left.M11 * right.M14 + left.M12 * right.M24 + left.M13 * right.M34 + left.M14 * right.M44; + + result.M21 = left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31 + left.M24 * right.M41; + result.M22 = left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32 + left.M24 * right.M42; + result.M23 = left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33 + left.M24 * right.M43; + result.M24 = left.M21 * right.M14 + left.M22 * right.M24 + left.M23 * right.M34 + left.M24 * right.M44; + + result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31 + left.M34 * right.M41; + result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32 + left.M34 * right.M42; + result.M33 = left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33 + left.M34 * right.M43; + result.M34 = left.M31 * right.M14 + left.M32 * right.M24 + left.M33 * right.M34 + left.M34 * right.M44; + + result.M41 = left.M41 * right.M11 + left.M42 * right.M21 + left.M43 * right.M31 + left.M44 * right.M41; + result.M42 = left.M41 * right.M12 + left.M42 * right.M22 + left.M43 * right.M32 + left.M44 * right.M42; + result.M43 = left.M41 * right.M13 + left.M42 * right.M23 + left.M43 * right.M33 + left.M44 * right.M43; + result.M44 = left.M41 * right.M14 + left.M42 * right.M24 + left.M43 * right.M34 + left.M44 * right.M44; + } + + public static MatrixFloat4x4 operator * (MatrixFloat4x4 left, MatrixFloat4x4 right) + { + return Multiply (left, right); + } + + public static bool operator == (MatrixFloat4x4 left, MatrixFloat4x4 right) + { + return left.Equals (right); + } + + public static bool operator != (MatrixFloat4x4 left, MatrixFloat4x4 right) + { + return !left.Equals (right); + } + + public static explicit operator global::OpenTK.Matrix4 (MatrixFloat4x4 value) + { + return new global::OpenTK.Matrix4 ( + value.M11, value.M12, value.M13, value.M14, + value.M21, value.M22, value.M23, value.M24, + value.M31, value.M32, value.M33, value.M34, + value.M41, value.M42, value.M43, value.M44); + } + + public static explicit operator MatrixFloat4x4 (global::OpenTK.Matrix4 value) + { + return new MatrixFloat4x4 (value.Column0, value.Column1, value.Column2, value.Column3); + } + + public override string ToString () + { + return + $"({M11}, {M12}, {M13}, {M14})\n" + + $"({M21}, {M22}, {M23}, {M24})\n" + + $"({M31}, {M32}, {M33}, {M34})\n" + + $"({M41}, {M42}, {M43}, {M44})"; + } + + public override int GetHashCode () + { + return + M11.GetHashCode () ^ M12.GetHashCode () ^ M13.GetHashCode () ^ M14.GetHashCode () ^ + M21.GetHashCode () ^ M22.GetHashCode () ^ M23.GetHashCode () ^ M24.GetHashCode () ^ + M31.GetHashCode () ^ M32.GetHashCode () ^ M33.GetHashCode () ^ M34.GetHashCode () ^ + M41.GetHashCode () ^ M42.GetHashCode () ^ M43.GetHashCode () ^ M44.GetHashCode (); + } + + public override bool Equals (object obj) + { + if (!(obj is MatrixFloat4x4)) + return false; + + return Equals ((MatrixFloat4x4) obj); + } + + public bool Equals (MatrixFloat4x4 other) + { + return + M11 == other.M11 && M12 == other.M12 && M13 == other.M13 && M14 == other.M14 && + M21 == other.M21 && M22 == other.M22 && M23 == other.M23 && M24 == other.M24 && + M31 == other.M31 && M32 == other.M32 && M33 == other.M33 && M34 == other.M34 && + M41 == other.M41 && M42 == other.M42 && M43 == other.M43 && M44 == other.M44; + } + } +} diff --git a/src/frameworks.sources b/src/frameworks.sources index cbf27758b0a2..79c04ad310ef 100644 --- a/src/frameworks.sources +++ b/src/frameworks.sources @@ -1513,6 +1513,9 @@ SHARED_CORE_SOURCES = \ ObjCRuntime/Protocol.cs \ ObjCRuntime/Registrar.core.cs \ ObjCRuntime/Selector.cs \ + Simd/MatrixFloat2x2.cs \ + Simd/MatrixFloat3x3.cs \ + Simd/MatrixFloat4x4.cs \ SHARED_SOURCES = \ ../runtime/Delegates.generated.cs \ diff --git a/tests/monotouch-test/Asserts.cs b/tests/monotouch-test/Asserts.cs index 03ddbc8db012..147a05b1f891 100644 --- a/tests/monotouch-test/Asserts.cs +++ b/tests/monotouch-test/Asserts.cs @@ -10,6 +10,7 @@ using MonoTouch.ModelIO; #endif using OpenTK; +using Simd; using NUnit.Framework; public static class Asserts @@ -25,6 +26,11 @@ public static void AreEqual (float expected, float actual, string message) Assert.AreEqual (expected, actual, message + " (M)"); } + public static void AreEqual (float expected, float actual, float delta, string message) + { + Assert.AreEqual (expected, actual, delta, message); + } + public static void AreEqual (Vector2 expected, Vector2 actual, string message) { Assert.AreEqual (expected.X, actual.X, message + " (X)"); @@ -38,6 +44,13 @@ public static void AreEqual (Vector3 expected, Vector3 actual, string message) Assert.AreEqual (expected.Z, actual.Z, 0.001, message + " (Z)"); } + public static void AreEqual (Vector3 expected, Vector3 actual, float delta, string message) + { + Assert.AreEqual (expected.X, actual.X, delta, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, delta, message + " (Y)"); + Assert.AreEqual (expected.Z, actual.Z, delta, message + " (Z)"); + } + public static void AreEqual (Vector4 expected, Vector4 actual, string message) { Assert.AreEqual (expected.X, actual.X, message + " (X)"); @@ -46,6 +59,14 @@ public static void AreEqual (Vector4 expected, Vector4 actual, string message) Assert.AreEqual (expected.W, actual.W, message + " (W)"); } + public static void AreEqual (Vector4 expected, Vector4 actual, float delta, string message) + { + Assert.AreEqual (expected.X, actual.X, delta, message + " (X)"); + Assert.AreEqual (expected.Y, actual.Y, delta, message + " (Y)"); + Assert.AreEqual (expected.Z, actual.Z, delta, message + " (Z)"); + Assert.AreEqual (expected.W, actual.W, delta, message + " (W)"); + } + public static void AreEqual (Matrix2 expected, Matrix2 actual, string message) { AreEqual (expected.R0C0, actual.R0C0, message + " (R0C0)"); @@ -104,6 +125,190 @@ public static void AreEqual (MPSImageHistogramInfo expected, MPSImageHistogramIn Assert.AreEqual (expected.NumberOfHistogramEntries, actual.NumberOfHistogramEntries, message + " NumberOfHistogramEntries"); } #endif // !MONOMAC + + public static void AreEqual (MatrixFloat2x2 expected, MatrixFloat2x2 actual, string message) + { + AreEqual (expected.M11, actual.M11, message + " (M11)"); + AreEqual (expected.M21, actual.M21, message + " (M21)"); + AreEqual (expected.M12, actual.M12, message + " (M12)"); + AreEqual (expected.M22, actual.M22, message + " (M22)"); + } + + public static void AreEqual (MatrixFloat2x2 expected, MatrixFloat2x2 actual, float delta, string message) + { + AreEqual (expected.M11, actual.M11, delta, message + " (M11)"); + AreEqual (expected.M21, actual.M21, delta, message + " (M21)"); + AreEqual (expected.M12, actual.M12, delta, message + " (M12)"); + AreEqual (expected.M22, actual.M22, delta, message + " (M22)"); + } + + public static void AreEqual (Matrix2 expected, MatrixFloat2x2 actual, string message) + { + AreEqual (expected.R0C0, actual.M11, message + " (M11)"); + AreEqual (expected.R0C1, actual.M12, message + " (M12)"); + AreEqual (expected.R1C0, actual.M21, message + " (M21)"); + AreEqual (expected.R1C1, actual.M22, message + " (M22)"); + } + + public static void AreEqual (MatrixFloat2x2 expected, Matrix2 actual, string message) + { + AreEqual (expected.M11, actual.R0C0, message + " (M11)"); + AreEqual (expected.M12, actual.R0C1, message + " (M12)"); + AreEqual (expected.M21, actual.R1C0, message + " (M21)"); + AreEqual (expected.M22, actual.R1C1, message + " (M22)"); + } + + public static void AreEqual (MatrixFloat3x3 expected, MatrixFloat3x3 actual, string message) + { + AreEqual (expected.M11, actual.M11, message + " (M11)"); + AreEqual (expected.M21, actual.M21, message + " (M21)"); + AreEqual (expected.M31, actual.M31, message + " (M31)"); + AreEqual (expected.M12, actual.M12, message + " (M12)"); + AreEqual (expected.M22, actual.M22, message + " (M22)"); + AreEqual (expected.M32, actual.M32, message + " (M32)"); + AreEqual (expected.M13, actual.M13, message + " (M13)"); + AreEqual (expected.M23, actual.M23, message + " (M23)"); + AreEqual (expected.M33, actual.M33, message + " (M33)"); + } + + public static void AreEqual (MatrixFloat3x3 expected, MatrixFloat3x3 actual, float delta, string message) + { + AreEqual (expected.M11, actual.M11, delta, message + " (M11)"); + AreEqual (expected.M21, actual.M21, delta, message + " (M21)"); + AreEqual (expected.M31, actual.M31, delta, message + " (M31)"); + AreEqual (expected.M12, actual.M12, delta, message + " (M12)"); + AreEqual (expected.M22, actual.M22, delta, message + " (M22)"); + AreEqual (expected.M32, actual.M32, delta, message + " (M32)"); + AreEqual (expected.M13, actual.M13, delta, message + " (M13)"); + AreEqual (expected.M23, actual.M23, delta, message + " (M23)"); + AreEqual (expected.M33, actual.M33, delta, message + " (M33)"); + } + + public static void AreEqual (Matrix3 expected, MatrixFloat3x3 actual, string message) + { + AreEqual (expected.R0C0, actual.M11, message + " (M11)"); + AreEqual (expected.R0C1, actual.M12, message + " (M12)"); + AreEqual (expected.R0C2, actual.M13, message + " (M13)"); + AreEqual (expected.R1C0, actual.M21, message + " (M21)"); + AreEqual (expected.R1C1, actual.M22, message + " (M22)"); + AreEqual (expected.R1C2, actual.M23, message + " (M23)"); + AreEqual (expected.R2C0, actual.M31, message + " (M31)"); + AreEqual (expected.R2C1, actual.M32, message + " (M32)"); + AreEqual (expected.R2C2, actual.M33, message + " (M33)"); + } + + public static void AreEqual (MatrixFloat3x3 expected, Matrix3 actual, string message) + { + AreEqual (expected.M11, actual.R0C0, message + " (M11)"); + AreEqual (expected.M12, actual.R0C1, message + " (M12)"); + AreEqual (expected.M13, actual.R0C2, message + " (M13)"); + AreEqual (expected.M21, actual.R1C0, message + " (M21)"); + AreEqual (expected.M22, actual.R1C1, message + " (M22)"); + AreEqual (expected.M23, actual.R1C2, message + " (M23)"); + AreEqual (expected.M31, actual.R2C0, message + " (M31)"); + AreEqual (expected.M32, actual.R2C1, message + " (M32)"); + AreEqual (expected.M33, actual.R2C2, message + " (M33)"); + } + + public static void AreEqual (MatrixFloat4x4 expected, MatrixFloat4x4 actual, string message) + { + AreEqual (expected.M11, actual.M11, message + " (M11)"); + AreEqual (expected.M21, actual.M21, message + " (M21)"); + AreEqual (expected.M31, actual.M31, message + " (M31)"); + AreEqual (expected.M41, actual.M41, message + " (M41)"); + AreEqual (expected.M12, actual.M12, message + " (M12)"); + AreEqual (expected.M22, actual.M22, message + " (M22)"); + AreEqual (expected.M32, actual.M32, message + " (M32)"); + AreEqual (expected.M42, actual.M42, message + " (M42)"); + AreEqual (expected.M13, actual.M13, message + " (M13)"); + AreEqual (expected.M23, actual.M23, message + " (M23)"); + AreEqual (expected.M33, actual.M33, message + " (M33)"); + AreEqual (expected.M43, actual.M43, message + " (M43)"); + AreEqual (expected.M14, actual.M14, message + " (M14)"); + AreEqual (expected.M24, actual.M24, message + " (M24)"); + AreEqual (expected.M34, actual.M34, message + " (M34)"); + AreEqual (expected.M44, actual.M44, message + " (M44)"); + } + + public static void AreEqual (MatrixFloat4x4 expected, MatrixFloat4x4 actual, float delta, string message) + { + AreEqual (expected.M11, actual.M11, delta, message + " (M11)"); + AreEqual (expected.M21, actual.M21, delta, message + " (M21)"); + AreEqual (expected.M31, actual.M31, delta, message + " (M31)"); + AreEqual (expected.M41, actual.M41, delta, message + " (M41)"); + AreEqual (expected.M12, actual.M12, delta, message + " (M12)"); + AreEqual (expected.M22, actual.M22, delta, message + " (M22)"); + AreEqual (expected.M32, actual.M32, delta, message + " (M32)"); + AreEqual (expected.M42, actual.M42, delta, message + " (M42)"); + AreEqual (expected.M13, actual.M13, delta, message + " (M13)"); + AreEqual (expected.M23, actual.M23, delta, message + " (M23)"); + AreEqual (expected.M33, actual.M33, delta, message + " (M33)"); + AreEqual (expected.M43, actual.M43, delta, message + " (M43)"); + AreEqual (expected.M14, actual.M14, delta, message + " (M14)"); + AreEqual (expected.M24, actual.M24, delta, message + " (M24)"); + AreEqual (expected.M34, actual.M34, delta, message + " (M34)"); + AreEqual (expected.M44, actual.M44, delta, message + " (M44)"); + } + + public static void AreEqual (Matrix4 expected, MatrixFloat4x4 actual, string message) + { + AreEqual (expected.M11, actual.M11, message + " (M11)"); + AreEqual (expected.M21, actual.M21, message + " (M21)"); + AreEqual (expected.M31, actual.M31, message + " (M31)"); + AreEqual (expected.M41, actual.M41, message + " (M41)"); + AreEqual (expected.M12, actual.M12, message + " (M12)"); + AreEqual (expected.M22, actual.M22, message + " (M22)"); + AreEqual (expected.M32, actual.M32, message + " (M32)"); + AreEqual (expected.M42, actual.M42, message + " (M42)"); + AreEqual (expected.M13, actual.M13, message + " (M13)"); + AreEqual (expected.M23, actual.M23, message + " (M23)"); + AreEqual (expected.M33, actual.M33, message + " (M33)"); + AreEqual (expected.M43, actual.M43, message + " (M43)"); + AreEqual (expected.M14, actual.M14, message + " (M14)"); + AreEqual (expected.M24, actual.M24, message + " (M24)"); + AreEqual (expected.M34, actual.M34, message + " (M34)"); + AreEqual (expected.M44, actual.M44, message + " (M44)"); + } + + public static void AreEqual (Matrix4 expected, MatrixFloat4x4 actual, float delta, string message) + { + AreEqual (expected.M11, actual.M11, delta, message + " (M11)"); + AreEqual (expected.M21, actual.M21, delta, message + " (M21)"); + AreEqual (expected.M31, actual.M31, delta, message + " (M31)"); + AreEqual (expected.M41, actual.M41, delta, message + " (M41)"); + AreEqual (expected.M12, actual.M12, delta, message + " (M12)"); + AreEqual (expected.M22, actual.M22, delta, message + " (M22)"); + AreEqual (expected.M32, actual.M32, delta, message + " (M32)"); + AreEqual (expected.M42, actual.M42, delta, message + " (M42)"); + AreEqual (expected.M13, actual.M13, delta, message + " (M13)"); + AreEqual (expected.M23, actual.M23, delta, message + " (M23)"); + AreEqual (expected.M33, actual.M33, delta, message + " (M33)"); + AreEqual (expected.M43, actual.M43, delta, message + " (M43)"); + AreEqual (expected.M14, actual.M14, delta, message + " (M14)"); + AreEqual (expected.M24, actual.M24, delta, message + " (M24)"); + AreEqual (expected.M34, actual.M34, delta, message + " (M34)"); + AreEqual (expected.M44, actual.M44, delta, message + " (M44)"); + } + + public static void AreEqual (MatrixFloat4x4 expected, Matrix4 actual, string message) + { + AreEqual (expected.M11, actual.M11, message + " (M11)"); + AreEqual (expected.M21, actual.M21, message + " (M21)"); + AreEqual (expected.M31, actual.M31, message + " (M31)"); + AreEqual (expected.M41, actual.M41, message + " (M41)"); + AreEqual (expected.M12, actual.M12, message + " (M12)"); + AreEqual (expected.M22, actual.M22, message + " (M22)"); + AreEqual (expected.M32, actual.M32, message + " (M32)"); + AreEqual (expected.M42, actual.M42, message + " (M42)"); + AreEqual (expected.M13, actual.M13, message + " (M13)"); + AreEqual (expected.M23, actual.M23, message + " (M23)"); + AreEqual (expected.M33, actual.M33, message + " (M33)"); + AreEqual (expected.M43, actual.M43, message + " (M43)"); + AreEqual (expected.M14, actual.M14, message + " (M14)"); + AreEqual (expected.M24, actual.M24, message + " (M24)"); + AreEqual (expected.M34, actual.M34, message + " (M34)"); + AreEqual (expected.M44, actual.M44, message + " (M44)"); + } #endif // !__WATCHOS__ } diff --git a/tests/monotouch-test/Simd/MatrixFloat2x2Test.cs b/tests/monotouch-test/Simd/MatrixFloat2x2Test.cs new file mode 100644 index 000000000000..72bf6c71bc99 --- /dev/null +++ b/tests/monotouch-test/Simd/MatrixFloat2x2Test.cs @@ -0,0 +1,315 @@ + +using System; +using System.Diagnostics; + +using Foundation; +using ObjCRuntime; + +using OpenTK; +using Simd; + +using NUnit.Framework; + +namespace MonoTouchFixtures.Simd +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class MatrixFloat2x2Test + { + [Test] + public void Identity () + { + var identity = new MatrixFloat2x2 { + M11 = 1f, + M22 = 1f, + }; + Asserts.AreEqual (identity, MatrixFloat2x2.Identity, "identity"); + Asserts.AreEqual (Matrix2.Identity, MatrixFloat2x2.Identity, "opentk identity"); + } + + [Test] + public void ColumnConstructor () + { + var expected = GetTestMatrix (); + var actual = new MatrixFloat2x2 ( + new Vector2 (expected.R0C0, expected.R1C0), + new Vector2 (expected.R0C1, expected.R1C1) + ); + Asserts.AreEqual (expected, actual, "ctor 1"); + } + + [Test] + public void ElementConstructor () + { + var expected = GetTestMatrix (); + var actual = new MatrixFloat2x2 (expected.R0C0, expected.R0C1, + expected.R1C0, expected.R1C1); + Asserts.AreEqual (expected, actual, "ctor 1"); + + } + + [Test] + public void Determinant () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat2x2) expected; + Assert.AreEqual (expected.Determinant, actual.Determinant, 0.000001f, "determinant\n" + actual); + } + + [Test] + public void Elements () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat2x2) expected; + + Assert.AreEqual (expected.R0C0, actual.M11, "m11 getter"); + Assert.AreEqual (expected.R0C1, actual.M12, "m12 getter"); + Assert.AreEqual (expected.R1C0, actual.M21, "m21 getter"); + Assert.AreEqual (expected.R1C1, actual.M22, "m22 getter"); + + var newExpected = GetTestMatrix (); + actual.M11 = newExpected.R0C0; + actual.M12 = newExpected.R0C1; + actual.M21 = newExpected.R1C0; + actual.M22 = newExpected.R1C1; + Assert.AreEqual (newExpected.R0C0, actual.M11, "m11 setter"); + Assert.AreEqual (newExpected.R0C1, actual.M12, "m12 setter"); + Assert.AreEqual (newExpected.R1C0, actual.M21, "m21 setter"); + Assert.AreEqual (newExpected.R1C1, actual.M22, "m22 setter"); + } + + [Test] + public void TransposeInstance () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat2x2) expected; + + expected.Transpose (); + actual.Transpose (); + + Asserts.AreEqual (expected, actual, "transpose"); + } + + [Test] + public void TransposeStatic () + { + var input = GetTestMatrix (); + var inputSimd = (MatrixFloat2x2) input; + + Matrix2 expected; + Matrix2.Transpose (ref input, out expected); + var actual = MatrixFloat2x2.Transpose (inputSimd); + + Asserts.AreEqual (expected, actual, "transpose"); + + input = GetTestMatrix (); + inputSimd = (MatrixFloat2x2) input; + Matrix2.Transpose (ref input, out expected); + MatrixFloat2x2.Transpose (ref inputSimd, out actual); + Asserts.AreEqual (expected, actual, "transpose out/ref"); + } + + [Test] + public void TransposeStatic_ByRef () + { + var input = GetTestMatrix (); + var inputSimd = (MatrixFloat2x2) input; + + Matrix2 expected; + MatrixFloat2x2 actual; + + Matrix2.Transpose (ref input, out expected); + MatrixFloat2x2.Transpose (ref inputSimd, out actual); + Asserts.AreEqual (expected, actual, "transpose out/ref"); + } + + [Test] + public void Multiply () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat2x2) inputL; + var inputSimdR = (MatrixFloat2x2) inputR; + Matrix2 expected; + Matrix2.Multiply (ref inputR, ref inputL, out expected); // OpenTK.Matrix2 got left/right mixed up... + var actual = MatrixFloat2x2.Multiply (inputSimdL, inputSimdR); + + Asserts.AreEqual (expected, actual, "multiply"); + } + + [Test] + public void Multiply_ByRef () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat2x2) inputL; + var inputSimdR = (MatrixFloat2x2) inputR; + Matrix2 expected; + MatrixFloat2x2 actual; + + Matrix2.Multiply (ref inputR, ref inputL, out expected); // OpenTK.Matrix2 got left/right mixed up... + MatrixFloat2x2.Multiply (ref inputSimdL, ref inputSimdR, out actual); + + Asserts.AreEqual (expected, actual, "multiply"); + } + + + [Test] + public void Multiply_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat2x2) inputL; + var inputSimdR = (MatrixFloat2x2) inputR; + Matrix2 expected; + Matrix2.Multiply (ref inputR, ref inputL, out expected); // OpenTK.Matrix2 got left/right mixed up... + var actual = inputSimdL * inputSimdR; + + Asserts.AreEqual (expected, actual, "multiply"); + } + + [Test] + public void Equality_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat2x2) inputL; + var inputSimdR = (MatrixFloat2x2) inputR; + + // matrices are different + Assert.AreEqual (inputL.Equals (inputR), inputSimdL == inputSimdR, "inequality"); + Assert.IsFalse (inputL.Equals (inputR), "inequality 2 expected"); + Assert.IsFalse (inputSimdL == inputSimdR, "inequality 2 actual"); + + inputL = inputR; + inputSimdL = inputSimdR; + // matrices are identical + Assert.AreEqual (inputL.Equals (inputR), inputSimdL == inputSimdR, "equality"); + Assert.IsTrue (inputL.Equals (inputR), "equality 2 expected"); + Assert.IsTrue (inputSimdL == inputSimdR, "equality 2 actual"); + + Assert.IsTrue (MatrixFloat2x2.Identity == (MatrixFloat2x2) Matrix2.Identity, "identity equality"); + } + + [Test] + public void Inequality_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat2x2) inputL; + var inputSimdR = (MatrixFloat2x2) inputR; + + // matrices are different + Assert.AreEqual (!inputL.Equals (inputR), inputSimdL != inputSimdR, "inequality"); + Assert.IsTrue (!inputL.Equals (inputR), "inequality 2 expected"); + Assert.IsTrue (inputSimdL != inputSimdR, "inequality 2 actual"); + + inputL = inputR; + inputSimdL = inputSimdR; + // matrices are identical + Assert.AreEqual (!inputL.Equals (inputR), inputSimdL != inputSimdR, "equality"); + Assert.IsFalse (!inputL.Equals (inputR), "equality 2 expected"); + Assert.IsFalse (inputSimdL != inputSimdR, "equality 2 actual"); + + Assert.IsFalse (MatrixFloat2x2.Identity != (MatrixFloat2x2) Matrix2.Identity, "identity equality"); + } + + [Test] + public void Explicit_Operator_ToMatrix2 () + { + var expected = (MatrixFloat2x2) GetTestMatrix (); + var actual = (Matrix2) expected; + + Asserts.AreEqual (expected, actual, "tomatrix2"); + + actual = (Matrix2) MatrixFloat2x2.Identity; + Asserts.AreEqual (MatrixFloat2x2.Identity, actual, "tomatrix2 identity"); + Asserts.AreEqual (Matrix2.Identity, actual, "tomatrix2 identity2"); + } + + [Test] + public void Explicit_Operator_FromMatrix2 () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat2x2) expected; + + Asserts.AreEqual (expected, actual, "frommatrix2"); + + actual = (MatrixFloat2x2) Matrix2.Identity; + Asserts.AreEqual (MatrixFloat2x2.Identity, actual, "tomatrix2 identity"); + Asserts.AreEqual (Matrix2.Identity, actual, "tomatrix2 identity2"); + } + + [Test] + public void ToStringTest () + { + var actual = new MatrixFloat2x2 (1, 2, 3, 4); + + Assert.AreEqual ("(1, 2)\n(3, 4)", actual.ToString (), "tostring"); + } + + // GetHashCode doesn't have to be identical, so no need to test + + [Test] + public void Equals_Object () + { + var expectedA = GetTestMatrix (); + var expectedB = GetTestMatrix (); + var actualA = (MatrixFloat2x2) expectedA; + var actualB = (MatrixFloat2x2) expectedB; + + Assert.IsTrue (actualA.Equals ((object) actualA), "self"); + Assert.IsFalse (actualA.Equals ((object) actualB), "other"); + Assert.IsFalse (actualA.Equals (null), "null"); + Assert.IsFalse (actualA.Equals (expectedA), "other type"); + } + + [Test] + public void Equals_Matrix () + { + var expectedA = GetTestMatrix (); + var expectedB = GetTestMatrix (); + var actualA = (MatrixFloat2x2) expectedA; + var actualB = (MatrixFloat2x2) expectedB; + + Assert.IsTrue (actualA.Equals (actualA), "self"); + Assert.IsFalse (actualA.Equals (actualB), "other"); + } + + // A collection of test matrices. + // + // I initially tried randomly generating test matrices, but it turns out + // there are accumulative computational differences in the different algorithms + // between Matrix2 and MatrixFloat2x2. Since the differences are accumulative, + // I couldn't find a minimal sensible delta values when comparing + // matrices. + // + // So I just serialized a few matrices that were randomly generated, and + // these have been tested to not produce accumulative computational differences. + // + static Matrix2 [] test_matrices = new [] { + new Matrix2 (3, 5, 7, 11), + new Matrix2 (5, 7, 11, 13), + new Matrix2 (7, 11, 13, 17), + new Matrix2 (0.1532144f, 0.5451511f, 0.2004739f, 0.8351463f), + new Matrix2 (0.7717745f, 0.559364f, 0.00918373f, 0.6579159f), + new Matrix2 (0.2023053f, 0.4701468f, 0.6618567f, 0.7685714f), + new Matrix2 (9.799572E+08f, 1.64794E+09f, 1.117296E+09f, 1.239858E+09f), + new Matrix2 (1.102396E+09f, 3.082477E+08f, 1.126484E+09f, 5.022931E+08f), + new Matrix2 (2.263112E+08f, 8.79644E+08f, 1.303282E+09f, 1.654159E+09f), + new Matrix2 (0.4904693f, 0.841727f, 0.2294401f, 0.5736054f), + new Matrix2 (0.1252193f, 0.08986127f, 0.3407605f, 0.9144857f), + new Matrix2 (8.176959E+08f, 1.386156E+09f, 5.956444E+08f, 4.210506E+08f), + new Matrix2 (0.006755914f, 0.07464754f, 0.287938f, 0.3724834f), + }; + + static int counter; + internal static Matrix2 GetTestMatrix () + { + counter++; + if (counter == test_matrices.Length) + counter = 0; + return test_matrices [counter]; + } + } +} diff --git a/tests/monotouch-test/Simd/MatrixFloat3x3Test.cs b/tests/monotouch-test/Simd/MatrixFloat3x3Test.cs new file mode 100644 index 000000000000..ad936d48479a --- /dev/null +++ b/tests/monotouch-test/Simd/MatrixFloat3x3Test.cs @@ -0,0 +1,333 @@ + +using System; +using System.Diagnostics; + +using Foundation; +using ObjCRuntime; + +using OpenTK; +using Simd; + +using NUnit.Framework; + +namespace MonoTouchFixtures.Simd +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class MatrixFloat3x3Test + { + [Test] + public void Identity () + { + var identity = new MatrixFloat3x3 { + M11 = 1f, + M22 = 1f, + M33 = 1f, + }; + Asserts.AreEqual (identity, MatrixFloat3x3.Identity, "identity"); + Asserts.AreEqual (Matrix3.Identity, MatrixFloat3x3.Identity, "opentk identity"); + } + + [Test] + public void ColumnConstructor () + { + var expected = GetTestMatrix (); + var actual = new MatrixFloat3x3 ( + new Vector3 (expected.R0C0, expected.R1C0, expected.R2C0), + new Vector3 (expected.R0C1, expected.R1C1, expected.R2C1), + new Vector3 (expected.R0C2, expected.R1C2, expected.R2C2) + ); + Asserts.AreEqual (expected, actual, "ctor 1"); + } + + [Test] + public void ElementConstructor () + { + var expected = GetTestMatrix (); + var actual = new MatrixFloat3x3 (expected.R0C0, expected.R0C1, expected.R0C2, + expected.R1C0, expected.R1C1, expected.R1C2, + expected.R2C0, expected.R2C1, expected.R2C2); + Asserts.AreEqual (expected, actual, "ctor 1"); + + } + + [Test] + public void Determinant () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat3x3) expected; + Assert.AreEqual (expected.Determinant, actual.Determinant, 0.000001f, "determinant\n" + actual); + } + + [Test] + public void Elements () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat3x3) expected; + + Assert.AreEqual (expected.R0C0, actual.M11, "m11 getter"); + Assert.AreEqual (expected.R0C1, actual.M12, "m12 getter"); + Assert.AreEqual (expected.R0C2, actual.M13, "m13 getter"); + Assert.AreEqual (expected.R1C0, actual.M21, "m21 getter"); + Assert.AreEqual (expected.R1C1, actual.M22, "m22 getter"); + Assert.AreEqual (expected.R1C2, actual.M23, "m23 getter"); + Assert.AreEqual (expected.R2C0, actual.M31, "m31 getter"); + Assert.AreEqual (expected.R2C1, actual.M32, "m32 getter"); + Assert.AreEqual (expected.R2C2, actual.M33, "m33 getter"); + + var newExpected = GetTestMatrix (); + actual.M11 = newExpected.R0C0; + actual.M12 = newExpected.R0C1; + actual.M13 = newExpected.R0C2; + actual.M21 = newExpected.R1C0; + actual.M22 = newExpected.R1C1; + actual.M23 = newExpected.R1C2; + actual.M31 = newExpected.R2C0; + actual.M32 = newExpected.R2C1; + actual.M33 = newExpected.R2C2; + Assert.AreEqual (newExpected.R0C0, actual.M11, "m11 setter"); + Assert.AreEqual (newExpected.R0C1, actual.M12, "m12 setter"); + Assert.AreEqual (newExpected.R0C2, actual.M13, "m13 setter"); + Assert.AreEqual (newExpected.R1C0, actual.M21, "m21 setter"); + Assert.AreEqual (newExpected.R1C1, actual.M22, "m22 setter"); + Assert.AreEqual (newExpected.R1C2, actual.M23, "m23 setter"); + Assert.AreEqual (newExpected.R2C0, actual.M31, "m31 setter"); + Assert.AreEqual (newExpected.R2C1, actual.M32, "m32 setter"); + Assert.AreEqual (newExpected.R2C2, actual.M33, "m33 setter"); + } + + [Test] + public void TransposeInstance () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat3x3) expected; + + expected.Transpose (); + actual.Transpose (); + + Asserts.AreEqual (expected, actual, "transpose"); + } + + [Test] + public void TransposeStatic () + { + var input = GetTestMatrix (); + var inputSimd = (MatrixFloat3x3) input; + + Matrix3 expected; + Matrix3.Transpose (ref input, out expected); + var actual = MatrixFloat3x3.Transpose (inputSimd); + + Asserts.AreEqual (expected, actual, "transpose"); + + input = GetTestMatrix (); + inputSimd = (MatrixFloat3x3) input; + Matrix3.Transpose (ref input, out expected); + MatrixFloat3x3.Transpose (ref inputSimd, out actual); + Asserts.AreEqual (expected, actual, "transpose out/ref"); + } + + [Test] + public void TransposeStatic_ByRef () + { + var input = GetTestMatrix (); + var inputSimd = (MatrixFloat3x3) input; + + Matrix3 expected; + MatrixFloat3x3 actual; + + Matrix3.Transpose (ref input, out expected); + MatrixFloat3x3.Transpose (ref inputSimd, out actual); + Asserts.AreEqual (expected, actual, "transpose out/ref"); + } + + [Test] + public void Multiply () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat3x3) inputL; + var inputSimdR = (MatrixFloat3x3) inputR; + Matrix3 expected; + Matrix3.Multiply (ref inputR, ref inputL, out expected); // OpenTK.Matrix3 got left/right mixed up... + var actual = MatrixFloat3x3.Multiply (inputSimdL, inputSimdR); + + Asserts.AreEqual (expected, actual, "multiply"); + } + + [Test] + public void Multiply_ByRef () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat3x3) inputL; + var inputSimdR = (MatrixFloat3x3) inputR; + Matrix3 expected; + MatrixFloat3x3 actual; + + Matrix3.Multiply (ref inputR, ref inputL, out expected); // OpenTK.Matrix3 got left/right mixed up... + MatrixFloat3x3.Multiply (ref inputSimdL, ref inputSimdR, out actual); + + Asserts.AreEqual (expected, actual, "multiply"); + } + + + [Test] + public void Multiply_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat3x3) inputL; + var inputSimdR = (MatrixFloat3x3) inputR; + Matrix3 expected; + Matrix3.Multiply (ref inputR, ref inputL, out expected); // OpenTK.Matrix3 got left/right mixed up... + var actual = inputSimdL * inputSimdR; + + Asserts.AreEqual (expected, actual, "multiply"); + } + + [Test] + public void Equality_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat3x3) inputL; + var inputSimdR = (MatrixFloat3x3) inputR; + + // matrices are different + Assert.AreEqual (inputL.Equals (inputR), inputSimdL == inputSimdR, "inequality"); + Assert.IsFalse (inputL.Equals (inputR), "inequality 2 expected"); + Assert.IsFalse (inputSimdL == inputSimdR, "inequality 2 actual"); + + inputL = inputR; + inputSimdL = inputSimdR; + // matrices are identical + Assert.AreEqual (inputL.Equals (inputR), inputSimdL == inputSimdR, "equality"); + Assert.IsTrue (inputL.Equals (inputR), "equality 2 expected"); + Assert.IsTrue (inputSimdL == inputSimdR, "equality 2 actual"); + + Assert.IsTrue (MatrixFloat3x3.Identity == (MatrixFloat3x3) Matrix3.Identity, "identity equality"); + } + + [Test] + public void Inequality_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat3x3) inputL; + var inputSimdR = (MatrixFloat3x3) inputR; + + // matrices are different + Assert.AreEqual (!inputL.Equals (inputR), inputSimdL != inputSimdR, "inequality"); + Assert.IsTrue (!inputL.Equals (inputR), "inequality 2 expected"); + Assert.IsTrue (inputSimdL != inputSimdR, "inequality 2 actual"); + + inputL = inputR; + inputSimdL = inputSimdR; + // matrices are identical + Assert.AreEqual (!inputL.Equals (inputR), inputSimdL != inputSimdR, "equality"); + Assert.IsFalse (!inputL.Equals (inputR), "equality 2 expected"); + Assert.IsFalse (inputSimdL != inputSimdR, "equality 2 actual"); + + Assert.IsFalse (MatrixFloat3x3.Identity != (MatrixFloat3x3) Matrix3.Identity, "identity equality"); + } + + [Test] + public void Explicit_Operator_ToMatrix3 () + { + var expected = (MatrixFloat3x3) GetTestMatrix (); + var actual = (Matrix3) expected; + + Asserts.AreEqual (expected, actual, "tomatrix4"); + + actual = (Matrix3) MatrixFloat3x3.Identity; + Asserts.AreEqual (MatrixFloat3x3.Identity, actual, "tomatrix4 identity"); + Asserts.AreEqual (Matrix3.Identity, actual, "tomatrix4 identity2"); + } + + [Test] + public void Explicit_Operator_FromMatrix3 () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat3x3) expected; + + Asserts.AreEqual (expected, actual, "frommatrix4"); + + actual = (MatrixFloat3x3) Matrix3.Identity; + Asserts.AreEqual (MatrixFloat3x3.Identity, actual, "tomatrix4 identity"); + Asserts.AreEqual (Matrix3.Identity, actual, "tomatrix4 identity2"); + } + + [Test] + public void ToStringTest () + { + var actual = new MatrixFloat3x3 (1, 2, 3, 4, 5, 6, 7, 8, 9); + + Assert.AreEqual ("(1, 2, 3)\n(4, 5, 6)\n(7, 8, 9)", actual.ToString (), "tostring"); + } + + // GetHashCode doesn't have to be identical, so no need to test + + [Test] + public void Equals_Object () + { + var expectedA = GetTestMatrix (); + var expectedB = GetTestMatrix (); + var actualA = (MatrixFloat3x3) expectedA; + var actualB = (MatrixFloat3x3) expectedB; + + Assert.IsTrue (actualA.Equals ((object) actualA), "self"); + Assert.IsFalse (actualA.Equals ((object) actualB), "other"); + Assert.IsFalse (actualA.Equals (null), "null"); + Assert.IsFalse (actualA.Equals (expectedA), "other type"); + } + + [Test] + public void Equals_Matrix () + { + var expectedA = GetTestMatrix (); + var expectedB = GetTestMatrix (); + var actualA = (MatrixFloat3x3) expectedA; + var actualB = (MatrixFloat3x3) expectedB; + + Assert.IsTrue (actualA.Equals (actualA), "self"); + Assert.IsFalse (actualA.Equals (actualB), "other"); + } + + // A collection of test matrices. + // + // I initially tried randomly generating test matrices, but it turns out + // there are accumulative computational differences in the different algorithms + // between Matrix3 and MatrixFloat3x3. Since the differences are accumulative, + // I couldn't find a minimal sensible delta values when comparing + // matrices. + // + // So I just serialized a few matrices that were randomly generated, and + // these have been tested to not produce accumulative computational differences. + // + static Matrix3 [] test_matrices = new [] { + new Matrix3 (3, 5, 7, 11, 13, 17, 19, 23, 29), + new Matrix3 (5, 7, 11, 13, 17, 19, 23, 29, 31), + new Matrix3 (7, 11, 13, 17, 19, 23, 29, 31, 37), + new Matrix3 (0.1532144f, 0.5451511f, 0.2004739f, 0.8351463f, 0.9884372f, 0.1313103f, 0.3327205f, 0.01164342f, 0.6563147f), + new Matrix3 (0.7717745f, 0.559364f, 0.00918373f, 0.6579159f, 0.123461f, 0.9993145f, 0.5487496f, 0.2823398f, 0.9710717f), + new Matrix3 (0.2023053f, 0.4701468f, 0.6618567f, 0.7685714f, 0.8561344f, 0.009231919f, 0.6150167f, 0.7542298f, 0.550727f), + new Matrix3 (9.799572E+08f, 1.64794E+09f, 1.117296E+09f, 1.239858E+09f, 6.389504E+07f, 1.172175E+09f, 1.399567E+09f, 1.187143E+09f, 3.729208E+07f), + new Matrix3 (1.102396E+09f, 3.082477E+08f, 1.126484E+09f, 5.022931E+08f, 1.966322E+09f, 1.1814E+09f, 8.464673E+08f, 1.940651E+09f, 1.229937E+09f), + new Matrix3 (2.263112E+08f, 8.79644E+08f, 1.303282E+09f, 1.654159E+09f, 3.705524E+08f, 1.984941E+09f, 2.175935E+07f, 4.633518E+08f, 1.801243E+09f), + new Matrix3 (0.4904693f, 0.841727f, 0.2294401f, 0.5736054f, 0.5406881f, 0.2172498f, 0.1261143f, 0.6736677f, 0.4570194f), + new Matrix3 (0.1252193f, 0.08986127f, 0.3407605f, 0.9144857f, 0.340791f, 0.2192288f, 0.5144276f, 0.01813344f, 0.07687104f), + new Matrix3 (8.176959E+08f, 1.386156E+09f, 5.956444E+08f, 4.210506E+08f, 1.212676E+09f, 4.131035E+08f, 1.032453E+09f, 2.074689E+08f, 1.536594E+09f), + new Matrix3 (0.006755914f, 0.07464754f, 0.287938f, 0.3724834f, 0.1496783f, 0.6224982f, 0.7150125f, 0.5554719f, 0.4638171f), + }; + + static int counter; + internal static Matrix3 GetTestMatrix () + { + counter++; + if (counter == test_matrices.Length) + counter = 0; + return test_matrices [counter]; + } + } +} diff --git a/tests/monotouch-test/Simd/MatrixFloat4x4Test.cs b/tests/monotouch-test/Simd/MatrixFloat4x4Test.cs new file mode 100644 index 000000000000..c0f351af14e0 --- /dev/null +++ b/tests/monotouch-test/Simd/MatrixFloat4x4Test.cs @@ -0,0 +1,348 @@ + +using System; +using System.Diagnostics; + +using Foundation; +using ObjCRuntime; + +using OpenTK; +using Simd; + +using NUnit.Framework; + +namespace MonoTouchFixtures.Simd +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class MatrixFloat4x4Test + { + [Test] + public void Identity () + { + var identity = new MatrixFloat4x4 { + M11 = 1f, + M22 = 1f, + M33 = 1f, + M44 = 1f, + }; + Asserts.AreEqual (identity, MatrixFloat4x4.Identity, "identity"); + Asserts.AreEqual (Matrix4.Identity, MatrixFloat4x4.Identity, "opentk identity"); + } + + [Test] + public void ColumnConstructor () + { + var expected = GetTestMatrix (); + var actual = new MatrixFloat4x4 (expected.Column0, expected.Column1, expected.Column2, expected.Column3); + Asserts.AreEqual (expected, actual, "ctor 1"); + } + + [Test] + public void ElementConstructor () + { + var expected = GetTestMatrix (); + var actual = new MatrixFloat4x4 (expected.M11, expected.M12, expected.M13, expected.M14, + expected.M21, expected.M22, expected.M23, expected.M24, + expected.M31, expected.M32, expected.M33, expected.M34, + expected.M41, expected.M42, expected.M43, expected.M44); + Asserts.AreEqual (expected, actual, "ctor 1"); + + } + + [Test] + public void Determinant () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat4x4) expected; + Assert.AreEqual (expected.Determinant, actual.Determinant, 0.000001f, "determinant\n" + actual); + + } + + [Test] + public void Elements () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat4x4) expected; + + Assert.AreEqual (expected.M11, actual.M11, "m11 getter"); + Assert.AreEqual (expected.M12, actual.M12, "m12 getter"); + Assert.AreEqual (expected.M13, actual.M13, "m13 getter"); + Assert.AreEqual (expected.M14, actual.M14, "m14 getter"); + Assert.AreEqual (expected.M21, actual.M21, "m21 getter"); + Assert.AreEqual (expected.M22, actual.M22, "m22 getter"); + Assert.AreEqual (expected.M23, actual.M23, "m23 getter"); + Assert.AreEqual (expected.M24, actual.M24, "m24 getter"); + Assert.AreEqual (expected.M31, actual.M31, "m31 getter"); + Assert.AreEqual (expected.M32, actual.M32, "m32 getter"); + Assert.AreEqual (expected.M33, actual.M33, "m33 getter"); + Assert.AreEqual (expected.M34, actual.M34, "m34 getter"); + Assert.AreEqual (expected.M41, actual.M41, "m41 getter"); + Assert.AreEqual (expected.M42, actual.M42, "m42 getter"); + Assert.AreEqual (expected.M43, actual.M43, "m43 getter"); + Assert.AreEqual (expected.M44, actual.M44, "m44 getter"); + + var newExpected = GetTestMatrix (); + actual.M11 = newExpected.M11; + actual.M12 = newExpected.M12; + actual.M13 = newExpected.M13; + actual.M14 = newExpected.M14; + actual.M21 = newExpected.M21; + actual.M22 = newExpected.M22; + actual.M23 = newExpected.M23; + actual.M24 = newExpected.M24; + actual.M31 = newExpected.M31; + actual.M32 = newExpected.M32; + actual.M33 = newExpected.M33; + actual.M34 = newExpected.M34; + actual.M41 = newExpected.M41; + actual.M42 = newExpected.M42; + actual.M43 = newExpected.M43; + actual.M44 = newExpected.M44; + Assert.AreEqual (newExpected.M11, actual.M11, "m11 setter"); + Assert.AreEqual (newExpected.M12, actual.M12, "m12 setter"); + Assert.AreEqual (newExpected.M13, actual.M13, "m13 setter"); + Assert.AreEqual (newExpected.M14, actual.M14, "m14 setter"); + Assert.AreEqual (newExpected.M21, actual.M21, "m21 setter"); + Assert.AreEqual (newExpected.M22, actual.M22, "m22 setter"); + Assert.AreEqual (newExpected.M23, actual.M23, "m23 setter"); + Assert.AreEqual (newExpected.M24, actual.M24, "m24 setter"); + Assert.AreEqual (newExpected.M31, actual.M31, "m31 setter"); + Assert.AreEqual (newExpected.M32, actual.M32, "m32 setter"); + Assert.AreEqual (newExpected.M33, actual.M33, "m33 setter"); + Assert.AreEqual (newExpected.M34, actual.M34, "m34 setter"); + Assert.AreEqual (newExpected.M41, actual.M41, "m41 setter"); + Assert.AreEqual (newExpected.M42, actual.M42, "m42 setter"); + Assert.AreEqual (newExpected.M43, actual.M43, "m43 setter"); + Assert.AreEqual (newExpected.M44, actual.M44, "m44 setter"); + } + + [Test] + public void TransposeInstance () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat4x4) expected; + + expected.Transpose (); + actual.Transpose (); + + Asserts.AreEqual (expected, actual, "transpose"); + } + + [Test] + public void TransposeStatic () + { + var input = GetTestMatrix (); + var inputSimd = (MatrixFloat4x4) input; + + var expected = Matrix4.Transpose (input); + var actual = MatrixFloat4x4.Transpose (inputSimd); + + Asserts.AreEqual (expected, actual, "transpose"); + + input = GetTestMatrix (); + inputSimd = (MatrixFloat4x4) input; + Matrix4.Transpose (ref input, out expected); + MatrixFloat4x4.Transpose (ref inputSimd, out actual); + Asserts.AreEqual (expected, actual, "transpose out/ref"); + } + + [Test] + public void TransposeStatic_ByRef () + { + var input = GetTestMatrix (); + var inputSimd = (MatrixFloat4x4) input; + + Matrix4 expected; + MatrixFloat4x4 actual; + + Matrix4.Transpose (ref input, out expected); + MatrixFloat4x4.Transpose (ref inputSimd, out actual); + Asserts.AreEqual (expected, actual, "transpose out/ref"); + } + + [Test] + public void Multiply () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat4x4) inputL; + var inputSimdR = (MatrixFloat4x4) inputR; + var expected = Matrix4.Mult (inputL, inputR); + var actual = MatrixFloat4x4.Multiply (inputSimdL, inputSimdR); + + Asserts.AreEqual (expected, actual, "multiply"); + } + + [Test] + public void Multiply_ByRef () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat4x4) inputL; + var inputSimdR = (MatrixFloat4x4) inputR; + Matrix4 expected; + MatrixFloat4x4 actual; + + Matrix4.Mult (ref inputL, ref inputR, out expected); + MatrixFloat4x4.Multiply (ref inputSimdL, ref inputSimdR, out actual); + + Asserts.AreEqual (expected, actual, "multiply"); + } + + + [Test] + public void Multiply_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat4x4) inputL; + var inputSimdR = (MatrixFloat4x4) inputR; + var expected = inputL * inputR; + var actual = inputSimdL * inputSimdR; + + Asserts.AreEqual (expected, actual, "multiply"); + } + + [Test] + public void Equality_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat4x4) inputL; + var inputSimdR = (MatrixFloat4x4) inputR; + + // matrices are different + Assert.AreEqual (inputL == inputR, inputSimdL == inputSimdR, "inequality"); + Assert.IsFalse (inputL == inputR, "inequality 2 expected"); + Assert.IsFalse (inputSimdL == inputSimdR, "inequality 2 actual"); + + inputL = inputR; + inputSimdL = inputSimdR; + // matrices are identical + Assert.AreEqual (inputL == inputR, inputSimdL == inputSimdR, "equality"); + Assert.IsTrue (inputL == inputR, "equality 2 expected"); + Assert.IsTrue (inputSimdL == inputSimdR, "equality 2 actual"); + + Assert.IsTrue (MatrixFloat4x4.Identity == (MatrixFloat4x4) Matrix4.Identity, "identity equality"); + } + + [Test] + public void Inequality_Operator () + { + var inputL = GetTestMatrix (); + var inputR = GetTestMatrix (); + var inputSimdL = (MatrixFloat4x4) inputL; + var inputSimdR = (MatrixFloat4x4) inputR; + + // matrices are different + Assert.AreEqual (inputL != inputR, inputSimdL != inputSimdR, "inequality"); + Assert.IsTrue (inputL != inputR, "inequality 2 expected"); + Assert.IsTrue (inputSimdL != inputSimdR, "inequality 2 actual"); + + inputL = inputR; + inputSimdL = inputSimdR; + // matrices are identical + Assert.AreEqual (inputL != inputR, inputSimdL != inputSimdR, "equality"); + Assert.IsFalse (inputL != inputR, "equality 2 expected"); + Assert.IsFalse (inputSimdL != inputSimdR, "equality 2 actual"); + + Assert.IsFalse (MatrixFloat4x4.Identity != (MatrixFloat4x4) Matrix4.Identity, "identity equality"); + } + + [Test] + public void Explicit_Operator_ToMatrix4 () + { + var expected = (MatrixFloat4x4) GetTestMatrix (); + var actual = (Matrix4) expected; + + Asserts.AreEqual (expected, actual, "tomatrix4"); + + actual = (Matrix4) MatrixFloat4x4.Identity; + Asserts.AreEqual (MatrixFloat4x4.Identity, actual, "tomatrix4 identity"); + Asserts.AreEqual (Matrix4.Identity, actual, "tomatrix4 identity2"); + } + + [Test] + public void Explicit_Operator_FromMatrix4 () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat4x4) expected; + + Asserts.AreEqual (expected, actual, "frommatrix4"); + + actual = (MatrixFloat4x4) Matrix4.Identity; + Asserts.AreEqual (MatrixFloat4x4.Identity, actual, "tomatrix4 identity"); + Asserts.AreEqual (Matrix4.Identity, actual, "tomatrix4 identity2"); + } + + [Test] + public void ToStringTest () + { + var expected = GetTestMatrix (); + var actual = (MatrixFloat4x4) expected; + + Assert.AreEqual (expected.ToString (), actual.ToString (), "tostring"); + } + + // GetHashCode doesn't have to be identical, so no need to test + + [Test] + public void Equals_Object () + { + var expectedA = GetTestMatrix (); + var expectedB = GetTestMatrix (); + var actualA = (MatrixFloat4x4) expectedA; + var actualB = (MatrixFloat4x4) expectedB; + + Assert.IsTrue (actualA.Equals ((object) actualA), "self"); + Assert.IsFalse (actualA.Equals ((object) actualB), "other"); + Assert.IsFalse (actualA.Equals (null), "null"); + Assert.IsFalse (actualA.Equals (expectedA), "other type"); + } + + [Test] + public void Equals_Matrix () + { + var expectedA = GetTestMatrix (); + var expectedB = GetTestMatrix (); + var actualA = (MatrixFloat4x4) expectedA; + var actualB = (MatrixFloat4x4) expectedB; + + Assert.IsTrue (actualA.Equals (actualA), "self"); + Assert.IsFalse (actualA.Equals (actualB), "other"); + } + + // A collection of test matrices. + // + // I initially tried randomly generating test matrices, but it turns out + // there are accumulative computational differences in the different algorithms + // between Matrix4 and MatrixFloat4x4. Since the differences are accumulative, + // I couldn't find a minimal sensible delta values when comparing + // matrices. + // + // So I just serialized a few matrices that were randomly generated, and + // these have been tested to not produce accumulative computational differences. + // + static Matrix4 [] test_matrices = new [] { + new Matrix4 (0.1532144f, 0.5451511f, 0.2004739f, 0.8351463f, 0.9884372f, 0.1313103f, 0.3327205f, 0.01164342f, 0.6563147f, 0.7923161f, 0.6764754f, 0.07481737f, 0.03239552f, 0.7156482f, 0.6136858f, 0.1864168f), + new Matrix4 (0.7717745f, 0.559364f, 0.00918373f, 0.6579159f, 0.123461f, 0.9993145f, 0.5487496f, 0.2823398f, 0.9710717f, 0.8750508f, 0.472472f, 0.2608089f, 0.5771761f, 0.5617125f, 0.176998f, 0.1271691f), + new Matrix4 (0.2023053f, 0.4701468f, 0.6618567f, 0.7685714f, 0.8561344f, 0.009231919f, 0.6150167f, 0.7542298f, 0.550727f, 0.3625788f, 0.6639862f, 0.5763468f, 0.9717328f, 0.003812184f, 0.985266f, 0.7540002f), + new Matrix4 (9.799572E+08f, 1.64794E+09f, 1.117296E+09f, 1.239858E+09f, 6.389504E+07f, 1.172175E+09f, 1.399567E+09f, 1.187143E+09f, 3.729208E+07f, 5.50313E+08f, 1.847369E+09f, 1.612405E+09f, 1.699488E+08f, 4.952176E+08f, 1.07262E+09f, 2.035059E+09f), + new Matrix4 (1.102396E+09f, 3.082477E+08f, 1.126484E+09f, 5.022931E+08f, 1.966322E+09f, 1.1814E+09f, 8.464673E+08f, 1.940651E+09f, 1.229937E+09f, 1.367379E+09f, 1.900015E+09f, 1.516109E+09f, 2.146064E+09f, 1.870971E+09f, 1.046267E+09f, 1.088363E+09f), + new Matrix4 (2.263112E+08f, 8.79644E+08f, 1.303282E+09f, 1.654159E+09f, 3.705524E+08f, 1.984941E+09f, 2.175935E+07f, 4.633518E+08f, 1.801243E+09f, 1.616996E+09f, 1.620852E+09f, 7291498f, 1.012728E+09f, 2.834145E+08f, 3.5328E+08f, 1.35012E+09f), + new Matrix4 (0.4904693f, 0.841727f, 0.2294401f, 0.5736054f, 0.5406881f, 0.2172498f, 0.1261143f, 0.6736677f, 0.4570194f, 0.9091009f, 0.7669608f, 0.8468134f, 0.01802658f, 0.3850208f, 0.3730424f, 0.2440258f), + new Matrix4 (0.1252193f, 0.08986127f, 0.3407605f, 0.9144857f, 0.340791f, 0.2192288f, 0.5144276f, 0.01813344f, 0.07687104f, 0.7971596f, 0.6393988f, 0.9002907f, 0.1011457f, 0.5047605f, 0.7202546f, 0.07729452f), + new Matrix4 (8.176959E+08f, 1.386156E+09f, 5.956444E+08f, 4.210506E+08f, 1.212676E+09f, 4.131035E+08f, 1.032453E+09f, 2.074689E+08f, 1.536594E+09f, 3.266183E+07f, 5.222072E+08f, 7.923175E+08f, 1.762531E+09f, 7.901702E+08f, 8.1975E+08f, 1.630734E+09f), + new Matrix4 (0.006755914f, 0.07464754f, 0.287938f, 0.3724834f, 0.1496783f, 0.6224982f, 0.7150125f, 0.5554719f, 0.4638171f, 0.4200902f, 0.4867154f, 0.773377f, 0.3558737f, 0.4043404f, 0.04670618f, 0.7695189f), + }; + + static int counter; + internal static Matrix4 GetTestMatrix () + { + counter++; + if (counter == test_matrices.Length) + counter = 0; + return test_matrices [counter]; + } + } +} diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj index e6566b55b1c7..4913bb144c84 100644 --- a/tests/monotouch-test/monotouch-test.csproj +++ b/tests/monotouch-test/monotouch-test.csproj @@ -647,6 +647,9 @@ + + + @@ -718,6 +721,7 @@ + From 6e96f1d56b8b9d787e8d0b1d19c974071bcceed4 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 12:15:10 +0200 Subject: [PATCH 03/17] [ARKit] Use the new Simd matrix types. --- runtime/bindings-generator.cs | 107 ++++++++++++++++++++++++++++++++++ runtime/bindings.h | 8 +++ src/arkit.cs | 4 +- 3 files changed, 117 insertions(+), 2 deletions(-) diff --git a/runtime/bindings-generator.cs b/runtime/bindings-generator.cs index 6fdde04a0d9a..72b29b9451d5 100644 --- a/runtime/bindings-generator.cs +++ b/runtime/bindings-generator.cs @@ -2004,6 +2004,18 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // IntPtr func (MatrixFloat3x3)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.MatrixFloat3x3 }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // MDLVoxelIndexExtent2 func ()", @@ -2013,6 +2025,15 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // MatrixFloat3x3 func ()", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat3x3, + } + ); + data.Add ( new FunctionData { Comment = " // void func (MDLVoxelIndexExtent2)", @@ -2020,6 +2041,18 @@ static IEnumerable GetFunctionData () Variants = Variants.NonStret, Parameters = new ParameterData [] { new ParameterData { TypeData = Types.MDLVoxelIndexExtent2 }, + } + } + ); + + data.Add ( + new FunctionData { + Comment = " // IntPtr func (MatrixFloat4x4)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData[] { + new ParameterData { TypeData = Types.MatrixFloat4x4 }, }, } ); @@ -2036,6 +2069,58 @@ static IEnumerable GetFunctionData () } ); + + data.Add ( + new FunctionData { + Comment = " // MatrixFloat4x4 func ()", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat4x4, + } + ); + + data.Add ( + new FunctionData { + Comment = " // MatrixFloat4x4 func (int, CGSize, nfloat, nfloat)", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat4x4, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.Int32 }, + new ParameterData { TypeData = Types.CGSize }, + new ParameterData { TypeData = Types.NFloat }, + new ParameterData { TypeData = Types.NFloat }, + }, + } + ); + + data.Add ( + new FunctionData { + Comment = " // MatrixFloat4x4 func (Int64, CGSize, nfloat, nfloat)", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat4x4, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.Int64 }, + new ParameterData { TypeData = Types.CGSize }, + new ParameterData { TypeData = Types.NFloat }, + new ParameterData { TypeData = Types.NFloat }, + }, + } + ); + + data.Add ( + new FunctionData { + Comment = " // MatrixFloat4x4 func (nint)", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat4x4, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.NInt }, + }, + } + ); + // We must expand functions with native types to their actual type as well. for (int i = data.Count - 1; i >= 0; i--) { if (!data [i].HasNativeType) @@ -2093,6 +2178,7 @@ static void MarshalToManaged (StringWriter writer, TypeData type, string nativeV writer.WriteLine ("\t}"); break; case "Matrix3": + case "MatrixFloat3x3": writer.WriteLine ("\tfor (int i = 0; i < 3; i++) {"); writer.WriteLine ("\t\t{0}{2}columns [i].a = {1}.columns [i] [0];", managedVariable, nativeVariable, accessor); writer.WriteLine ("\t\t{0}{2}columns [i].b = {1}.columns [i] [1];", managedVariable, nativeVariable, accessor); @@ -2100,6 +2186,7 @@ static void MarshalToManaged (StringWriter writer, TypeData type, string nativeV writer.WriteLine ("\t}"); break; case "Matrix4": + case "MatrixFloat4x4": writer.WriteLine ("\tfor (int i = 0; i < 4; i++) {"); writer.WriteLine ("\t\t{0}{2}columns [i].a = {1}.columns [i] [0];", managedVariable, nativeVariable, accessor); writer.WriteLine ("\t\t{0}{2}columns [i].b = {1}.columns [i] [1];", managedVariable, nativeVariable, accessor); @@ -2209,6 +2296,7 @@ static void MarshalToNative (StringWriter writer, TypeData type, string nativeVa writer.WriteLine ("\t}"); break; case "Matrix3": + case "MatrixFloat3x3": writer.WriteLine ("\tfor (int i = 0; i < 3; i++) {"); writer.WriteLine ("\t\t{0}.columns [i][0] = {1}{2}columns [i].a;", nativeVariable, managedVariable, accessor); writer.WriteLine ("\t\t{0}.columns [i][1] = {1}{2}columns [i].b;", nativeVariable, managedVariable, accessor); @@ -2216,6 +2304,7 @@ static void MarshalToNative (StringWriter writer, TypeData type, string nativeVa writer.WriteLine ("\t}"); break; case "Matrix4": + case "MatrixFloat4x4": writer.WriteLine ("\tfor (int i = 0; i < 4; i++) {"); writer.WriteLine ("\t\t{0}.columns [i][0] = {1}{2}columns [i].a;", nativeVariable, managedVariable, accessor); writer.WriteLine ("\t\t{0}.columns [i][1] = {1}{2}columns [i].b;", nativeVariable, managedVariable, accessor); @@ -2745,6 +2834,15 @@ public static class Types { IsX86Stret = true, IsX64Stret = true, }; + public static TypeData MatrixFloat3x3 = new TypeData { + ManagedType = "MatrixFloat3x3", + NativeType = "matrix_float3x3", + NativeWrapperType = "struct MatrixFloat3x3", + RequireMarshal = true, + IsARMStret = true, + IsX86Stret = true, + IsX64Stret = true, + }; public static TypeData Matrix4f = new TypeData { ManagedType = "Matrix4", NativeType = "matrix_float4x4", @@ -2754,6 +2852,15 @@ public static class Types { IsX86Stret = true, IsX64Stret = true, }; + public static TypeData MatrixFloat4x4 = new TypeData { + ManagedType = "MatrixFloat4x4", + NativeType = "matrix_float4x4", + NativeWrapperType = "struct MatrixFloat4x4", + RequireMarshal = true, + IsARMStret = true, + IsX86Stret = true, + IsX64Stret = true, + }; public static TypeData Double = new TypeData { ManagedType = "Double", NativeType = "double", diff --git a/runtime/bindings.h b/runtime/bindings.h index a6715b94ec9b..84d79e12c38f 100644 --- a/runtime/bindings.h +++ b/runtime/bindings.h @@ -162,10 +162,18 @@ struct Matrix3f { Vector3f columns [3]; }; +struct MatrixFloat3x3 { + Vector4f columns [3]; +}; + struct Matrix4f { Vector4f columns [4]; }; +struct MatrixFloat4x4 { + Vector4f columns [4]; +}; + struct QuatF { Vector4f vector; }; diff --git a/src/arkit.cs b/src/arkit.cs index af961b88975d..8c3a6043af99 100644 --- a/src/arkit.cs +++ b/src/arkit.cs @@ -22,8 +22,8 @@ using XamCore.UIKit; using Vector3 = global::OpenTK.Vector3; -using Matrix3 = global::OpenTK.Matrix3; -using Matrix4 = global::OpenTK.Matrix4; +using Matrix3 = global::Simd.MatrixFloat3x3; +using Matrix4 = global::Simd.MatrixFloat4x4; namespace XamCore.ARKit { From f6a01bbc275dd376ab1f07657f3a70ac1b37b198 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 12:15:17 +0200 Subject: [PATCH 04/17] [Vision] Use the new Simd matrix types. --- runtime/bindings-generator.cs | 11 +++++++++++ src/vision.cs | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/runtime/bindings-generator.cs b/runtime/bindings-generator.cs index 72b29b9451d5..385180c04ce8 100644 --- a/runtime/bindings-generator.cs +++ b/runtime/bindings-generator.cs @@ -2004,6 +2004,17 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // void func (MatrixFloat3x3)", + Prefix = "simd__", + Variants = Variants.NonStret, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.MatrixFloat3x3 }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // IntPtr func (MatrixFloat3x3)", diff --git a/src/vision.cs b/src/vision.cs index 098900b2fbc5..39add19020da 100644 --- a/src/vision.cs +++ b/src/vision.cs @@ -21,7 +21,7 @@ using XamCore.ImageIO; using Vector2 = global::OpenTK.Vector2; -using Matrix3 = global::OpenTK.Matrix3; +using Matrix3 = global::Simd.MatrixFloat3x3; namespace XamCore.Vision { From 788cd94355e7b70d660bd86820217678d8fcf5fd Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 12:17:22 +0200 Subject: [PATCH 05/17] [ModelIO] Use the new Simd-compatible matrix types, and deprecate the old API. --- runtime/bindings-generator.cs | 76 +++++++ src/ModelIO/MDLTransform.cs | 16 ++ src/ModelIO/MDLTransformComponent.cs | 33 +++ src/frameworks.sources | 2 + src/modelio.cs | 134 ++++++++++++ tests/bindings-test/StructsAndEnums.cs | 90 ++++++++ tests/monotouch-test/Asserts.cs | 21 ++ tests/monotouch-test/ModelIO/MDLCameraTest.cs | 86 ++++++++ .../ModelIO/MDLMaterialProperty.cs | 11 + .../ModelIO/MDLStereoscopicCameraTest.cs | 96 ++++++++ tests/monotouch-test/ModelIO/MDLTransform.cs | 47 ++++ .../ModelIO/MDLTransformComponentTest.cs | 207 ++++++++++++++++++ tests/monotouch-test/monotouch-test.csproj | 3 + tests/test-libraries/libtest.h | 15 ++ tests/test-libraries/libtest.m | 194 ++++++++++++++++ 15 files changed, 1031 insertions(+) create mode 100644 src/ModelIO/MDLTransform.cs create mode 100644 src/ModelIO/MDLTransformComponent.cs create mode 100644 tests/monotouch-test/ModelIO/MDLCameraTest.cs create mode 100644 tests/monotouch-test/ModelIO/MDLStereoscopicCameraTest.cs create mode 100644 tests/monotouch-test/ModelIO/MDLTransformComponentTest.cs diff --git a/runtime/bindings-generator.cs b/runtime/bindings-generator.cs index 385180c04ce8..010a9ad2de20 100644 --- a/runtime/bindings-generator.cs +++ b/runtime/bindings-generator.cs @@ -2056,6 +2056,17 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // void func (MatrixFloat4x4)", + Prefix = "simd__", + Variants = Variants.NonStret, + Parameters = new ParameterData[] { + new ParameterData { TypeData = Types.MatrixFloat4x4 }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // IntPtr func (MatrixFloat4x4)", @@ -2068,6 +2079,31 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // void func (MatrixFloat4x4, double)", + Prefix = "simd__", + Variants = Variants.NonStret, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.MatrixFloat4x4 }, + new ParameterData { TypeData = Types.Double }, + }, + } + ); + + data.Add ( + new FunctionData { + Comment = " // IntPtr func (MatrixFloat4x4, bool)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.MatrixFloat4x4 }, + new ParameterData { TypeData = Types.Bool }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // IntPtr func (MDLVoxelIndexExtent2)", @@ -2081,6 +2117,20 @@ static IEnumerable GetFunctionData () ); + data.Add ( + new FunctionData { + Comment = " // IntPtr func (IntPtr, nuint, MatrixFloat4x4)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.IntPtr }, + new ParameterData { TypeData = Types.NUInt }, + new ParameterData { TypeData = Types.MatrixFloat4x4 }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // MatrixFloat4x4 func ()", @@ -2120,6 +2170,18 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // MatrixFloat4x4 func (double)", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat4x4, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.Double }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // MatrixFloat4x4 func (nint)", @@ -2132,6 +2194,20 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // IntPtr func (IntPtr, nint, MatrixFloat4x4)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.IntPtr }, + new ParameterData { TypeData = Types.NInt }, + new ParameterData { TypeData = Types.MatrixFloat4x4 }, + }, + } + ); + // We must expand functions with native types to their actual type as well. for (int i = data.Count - 1; i >= 0; i--) { if (!data [i].HasNativeType) diff --git a/src/ModelIO/MDLTransform.cs b/src/ModelIO/MDLTransform.cs new file mode 100644 index 000000000000..54d944b426c9 --- /dev/null +++ b/src/ModelIO/MDLTransform.cs @@ -0,0 +1,16 @@ +#if XAMCORE_2_0 || !MONOMAC +using System; +using Simd; + +namespace XamCore.ModelIO { + public partial class MDLTransform { +#if !XAMCORE_4_0 + // Inlined from the MDLTransformComponent protocol. + public static MatrixFloat4x4 CreateGlobalTransform4x4 (MDLObject obj, double atTime) + { + return MatrixFloat4x4.Transpose ((MatrixFloat4x4) CreateGlobalTransform (obj, atTime)); + } +#endif + } +} +#endif \ No newline at end of file diff --git a/src/ModelIO/MDLTransformComponent.cs b/src/ModelIO/MDLTransformComponent.cs new file mode 100644 index 000000000000..bd6d14bcf183 --- /dev/null +++ b/src/ModelIO/MDLTransformComponent.cs @@ -0,0 +1,33 @@ +#if XAMCORE_2_0 && !XAMCORE_4_0 +using OpenTK; +using Simd; + +namespace XamCore.ModelIO { + public partial class MDLTransformComponent_Extensions { + public static MatrixFloat4x4 GetMatrix4x4 (this IMDLTransformComponent self) + { + return MatrixFloat4x4.Transpose ((MatrixFloat4x4) self.Matrix); + } + + public static void SetMatrix4x4 (this IMDLTransformComponent self, MatrixFloat4x4 value) + { + self.Matrix = (Matrix4) MatrixFloat4x4.Transpose (value); + } + + public static MatrixFloat4x4 GetLocalTransform4x4(this IMDLTransformComponent This, double time) + { + return MatrixFloat4x4.Transpose ((MatrixFloat4x4) GetLocalTransform (This, time)); + } + + public static void SetLocalTransform4x4 (this IMDLTransformComponent This, MatrixFloat4x4 transform, double time) + { + SetLocalTransform (This, (Matrix4) MatrixFloat4x4.Transpose (transform), time); + } + + public static void SetLocalTransform4x4 (this IMDLTransformComponent This, MatrixFloat4x4 transform) + { + SetLocalTransform (This, (Matrix4) MatrixFloat4x4.Transpose (transform)); + } + } +} +#endif \ No newline at end of file diff --git a/src/frameworks.sources b/src/frameworks.sources index 79c04ad310ef..bcd8d457996a 100644 --- a/src/frameworks.sources +++ b/src/frameworks.sources @@ -998,6 +998,8 @@ MODELIO_CORE_SOURCES = \ MODELIO_SOURCES = \ ModelIO/MDLAsset.cs \ ModelIO/MDLNoiseTexture.cs \ + ModelIO/MDLTransform.cs \ + ModelIO/MDLTransformComponent.cs \ ModelIO/MDLVertexDescriptor.cs \ ModelIO/MDLMesh.cs \ diff --git a/src/modelio.cs b/src/modelio.cs index 418a7b199e77..88f63106cee8 100644 --- a/src/modelio.cs +++ b/src/modelio.cs @@ -22,9 +22,16 @@ using Vector3i = global::OpenTK.Vector3i; using Vector4 = global::OpenTK.Vector4; using Vector4i = global::OpenTK.Vector4i; +#if XAMCORE_4_0 +using Matrix2 = global::Simd.Matrix2; +using Matrix3 = global::Simd.Matrix3; +using Matrix4 = global::Simd.Matrix4; +#else using Matrix2 = global::OpenTK.Matrix2; using Matrix3 = global::OpenTK.Matrix3; using Matrix4 = global::OpenTK.Matrix4; +using Simd; +#endif using Quaternion = global::OpenTK.Quaternion; using MathHelper = global::OpenTK.MathHelper; #if MONOMAC @@ -212,10 +219,21 @@ interface MDLLightProbeIrradianceDataSource interface MDLCamera { [Export ("projectionMatrix")] +#if !XAMCORE_4_0 + [Obsolete ("Use 'ProjectionMatrix4x4' instead.")] +#endif Matrix4 ProjectionMatrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; } +#if !XAMCORE_4_0 + [Sealed] + [Export ("projectionMatrix")] + MatrixFloat4x4 ProjectionMatrix4x4 { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + } +#endif + [iOS (10,0)] [Mac (10,12)] [TV (10,0)] @@ -515,8 +533,19 @@ interface MDLMaterialProperty : MDLNamed, NSCopying [Export ("initWithName:semantic:matrix4x4:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] +#if !XAMCORE_4_0 + [Obsolete ("Use the '(string, MDLMaterialSemantic, MatrixFloat4x4)' overload instead.")] +#endif IntPtr Constructor (string name, MDLMaterialSemantic semantic, Matrix4 value); + +#if !XAMCORE_4_0 + [Sealed] + [Export ("initWithName:semantic:matrix4x4:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + IntPtr Constructor (string name, MDLMaterialSemantic semantic, MatrixFloat4x4 value); +#endif + [Export ("initWithName:semantic:URL:")] IntPtr Constructor (string name, MDLMaterialSemantic semantic, [NullAllowed] NSUrl url); @@ -572,12 +601,24 @@ Vector4 Float4Value { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#if !XAMCORE_4_0 + [Obsolete ("Use 'MatrixFloat4x4' instead.")] +#endif [Export ("matrix4x4", ArgumentSemantic.Assign)] Matrix4 Matrix4x4 { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#if !XAMCORE_4_0 + [Sealed] + [Export ("matrix4x4", ArgumentSemantic.Assign)] + MatrixFloat4x4 MatrixFloat4x4 { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } +#endif + [iOS (10,0)] [Mac (10,12)] [TV (10,0)] @@ -1362,29 +1403,77 @@ interface MDLStereoscopicCamera [Export ("overlap")] float Overlap { get; set; } +#if !XAMCORE_4_0 + [Obsolete ("Use 'LeftViewMatrix4x4' instead.")] +#endif [Export ("leftViewMatrix")] Matrix4 LeftViewMatrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; } +#if !XAMCORE_4_0 + [Sealed] + [Export ("leftViewMatrix")] + MatrixFloat4x4 LeftViewMatrix4x4 { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + get; + } +#endif + +#if !XAMCORE_4_0 + [Obsolete ("Use 'RightViewMatrix4x4' instead.")] +#endif [Export ("rightViewMatrix")] Matrix4 RightViewMatrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; } +#if !XAMCORE_4_0 + [Sealed] + [Export ("rightViewMatrix")] + MatrixFloat4x4 RightViewMatrix4x4 { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + get; + } +#endif + +#if !XAMCORE_4_0 + [Obsolete ("Use 'LeftProjectionMatrix4x4' instead.")] +#endif [Export ("leftProjectionMatrix")] Matrix4 LeftProjectionMatrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; } +#if !XAMCORE_4_0 + [Sealed] + [Export ("leftProjectionMatrix")] + MatrixFloat4x4 LeftProjectionMatrix4x4 { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + get; + } +#endif + +#if !XAMCORE_4_0 + [Obsolete ("Use 'RightProjectionMatrix4x4' instead.")] +#endif [Export ("rightProjectionMatrix")] Matrix4 RightProjectionMatrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; } + +#if !XAMCORE_4_0 + [Sealed] + [Export ("rightProjectionMatrix")] + MatrixFloat4x4 RightProjectionMatrix4x4 { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + get; + } +#endif } [iOS (9,0), Mac(10,11, onlyOn64 : true)] @@ -1576,10 +1665,23 @@ interface MDLTransform : MDLTransformComponent, NSCopying { [Export ("initWithTransformComponent:resetsTransform:")] IntPtr Constructor (IMDLTransformComponent component, bool resetsTransform); +#if !XAMCORE_4_0 + [Obsolete ("Use the '(MatrixFloat4x4)' overload instead.")] +#endif [Export ("initWithMatrix:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] IntPtr Constructor (Matrix4 matrix); +#if !XAMCORE_4_0 + [Sealed] + [Export ("initWithMatrix:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + IntPtr Constructor (MatrixFloat4x4 matrix); +#endif + +#if !XAMCORE_4_0 + [Obsolete ("Use the '(MatrixFloat4x4, bool)' overload instead.")] +#endif [iOS (10,0)] [Mac (10,12)] [TV (10,0)] @@ -1587,6 +1689,14 @@ interface MDLTransform : MDLTransformComponent, NSCopying { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] IntPtr Constructor (Matrix4 matrix, bool resetsTransform); +#if !XAMCORE_4_0 + [Sealed] + [iOS (10,0), Mac (10,12), TV (10,0)] + [Export ("initWithMatrix:resetsTransform:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + IntPtr Constructor (MatrixFloat4x4 matrix, bool resetsTransform); +#endif + [Export ("setIdentity")] void SetIdentity (); @@ -1606,10 +1716,20 @@ interface MDLTransform : MDLTransformComponent, NSCopying { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] Vector3 GetRotation (double atTime); +#if !XAMCORE_4_0 + [Obsolete ("Use 'GetRotationMatrix4x4' instead.")] +#endif [Export ("rotationMatrixAtTime:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] Matrix4 GetRotationMatrix (double atTime); +#if !XAMCORE_4_0 + [Sealed] + [Export ("rotationMatrixAtTime:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + MatrixFloat4x4 GetRotationMatrix4x4 (double atTime); +#endif + [Export ("setShear:forTime:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] void SetShear (Vector3 scale, double time); @@ -1629,8 +1749,19 @@ interface MDLTransform : MDLTransformComponent, NSCopying { [iOS (10,3), TV (10,2), Mac (10,12,4)] [Export ("setMatrix:forTime:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] +#if !XAMCORE_4_0 + [Obsolete ("Use 'SetMatrix4x4' instead.")] +#endif void SetMatrix (Matrix4 matrix, double time); +#if !XAMCORE_4_0 + [Sealed] + [iOS (10,3), TV (10,2), Mac (10,12,4)] + [Export ("setMatrix:forTime:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + void SetMatrix4x4 (MatrixFloat4x4 matrix, double time); +#endif + [Export ("shear", ArgumentSemantic.Assign)] Vector3 Shear { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] @@ -1713,6 +1844,9 @@ Matrix4 Matrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] Matrix4 GetLocalTransform (double atTime); +#if !XAMCORE_4_0 + [Obsolete ("Use 'CreateGlobalTransform4x4' instead.")] +#endif [Static] [Export ("globalTransformWithObject:atTime:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] diff --git a/tests/bindings-test/StructsAndEnums.cs b/tests/bindings-test/StructsAndEnums.cs index 26e6b3c0730d..1d488c1029ed 100644 --- a/tests/bindings-test/StructsAndEnums.cs +++ b/tests/bindings-test/StructsAndEnums.cs @@ -3,13 +3,103 @@ #if !__UNIFIED__ using nint=System.Int32; +#else +using Foundation; +using ObjCRuntime; #endif +using Simd; + namespace Bindings.Test { public static class CFunctions { [DllImport ("__Internal")] public static extern int theUltimateAnswer (); + + [DllImport ("__Internal")] + public static extern void x_get_matrix_float2x2 (IntPtr self, string sel, out float r0c0, out float r0c1, out float r1c0, out float r1c1); + + [DllImport ("__Internal")] + public static extern void x_get_matrix_float3x3 (IntPtr self, string sel, out float r0c0, out float r0c1, out float r0c2, out float r1c0, out float r1c1, out float r1c2, out float r2c0, out float r2c1, out float r2c2); + + [DllImport ("__Internal")] + public static extern void x_get_matrix_float4x4 (IntPtr self, string sel, out float r0c0, out float r0c1, out float r0c2, out float r0c3, out float r1c0, out float r1c1, out float r1c2, out float r1c3, out float r2c0, out float r2c1, out float r2c2, out float r2c3, out float r3c0, out float r3c1, out float r3c2, out float r3c3); + + public static MatrixFloat2x2 GetMatrixFloat2x2 (NSObject obj, string selector) + { + float r0c0, r0c1, r1c0, r1c1; + x_get_matrix_float2x2 (obj.Handle, selector, out r0c0, out r0c1, out r1c0, out r1c1); + return new MatrixFloat2x2 ( + r0c0, r0c1, + r1c0, r1c1); + } + + public static MatrixFloat3x3 GetMatrixFloat3x3 (NSObject obj, string selector) + { + float r0c0, r0c1, r0c2, r1c0, r1c1, r1c2, r2c0, r2c1, r2c2; + x_get_matrix_float3x3 (obj.Handle, selector, out r0c0, out r0c1, out r0c2, out r1c0, out r1c1, out r1c2, out r2c0, out r2c1, out r2c2); + return new MatrixFloat3x3 ( + r0c0, r0c1, r0c2, + r1c0, r1c1, r1c2, + r2c0, r2c1, r2c2); + + } + + public static MatrixFloat4x4 GetMatrixFloat4x4 (NSObject obj, string selector) + { + float r0c0, r0c1, r0c2, r0c3, r1c0, r1c1, r1c2, r1c3, r2c0, r2c1, r2c2, r2c3, r3c0, r3c1, r3c2, r3c3; + x_get_matrix_float4x4 (obj.Handle, selector, out r0c0, out r0c1, out r0c2, out r0c3, out r1c0, out r1c1, out r1c2, out r1c3, out r2c0, out r2c1, out r2c2, out r2c3, out r3c0, out r3c1, out r3c2, out r3c3); + return new MatrixFloat4x4 ( + r0c0, r0c1, r0c2, r0c3, + r1c0, r1c1, r1c2, r1c3, + r2c0, r2c1, r2c2, r2c3, + r3c0, r3c1, r3c2, r3c3); + } + + +#if !__WATCHOS__ + [DllImport ("__Internal")] + public static extern void x_mdltransformcomponent_get_local_transform (IntPtr self, double time, out float r0c0, out float r0c1, out float r0c2, out float r0c3, out float r1c0, out float r1c1, out float r1c2, out float r1c3, out float r2c0, out float r2c1, out float r2c2, out float r2c3, out float r3c0, out float r3c1, out float r3c2, out float r3c3); + + public static MatrixFloat4x4 MDLTransformComponent_GetLocalTransform (INativeObject obj, double time) + { + float r0c0, r0c1, r0c2, r0c3, r1c0, r1c1, r1c2, r1c3, r2c0, r2c1, r2c2, r2c3, r3c0, r3c1, r3c2, r3c3; + x_mdltransformcomponent_get_local_transform (obj.Handle, time, out r0c0, out r0c1, out r0c2, out r0c3, out r1c0, out r1c1, out r1c2, out r1c3, out r2c0, out r2c1, out r2c2, out r2c3, out r3c0, out r3c1, out r3c2, out r3c3); + return new MatrixFloat4x4 ( + r0c0, r0c1, r0c2, r0c3, + r1c0, r1c1, r1c2, r1c3, + r2c0, r2c1, r2c2, r2c3, + r3c0, r3c1, r3c2, r3c3); + } + + [DllImport ("__Internal")] + public static extern void x_mdltransform_create_global_transform (IntPtr obj, double time, out float r0c0, out float r0c1, out float r0c2, out float r0c3, out float r1c0, out float r1c1, out float r1c2, out float r1c3, out float r2c0, out float r2c1, out float r2c2, out float r2c3, out float r3c0, out float r3c1, out float r3c2, out float r3c3); + + public static MatrixFloat4x4 MDLTransform_CreateGlobalTransform (INativeObject obj, double time) + { + float r0c0, r0c1, r0c2, r0c3, r1c0, r1c1, r1c2, r1c3, r2c0, r2c1, r2c2, r2c3, r3c0, r3c1, r3c2, r3c3; + x_mdltransform_create_global_transform (obj.Handle, time, out r0c0, out r0c1, out r0c2, out r0c3, out r1c0, out r1c1, out r1c2, out r1c3, out r2c0, out r2c1, out r2c2, out r2c3, out r3c0, out r3c1, out r3c2, out r3c3); + return new MatrixFloat4x4 ( + r0c0, r0c1, r0c2, r0c3, + r1c0, r1c1, r1c2, r1c3, + r2c0, r2c1, r2c2, r2c3, + r3c0, r3c1, r3c2, r3c3); + } + + [DllImport ("__Internal")] + public static extern void x_mdltransform_get_rotation_matrix (IntPtr obj, double time, out float r0c0, out float r0c1, out float r0c2, out float r0c3, out float r1c0, out float r1c1, out float r1c2, out float r1c3, out float r2c0, out float r2c1, out float r2c2, out float r2c3, out float r3c0, out float r3c1, out float r3c2, out float r3c3); + + public static MatrixFloat4x4 MDLTransform_GetRotationMatrix (INativeObject obj, double time) + { + float r0c0, r0c1, r0c2, r0c3, r1c0, r1c1, r1c2, r1c3, r2c0, r2c1, r2c2, r2c3, r3c0, r3c1, r3c2, r3c3; + x_mdltransform_get_rotation_matrix (obj.Handle, time, out r0c0, out r0c1, out r0c2, out r0c3, out r1c0, out r1c1, out r1c2, out r1c3, out r2c0, out r2c1, out r2c2, out r2c3, out r3c0, out r3c1, out r3c2, out r3c3); + return new MatrixFloat4x4 ( + r0c0, r0c1, r0c2, r0c3, + r1c0, r1c1, r1c2, r1c3, + r2c0, r2c1, r2c2, r2c3, + r3c0, r3c1, r3c2, r3c3); + } +#endif } } diff --git a/tests/monotouch-test/Asserts.cs b/tests/monotouch-test/Asserts.cs index 147a05b1f891..d40d7e71256a 100644 --- a/tests/monotouch-test/Asserts.cs +++ b/tests/monotouch-test/Asserts.cs @@ -88,6 +88,19 @@ public static void AreEqual (Matrix3 expected, Matrix3 actual, string message) AreEqual (expected.R2C2, actual.R2C2, message + " (R2C2)"); } + public static void AreEqual (Matrix3 expected, Matrix3 actual, float delta, string message) + { + AreEqual (expected.R0C0, actual.R0C0, delta, message + " (R0C0)"); + AreEqual (expected.R0C1, actual.R0C1, delta, message + " (R0C1)"); + AreEqual (expected.R0C2, actual.R0C2, delta, message + " (R0C2)"); + AreEqual (expected.R1C0, actual.R1C0, delta, message + " (R1C0)"); + AreEqual (expected.R1C1, actual.R1C1, delta, message + " (R1C1)"); + AreEqual (expected.R1C2, actual.R1C2, delta, message + " (R1C2)"); + AreEqual (expected.R2C0, actual.R2C0, delta, message + " (R2C0)"); + AreEqual (expected.R2C1, actual.R2C1, delta, message + " (R2C1)"); + AreEqual (expected.R2C2, actual.R2C2, delta, message + " (R2C2)"); + } + public static void AreEqual (Matrix4 expected, Matrix4 actual, string message) { AreEqual (expected.Column0, actual.Column0, message + " (Col0)"); @@ -96,6 +109,14 @@ public static void AreEqual (Matrix4 expected, Matrix4 actual, string message) AreEqual (expected.Column3, actual.Column3, message + " (Col3)"); } + public static void AreEqual (Matrix4 expected, Matrix4 actual, float delta, string message) + { + AreEqual (expected.Column0, actual.Column0, delta, message + " (Col0)"); + AreEqual (expected.Column1, actual.Column1, delta, message + " (Col1)"); + AreEqual (expected.Column2, actual.Column2, delta, message + " (Col2)"); + AreEqual (expected.Column3, actual.Column3, delta, message + " (Col3)"); + } + public static void AreEqual (Vector2i expected, Vector2i actual, string message) { Assert.AreEqual (expected.X, actual.X, message + " (X)"); diff --git a/tests/monotouch-test/ModelIO/MDLCameraTest.cs b/tests/monotouch-test/ModelIO/MDLCameraTest.cs new file mode 100644 index 000000000000..4cf2bb4cefae --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLCameraTest.cs @@ -0,0 +1,86 @@ +// +// MDLCamera Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2017 Microsoft Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +#if !MONOMAC +using UIKit; +#endif +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using Simd; +using Bindings.Test; + +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO +{ + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDCameraTest + { + [TestFixtureSetUp] + public void Setup () + { + TestRuntime.AssertXcodeVersion (7, 0); + } + + [Test] + public void ProjectionMatrix () + { + using (var obj = new MDLCamera ()) { + Assert.AreEqual (0.1f, obj.NearVisibilityDistance, 0.0001f, "NearVisibilityDistance"); + Assert.AreEqual (1000f, obj.FarVisibilityDistance, 0.0001f, "FarVisibilityDistance"); + Assert.AreEqual (54f, obj.FieldOfView, 0.0001f, "FieldOfView"); + var initialProjectionMatrix = new Matrix4 ( + 1.308407f, 0, 0, 0, + 0, 1.962611f, 0, 0, + 0, 0, -1.0002f, -1, + 0, 0, -0.20002f, 0 + ); + Asserts.AreEqual (initialProjectionMatrix, obj.ProjectionMatrix, 0.0001f, "Initial"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) initialProjectionMatrix), obj.ProjectionMatrix4x4, 0.0001f, "Initial 4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) initialProjectionMatrix), CFunctions.GetMatrixFloat4x4 (obj, "projectionMatrix"), 0.0001f, "Initial native"); + + obj.NearVisibilityDistance = 1.0f; + var modifiedProjectionMatrix = new Matrix4 ( + 1.308407f, 0, 0, 0, + 0, 1.962611f, 0, 0, + 0, 0, -1.002002f, -1, + 0, 0, -2.002002f, 0 + ); + Asserts.AreEqual (modifiedProjectionMatrix, obj.ProjectionMatrix, 0.0001f, "Second"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) modifiedProjectionMatrix), obj.ProjectionMatrix4x4, 0.0001f, "Second 4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) modifiedProjectionMatrix), CFunctions.GetMatrixFloat4x4 (obj, "projectionMatrix"), 0.0001f, "Second native"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs b/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs index 7141bd500f86..4e1e68622109 100644 --- a/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs +++ b/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs @@ -33,6 +33,8 @@ using MonoTouch.ObjCRuntime; #endif using OpenTK; +using Simd; +using Bindings.Test; using NUnit.Framework; namespace MonoTouchFixtures.ModelIO { @@ -101,6 +103,7 @@ public void Ctors () Vector3 V3; Vector4 V4; Matrix4 M4; + MatrixFloat4x4 M4x4; MDLTextureSampler tsv; NSUrl url; @@ -122,6 +125,7 @@ public void Ctors () V3 = new Vector3 (3, 4, 5); V4 = new Vector4 (6, 7, 8, 9); M4 = new Matrix4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + M4x4 = new MatrixFloat4x4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); tsv = new MDLTextureSampler (); url = new NSUrl ("http://xamarin.com"); @@ -187,6 +191,13 @@ public void Ctors () using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, M4)) { Asserts.AreEqual (M4, obj.Matrix4x4, "7 Matrix4x4"); + Asserts.AreEqual (CFunctions.GetMatrixFloat4x4 (obj, "matrix4x4"), obj.MatrixFloat4x4, "7b MatrixFloat4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) M4), obj.MatrixFloat4x4, "7c MatrixFloat4x4"); + } + + using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, M4x4)) { + Asserts.AreEqual (CFunctions.GetMatrixFloat4x4 (obj, "matrix4x4"), obj.MatrixFloat4x4, "7' MatrixFloat4x4"); + Asserts.AreEqual (M4x4, obj.MatrixFloat4x4, "7'b MatrixFloat4x4"); } using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, V4)) { diff --git a/tests/monotouch-test/ModelIO/MDLStereoscopicCameraTest.cs b/tests/monotouch-test/ModelIO/MDLStereoscopicCameraTest.cs new file mode 100644 index 000000000000..ffa3b83594d9 --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLStereoscopicCameraTest.cs @@ -0,0 +1,96 @@ +// +// MDLStereoscopicCamera Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2017 Microsoft Inc. +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using CoreGraphics; +using Foundation; +#if !MONOMAC +using UIKit; +#endif +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.CoreGraphics; +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using Simd; +using Bindings.Test; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO +{ + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLStereoscopicCameraTest + { + [TestFixtureSetUp] + public void Setup () + { + TestRuntime.AssertXcodeVersion (7, 0); + } + + [Test] + public void Properties () + { + using (var obj = new MDLStereoscopicCamera ()) { + Assert.AreEqual (63f, obj.InterPupillaryDistance, "InterPupillaryDistance"); + Assert.AreEqual (0f, obj.LeftVergence, "LeftVergence"); + Assert.AreEqual (0f, obj.RightVergence, "RightVergence"); + Assert.AreEqual (0f, obj.Overlap, "Overlap"); + + var mat1 = new Matrix4 ( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + -0.63f, 0, 0, 1); + Asserts.AreEqual (mat1, obj.LeftViewMatrix, "LeftViewMatrix"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat1), obj.LeftViewMatrix4x4, "LeftViewMatrix4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat1), CFunctions.GetMatrixFloat4x4 (obj, "leftViewMatrix"), "LeftViewMatrix4x4 native"); + + var mat2 = new Matrix4 ( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0.63f, 0, 0, 1); + Asserts.AreEqual (mat2, obj.RightViewMatrix, "RightViewMatrix"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat2), obj.RightViewMatrix4x4, "RightViewMatrix4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat2), CFunctions.GetMatrixFloat4x4 (obj, "rightViewMatrix"), "RightViewMatrix4x4 native"); + + var mat3 = new Matrix4 ( + 1.308407f, 0, 0, 0, + 0, 1.962611f, 0, 0, + 0, 0, -1.0002f, -1, + 0, 0, -0.20002f, 0); + Asserts.AreEqual (mat3, obj.LeftProjectionMatrix, 0.0001f, "LeftProjectionMatrix"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat3), obj.LeftProjectionMatrix4x4, 0.0001f, "LeftProjectionMatrix4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat3), CFunctions.GetMatrixFloat4x4 (obj, "leftProjectionMatrix"), 0.0001f, "LeftProjectionMatrix4x4 native"); + + Asserts.AreEqual (mat3, obj.RightProjectionMatrix, 0.0001f, "RightProjectionMatrix"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat3), obj.RightProjectionMatrix4x4, 0.0001f, "RightProjectionMatrix4x4"); + Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) mat3), CFunctions.GetMatrixFloat4x4 (obj, "rightProjectionMatrix"), 0.0001f, "RightProjectionMatrix4x4 native"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/ModelIO/MDLTransform.cs b/tests/monotouch-test/ModelIO/MDLTransform.cs index b169ecabac48..4c9435bd32af 100644 --- a/tests/monotouch-test/ModelIO/MDLTransform.cs +++ b/tests/monotouch-test/ModelIO/MDLTransform.cs @@ -30,6 +30,8 @@ using MonoTouch.ObjCRuntime; #endif using OpenTK; +using Simd; +using Bindings.Test; using NUnit.Framework; namespace MonoTouchFixtures.ModelIO { @@ -120,6 +122,31 @@ public void Ctors () obj.Rotation = V3; Asserts.AreEqual (V3, obj.Rotation, "Rotation 2"); } + + var m4 = new Matrix4 ( + 4, 0, 0, 0, + 0, 3, 0, 0, + 0, 0, 2, 0, + 2, 3, 4, 1); + using (var obj = new MDLTransform (m4)) { + Asserts.AreEqual (Vector3.Zero, obj.Rotation, "Rotation 3"); + Asserts.AreEqual (new Vector3 (4, 3, 2), obj.Scale, "Scale 3"); + Asserts.AreEqual (new Vector3 (2, 3, 4), obj.Translation, "Translation 3"); + Asserts.AreEqual (m4, obj.Matrix, 0.0001f, "Matrix 3"); + } + + var m4x4 = new MatrixFloat4x4 ( + 4, 0, 0, 2, + 0, 3, 0, 3, + 0, 0, 2, 4, + 0, 0, 0, 1); + using (var obj = new MDLTransform (m4x4)) { + Asserts.AreEqual (Vector3.Zero, obj.Rotation, "Rotation 4"); + Asserts.AreEqual (new Vector3 (4, 3, 2), obj.Scale, "Scale 4"); + Asserts.AreEqual (new Vector3 (2, 3, 4), obj.Translation, "Translation 4"); + Asserts.AreEqual (m4x4, obj.GetMatrix4x4 (), 0.0001f, "Matrix4x4 4"); + Asserts.AreEqual (m4x4, CFunctions.GetMatrixFloat4x4 (obj, "matrix"), 0.0001f, "Matrix4x4-native 4"); + } } [Test] @@ -157,6 +184,26 @@ public void RotationAtTimeTest () Asserts.AreEqual (V3, obj.GetRotation (0), "RotationAtTime"); } } + + [Test] + public void GetRotationMatrixTest () + { + var matrix = Matrix4.Identity; + var V3 = new Vector3 (1, 0, 0); + + using (var obj = new MDLTransform (matrix)) { + obj.SetRotation (V3, 0); + var expected = new MatrixFloat4x4 ( + 1, 0, 0, 0, + 0, (float) Math.Cos (1.0f), (float) -Math.Sin(1.0f), 0, + 0, (float) Math.Sin (1.0f), (float) Math.Cos(1.0f), 0, + 0, 0, 0, 1 + ); + Asserts.AreEqual ((Matrix4) MatrixFloat4x4.Transpose (expected), obj.GetRotationMatrix (0), 0.00001f, "GetRotationMatrix"); + Asserts.AreEqual (expected, obj.GetRotationMatrix4x4 (0), 0.00001f, "GetRotationMatrix4x4"); + Asserts.AreEqual (expected, CFunctions.MDLTransform_GetRotationMatrix (obj, 0), 0.00001f, "GetRotationMatrix4x4 native"); + } + } } } diff --git a/tests/monotouch-test/ModelIO/MDLTransformComponentTest.cs b/tests/monotouch-test/ModelIO/MDLTransformComponentTest.cs new file mode 100644 index 000000000000..3c676fe9d1a5 --- /dev/null +++ b/tests/monotouch-test/ModelIO/MDLTransformComponentTest.cs @@ -0,0 +1,207 @@ +// +// MDLTransformComponent Unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2017 Microsoft inc +// + +#if !__WATCHOS__ + +using System; +#if XAMCORE_2_0 +using Foundation; +#if !MONOMAC +using UIKit; +#endif +#if !__TVOS__ +using MultipeerConnectivity; +#endif +using ModelIO; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +#if !__TVOS__ +using MonoTouch.MultipeerConnectivity; +#endif +using MonoTouch.UIKit; +using MonoTouch.ModelIO; +using MonoTouch.ObjCRuntime; +#endif +using OpenTK; +using Simd; +using Bindings.Test; +using NUnit.Framework; + +namespace MonoTouchFixtures.ModelIO +{ + + [TestFixture] + // we want the test to be available if we use the linker + [Preserve (AllMembers = true)] + public class MDLTransformComponentTest + { + [TestFixtureSetUp] + public void Setup () + { + TestRuntime.AssertXcodeVersion (7, 0); + } + + [Test] + public void MatrixTest () + { + var m4 = new Matrix4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + var m4x4 = (MatrixFloat4x4) m4; + + using (var obj = new MDLTransform ()) { + // identity + Asserts.AreEqual (Matrix4.Identity, obj.Matrix, "Initial identity"); + Asserts.AreEqual (MatrixFloat4x4.Identity, obj.GetMatrix4x4 (), "Initial identity 4x4"); + Asserts.AreEqual (MatrixFloat4x4.Identity, CFunctions.GetMatrixFloat4x4 (obj, "matrix"), "Initial identity native"); + + // translate the transform somewhere + obj.SetTranslation (new Vector3 (2, 2, 2), 0); + + // the matrix should now be a translation matrix like this: + // 1 0 0 0 2 + // 0 1 0 0 2 + // 0 0 1 0 2 + // 0 0 0 1 0 + // but since Matrix4 is transposed when compared to MatrixFloat4x4, we get this: + + Asserts.AreEqual (new Matrix4 ( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 2, 2, 2, 1 + ), obj.Matrix, "Translated"); + + // The 4x4 version is correct: + Asserts.AreEqual (new Matrix4 ( + 1, 0, 0, 2, + 0, 1, 0, 2, + 0, 0, 1, 2, + 0, 0, 0, 1 + ), obj.GetMatrix4x4 (), "Translated 4x4"); + + // Let's set the matrix to something (different from the identity matrix) + obj.Matrix = m4; + + // And the matrix resets to the identify matrix. + Asserts.AreEqual (Matrix4.Identity, obj.Matrix, "After set_Matrix"); + + // Translate again + obj.SetTranslation (new Vector3 (3, 3, 3), 0); + + // Set the matrix using a 4x4 matrix + obj.SetMatrix4x4 (m4x4); + + // And we still get the identity matrix back + Asserts.AreEqual (MatrixFloat4x4.Identity, obj.GetMatrix4x4 (), "After set_Matrix 2"); + } + } + + [Test] + public void LocalTransformTest () + { + var m4 = new Matrix4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + var m4x4 = (MatrixFloat4x4) m4; + + using (var obj = new MDLTransform ()) { + var component = (IMDLTransformComponent) obj; + // identity + Asserts.AreEqual (Matrix4.Identity, component.GetLocalTransform (0), "Initial identity"); + Asserts.AreEqual (MatrixFloat4x4.Identity, component.GetLocalTransform4x4 (0), "Initial identity 4x4"); + Asserts.AreEqual (MatrixFloat4x4.Identity, CFunctions.MDLTransformComponent_GetLocalTransform (component, 0), "Initial identity native"); + + // translate the transform somewhere + obj.SetTranslation (new Vector3 (2, 2, 2), 0); + + // the local transform should now be a translation matrix like this: + // 1 0 0 0 2 + // 0 1 0 0 2 + // 0 0 1 0 2 + // 0 0 0 1 0 + // but since Matrix4 is transposed when compared to MatrixFloat4x4, we get this: + + Asserts.AreEqual (new Matrix4 ( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 2, 2, 2, 1 + ), component.GetLocalTransform (0), "Translated"); + + // The 4x4 version is correct: + Asserts.AreEqual (new Matrix4 ( + 1, 0, 0, 2, + 0, 1, 0, 2, + 0, 0, 1, 2, + 0, 0, 0, 1 + ), component.GetLocalTransform4x4 (0), "Translated 4x4"); + + // Let's set the local transform at time 1 to something (different from the identity matrix) + component.SetLocalTransform (m4, 1); + + // At time 1 the transform matrix is now the identity matrix + Asserts.AreEqual (Matrix4.Identity, component.GetLocalTransform (1), "After SetLocalTransform at 1"); + + // At time 0.5 we get a middle ground + Asserts.AreEqual (new Matrix4 ( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 1, 1, 1, 1 + ), component.GetLocalTransform (0.5), 0.00001f, "AfterSetLocalTransform at 0.5"); + + // And at time 0 we still have the translated matrix. + Asserts.AreEqual (new Matrix4 ( + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 2, 2, 2, 1 + ), component.GetLocalTransform (0), 0.00001f, "AfterSetLocalTransform at 0"); + + // Let's set the local transform at all times + component.SetLocalTransform (m4); + + // And we get the identity matrix back at all times + Asserts.AreEqual (Matrix4.Identity, component.GetLocalTransform (0), "Second identity at 0"); + Asserts.AreEqual (Matrix4.Identity, component.GetLocalTransform (1), "Second identity at 1"); + + // Translate again + obj.SetTranslation (new Vector3 (3, 3, 3), 0); + + // Set the local transform using a 4x4 matrix + component.SetLocalTransform4x4 (m4x4, 1); + + // And at time 0.5 we still get a middle ground + // The numbers are different now because the translation matrix was different, + // and the matrix is correct because we're checking the 4x4 version. + Asserts.AreEqual (new MatrixFloat4x4 ( + 1, 0, 0, 1.5f, + 0, 1, 0, 1.5f, + 0, 0, 1, 1.5f, + 0, 0, 0, 1 + ), component.GetLocalTransform4x4 (0.5), 0.00001f, "AfterSetLocalTransform4x4 at 0.5"); + } + } + + [Test] + public void CreateGlobalTransformTest () + { + Matrix4 m4; + MatrixFloat4x4 m4x4; + + using (var obj = new MDLObject ()) { + m4 = MDLTransform.CreateGlobalTransform (obj, 0); + Asserts.AreEqual ((Matrix4) MatrixFloat4x4.Transpose (CFunctions.MDLTransform_CreateGlobalTransform (obj, 0)), m4, "CreateGlobalTransform"); + + m4x4 = MDLTransform.CreateGlobalTransform4x4 (obj, 0); + Asserts.AreEqual (CFunctions.MDLTransform_CreateGlobalTransform (obj, 0), m4, "CreateGlobalTransform4x4"); + } + } + } +} + +#endif // !__WATCHOS__ diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj index 4913bb144c84..073f312b3049 100644 --- a/tests/monotouch-test/monotouch-test.csproj +++ b/tests/monotouch-test/monotouch-test.csproj @@ -668,6 +668,9 @@ + + + diff --git a/tests/test-libraries/libtest.h b/tests/test-libraries/libtest.h index d76617306736..3ab8b21d4d5e 100644 --- a/tests/test-libraries/libtest.h +++ b/tests/test-libraries/libtest.h @@ -1,7 +1,12 @@ #import +#include #include "rename.h" +#if !TARGET_OS_WATCH +#import +#endif + #ifdef __cplusplus extern "C" { #endif @@ -9,6 +14,16 @@ extern "C" { int theUltimateAnswer (); void useZLib (); +void x_get_matrix_float2x2 (id self, const char *sel, float* r0c0, float* r0c1, float* r1c0, float* r1c1); +void x_get_matrix_float3x3 (id self, const char *sel, float* r0c0, float* r0c1, float* r0c2, float* r1c0, float* r1c1, float* r1c2, float* r2c0, float* r2c1, float* r2c2); +void x_get_matrix_float4x4 (id self, const char *sel, float* r0c0, float* r0c1, float* r0c2, float* r0c3, float* r1c0, float* r1c1, float* r1c2, float* r1c3, float* r2c0, float* r2c1, float* r2c2, float* r2c3, float* r3c0, float* r3c1, float* r3c2, float* r3c3); + +#if !TARGET_OS_WATCH +void x_mdltransformcomponent_get_local_transform (id self, NSTimeInterval time, float* r0c0, float* r0c1, float* r0c2, float* r0c3, float* r1c0, float* r1c1, float* r1c2, float* r1c3, float* r2c0, float* r2c1, float* r2c2, float* r2c3, float* r3c0, float* r3c1, float* r3c2, float* r3c3); +void x_mdltransform_create_global_transform (MDLObject *object, NSTimeInterval time, float* r0c0, float* r0c1, float* r0c2, float* r0c3, float* r1c0, float* r1c1, float* r1c2, float* r1c3, float* r2c0, float* r2c1, float* r2c2, float* r2c3, float* r3c0, float* r3c1, float* r3c2, float* r3c3); +void x_mdltransform_get_rotation_matrix (MDLTransform *self, NSTimeInterval time, float* r0c0, float* r0c1, float* r0c2, float* r0c3, float* r1c0, float* r1c1, float* r1c2, float* r1c3, float* r2c0, float* r2c1, float* r2c2, float* r2c3, float* r3c0, float* r3c1, float* r3c2, float* r3c3); +#endif + /* * Various structs used in ObjCRegistrarTest */ diff --git a/tests/test-libraries/libtest.m b/tests/test-libraries/libtest.m index b8ac5d3ab511..73c7764ee504 100644 --- a/tests/test-libraries/libtest.m +++ b/tests/test-libraries/libtest.m @@ -1,6 +1,8 @@ #import +#include #include +#include #include #include "libtest.h" @@ -15,6 +17,198 @@ void useZLib () printf ("ZLib version: %s\n", zlibVersion ()); } +typedef matrix_float2x2 (*func_x_get_matrix_float2x2_msgSend) (id self, SEL sel); +void +x_get_matrix_float2x2 (id self, const char *sel, + float* r0c0, float* r0c1, + float* r1c0, float* r1c1) +{ + matrix_float2x2 rv; +#if __i386__ + IMP msgSend = (IMP) objc_msgSend_stret; +#elif __x86_64__ + IMP msgSend = (IMP) objc_msgSend; +#elif __arm64__ + IMP msgSend = (IMP) objc_msgSend; +#elif __arm__ + IMP msgSend = (IMP) objc_msgSend_stret; +#else +#error unknown architecture +#endif + rv = ((func_x_get_matrix_float2x2_msgSend) msgSend) (self, sel_registerName (sel)); + *r0c0 = rv.columns[0][0]; + *r0c1 = rv.columns[1][0]; + *r1c0 = rv.columns[0][1]; + *r1c1 = rv.columns[1][1]; +} + +typedef matrix_float3x3 (*func_x_get_matrix_float3x3_msgSend) (id self, SEL sel); +void +x_get_matrix_float3x3 (id self, const char *sel, + float* r0c0, float* r0c1, float* r0c2, + float* r1c0, float* r1c1, float* r1c2, + float* r2c0, float* r2c1, float* r2c2) +{ + matrix_float3x3 rv; +#if __i386__ + IMP msgSend = (IMP) objc_msgSend_stret; +#elif __x86_64__ + IMP msgSend = (IMP) objc_msgSend_stret; +#elif __arm64__ + IMP msgSend = (IMP) objc_msgSend; +#elif __arm__ + IMP msgSend = (IMP) objc_msgSend_stret; +#else +#error unknown architecture +#endif + rv = ((func_x_get_matrix_float3x3_msgSend) msgSend) (self, sel_registerName (sel)); + *r0c0 = rv.columns[0][0]; + *r0c1 = rv.columns[1][0]; + *r0c2 = rv.columns[2][0]; + + *r1c0 = rv.columns[0][1]; + *r1c1 = rv.columns[1][1]; + *r1c2 = rv.columns[2][1]; + + *r2c0 = rv.columns[0][2]; + *r2c1 = rv.columns[1][2]; + *r2c2 = rv.columns[2][2]; +} + +typedef matrix_float4x4 (*func_x_get_matrix_float4x4_msgSend) (id self, SEL sel); +void +x_get_matrix_float4x4 (id self, const char *sel, + float* r0c0, float* r0c1, float* r0c2, float* r0c3, + float* r1c0, float* r1c1, float* r1c2, float* r1c3, + float* r2c0, float* r2c1, float* r2c2, float* r2c3, + float* r3c0, float* r3c1, float* r3c2, float* r3c3) +{ + matrix_float4x4 rv; +#if __i386__ + IMP msgSend = (IMP) objc_msgSend_stret; +#elif __x86_64__ + IMP msgSend = (IMP) objc_msgSend_stret; +#elif __arm64__ + IMP msgSend = (IMP) objc_msgSend; +#elif __arm__ + IMP msgSend = (IMP) objc_msgSend_stret; +#else +#error unknown architecture +#endif + rv = ((func_x_get_matrix_float4x4_msgSend) msgSend) (self, sel_registerName (sel)); + *r0c0 = rv.columns[0][0]; + *r0c1 = rv.columns[1][0]; + *r0c2 = rv.columns[2][0]; + *r0c3 = rv.columns[3][0]; + + *r1c0 = rv.columns[0][1]; + *r1c1 = rv.columns[1][1]; + *r1c2 = rv.columns[2][1]; + *r1c3 = rv.columns[3][1]; + + *r2c0 = rv.columns[0][2]; + *r2c1 = rv.columns[1][2]; + *r2c2 = rv.columns[2][2]; + *r2c3 = rv.columns[3][2]; + + *r3c0 = rv.columns[0][3]; + *r3c1 = rv.columns[1][3]; + *r3c2 = rv.columns[2][3]; + *r3c3 = rv.columns[3][3]; +} + +#if !TARGET_OS_WATCH +void +x_mdltransformcomponent_get_local_transform (id self, NSTimeInterval time, + float* r0c0, float* r0c1, float* r0c2, float* r0c3, + float* r1c0, float* r1c1, float* r1c2, float* r1c3, + float* r2c0, float* r2c1, float* r2c2, float* r2c3, + float* r3c0, float* r3c1, float* r3c2, float* r3c3) +{ + matrix_float4x4 rv; + rv = [self localTransformAtTime: time]; + *r0c0 = rv.columns[0][0]; + *r0c1 = rv.columns[1][0]; + *r0c2 = rv.columns[2][0]; + *r0c3 = rv.columns[3][0]; + + *r1c0 = rv.columns[0][1]; + *r1c1 = rv.columns[1][1]; + *r1c2 = rv.columns[2][1]; + *r1c3 = rv.columns[3][1]; + + *r2c0 = rv.columns[0][2]; + *r2c1 = rv.columns[1][2]; + *r2c2 = rv.columns[2][2]; + *r2c3 = rv.columns[3][2]; + + *r3c0 = rv.columns[0][3]; + *r3c1 = rv.columns[1][3]; + *r3c2 = rv.columns[2][3]; + *r3c3 = rv.columns[3][3]; +} + +void +x_mdltransform_create_global_transform (MDLObject *object, NSTimeInterval time, + float* r0c0, float* r0c1, float* r0c2, float* r0c3, + float* r1c0, float* r1c1, float* r1c2, float* r1c3, + float* r2c0, float* r2c1, float* r2c2, float* r2c3, + float* r3c0, float* r3c1, float* r3c2, float* r3c3) +{ + matrix_float4x4 rv; + rv = [MDLTransform globalTransformWithObject: object atTime: time]; + *r0c0 = rv.columns[0][0]; + *r0c1 = rv.columns[1][0]; + *r0c2 = rv.columns[2][0]; + *r0c3 = rv.columns[3][0]; + + *r1c0 = rv.columns[0][1]; + *r1c1 = rv.columns[1][1]; + *r1c2 = rv.columns[2][1]; + *r1c3 = rv.columns[3][1]; + + *r2c0 = rv.columns[0][2]; + *r2c1 = rv.columns[1][2]; + *r2c2 = rv.columns[2][2]; + *r2c3 = rv.columns[3][2]; + + *r3c0 = rv.columns[0][3]; + *r3c1 = rv.columns[1][3]; + *r3c2 = rv.columns[2][3]; + *r3c3 = rv.columns[3][3]; +} + +void +x_mdltransform_get_rotation_matrix (MDLTransform *self, NSTimeInterval time, + float* r0c0, float* r0c1, float* r0c2, float* r0c3, + float* r1c0, float* r1c1, float* r1c2, float* r1c3, + float* r2c0, float* r2c1, float* r2c2, float* r2c3, + float* r3c0, float* r3c1, float* r3c2, float* r3c3) +{ + matrix_float4x4 rv; + rv = [self rotationMatrixAtTime: time]; + *r0c0 = rv.columns[0][0]; + *r0c1 = rv.columns[1][0]; + *r0c2 = rv.columns[2][0]; + *r0c3 = rv.columns[3][0]; + + *r1c0 = rv.columns[0][1]; + *r1c1 = rv.columns[1][1]; + *r1c2 = rv.columns[2][1]; + *r1c3 = rv.columns[3][1]; + + *r2c0 = rv.columns[0][2]; + *r2c1 = rv.columns[1][2]; + *r2c2 = rv.columns[2][2]; + *r2c3 = rv.columns[3][2]; + + *r3c0 = rv.columns[0][3]; + *r3c1 = rv.columns[1][3]; + *r3c2 = rv.columns[2][3]; + *r3c3 = rv.columns[3][3]; +} +#endif // !TARGET_OS_WATCH + @interface UltimateMachine : NSObject { } From 5303155836fe617b8a68cffaa9ec3877ce0667ab Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 12:18:04 +0200 Subject: [PATCH 06/17] [GameplayKit] Use the new Simd-compatible matrix types, and deprecate the old API. --- src/gameplaykit.cs | 17 +++++ .../GameplayKit/GKAgent3DTest.cs | 62 +++++++++++++++++++ tests/monotouch-test/monotouch-test.csproj | 1 + 3 files changed, 80 insertions(+) create mode 100644 tests/monotouch-test/GameplayKit/GKAgent3DTest.cs diff --git a/src/gameplaykit.cs b/src/gameplaykit.cs index 587dddb718ee..8aad4729ab68 100644 --- a/src/gameplaykit.cs +++ b/src/gameplaykit.cs @@ -18,6 +18,7 @@ using Vector3 = global::OpenTK.Vector3; using Vector3d = global::OpenTK.Vector3d; using Matrix3 = global::OpenTK.Matrix3; +using Simd; #if MONOMAC using SKColor = XamCore.AppKit.NSColor; @@ -132,6 +133,8 @@ Vector3 Velocity { [Export ("rightHanded")] bool RightHanded { get; set; } +#if !XAMCORE_4_0 + [Obsolete ("Use 'Rotation3x3' instead.")] [Export ("rotation", ArgumentSemantic.Assign)] Matrix3 Rotation { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] @@ -139,6 +142,20 @@ Matrix3 Rotation { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#endif + + [Export ("rotation", ArgumentSemantic.Assign)] +#if XAMCORE_4_0 + MatrixFloat3x3 Rotation { +#else + [Sealed] + MatrixFloat3x3 Rotation3x3 { +#endif + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + set; + } [Export ("updateWithDeltaTime:")] void Update (double deltaTimeInSeconds); diff --git a/tests/monotouch-test/GameplayKit/GKAgent3DTest.cs b/tests/monotouch-test/GameplayKit/GKAgent3DTest.cs new file mode 100644 index 000000000000..cd814ee216e7 --- /dev/null +++ b/tests/monotouch-test/GameplayKit/GKAgent3DTest.cs @@ -0,0 +1,62 @@ +// +// Unit tests for GKAgent3D +// +// Authors: +// Rolf Bjarne Kvinge +// +// +// Copyright 2017 Microsoft Inc. All rights reserved. +// + +#if !__WATCHOS__ + +using System; +using OpenTK; + +#if XAMCORE_2_0 +using Foundation; +using GameplayKit; +#else +using MonoTouch.Foundation; +using MonoTouch.GameplayKit; +#endif +using Simd; +using Bindings.Test; +using NUnit.Framework; + +namespace MonoTouchFixtures.GamePlayKit +{ + [TestFixture] + [Preserve (AllMembers = true)] + public class GKAgent3DTest + { + [Test] + public void RotationTest () + { + using (var obj = new GKAgent3D ()) { + var initial = new Matrix3 (0, 0, 1, + 0, 1, 0, + 1, 0, 0); + Asserts.AreEqual (initial, obj.Rotation, "Rotation"); + Asserts.AreEqual ((MatrixFloat3x3) initial, obj.Rotation3x3, "Rotation3x3"); + + var mat = new Matrix3 (1, 2, 3, + 4, 5, 6, + 7, 8, 9); + var mat3x3 = (MatrixFloat3x3) mat; + + obj.Rotation = mat; + Asserts.AreEqual (mat, obj.Rotation, "Rotation after setter"); + var transposed3x3 = MatrixFloat3x3.Transpose ((MatrixFloat3x3) mat); + Asserts.AreEqual (transposed3x3, obj.Rotation3x3, "Rotation3x3 after setter"); + Asserts.AreEqual (transposed3x3, CFunctions.GetMatrixFloat3x3 (obj, "rotation"), "Rotation3x3 after setter native"); + + obj.Rotation3x3 = mat3x3; + Asserts.AreEqual (mat3x3, obj.Rotation3x3, "Rotation3x3 after setter 3x3"); + Asserts.AreEqual (mat3x3, CFunctions.GetMatrixFloat3x3 (obj, "rotation"), "Rotation3x3 after setter native 3x3"); + } + } + } +} + +#endif // __WATCHOS__ diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj index 073f312b3049..c52e68a02fa1 100644 --- a/tests/monotouch-test/monotouch-test.csproj +++ b/tests/monotouch-test/monotouch-test.csproj @@ -635,6 +635,7 @@ + From c2c78cee08644f3c13377c721a7c0174de795bb1 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 12:18:59 +0200 Subject: [PATCH 07/17] [SpriteKit] Use the new Simd-compatible matrix types, and deprecate the old API. --- runtime/bindings-generator.cs | 70 ++++++++++ runtime/bindings.h | 4 + src/SpriteKit/SKUniform.cs | 66 ++++++++- src/spritekit.cs | 132 ++++++++++++++++-- .../SpriteKit/SKTransformNodeTest.cs | 23 +++ tests/monotouch-test/SpriteKit/UniformTest.cs | 74 ++++++++++ 6 files changed, 351 insertions(+), 18 deletions(-) diff --git a/runtime/bindings-generator.cs b/runtime/bindings-generator.cs index 010a9ad2de20..eddf70282cf0 100644 --- a/runtime/bindings-generator.cs +++ b/runtime/bindings-generator.cs @@ -1991,6 +1991,26 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // void func (MatrixFloat2x2)", + Prefix = "simd__", + Variants = Variants.NonStret, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.MatrixFloat2x2 }, + }, + } + ); + + data.Add ( + new FunctionData { + Comment = " // MatrixFloat2x2 func ()", + Prefix = "simd__", + Variants = Variants.All, + ReturnType = Types.MatrixFloat2x2, + } + ); + data.Add ( new FunctionData { Comment = " // IntPtr func (IntPtr, ref MPSImageHistogramInfo)", @@ -2004,6 +2024,19 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // IntPtr func (IntPtr, MatrixFloat2x2)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.IntPtr }, + new ParameterData { TypeData = Types.MatrixFloat2x2 }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // void func (MatrixFloat3x3)", @@ -2056,6 +2089,19 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // IntPtr func (IntPtr, MatrixFloat3x3)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.IntPtr }, + new ParameterData { TypeData = Types.MatrixFloat3x3 }, + }, + } + ); + data.Add ( new FunctionData { Comment = " // void func (MatrixFloat4x4)", @@ -2208,6 +2254,19 @@ static IEnumerable GetFunctionData () } ); + data.Add ( + new FunctionData { + Comment = " // IntPtr func (IntPtr, MatrixFloat4x4)", + Prefix = "simd__", + Variants = Variants.NonStret, + ReturnType = Types.IntPtr, + Parameters = new ParameterData [] { + new ParameterData { TypeData = Types.IntPtr }, + new ParameterData { TypeData = Types.MatrixFloat4x4 }, + }, + } + ); + // We must expand functions with native types to their actual type as well. for (int i = data.Count - 1; i >= 0; i--) { if (!data [i].HasNativeType) @@ -2259,6 +2318,7 @@ static void MarshalToManaged (StringWriter writer, TypeData type, string nativeV } break; case "Matrix2": + case "MatrixFloat2x2": writer.WriteLine ("\tfor (int i = 0; i < 2; i++) {"); writer.WriteLine ("\t\t{0}{2}columns [i].a = {1}.columns [i] [0];", managedVariable, nativeVariable, accessor); writer.WriteLine ("\t\t{0}{2}columns [i].b = {1}.columns [i] [1];", managedVariable, nativeVariable, accessor); @@ -2377,6 +2437,7 @@ static void MarshalToNative (StringWriter writer, TypeData type, string nativeVa } break; case "Matrix2": + case "MatrixFloat2x2": writer.WriteLine ("\tfor (int i = 0; i < 2; i++) {"); writer.WriteLine ("\t\t{0}.columns [i][0] = {1}{2}columns [i].a;", nativeVariable, managedVariable, accessor); writer.WriteLine ("\t\t{0}.columns [i][1] = {1}{2}columns [i].b;", nativeVariable, managedVariable, accessor); @@ -2912,6 +2973,15 @@ public static class Types { IsX86Stret = true, IsX64Stret = false, }; + public static TypeData MatrixFloat2x2 = new TypeData { + ManagedType = "MatrixFloat2x2", + NativeType = "matrix_float2x2", + NativeWrapperType = "struct MatrixFloat2x2", + RequireMarshal = true, + IsARMStret = true, + IsX86Stret = true, + IsX64Stret = false, + }; public static TypeData Matrix3f = new TypeData { ManagedType = "Matrix3", NativeType = "matrix_float3x3", diff --git a/runtime/bindings.h b/runtime/bindings.h index 84d79e12c38f..a8ed445c3e76 100644 --- a/runtime/bindings.h +++ b/runtime/bindings.h @@ -158,6 +158,10 @@ struct Matrix2f { Vector2f columns [2]; }; +struct MatrixFloat2x2 { + Vector2f columns [2]; +}; + struct Matrix3f { Vector3f columns [3]; }; diff --git a/src/SpriteKit/SKUniform.cs b/src/SpriteKit/SKUniform.cs index b05c8ab4f06e..703a5e58587b 100644 --- a/src/SpriteKit/SKUniform.cs +++ b/src/SpriteKit/SKUniform.cs @@ -11,6 +11,8 @@ using XamCore.Foundation; using XamCore.ObjCRuntime; +using Simd; + using Vector2 = global::OpenTK.Vector2; using Vector3 = global::OpenTK.Vector3; using Vector4 = global::OpenTK.Vector4; @@ -71,9 +73,18 @@ public SKUniform (string name, Vector4 value) InitializeHandle (InitWithNameFloatVector4 (name, value), "initWithName:floatVector4:"); } +#if !XAMCORE_4_0 // Apple deprecated initWithName:floatMatrix2: in macOS10.12/iOS10.0 // and made available initWithName:matrixFloat2x2: so we invoke // the right one at runtime depending on which OS version we are running + // + // Unfortunately our 'initWithName:matrixFloat2x2:' implementation is + // incorrect (the matrix is transposed), but changing it would be a + // breaking change, so we obsolete this constructor and provide a new + // one which implements (only) 'initWithName:matrixFloat2x2:' + // correctly. However, this constructor still does the right thing for + // < macOS 10.12 / iOS 10.0 + [Obsolete ("Use the '(string, MatrixFloat2x2)' overload instead.")] public SKUniform (string name, Matrix2 value) { if (CheckSystemVersion ()) @@ -85,6 +96,14 @@ public SKUniform (string name, Matrix2 value) // Apple deprecated initWithName:floatMatrix3: in macOS10.12/iOS10.0 // and made available initWithName:matrixFloat3x3: so we invoke // the right one at runtime depending on which OS version we are running + // + // Unfortunately our 'initWithName:matrixFloat3x3:' implementation is + // incorrect (the matrix is transposed), but changing it would be a + // breaking change, so we obsolete this constructor and provide a new + // one which implements (only) 'initWithName:matrixFloat3x3:' + // correctly. However, this constructor still does the right thing for + // < macOS 10.12 / iOS 10.0 + [Obsolete ("Use the '(string, MatrixFloat3x3)' overload instead.")] public SKUniform (string name, Matrix3 value) { if (CheckSystemVersion ()) @@ -96,6 +115,14 @@ public SKUniform (string name, Matrix3 value) // Apple deprecated initWithName:floatMatrix4: in macOS10.12/iOS10.0 // and made available initWithName:matrixFloat4x4: so we invoke // the right one at runtime depending on which OS version we are running + // + // Unfortunately our 'initWithName:matrixFloat4x4:' implementation is + // incorrect (the matrix is transposed), but changing it would be a + // breaking change, so we obsolete this constructor and provide a new + // one which implements (only) 'initWithName:matrixFloat4x4:' + // correctly. However, this constructor still does the right thing for + // < macOS 10.12 / iOS 10.0 + [Obsolete ("Use the '(string, MatrixFloat4x4)' overload instead.")] public SKUniform (string name, Matrix4 value) { if (CheckSystemVersion ()) @@ -103,6 +130,7 @@ public SKUniform (string name, Matrix4 value) else InitializeHandle (InitWithNameFloatMatrix4 (name, value), "initWithName:floatMatrix4:"); } +#endif // !XAMCORE_4_0 // Apple deprecated floatVector2Value in macOS10.12/iOS10.0 // and made available vectorFloat2Value so we invoke @@ -161,20 +189,29 @@ public virtual Vector4 FloatVector4Value } } +#if !XAMCORE_4_0 // Apple deprecated floatMatrix2Value in macOS10.12/iOS10.0 // and made available matrixFloat2x2Value so we invoke // the right one at runtime depending on which OS version we are running + // + // Unfortunately our 'matrixFloat2x2Value' implementation is incorrect + // (we return a transposed matrix), but changing it would be a + // breaking change, so we obsolete this property and provide a new one + // which implements (only) 'matrixFloat4x4Value' correctly. However, + // this property still returns the correct matrix for < macOS 10.12 / + // iOS 10.0 + [Obsolete ("Use 'MatrixFloat2x2Value' instead.")] public virtual Matrix2 FloatMatrix2Value { get { if (CheckSystemVersion ()) - return _MatrixFloat2x2Value; + return (Matrix2) MatrixFloat2x2.Transpose (MatrixFloat2x2Value); else return _FloatMatrix2Value; } set { if (CheckSystemVersion ()) - _MatrixFloat2x2Value = value; + MatrixFloat2x2Value = MatrixFloat2x2.Transpose ((MatrixFloat2x2) value); else _FloatMatrix2Value = value; } @@ -183,17 +220,25 @@ public virtual Matrix2 FloatMatrix2Value // Apple deprecated floatMatrix3Value in macOS10.12/iOS10.0 // and made available matrixFloat3x3Value so we invoke // the right one at runtime depending on which OS version we are running + // + // Unfortunately our 'matrixFloat3x3Value' implementation is incorrect + // (we return a transposed matrix), but changing it would be a + // breaking change, so we obsolete this property and provide a new one + // which implements (only) 'matrixFloat3x3Value' correctly. However, + // this property still returns the correct matrix for < macOS 10.12 / + // iOS 10.0 + [Obsolete ("Use 'MatrixFloat3x3Value' instead.")] public virtual Matrix3 FloatMatrix3Value { get { if (CheckSystemVersion ()) - return _MatrixFloat3x3Value; + return (Matrix3) MatrixFloat3x3.Transpose (MatrixFloat3x3Value); else return _FloatMatrix3Value; } set { if (CheckSystemVersion ()) - _MatrixFloat3x3Value = value; + MatrixFloat3x3Value = MatrixFloat3x3.Transpose ((MatrixFloat3x3) value); else _FloatMatrix3Value = value; } @@ -202,21 +247,30 @@ public virtual Matrix3 FloatMatrix3Value // Apple deprecated floatMatrix4Value in macOS10.12/iOS10.0 // and made available matrixFloat4x4Value so we invoke // the right one at runtime depending on which OS version we are running + // + // Unfortunately our 'matrixFloat4x4Value' implementation is incorrect + // (we return a transposed matrix), but changing it would be a + // breaking change, so we obsolete this property and provide a new one + // which implements (only) 'matrixFloat4x4Value' correctly. However, + // this property still returns the correct matrix for < macOS 10.12 / + // iOS 10.0 + [Obsolete ("Use 'MatrixFloat4x4Value' instead.")] public virtual Matrix4 FloatMatrix4Value { get { if (CheckSystemVersion ()) - return _MatrixFloat4x4Value; + return (Matrix4) MatrixFloat4x4.Transpose (MatrixFloat4x4Value); else return _FloatMatrix4Value; } set { if (CheckSystemVersion ()) - _MatrixFloat4x4Value = value; + MatrixFloat4x4Value = MatrixFloat4x4.Transpose ((MatrixFloat4x4) value); else _FloatMatrix4Value = value; } } +#endif // !XAMCORE_4_0 } } #endif // XAMCORE_2_0 diff --git a/src/spritekit.cs b/src/spritekit.cs index b5e67c614d06..5b58b0598c77 100644 --- a/src/spritekit.cs +++ b/src/spritekit.cs @@ -30,6 +30,7 @@ using Matrix2 = global::OpenTK.Matrix2; using Matrix3 = global::OpenTK.Matrix3; using Matrix4 = global::OpenTK.Matrix4; +using Simd; using Vector4 = global::OpenTK.Vector4; using Quaternion = global::OpenTK.Quaternion; @@ -1748,14 +1749,19 @@ interface SKUniform : NSCopying, NSCoding { IntPtr InitWithNameVectorFloat4 (string name, Vector4 value); #endif +#if !XAMCORE_4_0 [Internal] [NoWatch] [Availability (Deprecated = Platform.iOS_10_0 | Platform.Mac_10_12)] [Export ("initWithName:floatMatrix2:")] IntPtr InitWithNameFloatMatrix2 (string name, Matrix2 value); +#endif +#if !XAMCORE_4_0 + [Obsolete ("Use the '(string, MatrixFloat2x2)' overload instead.")] [iOS (10,0)][Mac (10,12)] [TV (10,0)] + [Sealed] [Export ("initWithName:matrixFloat2x2:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] #if WATCH @@ -1764,15 +1770,25 @@ interface SKUniform : NSCopying, NSCoding { [Internal] IntPtr InitWithNameMatrixFloat2x2 (string name, Matrix2 value); #endif +#endif // !XAMCORE_4_0 + + [iOS (10,0)][Mac (10,12)] + [TV (10,0)] + [Export ("initWithName:matrixFloat2x2:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + IntPtr Constructor (string name, MatrixFloat2x2 value); +#if !XAMCORE_4_0 [Internal] [NoWatch] [Availability (Deprecated = Platform.iOS_10_0 | Platform.Mac_10_12)] [Export ("initWithName:floatMatrix3:")] IntPtr InitWithNameFloatMatrix3 (string name, Matrix3 value); + [Obsolete ("Use the '(string, MatrixFloat3x3)' overload instead.")] [iOS (10,0)][Mac (10,12)] [TV (10,0)] + [Sealed] [Export ("initWithName:matrixFloat3x3:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] #if WATCH @@ -1781,16 +1797,28 @@ interface SKUniform : NSCopying, NSCoding { [Internal] IntPtr InitWithNameMatrixFloat3x3 (string name, Matrix3 value); #endif +#endif + + [iOS (10,0)][Mac (10,12)] + [TV (10,0)] + [Export ("initWithName:matrixFloat3x3:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + IntPtr Constructor (string name, MatrixFloat3x3 value); +#if !XAMCORE_4_0 [Internal] [NoWatch] [Availability (Deprecated = Platform.iOS_10_0 | Platform.Mac_10_12)] [Export ("initWithName:floatMatrix4:")] IntPtr InitWithNameFloatMatrix4 (string name, Matrix4 value); +#endif +#if !XAMCORE_4_0 + [Obsolete ("Use the '(string, MatrixFloat4x4)' overload instead.")] [iOS (10,0)][Mac (10,12)] [TV (10,0)] [Export ("initWithName:matrixFloat4x4:")] + [Sealed] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] #if WATCH IntPtr Constructor (string name, Matrix4 value); @@ -1798,6 +1826,13 @@ interface SKUniform : NSCopying, NSCoding { [Internal] IntPtr InitWithNameMatrixFloat4x4 (string name, Matrix4 value); #endif +#endif + + [iOS (10,0)][Mac (10,12)] + [TV (10,0)] + [Export ("initWithName:matrixFloat4x4:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + IntPtr Constructor (string name, MatrixFloat4x4 value); [Export ("name")] string Name { get; } @@ -1868,59 +1903,92 @@ Vector4 _VectorFloat4Value { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#if !XAMCORE_4_0 [Internal] [Availability (Deprecated = Platform.iOS_10_0 | Platform.Mac_10_12)] [NoWatch] [Export ("floatMatrix2Value")] Matrix2 _FloatMatrix2Value { get; set; } +#endif +#if !XAMCORE_4_0 && WATCH + [Obsolete ("Use 'MatrixFloat2x2Value' instead.")] [iOS (10,0)][Mac (10,12)] [TV (10,0)] [Export ("matrixFloat2x2Value", ArgumentSemantic.Assign)] -#if WATCH Matrix2 FloatMatrix2x2Value { -#else - [Internal] - Matrix2 _MatrixFloat2x2Value { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } +#endif + +#if !XAMCORE_4_0 && WATCH + [Sealed] // The selector is already used in the 'FloatMatrix2x2Value' property. #endif + [iOS (10,0)][Mac (10,12)] + [TV (10,0)] + [Export ("matrixFloat2x2Value", ArgumentSemantic.Assign)] + MatrixFloat2x2 MatrixFloat2x2Value { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#if !XAMCORE_4_0 [Internal] [NoWatch] [Availability (Deprecated = Platform.iOS_10_0 | Platform.Mac_10_12)] [Export ("floatMatrix3Value")] Matrix3 _FloatMatrix3Value { get; set; } +#endif +#if !XAMCORE_4_0 && WATCH + [Obsolete ("Use 'MatrixFloat3x3Value' instead.")] [iOS (10,0)][Mac (10,12)] [TV (10,0)] [Export ("matrixFloat3x3Value", ArgumentSemantic.Assign)] -#if WATCH Matrix3 FloatMatrix3x3Value { -#else - [Internal] - Matrix3 _MatrixFloat3x3Value { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } +#endif + +#if !XAMCORE_4_0 && WATCH + [Sealed] // The selector is already used in the 'FloatMatrix3x3Value' property. #endif + [iOS (10,0)][Mac (10,12)] + [TV (10,0)] + [Export ("matrixFloat3x3Value", ArgumentSemantic.Assign)] + MatrixFloat3x3 MatrixFloat3x3Value { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#if !XAMCORE_4_0 [Internal] [NoWatch] [Availability (Deprecated = Platform.iOS_10_0 | Platform.Mac_10_12)] [Export ("floatMatrix4Value")] Matrix4 _FloatMatrix4Value { get; set; } +#endif +#if !XAMCORE_4_0 && WATCH + [Obsolete ("Use 'FloatMatrix4x4Value' instead.")] [iOS (10,0)][Mac (10,12)] [TV (10,0)] [Export ("matrixFloat4x4Value", ArgumentSemantic.Assign)] -#if WATCH Matrix4 FloatMatrix4x4Value { -#else - [Internal] - Matrix4 _MatrixFloat4x4Value { + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } #endif + +#if !XAMCORE_4_0 && WATCH + [Sealed] // The selector is already used in the 'FloatMatrix4x4Value' property. +#endif + [iOS (10,0)][Mac (10,12)] + [TV (10,0)] + [Export ("matrixFloat4x4Value", ArgumentSemantic.Assign)] + MatrixFloat4x4 MatrixFloat4x4Value { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } @@ -1952,23 +2020,50 @@ Matrix4 _MatrixFloat4x4Value { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] SKUniform Create (string name, Vector4 value); +#if !XAMCORE_4_0 + [Obsolete ("Use the '(string, MatrixFloat2x2)' overload instead.")] [iOS (10,0)][Mac (10,12)] [Static] [Export ("uniformWithName:matrixFloat2x2:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] SKUniform Create (string name, Matrix2 value); +#endif + + [iOS (10,0)][Mac (10,12)] + [Static] + [Export ("uniformWithName:matrixFloat2x2:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + SKUniform Create (string name, MatrixFloat2x2 value); +#if !XAMCORE_4_0 + [Obsolete ("Use the '(string, MatrixFloat3x3)' overload instead.")] [iOS (10,0)][Mac (10,12)] [Static] [Export ("uniformWithName:matrixFloat3x3:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] SKUniform Create (string name, Matrix3 value); +#endif + + [iOS (10,0)][Mac (10,12)] + [Static] + [Export ("uniformWithName:matrixFloat3x3:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + SKUniform Create (string name, MatrixFloat3x3 value); +#if !XAMCORE_4_0 + [Obsolete ("Use 'the '(string, MatrixFloat4x4)' overload instead.")] [iOS (10,0)][Mac (10,12)] [Static] [Export ("uniformWithName:matrixFloat4x4:")] [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] SKUniform Create (string name, Matrix4 value); +#endif + + [iOS (10,0)][Mac (10,12)] + [Static] + [Export ("uniformWithName:matrixFloat4x4:")] + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] + SKUniform Create (string name, MatrixFloat4x4 value); } delegate void SKActionDurationHandler (SKNode node, nfloat elapsedTime); @@ -3323,12 +3418,25 @@ Vector3 EulerAngles { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#if !XAMCORE_4_0 + [Obsolete ("Use 'RotationMatrix3x3' instead.")] [Export ("rotationMatrix")] Matrix3 RotationMatrix { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } +#endif + [Export ("rotationMatrix")] +#if XAMCORE_4_0 + MatrixFloat3x3 RotationMatrix { +#else + [Sealed] + MatrixFloat3x3 RotationMatrix3x3 { +#endif + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; + [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; + } [Export ("quaternion")] Quaternion Quaternion { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; diff --git a/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs b/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs index 2f2fcfa13574..1ee4492d33ce 100644 --- a/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs +++ b/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs @@ -15,6 +15,8 @@ using MonoTouch.ObjCRuntime; #endif using OpenTK; +using Simd; +using Bindings.Test; using NUnit.Framework; namespace MonoTouchFixtures.SpriteKit { @@ -51,6 +53,27 @@ public void RotationMatrix () obj.RotationMatrix = Matrix3.Zero; // In Swift, a rotated zero matrice also becomes the identity matrice. Asserts.AreEqual (Matrix3.Identity, obj.RotationMatrix, "RotationMatrix"); + // Changing XRotation (or YRotation for that matter), makes the RotationMatrix change too + obj.XRotation = (nfloat) (Math.PI / 2); + var rotatedMatrix = new MatrixFloat3x3 ( + 1, 0, 0, + 0, 0, -1, + 0, 1, 0 + ); + Asserts.AreEqual (rotatedMatrix, obj.RotationMatrix3x3, 0.000001f, "RotationMatrix3x3 a"); + Asserts.AreEqual (rotatedMatrix, CFunctions.GetMatrixFloat3x3 (obj, "rotationMatrix"), 0.000001f, "RotationMatrix3x3 native a"); + Asserts.AreEqual ((Matrix3) MatrixFloat3x3.Transpose (rotatedMatrix), obj.RotationMatrix, 0.000001f, "RotationMatrix a"); + + // Got this matrix after setting both XRotation and YRotation to Pi/2 + rotatedMatrix = new MatrixFloat3x3 ( + 0, 1, 0, + 0, 0, -1, + -1, 0, 0 + ); + obj.RotationMatrix3x3 = rotatedMatrix; + Asserts.AreEqual (rotatedMatrix, obj.RotationMatrix3x3, 0.000001f, "RotationMatrix3x3 b"); + Assert.AreEqual ((nfloat) (Math.PI / 2), obj.XRotation, 0.000001f, "XRotation b"); + Assert.AreEqual (0, obj.YRotation, 0.000001f, "YRotation b"); // Setting YRotation changes RotationMatrix, but setting RotationMatrix doesn't change YRotation. } } diff --git a/tests/monotouch-test/SpriteKit/UniformTest.cs b/tests/monotouch-test/SpriteKit/UniformTest.cs index 8918e56a2765..27efb3465002 100644 --- a/tests/monotouch-test/SpriteKit/UniformTest.cs +++ b/tests/monotouch-test/SpriteKit/UniformTest.cs @@ -15,7 +15,9 @@ using MonoTouch.ObjCRuntime; #endif using OpenTK; +using Simd; using NUnit.Framework; +using Bindings.Test; namespace MonoTouchFixtures.SpriteKit { @@ -76,6 +78,9 @@ public void Ctors () Matrix2 M2; Matrix3 M3; Matrix4 M4; + MatrixFloat2x2 M2x2; + MatrixFloat3x3 M3x3; + MatrixFloat4x4 M4x4; using (var obj = new SKUniform ("name")) { var M4Zero = new Matrix4 (Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero); @@ -97,6 +102,9 @@ public void Ctors () M2 = new Matrix2 (1, 2, 3, 4); M3 = new Matrix3 (1, 2, 3, 4, 5, 6, 7, 8, 9); M4 = new Matrix4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + M2x2 = (MatrixFloat2x2) M2; + M3x3 = (MatrixFloat3x3) M3; + M4x4 = (MatrixFloat4x4) M4; obj.TextureValue = texture; Assert.AreEqual (texture, obj.TextureValue, "2 TextureValue"); @@ -123,6 +131,7 @@ public void Ctors () Asserts.AreEqual (M4, obj.FloatMatrix4Value, "2 FloatMatrix4Value"); } + bool hasSimdConstructors = TestRuntime.CheckXcodeVersion (8, 0); using (var obj = new SKUniform ("name", texture)) { Assert.AreEqual (texture, obj.TextureValue, "3 TextureValue"); } @@ -145,14 +154,79 @@ public void Ctors () using (var obj = new SKUniform ("name", M2)) { Asserts.AreEqual (M2, obj.FloatMatrix2Value, "8 FloatMatrix2Value"); + Asserts.AreEqual (M2, MatrixFloat2x2.Transpose (CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value")), "8b FloatMatrix2Value"); } using (var obj = new SKUniform ("name", M3)) { Asserts.AreEqual (M3, obj.FloatMatrix3Value, "9 FloatMatrix3Value"); + Asserts.AreEqual (M3, MatrixFloat3x3.Transpose (CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value")), "9b FloatMatrix3Value"); } using (var obj = new SKUniform ("name", M4)) { Asserts.AreEqual (M4, obj.FloatMatrix4Value, "10 FloatMatrix4Value"); + Asserts.AreEqual (M4, MatrixFloat4x4.Transpose (CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value")), "10b FloatMatrix4Value"); + } + + using (var obj = new SKUniform ("name", M2x2)) { + Asserts.AreEqual (M2x2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value"); + Asserts.AreEqual (M2x2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value"); + var tmp2 = new MatrixFloat2x2 (9, 8, 7, 6); + obj.MatrixFloat2x2Value = tmp2; + Asserts.AreEqual (tmp2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value second"); + Asserts.AreEqual (tmp2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value second"); + } + + using (var obj = new SKUniform ("name", M3x3)) { + Asserts.AreEqual (M3x3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value"); + Asserts.AreEqual (M3x3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value"); + var tmp3 = new MatrixFloat3x3 (9, 8, 7, 6, 5, 4, 3, 2, 1); + obj.MatrixFloat3x3Value = tmp3; + Asserts.AreEqual (tmp3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value second"); + Asserts.AreEqual (tmp3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value second"); + } + + using (var obj = new SKUniform ("name", M4x4)) { + Asserts.AreEqual (M4x4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value"); + Asserts.AreEqual (M4x4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b FloatMatrix4Value"); + var tmp4 = new MatrixFloat4x4 (9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6); + obj.MatrixFloat4x4Value = tmp4; + Asserts.AreEqual (tmp4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value second"); + Asserts.AreEqual (tmp4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b MatrixFloat4x4Value second"); + } + } + + [Test] + public void Create () + { + var M2x2 = new MatrixFloat2x2 (1, 2, 3, 4); + var M3x3 = new MatrixFloat3x3 (1, 2, 3, 4, 5, 6, 7, 8, 9); + var M4x4 = new MatrixFloat4x4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + + using (var obj = SKUniform.Create ("name", M2x2)) { + Asserts.AreEqual (M2x2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value"); + Asserts.AreEqual (M2x2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value"); + var tmp2 = new MatrixFloat2x2 (9, 8, 7, 6); + obj.MatrixFloat2x2Value = tmp2; + Asserts.AreEqual (tmp2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value second"); + Asserts.AreEqual (tmp2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value second"); + } + + using (var obj = SKUniform.Create ("name", M3x3)) { + Asserts.AreEqual (M3x3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value"); + Asserts.AreEqual (M3x3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value"); + var tmp3 = new MatrixFloat3x3 (9, 8, 7, 6, 5, 4, 3, 2, 1); + obj.MatrixFloat3x3Value = tmp3; + Asserts.AreEqual (tmp3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value second"); + Asserts.AreEqual (tmp3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value second"); + } + + using (var obj = SKUniform.Create ("name", M4x4)) { + Asserts.AreEqual (M4x4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value"); + Asserts.AreEqual (M4x4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b FloatMatrix4Value"); + var tmp4 = new MatrixFloat4x4 (9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6); + obj.MatrixFloat4x4Value = tmp4; + Asserts.AreEqual (tmp4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value second"); + Asserts.AreEqual (tmp4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b MatrixFloat4x4Value second"); } } } From 8ec1bafdd8a863d3503872065600e1445330bada Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 14:50:54 +0200 Subject: [PATCH 08/17] [xtro] Don't report missing [MarshalDirective] for obsolete methods. --- tests/xtro-sharpie/SimdCheck.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/xtro-sharpie/SimdCheck.cs b/tests/xtro-sharpie/SimdCheck.cs index f52485e7e602..7f3a19d21e2a 100644 --- a/tests/xtro-sharpie/SimdCheck.cs +++ b/tests/xtro-sharpie/SimdCheck.cs @@ -271,6 +271,9 @@ void CheckMarshalDirective (MethodDefinition method, string simd_type) if (!method.HasBody) return; + if (method.IsObsolete ()) + return; + // The [MarshalDirective] attribute isn't copied to the generated code, // so instead apply some heuristics and detect calls to the xamarin_simd__ P/Invoke, // and if there are any, then assume the method binding has a [MarshalDirective]. From 11b0eb96dc4dd1c7695c233cda128250041bfeaa Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 31 Aug 2017 14:51:44 +0200 Subject: [PATCH 09/17] [xtro] Remove unnecessary ignores. The implementation changed, and these stayed accidentally. --- tests/xtro-sharpie/common.ignore | 38 -------------------------------- 1 file changed, 38 deletions(-) diff --git a/tests/xtro-sharpie/common.ignore b/tests/xtro-sharpie/common.ignore index ac09bc6c59d9..c8d1b13ca3f7 100644 --- a/tests/xtro-sharpie/common.ignore +++ b/tests/xtro-sharpie/common.ignore @@ -73,11 +73,6 @@ ## part of category GKScore_Deprecated !missing-selector! GKScore::playerID not bound -# GameplayKit - -# Bound as GKAgent3D.Rotation3x3 -!simd-can't-map-native! GKAgent3D::rotation: could not find a managed method (selector: name: GKAgent3D::. Found the simd type 'matrix_float3x3' in the native signature.' - # Intents ## not exposed by our API (better use the OS version) @@ -184,39 +179,6 @@ !incorrect-protocol-member! MDLMeshBufferZone::allocator is REQUIRED and should be abstract !incorrect-protocol-member! MDLMeshBufferZone::capacity is REQUIRED and should be abstract -## MDLTransformComponent is a protocol, which makes mapping non-trivial because the only place that has the required information is in the protocol's ProtocolMember attributes. - -## This selector does not have a fixed version with the correct -## Simd matrix, because it's a static member in a protocol, so creating an -## extension method doesn't make much sense. -!simd-can't-map-native! MDLTransformComponent::globalTransformWithObject:atTime:: could not find a managed method (selector: globalTransformWithObject:atTime: name: +MDLTransformComponent::globalTransformWithObject:atTime:. Found the simd type 'matrix_float4x4' in the native signature. - -## A Simd-fixed version exists as an extension method in the protocol interface (MDLTransformComponent_Extensions.GetLocalTransform4x4) -!simd-can't-map-native! MDLTransformComponent::localTransformAtTime:: could not find a managed method (selector: localTransformAtTime: name: MDLTransformComponent::localTransformAtTime:. Found the simd type 'matrix_float4x4' in the native signature. - -## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.GetMatrix4x4 -!simd-can't-map-native! MDLTransformComponent::matrix: could not find a managed method (selector: name: MDLTransformComponent::matrix. Found the simd type 'matrix_float4x4' in the native signature. - -## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.SetMatrix4x4 -!simd-can't-map-native! MDLTransformComponent::setMatrix:: could not find a managed method (selector: setMatrix: name: MDLTransformComponent::setMatrix:. Found the simd type 'matrix_float4x4' in the native signature. - -## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.SetLocalTransform -!simd-can't-map-native! MDLTransformComponent::setLocalTransform:: could not find a managed method (selector: setLocalTransform: name: MDLTransformComponent::setLocalTransform:. Found the simd type 'matrix_float4x4' in the native signature. - -## A Simd-fixed version exists as an extension method: MDLTransformComponent_Extensions.SetLocalTransform -!simd-can't-map-native! MDLTransformComponent::setLocalTransform:forTime:: could not find a managed method (selector: setLocalTransform:forTime: name: MDLTransformComponent::setLocalTransform:forTime:. Found the simd type 'matrix_float4x4' in the native signature. - -## All the MDLMesh constructors below are bound as internal functions. -!simd-can't-map-native! MDLMesh::initBoxWithExtent:segments:inwardNormals:geometryType:allocator:: could not find a managed method (selector: initBoxWithExtent:segments:inwardNormals:geometryType:allocator: name: Generators::initBoxWithExtent:segments:inwardNormals:geometryType:allocator:. Found the simd type 'vector_uint3' in the native signature. -!simd-can't-map-native! MDLMesh::initCapsuleWithExtent:cylinderSegments:hemisphereSegments:inwardNormals:geometryType:allocator:: could not find a managed method (selector: initCapsuleWithExtent:cylinderSegments:hemisphereSegments:inwardNormals:geometryType:allocator: name: Generators::initCapsuleWithExtent:cylinderSegments:hemisphereSegments:inwardNormals:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. -!simd-can't-map-native! MDLMesh::initConeWithExtent:segments:inwardNormals:cap:geometryType:allocator:: could not find a managed method (selector: initConeWithExtent:segments:inwardNormals:cap:geometryType:allocator: name: Generators::initConeWithExtent:segments:inwardNormals:cap:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. -!simd-can't-map-native! MDLMesh::initCylinderWithExtent:segments:inwardNormals:topCap:bottomCap:geometryType:allocator:: could not find a managed method (selector: initCylinderWithExtent:segments:inwardNormals:topCap:bottomCap:geometryType:allocator: name: Generators::initCylinderWithExtent:segments:inwardNormals:topCap:bottomCap:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. -!simd-can't-map-native! MDLMesh::initHemisphereWithExtent:segments:inwardNormals:cap:geometryType:allocator:: could not find a managed method (selector: initHemisphereWithExtent:segments:inwardNormals:cap:geometryType:allocator: name: Generators::initHemisphereWithExtent:segments:inwardNormals:cap:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. -!simd-can't-map-native! MDLMesh::initPlaneWithExtent:segments:geometryType:allocator:: could not find a managed method (selector: initPlaneWithExtent:segments:geometryType:allocator: name: Generators::initPlaneWithExtent:segments:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. -!simd-can't-map-native! MDLMesh::initSphereWithExtent:segments:inwardNormals:geometryType:allocator:: could not find a managed method (selector: initSphereWithExtent:segments:inwardNormals:geometryType:allocator: name: Generators::initSphereWithExtent:segments:inwardNormals:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. -!simd-can't-map-native! MDLMesh::newBoxWithDimensions:segments:geometryType:inwardNormals:allocator:: could not find a managed method (selector: newBoxWithDimensions:segments:geometryType:inwardNormals:allocator: name: +Generators::newBoxWithDimensions:segments:geometryType:inwardNormals:allocator:. Found the simd type 'vector_uint3' in the native signature. -!simd-can't-map-native! MDLMesh::newPlaneWithDimensions:segments:geometryType:allocator:: could not find a managed method (selector: newPlaneWithDimensions:segments:geometryType:allocator: name: +Generators::newPlaneWithDimensions:segments:geometryType:allocator:. Found the simd type 'vector_uint2' in the native signature. - # Security ## part of mscorlib.dll -> mcs/class/corlib/CommonCrypto/CommonCrypto.cs to implement RNGCryptoServiceProvider From 96ad068015c1e47d2bc6a4c5de3cd0e76d826550 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 09:37:58 +0200 Subject: [PATCH 10/17] [xtro] Reword some of the Simd diagnostic messages according to review. --- tests/xtro-sharpie/SimdCheck.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/xtro-sharpie/SimdCheck.cs b/tests/xtro-sharpie/SimdCheck.cs index 7f3a19d21e2a..0a17cd69d2b1 100644 --- a/tests/xtro-sharpie/SimdCheck.cs +++ b/tests/xtro-sharpie/SimdCheck.cs @@ -207,7 +207,7 @@ bool IsExtVector (QualType type, ref string simd_type) 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'."); + Console.WriteLine ($"!unknown-simd-type! Could not detect that {typeName} is a Simd type, but its name contains 'simd'. Something needs fixing in SimdCheck.cs"); if (rv) simd_type = typeName; @@ -226,7 +226,7 @@ bool IsSimdType (QualType type, ref string simd_type, ref bool requires_marshal_ } 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"); + Console.WriteLine ($"!unknown-simd-type-mapping! The Simd type {simd_type} does not have a mapping to a managed type. Please add one in SimdCheck.cs"); return false; } @@ -303,7 +303,7 @@ void CheckMarshalDirective (MethodDefinition method, string simd_type) if (!anyCalls) return; - Console.WriteLine ($"!simd-missing-marshaldirective! {method}: simd type: {simd_type}"); + Console.WriteLine ($"!wrong-simd-missing-marshaldirective! {method}: simd type: {simd_type}"); } public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKind) @@ -359,7 +359,7 @@ public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKi 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."); + Console.WriteLine ($"!simd-can't-map-native! {decl}: could not find a managed method for the native method {decl.GetName ()} (selector: {decl.Selector}). Found the simd type '{simd_type}' in the native signature."); return; } From d562435005e68712082eecf69065370df2a186f7 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 11:11:06 +0200 Subject: [PATCH 11/17] [tests] Make sure test symbols don't clash between different test libraries. 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. --- tests/test-libraries/rename.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test-libraries/rename.h b/tests/test-libraries/rename.h index 5d51469e4781..4d8fc21c82ab 100644 --- a/tests/test-libraries/rename.h +++ b/tests/test-libraries/rename.h @@ -53,6 +53,12 @@ #define CtorChaining1 object_CtorChaining1 #define ObjCExceptionTest object_ObjCExceptionTest #define ObjCProtocolClassTest object_ObjCProtocolClassTest + #define x_mdltransform_get_rotation_matrix object_x_mdltransform_get_rotation_matrix + #define x_mdltransformcomponent_get_local_transform object_x_mdltransformcomponent_get_local_transform + #define x_mdltransform_create_global_transform object_x_mdltransform_create_global_transform + #define x_get_matrix_float4x4 object_x_get_matrix_float4x4 + #define x_get_matrix_float3x3 object_x_get_matrix_float3x3 + #define x_get_matrix_float2x2 object_x_get_matrix_float2x2 #elif PREFIX == 2 #define theUltimateAnswer ar_theUltimateAnswer #define useZLib ar_useZLib @@ -107,6 +113,12 @@ #define CtorChaining1 ar_CtorChaining1 #define ObjCExceptionTest ar_ObjCExceptionTest #define ObjCProtocolClassTest ar_ObjCProtocolClassTest + #define x_mdltransform_get_rotation_matrix ar_x_mdltransform_get_rotation_matrix + #define x_mdltransformcomponent_get_local_transform ar_x_mdltransformcomponent_get_local_transform + #define x_mdltransform_create_global_transform ar_x_mdltransform_create_global_transform + #define x_get_matrix_float4x4 ar_x_get_matrix_float4x4 + #define x_get_matrix_float3x3 ar_x_get_matrix_float3x3 + #define x_get_matrix_float2x2 ar_x_get_matrix_float2x2 #else // keep original names #endif From b80cfee33eb93b4f6f16ffe9ace534ee2735faee Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 11:14:46 +0200 Subject: [PATCH 12/17] [tests] Since libtest.a need ModelIO now, the corresponding LinkWith attributes need to state that too. --- .../XTest.framework.linkwith.cs | 15 ++++++++++++--- tests/bindings-test/libtest.linkwith.cs | 11 ++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/bindings-framework-test/XTest.framework.linkwith.cs b/tests/bindings-framework-test/XTest.framework.linkwith.cs index 8d0206b07deb..fb6f1c942109 100644 --- a/tests/bindings-framework-test/XTest.framework.linkwith.cs +++ b/tests/bindings-framework-test/XTest.framework.linkwith.cs @@ -7,7 +7,16 @@ using System.Runtime.InteropServices; #if __UNIFIED__ -[assembly: LinkWith ("XTest.framework")] -[assembly: LinkWith ("XStaticObjectTest.framework", LinkerFlags = "-lz")] -[assembly: LinkWith ("XStaticArTest.framework")] +[assembly: LinkWith ("XTest.framework", Frameworks = LinkWithConstants.Frameworks)] +[assembly: LinkWith ("XStaticObjectTest.framework", LinkerFlags = "-lz", Frameworks = LinkWithConstants.Frameworks)] +[assembly: LinkWith ("XStaticArTest.framework", Frameworks = LinkWithConstants.Frameworks)] #endif + +static class LinkWithConstants +{ +#if __WATCHOS__ + public const string Frameworks = ""; +#else + public const string Frameworks = "ModelIO"; +#endif +} diff --git a/tests/bindings-test/libtest.linkwith.cs b/tests/bindings-test/libtest.linkwith.cs index df0c9c264c2c..15cef4441237 100644 --- a/tests/bindings-test/libtest.linkwith.cs +++ b/tests/bindings-test/libtest.linkwith.cs @@ -6,9 +6,18 @@ #endif using System.Runtime.InteropServices; -[assembly: LinkWith ("libtest.a", LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Arm64 | LinkTarget.Simulator64, SmartLink = true, Frameworks = "Foundation" , LinkerFlags = "-lz")] +[assembly: LinkWith ("libtest.a", LinkTarget.Simulator | LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Arm64 | LinkTarget.Simulator64, SmartLink = true, Frameworks = LinkWithConstants.Frameworks, LinkerFlags = "-lz")] public static class LibTest { [DllImport ("__Internal")] public static extern int theUltimateAnswer (); } + +static class LinkWithConstants +{ +#if __WATCHOS__ + public const string Frameworks = "Foundation"; +#else + public const string Frameworks = "Foundation ModelIO"; +#endif +} From b97ea9f5d0bc33061ee97ae46ac1ac19aa74aebe Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 11:15:41 +0200 Subject: [PATCH 13/17] [introspection] Don't check native signatures on obsolete members, and 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 --- tests/introspection/ApiSignatureTest.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/introspection/ApiSignatureTest.cs b/tests/introspection/ApiSignatureTest.cs index bfd50cc1e95a..dfb92a153976 100644 --- a/tests/introspection/ApiSignatureTest.cs +++ b/tests/introspection/ApiSignatureTest.cs @@ -233,6 +233,10 @@ void CheckMemberSignature (MethodBase m, Type t, IntPtr class_ptr, ref int n) if (methodinfo == null && constructorinfo == null) return; + // Don't check obsolete methods, it could be obsoleted because it was broken. + if (m.GetCustomAttributes () != null) + return; + if (m.DeclaringType != t) return; @@ -388,9 +392,9 @@ static bool IgnoreSimd (Type pt) case "Vector4": case "Vector4i": case "Vector4d": - case "Matrix2": - case "Matrix3": - case "Matrix4": + case "MatrixFloat2x2": + case "MatrixFloat3x3": + case "MatrixFloat4x4": case "MDLAxisAlignedBoundingBox": // struct { Vector3, Vector3 } return true; default: From 6f2549fae60e695c1ead424d743d6a210ba3ae76 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 11:34:29 +0200 Subject: [PATCH 14/17] [monotouch-tests] Include more custom asserts for watchOS to make the 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' [...] --- tests/monotouch-test/Asserts.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/monotouch-test/Asserts.cs b/tests/monotouch-test/Asserts.cs index d40d7e71256a..6a1037aa64e2 100644 --- a/tests/monotouch-test/Asserts.cs +++ b/tests/monotouch-test/Asserts.cs @@ -15,7 +15,6 @@ public static class Asserts { -#if !__WATCHOS__ public static void AreEqual (bool expected, bool actual, string message) { Assert.AreEqual (expected, actual, message + " (M)"); @@ -123,11 +122,13 @@ public static void AreEqual (Vector2i expected, Vector2i actual, string message) Assert.AreEqual (expected.Y, actual.Y, message + " (Y)"); } +#if !__WATCHOS__ public static void AreEqual (MDLAxisAlignedBoundingBox expected, MDLAxisAlignedBoundingBox actual, string message) { AreEqual (expected.MaxBounds, actual.MaxBounds, message + " (MaxBounds)"); AreEqual (expected.MinBounds, actual.MinBounds, message + " (MinBounds)"); } +#endif // !__WATCHOS__ public static void AreEqual (Quaternion expected, Quaternion actual, string message) { @@ -137,7 +138,7 @@ public static void AreEqual (Quaternion expected, Quaternion actual, string mess Assert.AreEqual (expected.W, actual.W, message + " (W)"); } -#if !MONOMAC +#if !MONOMAC && !__WATCHOS__ public static void AreEqual (MPSImageHistogramInfo expected, MPSImageHistogramInfo actual, string message) { Assert.AreEqual (expected.HistogramForAlpha, actual.HistogramForAlpha, message + " HistogramForAlpha"); @@ -145,7 +146,7 @@ public static void AreEqual (MPSImageHistogramInfo expected, MPSImageHistogramIn Asserts.AreEqual (expected.MinPixelValue, actual.MinPixelValue, message + " MinPixelValue"); Assert.AreEqual (expected.NumberOfHistogramEntries, actual.NumberOfHistogramEntries, message + " NumberOfHistogramEntries"); } -#endif // !MONOMAC +#endif // !MONOMAC && !__WATCHOS__ public static void AreEqual (MatrixFloat2x2 expected, MatrixFloat2x2 actual, string message) { @@ -330,6 +331,5 @@ public static void AreEqual (MatrixFloat4x4 expected, Matrix4 actual, string mes AreEqual (expected.M34, actual.M34, message + " (M34)"); AreEqual (expected.M44, actual.M44, message + " (M44)"); } -#endif // !__WATCHOS__ } From 371827e7dc0366a0fdc102e70fa1212e0fbe6e63 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 11:58:29 +0200 Subject: [PATCH 15/17] [monotouch-test] Exclude code that requires the binding project from 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?) --- .../ModelIO/MDLMaterialProperty.cs | 6 ++++ tests/monotouch-test/ModelIO/MDLTransform.cs | 6 ++++ tests/monotouch-test/SpriteKit/UniformTest.cs | 32 +++++++++++++++++++ tests/xammac_tests/xammac_tests.csproj | 4 +-- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs b/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs index 4e1e68622109..6ef2d6f65c10 100644 --- a/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs +++ b/tests/monotouch-test/ModelIO/MDLMaterialProperty.cs @@ -34,7 +34,9 @@ #endif using OpenTK; using Simd; +#if !TEST_BINDINGS_UNAVAILABLE using Bindings.Test; +#endif using NUnit.Framework; namespace MonoTouchFixtures.ModelIO { @@ -191,12 +193,16 @@ public void Ctors () using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, M4)) { Asserts.AreEqual (M4, obj.Matrix4x4, "7 Matrix4x4"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (CFunctions.GetMatrixFloat4x4 (obj, "matrix4x4"), obj.MatrixFloat4x4, "7b MatrixFloat4x4"); +#endif Asserts.AreEqual (MatrixFloat4x4.Transpose ((MatrixFloat4x4) M4), obj.MatrixFloat4x4, "7c MatrixFloat4x4"); } using (var obj = new MDLMaterialProperty ("name", MDLMaterialSemantic.AmbientOcclusion, M4x4)) { +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (CFunctions.GetMatrixFloat4x4 (obj, "matrix4x4"), obj.MatrixFloat4x4, "7' MatrixFloat4x4"); +#endif Asserts.AreEqual (M4x4, obj.MatrixFloat4x4, "7'b MatrixFloat4x4"); } diff --git a/tests/monotouch-test/ModelIO/MDLTransform.cs b/tests/monotouch-test/ModelIO/MDLTransform.cs index 4c9435bd32af..4020dd22340a 100644 --- a/tests/monotouch-test/ModelIO/MDLTransform.cs +++ b/tests/monotouch-test/ModelIO/MDLTransform.cs @@ -31,7 +31,9 @@ #endif using OpenTK; using Simd; +#if !TEST_BINDINGS_UNAVAILABLE using Bindings.Test; +#endif using NUnit.Framework; namespace MonoTouchFixtures.ModelIO { @@ -145,7 +147,9 @@ public void Ctors () Asserts.AreEqual (new Vector3 (4, 3, 2), obj.Scale, "Scale 4"); Asserts.AreEqual (new Vector3 (2, 3, 4), obj.Translation, "Translation 4"); Asserts.AreEqual (m4x4, obj.GetMatrix4x4 (), 0.0001f, "Matrix4x4 4"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (m4x4, CFunctions.GetMatrixFloat4x4 (obj, "matrix"), 0.0001f, "Matrix4x4-native 4"); +#endif } } @@ -201,7 +205,9 @@ public void GetRotationMatrixTest () ); Asserts.AreEqual ((Matrix4) MatrixFloat4x4.Transpose (expected), obj.GetRotationMatrix (0), 0.00001f, "GetRotationMatrix"); Asserts.AreEqual (expected, obj.GetRotationMatrix4x4 (0), 0.00001f, "GetRotationMatrix4x4"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (expected, CFunctions.MDLTransform_GetRotationMatrix (obj, 0), 0.00001f, "GetRotationMatrix4x4 native"); +#endif } } } diff --git a/tests/monotouch-test/SpriteKit/UniformTest.cs b/tests/monotouch-test/SpriteKit/UniformTest.cs index 27efb3465002..7906af966606 100644 --- a/tests/monotouch-test/SpriteKit/UniformTest.cs +++ b/tests/monotouch-test/SpriteKit/UniformTest.cs @@ -17,7 +17,9 @@ using OpenTK; using Simd; using NUnit.Framework; +#if !TEST_BINDINGS_UNAVAILABLE using Bindings.Test; +#endif namespace MonoTouchFixtures.SpriteKit { @@ -154,44 +156,62 @@ public void Ctors () using (var obj = new SKUniform ("name", M2)) { Asserts.AreEqual (M2, obj.FloatMatrix2Value, "8 FloatMatrix2Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M2, MatrixFloat2x2.Transpose (CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value")), "8b FloatMatrix2Value"); +#endif } using (var obj = new SKUniform ("name", M3)) { Asserts.AreEqual (M3, obj.FloatMatrix3Value, "9 FloatMatrix3Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M3, MatrixFloat3x3.Transpose (CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value")), "9b FloatMatrix3Value"); +#endif } using (var obj = new SKUniform ("name", M4)) { Asserts.AreEqual (M4, obj.FloatMatrix4Value, "10 FloatMatrix4Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M4, MatrixFloat4x4.Transpose (CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value")), "10b FloatMatrix4Value"); +#endif } using (var obj = new SKUniform ("name", M2x2)) { Asserts.AreEqual (M2x2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M2x2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value"); +#endif var tmp2 = new MatrixFloat2x2 (9, 8, 7, 6); obj.MatrixFloat2x2Value = tmp2; Asserts.AreEqual (tmp2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value second"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (tmp2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value second"); +#endif } using (var obj = new SKUniform ("name", M3x3)) { Asserts.AreEqual (M3x3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M3x3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value"); +#endif var tmp3 = new MatrixFloat3x3 (9, 8, 7, 6, 5, 4, 3, 2, 1); obj.MatrixFloat3x3Value = tmp3; Asserts.AreEqual (tmp3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value second"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (tmp3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value second"); +#endif } using (var obj = new SKUniform ("name", M4x4)) { Asserts.AreEqual (M4x4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M4x4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b FloatMatrix4Value"); +#endif var tmp4 = new MatrixFloat4x4 (9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6); obj.MatrixFloat4x4Value = tmp4; Asserts.AreEqual (tmp4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value second"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (tmp4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b MatrixFloat4x4Value second"); +#endif } } @@ -204,29 +224,41 @@ public void Create () using (var obj = SKUniform.Create ("name", M2x2)) { Asserts.AreEqual (M2x2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M2x2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value"); +#endif var tmp2 = new MatrixFloat2x2 (9, 8, 7, 6); obj.MatrixFloat2x2Value = tmp2; Asserts.AreEqual (tmp2, obj.MatrixFloat2x2Value, "11 MatrixFloat2x2Value second"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (tmp2, CFunctions.GetMatrixFloat2x2 (obj, "matrixFloat2x2Value"), "11b MatrixFloat2x2Value second"); +#endif } using (var obj = SKUniform.Create ("name", M3x3)) { Asserts.AreEqual (M3x3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M3x3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value"); +#endif var tmp3 = new MatrixFloat3x3 (9, 8, 7, 6, 5, 4, 3, 2, 1); obj.MatrixFloat3x3Value = tmp3; Asserts.AreEqual (tmp3, obj.MatrixFloat3x3Value, "12 MatrixFloat3x3Value second"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (tmp3, CFunctions.GetMatrixFloat3x3 (obj, "matrixFloat3x3Value"), "12b MatrixFloat3x3Value second"); +#endif } using (var obj = SKUniform.Create ("name", M4x4)) { Asserts.AreEqual (M4x4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (M4x4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b FloatMatrix4Value"); +#endif var tmp4 = new MatrixFloat4x4 (9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6); obj.MatrixFloat4x4Value = tmp4; Asserts.AreEqual (tmp4, obj.MatrixFloat4x4Value, "13 MatrixFloat4x4Value second"); +#if !TEST_BINDINGS_UNAVAILABLE Asserts.AreEqual (tmp4, CFunctions.GetMatrixFloat4x4 (obj, "matrixFloat4x4Value"), "13b MatrixFloat4x4Value second"); +#endif } } } diff --git a/tests/xammac_tests/xammac_tests.csproj b/tests/xammac_tests/xammac_tests.csproj index 831b77e2820f..4c4f707f8120 100644 --- a/tests/xammac_tests/xammac_tests.csproj +++ b/tests/xammac_tests/xammac_tests.csproj @@ -17,7 +17,7 @@ full false bin\x86\Debug - __UNIFIED__;DEBUG;MONOMAC;XAMCORE_2_0 + __UNIFIED__;DEBUG;MONOMAC;XAMCORE_2_0;TEST_BINDINGS_UNAVAILABLE prompt 4 false @@ -38,7 +38,7 @@ true bin\x86\Release - __UNIFIED__;MONOMAC;XAMCORE_2_0 + __UNIFIED__;MONOMAC;XAMCORE_2_0;TEST_BINDINGS_UNAVAILABLE prompt 4 false From 45c37d2905de9f41fac8bc06de1863aa62fad3e3 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 1 Sep 2017 15:17:51 +0200 Subject: [PATCH 16/17] [xtro] Reword some of the Simd diagnostic messages according to review. --- tests/xtro-sharpie/SimdCheck.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/xtro-sharpie/SimdCheck.cs b/tests/xtro-sharpie/SimdCheck.cs index 0a17cd69d2b1..be487ca64193 100644 --- a/tests/xtro-sharpie/SimdCheck.cs +++ b/tests/xtro-sharpie/SimdCheck.cs @@ -125,7 +125,7 @@ public override void VisitManagedMethod (MethodDefinition method) if (contains_simd_types && very_strict) { // We can't map this method to a native function. - Console.WriteLine ($"!simd-can't-map-managed! {method}"); + Console.WriteLine ($"!missing-simd-native-signature! {method}"); } return; } @@ -133,7 +133,7 @@ public override void VisitManagedMethod (MethodDefinition method) 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}'"); + Console.WriteLine ($"!duplicate-type-mapping! same key '{key}' for both '{existing.Method}' and '{method}'"); } else { managed_methods [key] = new ManagedSimdInfo { Method = method, ContainsInvalidMappingForSimd = invalid_simd_type @@ -359,7 +359,7 @@ public override void VisitObjCMethodDecl (ObjCMethodDecl decl, VisitKind visitKi return; if (!strict) return; - Console.WriteLine ($"!simd-can't-map-native! {decl}: could not find a managed method for the native method {decl.GetName ()} (selector: {decl.Selector}). Found the simd type '{simd_type}' in the native signature."); + Console.WriteLine ($"!missing-simd-managed-method! {decl}: could not find a managed method for the native method {decl.GetName ()} (selector: {decl.Selector}). Found the simd type '{simd_type}' in the native signature."); return; } From 977a976959df86578b77afc1e5828fcf9ce3ae66 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 4 Sep 2017 09:13:53 +0200 Subject: [PATCH 17/17] [SpriteKit] SKTransformNode is new in Xcode 9 so no need to keep the broken (and obsolete) non-simd version of RotationMatrix. --- src/spritekit.cs | 15 +-------------- .../SpriteKit/SKTransformNodeTest.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/spritekit.cs b/src/spritekit.cs index 5b58b0598c77..251a224a7aac 100644 --- a/src/spritekit.cs +++ b/src/spritekit.cs @@ -3418,25 +3418,12 @@ Vector3 EulerAngles { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } -#if !XAMCORE_4_0 - [Obsolete ("Use 'RotationMatrix3x3' instead.")] - [Export ("rotationMatrix")] - Matrix3 RotationMatrix { - [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; - [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; - } -#endif - [Export ("rotationMatrix")] -#if XAMCORE_4_0 MatrixFloat3x3 RotationMatrix { -#else - [Sealed] - MatrixFloat3x3 RotationMatrix3x3 { -#endif [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] set; } + [Export ("quaternion")] Quaternion Quaternion { [MarshalDirective (NativePrefix = "xamarin_simd__", Library = "__Internal")] get; diff --git a/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs b/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs index 1ee4492d33ce..0168d9f4ce3c 100644 --- a/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs +++ b/tests/monotouch-test/SpriteKit/SKTransformNodeTest.cs @@ -50,9 +50,10 @@ public void EulerAngles () public void RotationMatrix () { using (var obj = new SKTransformNode ()) { - obj.RotationMatrix = Matrix3.Zero; + var zero = new MatrixFloat3x3 (); + obj.RotationMatrix = zero; // In Swift, a rotated zero matrice also becomes the identity matrice. - Asserts.AreEqual (Matrix3.Identity, obj.RotationMatrix, "RotationMatrix"); + Asserts.AreEqual (MatrixFloat3x3.Identity, obj.RotationMatrix, "RotationMatrix"); // Changing XRotation (or YRotation for that matter), makes the RotationMatrix change too obj.XRotation = (nfloat) (Math.PI / 2); var rotatedMatrix = new MatrixFloat3x3 ( @@ -60,9 +61,8 @@ public void RotationMatrix () 0, 0, -1, 0, 1, 0 ); - Asserts.AreEqual (rotatedMatrix, obj.RotationMatrix3x3, 0.000001f, "RotationMatrix3x3 a"); - Asserts.AreEqual (rotatedMatrix, CFunctions.GetMatrixFloat3x3 (obj, "rotationMatrix"), 0.000001f, "RotationMatrix3x3 native a"); - Asserts.AreEqual ((Matrix3) MatrixFloat3x3.Transpose (rotatedMatrix), obj.RotationMatrix, 0.000001f, "RotationMatrix a"); + Asserts.AreEqual (rotatedMatrix, obj.RotationMatrix, 0.000001f, "RotationMatrix a"); + Asserts.AreEqual (rotatedMatrix, CFunctions.GetMatrixFloat3x3 (obj, "rotationMatrix"), 0.000001f, "RotationMatrix native a"); // Got this matrix after setting both XRotation and YRotation to Pi/2 rotatedMatrix = new MatrixFloat3x3 ( @@ -70,8 +70,8 @@ public void RotationMatrix () 0, 0, -1, -1, 0, 0 ); - obj.RotationMatrix3x3 = rotatedMatrix; - Asserts.AreEqual (rotatedMatrix, obj.RotationMatrix3x3, 0.000001f, "RotationMatrix3x3 b"); + obj.RotationMatrix = rotatedMatrix; + Asserts.AreEqual (rotatedMatrix, obj.RotationMatrix, 0.000001f, "RotationMatrix b"); Assert.AreEqual ((nfloat) (Math.PI / 2), obj.XRotation, 0.000001f, "XRotation b"); Assert.AreEqual (0, obj.YRotation, 0.000001f, "YRotation b"); // Setting YRotation changes RotationMatrix, but setting RotationMatrix doesn't change YRotation. }