Table of Contents

Class OnnxSessionFactory

Namespace
VisioForge.Core.AI
Assembly
VisioForge.Core.AI.dll

Builds Microsoft.ML.OnnxRuntime.SessionOptions with the same execution-provider selection and bundled-native preload logic used by VisioForge.Core.AI.OnnxInferenceEngine, for engines that own their own Microsoft.ML.OnnxRuntime.InferenceSession instances rather than going through that class.

public static class OnnxSessionFactory

Inheritance

Inherited Members

Remarks

Those engines cannot share VisioForge.Core.AI.OnnxInferenceEngine directly because each uses a different preprocessing path and its own input shapes — the multi-stage OCR pipeline (ImageNet normalization for the detector, midgray-padded crops for the recognizer, one session per stage), and the open-vocabulary detector (a multi-input image + text session). They still want the hard-won provider selection (Auto resolves to the best provider actually compiled into the loaded native build) and the Windows DirectML preload, so that logic lives here and is reused by all of them.

Methods

CreateSessionOptions(OnnxExecutionProvider, int, BaseContext, out OnnxExecutionProvider)

Creates session options configured with the requested execution provider (CPU fallback always appended) and extended graph optimization. Best-effort: an unavailable hardware provider falls back to CPU with a warning.

public static SessionOptions CreateSessionOptions(OnnxExecutionProvider provider, int deviceId, BaseContext context, out OnnxExecutionProvider activeProvider)

Parameters

provider OnnxExecutionProvider

The requested execution provider; VisioForge.Core.Types.X.AI.OnnxExecutionProvider.Auto resolves to the fastest available.

deviceId int

The hardware device id for CUDA / DirectML.

context BaseContext

Optional logging context.

activeProvider OnnxExecutionProvider

Receives the provider that was actually engaged.

Returns

SessionOptions

The configured Microsoft.ML.OnnxRuntime.SessionOptions. The caller owns and must dispose it.

ResolveAutoProvider()

Picks the fastest execution provider present in the loaded native build (CUDA, then DirectML, then CoreML, finally CPU) — that is, what VisioForge.Core.Types.X.AI.OnnxExecutionProvider.Auto resolves to. Public so an engine can inspect the choice before paying for it: a model whose graph the provider would fragment into hundreds of partitions is better off on CPU, and only the engine knows that.

public static OnnxExecutionProvider ResolveAutoProvider()

Returns

OnnxExecutionProvider

The best available execution provider.

ResolveAutoProvider(bool, out bool)

Picks the provider VisioForge.Core.Types.X.AI.OnnxExecutionProvider.Auto resolves to, optionally refusing CoreML.

public static OnnxExecutionProvider ResolveAutoProvider(bool vetoCoreML, out bool coreMLVetoed)

Parameters

vetoCoreML bool

When true, a resolution that would land on CoreML returns VisioForge.Core.Types.X.AI.OnnxExecutionProvider.CPU instead. Every other provider is unaffected.

coreMLVetoed bool

Receives true only when the veto actually changed the answer, so the caller can say why in the log without mistaking a machine that simply has no CoreML for one where the veto fired.

Returns

OnnxExecutionProvider

The best available execution provider, subject to the veto.

Remarks

The veto exists because CoreML is not uniformly good or bad — it is per model, and measurably so. Measured on macOS/arm64 with ORT 1.26, 100 inferences per combination, one process each: yolov8n splits into 3 CoreML partitions and runs 3.5 ms against 15-20 ms on CPU, and yolox_nano into 2 partitions at 3.6 ms against 6.1 ms — real acceleration that a blanket veto would throw away. rtdetr splits into 81 partitions and gains nothing for it: 109 ms against 105 ms on CPU, 1277 MB resident against 535 MB, and 2.3-4.2 s to create the session against 0.09 s. Open-vocabulary graphs are worse still (OWLv2 126 partitions, Grounding DINO 255). So the caller decides per model, and only the VisioForge.Core.Types.X.AI.OnnxExecutionProvider.Auto default is redirected — a caller who names CoreML explicitly still gets it.