Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions runtime/bindings-generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2632,6 +2632,15 @@ static IEnumerable<FunctionData> GetFunctionData ()
}
);

data.Add (
new FunctionData {
Comment = " // NVector16b func ()",
Prefix = "simd__",
Variants = Variants.NonStret,
ReturnType = Types.NVector16b,
}
);

// 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)
Expand Down Expand Up @@ -2798,6 +2807,10 @@ static void MarshalToManaged (StringWriter writer, TypeData type, string nativeV
writer.WriteLine ("\t{0}{2}min.b = {1}.min [1];", managedVariable, nativeVariable, accessor);
writer.WriteLine ("\t{0}{2}min.c = {1}.min [2];", managedVariable, nativeVariable, accessor);
break;
case "NVector16b":
writer.WriteLine ("\tfor (int i = 0; i < 16; i++)");
writer.WriteLine ("\t\t{0}{2}values [i] = {1} [i];", managedVariable, nativeVariable, accessor);
break;
default:
throw new NotImplementedException (string.Format ("MarshalToManaged for: NativeType: {0} ManagedType: {1}", type.NativeType, type.ManagedType));
}
Expand Down Expand Up @@ -2945,6 +2958,10 @@ static void MarshalToNative (StringWriter writer, TypeData type, string nativeVa
writer.WriteLine ("\t{0}.min [1] = {1}{2}min.b;", nativeVariable, managedVariable, accessor);
writer.WriteLine ("\t{0}.min [2] = {1}{2}min.c;", nativeVariable, managedVariable, accessor);
break;
case "VectorUChar16":
writer.WriteLine ("\tfor (int i = 0; i < 16; i++)");
writer.WriteLine ("\t\t{0} [i] = {1}{2}values[i];", nativeVariable, managedVariable, accessor);
break;
default:
throw new NotImplementedException (string.Format ("MarshalToNative for: NativeType: {0} ManagedType: {1}", type.NativeType, type.ManagedType));
}
Expand Down Expand Up @@ -3406,6 +3423,15 @@ public static class Types {
NativeWrapperType = "struct Vector4d",
RequireMarshal = true,
};

public static TypeData NVector16b = new TypeData {
ManagedType = "NVector16b",
NativeType = "vector_uchar16",
NativeWrapperType = "struct VectorUChar16",
RequireMarshal = true,
IsX64Stret = false,
};

public static TypeData Matrix2f = new TypeData {
ManagedType = "Matrix2",
NativeType = "matrix_float2x2",
Expand Down
6 changes: 6 additions & 0 deletions runtime/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ typedef __attribute__((__ext_vector_type__(2))) float vector_float2;
typedef __attribute__((__ext_vector_type__(3))) float vector_float3;
typedef __attribute__((__ext_vector_type__(4))) float vector_float4;

typedef __attribute__((__ext_vector_type__(16))) unsigned char vector_uchar16;

typedef struct { vector_float2 columns[2]; } matrix_float2x2;
typedef struct { vector_float3 columns[3]; } matrix_float3x3;
typedef struct { vector_float4 columns[4]; } matrix_float4x4;
Expand Down Expand Up @@ -252,6 +254,10 @@ struct MPSAxisAlignedBoundingBoxWrapper {
Vector3f max;
};

struct VectorUChar16 {
unsigned char values[16];
};

static_assert (sizeof (MPSImageHistogramInfoWrapper) == sizeof (MPSImageHistogramInfo), "Sizes aren't equal");

struct Vector4f xamarin_vector_float3__Vector4_objc_msgSend (id self, SEL sel);
Expand Down
4 changes: 2 additions & 2 deletions src/MetalPerformanceShaders/MPSCnnKernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public unsafe MPSCnnBinaryConvolution (IMTLDevice device, IMPSCnnConvolutionData
fixed (void* outputScaleTermsHandle = outputScaleTerms)
fixed (void* inputBiasTermsHandle = inputBiasTerms)
fixed (void* inputScaleTermsHandle = inputScaleTerms)
InitializeHandle (InitWithDevice (device, convolutionData, (IntPtr) outputBiasTermsHandle, (IntPtr) outputScaleTermsHandle, (IntPtr) inputBiasTermsHandle, (IntPtr) inputScaleTermsHandle, type, flags));
InitializeHandle (_InitWithDevice (device, convolutionData, (IntPtr) outputBiasTermsHandle, (IntPtr) outputScaleTermsHandle, (IntPtr) inputBiasTermsHandle, (IntPtr) inputScaleTermsHandle, type, flags));
}
}

Expand All @@ -45,7 +45,7 @@ public unsafe MPSCnnBinaryFullyConnected (IMTLDevice device, IMPSCnnConvolutionD
fixed (void* outputScaleTermsHandle = outputScaleTerms)
fixed (void* inputBiasTermsHandle = inputBiasTerms)
fixed (void* inputScaleTermsHandle = inputScaleTerms)
InitializeHandle (InitWithDevice (device, convolutionData, (IntPtr) outputBiasTermsHandle, (IntPtr) outputScaleTermsHandle, (IntPtr) inputBiasTermsHandle, (IntPtr) inputScaleTermsHandle, type, flags));
InitializeHandle (_InitWithDevice (device, convolutionData, (IntPtr) outputBiasTermsHandle, (IntPtr) outputScaleTermsHandle, (IntPtr) inputBiasTermsHandle, (IntPtr) inputScaleTermsHandle, type, flags));
}
}
}
26 changes: 26 additions & 0 deletions src/MetalPerformanceShaders/MPSEnums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ public enum MPSDataType : uint { // uint32_t
/// <summary>Indicates 32-bit floating point format data.</summary>
Float32 = FloatBit | 32,

[iOS (16, 2), MacCatalyst (16, 2), TV (16, 2)]
ComplexBit = 0x01000000,
[iOS (16, 2), MacCatalyst (16, 2), TV (16, 2)]
ComplexFloat32 = FloatBit | ComplexBit | 64,
[iOS (16, 2), MacCatalyst (16, 2), TV (16, 2)]
ComplexFloat16 = FloatBit | ComplexBit | 32,

/// <summary>To be added.</summary>
SignedBit = 0x20000000,
[TV (18, 4), Mac (15, 4), iOS (18, 4), MacCatalyst (18, 4)]
Expand Down Expand Up @@ -104,6 +111,13 @@ public enum MPSDataType : uint { // uint32_t
[MacCatalyst (14, 1)]
UInt64 = 64,

[iOS (15, 0), MacCatalyst (15, 0), TV (15, 0)]
AlternateEncodingBit = 0x80000000,
[iOS (15, 0), MacCatalyst (15, 0), TV (15, 0)]
Bool = AlternateEncodingBit | 8,
[iOS (16, 0), MacCatalyst (16, 0), TV (16, 0), Mac (14, 0)]
BFloat16 = AlternateEncodingBit | Float16,

/// <summary>To be added.</summary>
[MacCatalyst (13, 1)]
NormalizedBit = 0x40000000,
Expand Down Expand Up @@ -389,6 +403,18 @@ public enum MPSIntersectionDataType : ulong {
PrimitiveIndexInstanceIndex = 3,
/// <summary>To be added.</summary>
PrimitiveIndexInstanceIndexCoordinates = 4,

[iOS (15, 0), TV (15, 0), MacCatalyst (15, 0)]
PrimitiveIndexBufferIndex = 5,

[iOS (15, 0), TV (15, 0), MacCatalyst (15, 0)]
PrimitiveIndexBufferIndexCoordinates = 6,

[iOS (15, 0), TV (15, 0), MacCatalyst (15, 0)]
PrimitiveIndexBufferIndexInstanceIndex = 7,

[iOS (15, 0), TV (15, 0), MacCatalyst (15, 0)]
PrimitiveIndexBufferIndexInstanceIndexCoordinates = 8,
}

[MacCatalyst (13, 1)]
Expand Down
81 changes: 34 additions & 47 deletions src/MetalPerformanceShaders/MPSImageBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,52 +84,39 @@ public static nuint GetResourceSize (NSArray<MPSImage> imageBatch)
return size;
}

// TODO: Disabled due to 'MPSImageBatchIterate' is not in the native library rdar://47282304.
//[DllImport (Constants.MetalPerformanceShadersLibrary)]
//static extern nint MPSImageBatchIterate (IntPtr batch, IntPtr iterator);

//public delegate nint MPSImageBatchIterator (MPSImage image, nuint index);

//[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
//internal delegate nint DMPSImageBatchIterator (IntPtr block, IntPtr image, nuint index);

//// This class bridges native block invocations that call into C#
//static internal class MPSImageBatchIteratorTrampoline {
// static internal readonly DMPSImageBatchIterator Handler = Invoke;

// [MonoPInvokeCallback (typeof (DMPSImageBatchIterator))]
// static unsafe nint Invoke (IntPtr block, IntPtr image, nuint index)
// {
// var descriptor = (BlockLiteral *) block;
// var del = (MPSImageBatchIterator) descriptor->Target;
// nint retval;
// using (var img = Runtime.GetNSObject<MPSImage> (image)) {
// retval = del (img, index);
// }
// return retval;
// }
//}

//[BindingImpl (BindingImplOptions.Optimizable)]
//public static nint Iterate (NSArray<MPSImage> imageBatch, MPSImageBatchIterator iterator)
//{
// if (imageBatch is null)
// ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (imageBatch));
// if (iterator is null)
// ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (iterator));
// unsafe {
// BlockLiteral* block_ptr_iterator;
// BlockLiteral block_iterator;
// block_iterator = new BlockLiteral ();
// block_ptr_iterator = &block_iterator;
// block_iterator.SetupBlockUnsafe (MPSImageBatchIteratorTrampoline.Handler, iterator);

// nint ret = MPSImageBatchIterate (imageBatch.Handle, (IntPtr) block_ptr_iterator);

// block_ptr_iterator->CleanupBlock ();

// return ret;
// }
//}
[DllImport (Constants.MetalPerformanceShadersLibrary)]
unsafe static extern nint MPSImageBatchIterate (IntPtr batch, BlockLiteral* iterator);

public delegate nint MPSImageBatchIterator (MPSImage image, nuint index);

[UnmanagedCallersOnly]
static unsafe nint InvokeIterator (IntPtr block, IntPtr image, nuint index)
{
var del = (MPSImageBatchIterator) BlockLiteral.GetTarget<MPSImageBatchIterator> (block);
if (del is not null) {
using var img = Runtime.GetNSObject<MPSImage> (image)!;
return del (img, index);
}
return 0;
}

/// <summary>Iterate over the unique images in the image batch.</summary>
/// <param name="imageBatch">The batch of images to iterate over.</param>
/// <param name="iterator">The callback to call for each unique image.</param>
/// <returns>The value returned by the callback for the last image iterated over.</returns>
[BindingImpl (BindingImplOptions.Optimizable)]
public static nint Iterate (NSArray<MPSImage> imageBatch, MPSImageBatchIterator iterator)
{
if (iterator is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (iterator));

unsafe {
delegate* unmanaged<IntPtr, IntPtr, nuint, nint> trampoline = &InvokeIterator;
using var block = new BlockLiteral (trampoline, iterator, typeof (MPSImageBatch), nameof (InvokeIterator));
var rv = MPSImageBatchIterate (imageBatch.GetNonNullHandle (nameof (imageBatch)), &block);
GC.KeepAlive (imageBatch);
return rv;
}
}
}
}
46 changes: 46 additions & 0 deletions src/MetalPerformanceShaders/MPSImageCanny.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#nullable enable


using System;

using Foundation;
using Metal;
using ObjCRuntime;

namespace MetalPerformanceShaders {
partial class MPSImageCanny {
/// <summary>Create a new <see cref="MPSImageCanny" /> instance.</summary>
/// <param name="device">The device where the filter will run.</param>
/// <param name="transform">An array of 3 floats that describe how to transform rgb pixels to monochrome pixels.</param>
/// <param name="sigma">The standard deviation of a gaussian blur filter.</param>
public MPSImageCanny (IMTLDevice device, float [] transform, float sigma)
: this (NSObjectFlag.Empty)
{
if (transform is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (transform));
if (transform.Length < 3)
ObjCRuntime.ThrowHelper.ThrowArgumentOutOfRangeException (nameof (transform), $"Length must be at least '3'.");

unsafe {
fixed (float* transformPtr = transform) {
InitializeHandle (_InitWithDevice (device, (IntPtr) transformPtr, sigma), "initWithDevice:linearToGrayScaleTransform:sigma:");
}
}
}

/// <summary>Get an array with the 3 floats values that describe how to transform rgb pixels to monochrome pixels.</summary>
public float [] ColorTransform {
get {
var rv = new float [3];
unsafe {
fixed (float* ptr = rv)
NativeMemory.Copy ((void*) WeakColorTransform, ptr, (nuint) (sizeof (float) * rv.Length));
}
return rv;
}
}
}
}
53 changes: 50 additions & 3 deletions src/MetalPerformanceShaders/MPSNNGraph.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#nullable enable

using System;
Expand All @@ -9,14 +12,58 @@

namespace MetalPerformanceShaders {
public partial class MPSNNGraph {
/// <summary>Create a new <see cref="MPSNNGraph" /> instance.</summary>
/// <param name="device">The device where the filter will run.</param>
/// <param name="resultImages">The last images in the graph.</param>
/// <param name="resultsAreNeeded">An array of boolean for each element in the <paramref name="resultImages" /> array.</param>
/// <returns>A new <see cref="MPSNNGraph" /> if successful, <see langword="null" /> otherwise.</returns>
[SupportedOSPlatform ("tvos13.0")]
[SupportedOSPlatform ("macos")]
[SupportedOSPlatform ("ios13.0")]
[SupportedOSPlatform ("maccatalyst")]
public unsafe static MPSNNGraph? Create (IMTLDevice device, MPSNNImageNode [] resultImages, bool [] resultsAreNeeded)
public unsafe static MPSNNGraph? Create (IMTLDevice device, MPSNNImageNode [] resultImages, bool []? resultsAreNeeded)
{
fixed (void* resultsAreNeededHandle = resultsAreNeeded)
return Create (device, resultImages, (IntPtr) resultsAreNeededHandle);
ValidateParameters (resultImages, resultsAreNeeded, out var results);

unsafe {
fixed (void* resultsPointer = results)
return Create (device, resultImages, (IntPtr) resultsPointer);
}
}

/// <summary>Create a new <see cref="MPSNNGraph" /> instance.</summary>
/// <param name="device">The device where the filter will run.</param>
/// <param name="resultImages">The last images in the graph.</param>
/// <param name="resultsAreNeeded">An array of boolean for each element in the <paramref name="resultImages" /> array.</param>
[SupportedOSPlatform ("tvos13.0")]
[SupportedOSPlatform ("macos")]
[SupportedOSPlatform ("ios13.0")]
[SupportedOSPlatform ("maccatalyst")]
public MPSNNGraph (IMTLDevice device, MPSNNImageNode [] resultImages, bool []? resultsAreNeeded)
: base (NSObjectFlag.Empty)
{
ValidateParameters (resultImages, resultsAreNeeded, out var results);

unsafe {
fixed (void* resultsPointer = results)
InitializeHandle (_InitWithDevice (device, resultImages, (IntPtr) resultsPointer), "initWithDevice:resultImages:resultsAreNeeded:");
}
}

static void ValidateParameters (MPSNNImageNode [] resultImages, bool []? resultsAreNeeded, out byte []? results)
{
if (resultImages is null)
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (resultImages));

if (resultsAreNeeded is not null && resultsAreNeeded.Length < resultImages.Length)
ObjCRuntime.ThrowHelper.ThrowArgumentOutOfRangeException (nameof (resultsAreNeeded), "The length of 'resultsAreNeeded' must be at least as much as the length of 'resultImages' (or null).");

results = null;
if (resultsAreNeeded is not null) {
results = new byte [resultsAreNeeded.Length];
for (var i = 0; i < resultsAreNeeded.Length; i++)
results [i] = resultsAreNeeded [i].AsByte ();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#nullable enable

using System;

using Foundation;
using Metal;
using ObjCRuntime;

namespace MetalPerformanceShaders {
partial class MPSNNOptimizerStochasticGradientDescent {
#if !XAMCORE_5_0
/// <summary>Create a new <see cref="MPSNNOptimizerStochasticGradientDescent" /> instance.</summary>
/// <param name="device">The device where the filter will run.</param>
/// <param name="momentumScale">The scale to use when updating the momentum for the values.</param>
/// <param name="useNestrovMomentum">The Nesterov-style momentum update.</param>
/// <param name="optimizerDescriptor">Any additional properties to apply.</param>
public MPSNNOptimizerStochasticGradientDescent (IMTLDevice device, float momentumScale, bool useNestrovMomentum, MPSNNOptimizerDescriptor optimizerDescriptor)
#else
/// <summary>Create a new <see cref="MPSNNOptimizerStochasticGradientDescent" /> instance.</summary>
/// <param name="device">The device where the filter will run.</param>
/// <param name="momentumScale">The scale to use when updating the momentum for the values.</param>
/// <param name="useNesterovMomentum">The Nesterov-style momentum update.</param>
/// <param name="optimizerDescriptor">Any additional properties to apply.</param>
public MPSNNOptimizerStochasticGradientDescent (IMTLDevice device, float momentumScale, bool useNesterovMomentum, MPSNNOptimizerDescriptor optimizerDescriptor)
#endif
: this (NSObjectFlag.Empty)
{
#if !XAMCORE_5_0
var useNesterovMomentum = useNestrovMomentum;
#endif

if (!SystemVersion.IsAtLeastXcode12) {
InitializeHandle (_InitWithNestrovMomentum (device, momentumScale, useNesterovMomentum, optimizerDescriptor), "initWithDevice:momentumScale:useNestrovMomentum:optimizerDescriptor:");
return;
}

InitializeHandle (_InitWithNesterovMomentum (device, momentumScale, useNesterovMomentum, optimizerDescriptor), "initWithDevice:momentumScale:useNestrovMomentum:optimizerDescriptor:");
}
}
}
Loading
Loading