mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-22 22:01:08 +00:00
### Description <!-- Describe your changes. --> Update various test projects to .net8 from EOL frameworks. Replace the Xamarin based Android and iOS test projects with a MAUI based project that uses .net 8. Add new CoreML flags to C# bindings ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> Remove usage of EOL frameworks.
206 lines
6.9 KiB
C#
206 lines
6.9 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
using Microsoft.ML.OnnxRuntime.Tensors;
|
|
using System;
|
|
using System.Buffers;
|
|
|
|
namespace Microsoft.ML.OnnxRuntime
|
|
{
|
|
/// <summary>
|
|
/// Provides access from the underlying object that owns disposable OrtValue
|
|
/// The returned value does not own the actual memory and does nothing on Dispose()
|
|
/// </summary>
|
|
internal interface IOrtValueOwner : IDisposable
|
|
{
|
|
OrtValue Value { get; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// This class is used in conjunction with DisposableNamedOnnxValue to
|
|
/// own native collection OrtValue and dispose of it along with any DisposableNamedOnnxValues
|
|
/// </summary>
|
|
internal class NativeOrtValueCollectionOwner : IOrtValueOwner, IDisposable
|
|
{
|
|
private OrtValue _ortValue;
|
|
private IDisposable _disposables;
|
|
bool _disposed = false;
|
|
|
|
/// <summary>
|
|
/// _Ctor. Takes ownership of ortValue and sets it to null on success.
|
|
/// </summary>
|
|
/// <param name="ortValue">becomes null on success</param>
|
|
/// <param name="disposables">A collection of disposables that support composed types.
|
|
/// We stick them here and dispose them when this instance is disposed.
|
|
/// </param>
|
|
internal NativeOrtValueCollectionOwner(ref OrtValue ortValue, IDisposable disposables)
|
|
{
|
|
_ortValue = ortValue;
|
|
ortValue = null;
|
|
_disposables = disposables;
|
|
}
|
|
|
|
#region IOrtValueOwner
|
|
/// <summary>
|
|
/// Returns OrtValue that is owned by this instance
|
|
/// </summary>
|
|
public OrtValue Value { get { return _ortValue; } }
|
|
#endregion IOrtValueOwner
|
|
|
|
#region Disposable
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// dispose managed state (managed objects).
|
|
if (disposing)
|
|
{
|
|
if (_disposables != null)
|
|
{
|
|
_disposables.Dispose();
|
|
_disposables = null;
|
|
}
|
|
// _ortValueHolder can be null when no native memory is involved
|
|
if (_ortValue != null)
|
|
{
|
|
_ortValue.Dispose();
|
|
_ortValue = null;
|
|
}
|
|
_disposed = true;
|
|
}
|
|
}
|
|
public void Dispose()
|
|
{
|
|
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
#endregion Disposable
|
|
}
|
|
|
|
/// <summary>
|
|
/// This helper class owns the underlying OrtValue that is assumed to be a Tensor,
|
|
/// it does not support any other ortValues and caches Tensor properties.
|
|
///
|
|
/// It is easy to expose as a Tensor{T} as DenseTensor can take Memory Mapping from
|
|
/// this.
|
|
///
|
|
/// This class is disposable because of the MemoryManager inheritance. Because this class
|
|
/// always backs exactly only one DenseTensor<typeparamref name="T"/> instance, it does
|
|
/// not implement ref-counting for Pin/Unpin.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
internal class OrtValueTensor<T> : MemoryManager<T>, IOrtValueOwner
|
|
{
|
|
private OrtValue _ortValue; // Disposable
|
|
private readonly IntPtr _dataBufferPointer; // pointer to mutable tensor data in native memory
|
|
|
|
/// <summary>
|
|
/// Constructs an instance and takes ownership of ortValue on success
|
|
/// </summary>
|
|
/// <param name="ortValue">ortValue that is a Tensor. It becomes null on successful return.</param>
|
|
public OrtValueTensor(ref OrtValue ortValue)
|
|
{
|
|
var typeAndShapeInfo = ortValue.GetTensorTypeAndShape();
|
|
TensorElementType elemType = typeAndShapeInfo.ElementDataType;
|
|
|
|
var typeInfo = TensorBase.GetElementTypeInfo(elemType) ?? throw new OnnxRuntimeException(ErrorCode.InvalidArgument,
|
|
$"Unable to query type information for data type: {elemType}");
|
|
|
|
if (typeof(T) != typeInfo.TensorType)
|
|
{
|
|
throw new OnnxRuntimeException(ErrorCode.InvalidArgument,
|
|
$"The OrtValueTensor<T> type being instantiated for T = [{typeof(T)}] while supplied OrtValue contains T = [{typeInfo.TensorType}]");
|
|
}
|
|
|
|
ElementType = elemType;
|
|
ElementWidth = typeInfo.TypeSize;
|
|
Count = (int)typeAndShapeInfo.ElementCount;
|
|
|
|
Dimensions = Array.ConvertAll(typeAndShapeInfo.Shape, Convert.ToInt32);
|
|
|
|
NativeApiStatus.VerifySuccess(NativeMethods.OrtGetTensorMutableData(ortValue.Handle, out _dataBufferPointer));
|
|
|
|
// Transfer ownership
|
|
_ortValue = ortValue;
|
|
ortValue = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns OrtValue that is owned by this instance
|
|
/// </summary>
|
|
public OrtValue Value { get { return _ortValue; } }
|
|
|
|
public bool IsDisposed { get; private set; } = false;
|
|
|
|
public int[] Dimensions { get; }
|
|
|
|
public int Rank => Dimensions.Length;
|
|
|
|
public int Count { get; }
|
|
|
|
public int ElementWidth { get; }
|
|
|
|
public Tensors.TensorElementType ElementType { get; }
|
|
|
|
/// <summary>
|
|
/// Returns Span that is a view into the underlying native Tensor memory
|
|
/// </summary>
|
|
/// <returns>SpanT</returns>
|
|
public override Span<T> GetSpan()
|
|
{
|
|
Span<T> span = null;
|
|
unsafe
|
|
{
|
|
span = new Span<T>((void*)_dataBufferPointer, Count);
|
|
}
|
|
|
|
return span;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Satisfy MemoryManager abstract implementation.
|
|
/// </summary>
|
|
/// <param name="elementIndex">required for override</param>
|
|
/// <returns></returns>
|
|
public override MemoryHandle Pin(int elementIndex = 0)
|
|
{
|
|
unsafe
|
|
{
|
|
if (elementIndex >= Count)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(elementIndex));
|
|
}
|
|
return new MemoryHandle(new IntPtr(_dataBufferPointer.ToInt64() + (long)elementIndex * ElementWidth).ToPointer());
|
|
}
|
|
}
|
|
|
|
// MemoryHandle returned above by Pin() should be disposed.
|
|
// Unpin() is purely to satisfy the interface.
|
|
public override void Unpin() { }
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (IsDisposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_ortValue != null)
|
|
{
|
|
_ortValue.Dispose();
|
|
_ortValue = null;
|
|
}
|
|
IsDisposed = true;
|
|
}
|
|
}
|
|
}
|