Ahjo.Vulkan
0.1.6
dotnet add package Ahjo.Vulkan --version 0.1.6
NuGet\Install-Package Ahjo.Vulkan -Version 0.1.6
<PackageReference Include="Ahjo.Vulkan" Version="0.1.6" />
<PackageVersion Include="Ahjo.Vulkan" Version="0.1.6" />
<PackageReference Include="Ahjo.Vulkan" />
paket add Ahjo.Vulkan --version 0.1.6
#r "nuget: Ahjo.Vulkan, 0.1.6"
#:package Ahjo.Vulkan@0.1.6
#addin nuget:?package=Ahjo.Vulkan&version=0.1.6
#tool nuget:?package=Ahjo.Vulkan&version=0.1.6
Ahjo.Vulkan
Idiomatic C# wrapper over Vulkan with
integrated AMD VulkanMemoryAllocator.
Built for games: ref struct command-buffer recorders, readonly struct
resource handles, zero heap allocations on per-frame paths. Buffer/image
creation pairs VkBuffer/VkImage with its VMA allocation handle in a
single type so you never juggle the two halves manually.
Status: pre-1.0. The public surface may shift between 0.x releases as the wrapper fills in remaining Vulkan coverage. Tag your
PackageReferenceto an exact version.
Install
dotnet add package Ahjo.Vulkan
The Vulkan loader is platform-supplied — see
Ahjo.Vulkan.Native
for runtime requirements (Windows GPU drivers / libvulkan1 on Linux /
MoltenVK on macOS). The VMA shared library ships with the transitive
Ahjo.Vulkan.Vma.Native
dependency — no extra setup.
Platforms
Runs on Windows and Linux (x64, arm64) against a system Vulkan 1.4
loader. TFM: net10.0. macOS support (via MoltenVK) is on the roadmap
but not currently tested.
Design principles
Games-first. Low allocation, raw-pointer friendly, minimal ceremony.
This is an opinionated wrapper — not a SafeHandle-shaped .NET port. Same load-bearing idioms as the Ahjo Wgpu wrapper:
- Struct handles.
Buffer,Image,Pipeline, etc. arereadonly structs holding one Vulkan handle. Copy-by-value, no finalizer,default(T)is a legal null handle, double-dispose is UB. ref structcommand recorders + span-parameter descriptors. Recorders don't escape methods; spans live on method parameters, not descriptor fields, to keep escape-analysis happy.
Quick start
using Ahjo.Vulkan;
ReadOnlySpan<Utf8Name> extensions = stackalloc Utf8Name[]
{
Utf8Name.FromLiteral("VK_KHR_surface"u8),
};
using var instance = Instance.Create(new InstanceDescription
{
ApiVersion = VulkanVersion.V1_4,
EnableValidation = true, // appends VK_LAYER_KHRONOS_validation + VK_EXT_debug_utils
Extensions = extensions,
DebugCallback = msg => Console.Error.WriteLine($"[{msg.Severity}] {msg.Message}"),
});
A default(InstanceDescription) is also legal — ApiVersion falls back to
VulkanVersion.V1_4 and the wrapper uses a default callback that writes to
Console.Error.
Layered design
- Struct handles.
Buffer,Image,Pipeline,Queue,CommandBuffer, etc. arereadonly structs that satisfyIVulkanHandle<TSelf>(one or two rawVk*_T*fields,default(T)is a legal null handle, copy-by-value, no finalizer). Disposal is deterministic at the call site; double-dispose is undefined behavior — the wrapper does not zero-on-release.InstanceandDeviceare the exceptions: they aresealed classes with finalizers because they're once-per-process and worth backstopping. ChainBuilder<TRoot>. Stack-only bump allocator that lays out a VulkanpNextchain into a caller-suppliedSpan<byte>(typicallystackalloc byte[256]). Zero heap allocations. The generic constraintT : IChainable<TRoot>makes "this struct cannot extend that root" a compile error, not a runtime check.STypeis read from a static-abstract member — call sites never pass it.VulkanException+VkResult.ThrowIfFailed(). Single-success-result APIs throwVulkanExceptionon anything other thanVK_SUCCESS; the exception carries theVkResultand the originating function name. Hot- path APIs that legitimately return non-success codes (VK_INCOMPLETE,VK_SUBOPTIMAL_KHR,VK_TIMEOUT, …) surface theVkResultdirectly so callers can branch without paying for a throw.Utf8Name.FromLiteral("…"u8). Allconst char*parameters (extension names, layer names, debug labels, application names) flow throughUtf8Name. Pass"…"u8literals only — they live in the assembly's read- only data segment for process lifetime, are null-terminated, and don't require GC pinning. Never round-trip astringthroughEncoding.UTF8.GetBytesfor these slots: the resultingbyte[]is GC- movable and not null-terminated, and the pointer Vulkan sees will dangle. See theFromLiteralXML doc for the full contract. The wrapper'sVulkanExtensionsstatic class exposes ready-madeUtf8Nameconstants for the names it actively wraps (KhrSurface,KhrWin32Surface,KhrSwapchain).
Deeper rationale on each layer lives under
docs/superpowers/specs/
in the source repo.
Repository
Source, issues, samples: https://github.com/pekkah/Ahjo-Vulkan
License
MIT. © Pekka Heikura.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Ahjo.Vulkan.Native (>= 0.1.6)
- Ahjo.Vulkan.Vma.Native (>= 0.1.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.6 | 87 | 5/24/2026 |
| 0.1.5 | 103 | 5/23/2026 |
| 0.1.4 | 98 | 5/22/2026 |
| 0.1.3 | 91 | 5/22/2026 |
| 0.1.2 | 90 | 5/22/2026 |
| 0.1.1 | 87 | 5/21/2026 |
| 0.1.1-alpha.0.1 | 51 | 5/21/2026 |
| 0.1.0 | 96 | 5/21/2026 |
| 0.0.0-alpha.0.163 | 55 | 5/21/2026 |
| 0.0.0-alpha.0.162 | 49 | 5/21/2026 |
| 0.0.0-alpha.0.161 | 53 | 5/12/2026 |