Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
033a887
Add func typedefs
adrianlizarraga Jul 9, 2025
fcdb5cf
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Jul 9, 2025
03eb5fa
stub apis
adrianlizarraga Jul 15, 2025
3310968
merge main
adrianlizarraga Jul 17, 2025
c3693de
new branch. add 2 streams first
adrianlizarraga Jul 19, 2025
a69d5f9
Move away from using Graph's graph_proto_ member
adrianlizarraga Jul 19, 2025
5743dcd
fix deref assignment
adrianlizarraga Jul 20, 2025
fd87e0c
Clean up
adrianlizarraga Jul 21, 2025
a40f463
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Jul 21, 2025
0dadf4d
Use std::filesystem::path in ModelCompilationOptions; fix memleak in …
adrianlizarraga Jul 21, 2025
d94cf44
fix unused variable warning (as error)
adrianlizarraga Jul 21, 2025
5bfbddb
Merge main and fix conflicts
adrianlizarraga Aug 28, 2025
69a4338
Update handler function signature to take in the ExternalDataInfo for…
adrianlizarraga Aug 28, 2025
90ade82
Add test that reuses external initializers from original model
adrianlizarraga Aug 29, 2025
c36afe5
Define new ExternalDataInfo constructor only for non-minimal builds
adrianlizarraga Aug 29, 2025
c07dc11
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Aug 29, 2025
4b83a2b
Fix unused variable warning (as error)
adrianlizarraga Aug 29, 2025
91acc8f
another unused variable
adrianlizarraga Aug 29, 2025
6e5629a
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Aug 29, 2025
9b092bf
clean up
adrianlizarraga Aug 29, 2025
049b9ad
Start adding csharp api funcs
adrianlizarraga Aug 29, 2025
8e00a06
Remove qnn_factory memleak fix (address in different PR)
adrianlizarraga Aug 29, 2025
11a6c74
Add ExternalInitializerInfo to C++ api
adrianlizarraga Aug 29, 2025
9ca882f
Add compile_to_stream py api
adrianlizarraga Aug 29, 2025
6d522d8
Python bindings and tests
adrianlizarraga Aug 30, 2025
af996bb
C# API for WriteBuffer delegate
adrianlizarraga Aug 31, 2025
9b27b31
c# api handle initializers
adrianlizarraga Aug 31, 2025
9607193
missing documentation in c#
adrianlizarraga Aug 31, 2025
e65710a
Add ExternalInitializerInfo C# class
adrianlizarraga Aug 31, 2025
c16b327
Full C# API for delegate that handles initializers
adrianlizarraga Sep 1, 2025
0b2f0e6
Update comment
adrianlizarraga Sep 2, 2025
83758d1
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Sep 2, 2025
c62ed23
Address review comments
adrianlizarraga Sep 2, 2025
a35e7b6
Address review comments
adrianlizarraga Sep 3, 2025
d906855
Remove unused variable
adrianlizarraga Sep 3, 2025
255c2df
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Sep 3, 2025
3db3117
Merge main conflicts
adrianlizarraga Sep 3, 2025
c7f98de
Merge main again
adrianlizarraga Sep 3, 2025
9031635
Address review comments for C#
adrianlizarraga Sep 3, 2025
abd0297
Rename functions in C and python
adrianlizarraga Sep 3, 2025
d5012fb
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Sep 3, 2025
0e0497a
Address comments
adrianlizarraga Sep 4, 2025
0a61f1f
Merge branch 'main' into adrianl/compile-api-output-stream
adrianlizarraga Sep 4, 2025
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
372 changes: 349 additions & 23 deletions csharp/src/Microsoft.ML.OnnxRuntime/CompileModel.shared.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public struct OrtCompileApi
public IntPtr ModelCompilationOptions_SetFlags;
public IntPtr ModelCompilationOptions_SetEpContextBinaryInformation;
public IntPtr ModelCompilationOptions_SetGraphOptimizationLevel;
public IntPtr ModelCompilationOptions_SetOutputModelWriteFunc;
public IntPtr ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc;
}

internal class NativeMethods
Expand Down Expand Up @@ -118,6 +120,22 @@ public DOrtModelCompilationOptions_SetEpContextBinaryInformation
public DOrtModelCompilationOptions_SetGraphOptimizationLevel
OrtModelCompilationOptions_SetGraphOptimizationLevel;

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelWriteFunc(
IntPtr /* OrtModelCompilationOptions* */ options,
IntPtr /* DOrtWriteBufferDelegate */ writeFunc,
IntPtr /* void* */ state);
public DOrtModelCompilationOptions_SetOutputModelWriteFunc
OrtModelCompilationOptions_SetOutputModelWriteFunc;

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc(
IntPtr /* OrtModelCompilationOptions* */ options,
IntPtr /* DOrtHandleInitializerDataDelegate */ handleInitializerFunc,
IntPtr /* void* */ state);
public DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc
OrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc;

internal NativeMethods(OnnxRuntime.NativeMethods.DOrtGetCompileApi getCompileApi)
{

Expand Down Expand Up @@ -188,6 +206,17 @@ internal NativeMethods(OnnxRuntime.NativeMethods.DOrtGetCompileApi getCompileApi
_compileApi.ModelCompilationOptions_SetGraphOptimizationLevel,
typeof(DOrtModelCompilationOptions_SetGraphOptimizationLevel));

OrtModelCompilationOptions_SetOutputModelWriteFunc =
(DOrtModelCompilationOptions_SetOutputModelWriteFunc)Marshal.GetDelegateForFunctionPointer(
_compileApi.ModelCompilationOptions_SetOutputModelWriteFunc,
typeof(DOrtModelCompilationOptions_SetOutputModelWriteFunc));

OrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc =
(DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc)Marshal.
GetDelegateForFunctionPointer(
_compileApi.ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc,
typeof(DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc));

}
}
}
91 changes: 91 additions & 0 deletions csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ public struct OrtApi

public IntPtr Graph_GetModelMetadata;
public IntPtr GetModelCompatibilityForEpDevices;
public IntPtr CreateExternalInitializerInfo;
}

internal static class NativeMethods
Expand Down Expand Up @@ -787,9 +788,35 @@ static NativeMethods()
api_.SessionOptionsSetEpSelectionPolicyDelegate,
typeof(DSessionOptionsSetEpSelectionPolicyDelegate));

OrtReleaseExternalInitializerInfo =
(DOrtReleaseExternalInitializerInfo)Marshal.GetDelegateForFunctionPointer(
api_.ReleaseExternalInitializerInfo,
typeof(DOrtReleaseExternalInitializerInfo));

OrtExternalInitializerInfo_GetFilePath =
(DOrtExternalInitializerInfo_GetFilePath)Marshal.GetDelegateForFunctionPointer(
api_.ExternalInitializerInfo_GetFilePath,
typeof(DOrtExternalInitializerInfo_GetFilePath));

OrtExternalInitializerInfo_GetFileOffset =
(DOrtExternalInitializerInfo_GetFileOffset)Marshal.GetDelegateForFunctionPointer(
api_.ExternalInitializerInfo_GetFileOffset,
typeof(DOrtExternalInitializerInfo_GetFileOffset));

OrtExternalInitializerInfo_GetByteSize =
(DOrtExternalInitializerInfo_GetByteSize)Marshal.GetDelegateForFunctionPointer(
api_.ExternalInitializerInfo_GetByteSize,
typeof(DOrtExternalInitializerInfo_GetByteSize));

OrtGetModelCompatibilityForEpDevices = (DOrtGetModelCompatibilityForEpDevices)Marshal.GetDelegateForFunctionPointer(
api_.GetModelCompatibilityForEpDevices,
typeof(DOrtGetModelCompatibilityForEpDevices));

OrtCreateExternalInitializerInfo =
(DOrtCreateExternalInitializerInfo)Marshal.GetDelegateForFunctionPointer(
api_.CreateExternalInitializerInfo,
typeof(DOrtCreateExternalInitializerInfo));

}

internal class NativeLib
Expand Down Expand Up @@ -2382,6 +2409,70 @@ out IntPtr lora_adapter
public delegate ref CompileApi.OrtCompileApi DOrtGetCompileApi();
#endif
public static DOrtGetCompileApi OrtGetCompileApi;

/// <summary>
/// Delegate called by ORT to write a buffer (ONNX model bytes) to a custom destination (e.g., file or stream).
/// </summary>
/// <param name="state">State that was provided in when the delegate was registered.</param>
/// <param name="buffer">The buffer to write.</param>
/// <param name="bufferNumBytes">The size of the buffer in bytes.</param>
/// <returns>OrtStatus*</returns>
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr /* OrtStatus* */ DOrtWriteBufferToDestinationDelegate(
IntPtr /* void* */ state,
IntPtr /* const void* */ buffer,
UIntPtr /* size_t */ bufferNumBytes
);

/// <summary>
/// Function called by ORT to allow user to specify how an initializer should be saved while compiling
/// a model, that is, either written to an external file or stored within the model. ORT calls this function
/// for every initializer.
/// </summary>
/// <param name="state">State that was provided when the delegate was registered.</param>
/// <param name="initializerName">The initializer's name.</param>
/// <param name="initializerValue">The OrtValue containing the initializer's data, type, and shape</param>
/// <param name="externalInfo">The original initializer's location in an external file, or NULL.</param>
/// <param name="newExternalInfo">Output parameter set to a new OrtExternalInitializerInfo instance
/// indicating the location where the function implementation stored the initializer data. If the function
/// implementation sets `newExternalInfo` to NULL, ORT stores the initializer within the generated model.</param>
/// <returns></returns>
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr /* OrtStatus* */ DOrtGetInitializerLocationDelegate(
IntPtr /* void* */ state,
IntPtr /* const char* */ initializerName,
IntPtr /* const OrtValue* */ initializerValue,
IntPtr /* const OrtExternalInitializerInfo* */ externalInfo,
out IntPtr /* OrtExternalInitializerInfo** */ newExternalInfo
);

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate void DOrtReleaseExternalInitializerInfo(IntPtr /* OrtExternalInitializerInfo* */ info);

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr /* OrtStatus* */ DOrtCreateExternalInitializerInfo(
byte[] /* const ORTCHAR_T* */ filePath,
long /* int64_t */ fileOffset,
UIntPtr /* size_t */ byteSize,
out IntPtr /* OrtExternalInitializerInfo** */ outInfo);

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate IntPtr /* const ORTCHAR_T* */ DOrtExternalInitializerInfo_GetFilePath(
IntPtr /* const OrtExternalInitializerInfo* */ info);

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate long /* int64_t */ DOrtExternalInitializerInfo_GetFileOffset(
IntPtr /* const OrtExternalInitializerInfo* */ info);

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
public delegate UIntPtr /* size_t */ DOrtExternalInitializerInfo_GetByteSize(
IntPtr /* const OrtExternalInitializerInfo* */ info);

public static DOrtReleaseExternalInitializerInfo OrtReleaseExternalInitializerInfo;
public static DOrtCreateExternalInitializerInfo OrtCreateExternalInitializerInfo;
public static DOrtExternalInitializerInfo_GetFilePath OrtExternalInitializerInfo_GetFilePath;
public static DOrtExternalInitializerInfo_GetFileOffset OrtExternalInitializerInfo_GetFileOffset;
public static DOrtExternalInitializerInfo_GetByteSize OrtExternalInitializerInfo_GetByteSize;
#endregion

#region Auto EP API related
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,45 @@ internal static byte[] GetPlatformSerializedString(string str)
else
return StringToZeroTerminatedUtf8(str);
}

/// <summary>
/// Converts a null-terminated path string that is pointed to by the given IntPtr handle into
/// a C# UTF-16 string.
/// </summary>
/// <remarks>A path string on Windows is utf-16, but utf-8 on other operating systems.</remarks>
/// <param name="strPtr"></param>
/// <returns></returns>
internal static string StringFromNativePathString(IntPtr strPtr)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (strPtr == IntPtr.Zero)
{
return string.Empty;
}

// Get length of utf16 string by checking for two 0 bytes in a row.
int length = 0;
while (Marshal.ReadInt16(strPtr, length * 2) != 0)
{
length += 1;
}

if (length == 0)
{
return string.Empty;
}

unsafe
{
return System.Text.Encoding.Unicode.GetString((byte*)strPtr, length * 2);
}
}
else
{
return StringFromNativeUtf8(strPtr);
}
}
}

// Guards an array of disposable objects on stack and disposes them in reverse order
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.


namespace Microsoft.ML.OnnxRuntime
{
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

/// <summary>
/// Class to that stores information about the file location where an "external" initializer is stored.
/// </summary>
/// <see cref="OrtModelCompilationOptions.HandleInitializerDelegate"/>
public class OrtExternalInitializerInfo : SafeHandle, IReadOnlyExternalInitializerInfo
{
// Set to false when constructed with an externally managed constant handle owned by ORT.
private readonly bool _ownsHandle = true;

/// <summary>
/// Create a new OrtExternalInitializerInfo instance.
/// </summary>
/// <param name="filePath">The path to the file that stores the initializer data.</param>
/// <param name="fileOffset">The byte offset in the file where the data is stored.</param>
/// <param name="byteSize">The size of the data (in bytes) within the file.</param>
public OrtExternalInitializerInfo(string filePath, long fileOffset, long byteSize)
: base(IntPtr.Zero, ownsHandle: true)
{
var platformFilePath = NativeOnnxValueHelper.GetPlatformSerializedString(filePath);
NativeApiStatus.VerifySuccess(
NativeMethods.OrtCreateExternalInitializerInfo(platformFilePath, fileOffset, (UIntPtr)byteSize, out handle));
_ownsHandle = true;
}

/// <summary>
/// Create a new OrtExternalInitializerInfo instance from an existing native OrtExternalInitializerInfo handle.
/// </summary>
/// <param name="constHandle">Native OrtExternalInitializerInfo handle.</param>
/// <param name="ownsHandle">True if the OrtExternalInitializerInfo instance owns the native handle.
/// Defaults to false.</param>
internal OrtExternalInitializerInfo(IntPtr constHandle, bool ownsHandle = false)
: base(IntPtr.Zero, ownsHandle)
{
Debug.Assert(constHandle != IntPtr.Zero);
SetHandle(constHandle);
_ownsHandle = ownsHandle;
}

/// <summary>
/// Get the file path to the file that store's the initializer's data.
/// </summary>
/// <remarks>
/// The path is relative to the filesystem directory where the ONNX model was stored.
/// </remarks>
/// <returns>The file path.</returns>
public string GetFilePath()
{
IntPtr filePathPtr = NativeMethods.OrtExternalInitializerInfo_GetFilePath(handle);
if (filePathPtr == IntPtr.Zero)
{
return string.Empty;
}

return NativeOnnxValueHelper.StringFromNativePathString(filePathPtr);
}

/// <summary>
/// Get the byte offset within the file where the initializer's data is stored.
/// </summary>
/// <returns>The file offset location.</returns>
public long GetFileOffset()
{
return NativeMethods.OrtExternalInitializerInfo_GetFileOffset(handle);
}

/// <summary>
/// Get the size in bytes of the initializer's data within the file.
/// </summary>
/// <returns>The size in bytes of the initializer data.</returns>
public long GetByteSize()
{
UIntPtr byteSize = NativeMethods.OrtExternalInitializerInfo_GetByteSize(handle);
return checked((long)byteSize);
}

/// <summary>
/// Indicates whether the native handle is invalid.
/// </summary>
public override bool IsInvalid { get { return handle == IntPtr.Zero; } }

/// <summary>
/// Release the native instance of OrtExternalInitializerInfo if we own it.
/// </summary>
/// <returns>true on success and false on error.</returns>
protected override bool ReleaseHandle()
{
if (!_ownsHandle)
{
// Return false to indicate an error.
// ReleaseHandle() should not be called on a const handle that this class does not own.
return false;
}

NativeMethods.OrtReleaseExternalInitializerInfo(handle);
handle = IntPtr.Zero;
return true;
}
}

/// <summary>
/// Interface for all readonly methods implemented by OrtExternalInitializerInfo.
/// </summary>
public interface IReadOnlyExternalInitializerInfo
{
/// <summary>
/// Get the file path to the file that store's the initializer's data.
/// </summary>
/// <remarks>
/// The path is relative to the filesystem directory where the ONNX model was stored.
/// </remarks>
/// <returns>The file path.</returns>
string GetFilePath();

/// <summary>
/// Get the byte offset within the file where the initializer's data is stored.
/// </summary>
/// <returns>The file offset location.</returns>
long GetFileOffset();

/// <summary>
/// Get the size in bytes of the initializer's data within the file.
/// </summary>
/// <returns>The size in bytes of the initializer data.</returns>
long GetByteSize();
}
}
Loading
Loading