---
title: "Choose a Vulkan physical device in C#"
url: https://recursiveai.org/onegpu/cookbook/pick-a-vulkan-device/
description: "Enumerate Vulkan adapters and select a discrete or integrated GPU in C# with OneGpu. Includes name matching, environment overrides and a runnable example."
version: "1.0.0"
---

# Choose a Vulkan physical device in C#

**OneGpu** is a free, open-source GPU compute and rendering library for .NET from Recursive AI, on Vulkan, Metal and WebGPU. MIT or Apache-2.0, no bundled native binaries.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneGpu.Backends) · [GitHub](https://github.com/recursive-ai-oss/onegpu-csharp) · [Docs](https://recursiveai.org/onegpu/docs/) · [Download example (.zip)](https://recursiveai.org/onegpu/cookbook/pick-a-vulkan-device/pick-a-vulkan-device.zip)

Select a GPU by kind or name before creating its Vulkan device. OneGpu calls a Vulkan physical device an “adapter”. These examples need Windows or Linux and a Vulkan 1.3 driver.

On Apple silicon Macs, `GpuBackends` selects Metal instead; see [backend selection](https://recursiveai.org/onegpu/docs/environment/).

```shell
dotnet new console
dotnet add package RecursiveAI.OneGpu.Backends
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using RecursiveAI.OneGpu;

using var device = GpuBackends.CreateDevice(
    new GpuDeviceOptions { Adapter = "discrete" });
Console.WriteLine(device.Adapter.Name);
```

On the example machine, prints:

```text
NVIDIA GeForce RTX 4070
```

Unzip [the example](https://recursiveai.org/onegpu/cookbook/pick-a-vulkan-device/pick-a-vulkan-device.zip), then `dotnet run`.

## The full program

```csharp
using RecursiveAI.OneGpu;

foreach (var adapter in GpuBackends.EnumerateAdapters())
    Console.WriteLine($"{adapter.Kind}: {adapter.Name}");
using var device = GpuBackends.CreateDevice(
    new GpuDeviceOptions { Adapter = "discrete" });
Console.WriteLine($"Selected: {device.Adapter.Name}");
```

Output on Linux with Vulkan and an NVIDIA GeForce RTX 4070:

```text
Discrete: NVIDIA GeForce RTX 4070
Integrated: AMD Ryzen 9 7950X3D 16-Core Processor (RADV RAPHAEL_MENDOCINO)
Software: llvmpipe (LLVM 21.1.8, 256 bits)
Selected: NVIDIA GeForce RTX 4070
```

Adapter names vary by machine. If no adapter matches, device creation throws `GpuUnsupportedException`; `ONEGPU_ADAPTER`, when set, wins over the option in code.

## Variations

To choose the integrated GPU, replace the device creation:

```csharp
using var device = GpuBackends.CreateDevice(
    new GpuDeviceOptions { Adapter = "integrated" });
Console.WriteLine(device.Adapter.Name);
```

```text
AMD Ryzen 9 7950X3D 16-Core Processor (RADV RAPHAEL_MENDOCINO)
```

To match a model name, use `Adapter = "RTX"` instead; this selects the NVIDIA GeForce RTX 4070 on this machine.


## Related recipes

- [Run a compute shader in C#](https://recursiveai.org/onegpu/cookbook/run-a-compute-shader-in-csharp/)
- [Read a GPU buffer back to the CPU in C#](https://recursiveai.org/onegpu/cookbook/read-back-a-gpu-buffer/)
- [GPU matrix multiplication in C#](https://recursiveai.org/onegpu/cookbook/multiply-matrices-on-the-gpu/)

## The short answer

Enumerate adapters with `GpuBackends.EnumerateAdapters()`, then pass a kind or a name substring to `GpuDeviceOptions.Adapter` when creating the device. For example, `discrete` selects a matching discrete GPU and `integrated` selects an integrated one. Read `device.Adapter` afterward to see which adapter was actually chosen.

These examples use the Vulkan backend. On Windows and Linux it is the platform default; `ONEGPU_BACKEND=vulkan` can select it explicitly. A working Vulkan loader and driver are still required. An adapter that is not visible to Vulkan cannot be selected by its display name.

## How do you choose a Vulkan physical device in C#?

Use the enumeration output to choose between a class of GPU and a particular model. Kind selection is useful when deploying to different machines: `discrete` does not depend on one manufacturer’s model name. A substring such as `RTX` is useful when you want a particular adapter from the list on a known machine. Name matching is case-insensitive.

The selector chooses the first matching adapter in the backend’s order. According to the [adapter-order documentation](https://recursiveai.org/onegpu/docs/compute/), Vulkan sorts by kind first: discrete, integrated, virtual, software, then other. Ties use PCI vendor ID, device ID, name, API version with newest first, and the driver’s pipeline-cache UUID. The default is the first adapter in that order, not whichever driver happens to enumerate first.

A kind is therefore not an exact identity when several GPUs of that kind exist. A short name fragment can also match several adapters. Inspect the list and use a sufficiently specific name if the distinction matters. Create the device only after choosing: the option is applied during device creation rather than moving an already-created device to another GPU.

`ONEGPU_ADAPTER` overrides the C# option. This is useful for changing deployment configuration without rebuilding, but it also explains a program selecting an integrated GPU when its source says `Adapter = "discrete"`. Check that environment variable before treating the mismatch as a device-selection bug. An unset override leaves the code’s option in control.

## How do you get Vulkan GPU info?

The full program prints every visible adapter’s name and kind, then the selected device’s name. On the example machine the list includes a discrete NVIDIA GPU, an integrated RADV adapter and a software adapter. Your output depends on installed drivers and hardware; those three entries are observations from this machine, not a list every application should expect.

`GpuAdapterInfo` describes adapter identity, while `device.Capabilities.Compute` describes the limits and features exposed by the created device. Use the latter when deciding whether a shader can use a scalar type, subgroup operation or workgroup size. A familiar vendor or model name is not a substitute for querying the feature you actually need.

The [environment reference](https://recursiveai.org/onegpu/docs/environment/) specifies that a selector with no match throws `GpuUnsupportedException`. It does not silently fall back to a different GPU. If your application permits a fallback, make that an explicit policy: report the failed choice and deliberately create another device. Otherwise fail clearly so the caller knows its requested adapter was unavailable. The try/catch snippet below catches that exception without pretending a usable device was created.

This catches a deliberately unmatched selector:

```csharp
try
{
    using var device = GpuBackends.CreateDevice(
        new GpuDeviceOptions { Adapter = "no-such-adapter" });
}
catch (GpuUnsupportedException)
{
    Console.WriteLine("No matching adapter");
}
```

```text
No matching adapter
```
