How to use Vulkan in C#?

Madie

New Member
Messages
8
Reaction score
2
Basically everything I find on how to use the Vulkan API and set up basic rendering is for C++ and for some reason can't get them working in C# (I don't have a lot of experience with either language). Does anybody have any good tutorials or know where I could find them?
 
We have samples coming soon, but join us on discord if you haven’t already!

People are already starting to share their Vulkan code in Brutal
 
Hi, I made a sample project to learn how to use brutal myself. I wrote the parts that I know from Vulkan C++ and had AI fix my mistakes and assumptions. So full disclosure, while this is not vibe coded, I did use AI assistance for learning purposes. It uses Vulkan on Windows and Linux, OpenGL on Macs. I have not gotten around to use MoltenVK for this on Mac yet.

Link to repo: https://github.com/ardahamamcioglu/HelloBrutal.git
 
Thank you for making BRUTAL public!
I like C# and I like having the freedom of coding whatever while having some level of abstraction from the busy work.
 
Thanks for sharing this! It's exactly what I need to get learn Vulkan from the comfort of C#, since i've never used vulkan before!
 
We have samples coming soon, but join us on discord if you haven’t already!

People are already starting to share their Vulkan code in Brutal
I am in it already, but not phone verified (and not planning on doing so), so can't send any messages.
 
Hi, I made a sample project to learn how to use brutal myself. I wrote the parts that I know from Vulkan C++ and had AI fix my mistakes and assumptions. So full disclosure, while this is not vibe coded, I did use AI assistance for learning purposes. It uses Vulkan on Windows and Linux, OpenGL on Macs. I have not gotten around to use MoltenVK for this on Mac yet.

Link to repo: https://github.com/ardahamamcioglu/HelloBrutal.git
Amazing, thanks a lot!

Personally I don't mind AI usage as long as it's used as a tool, so no worries there.
 
Hi, I made a sample project to learn how to use brutal myself. I wrote the parts that I know from Vulkan C++ and had AI fix my mistakes and assumptions. So full disclosure, while this is not vibe coded, I did use AI assistance for learning purposes. It uses Vulkan on Windows and Linux, OpenGL on Macs. I have not gotten around to use MoltenVK for this on Mac yet.

Link to repo: https://github.com/ardahamamcioglu/HelloBrutal.git
Looking at the new examples dropped by @Rian Drake and after having a look at yours yesterday I noticed he uses this line as a 'cleaner' way to do the "Prefer Vulkan" check.

if (Platform.IsMacOS)
Glfw.WindowHint(GlfwWindowHint.OpenGlForwardCompat, 1);

Not saying its better just wanted to share <3
I will probably use this way for prototyping
 
I should check his examples. In the end I just turned it into a universal check for vulkan instead of a mac only thing. I am working on a branch that auto discovers vulkan SDK on mac so you don't have to run
Code
source ~/VulkanSDK/*/setup-env.sh && dotnet run
to run the application with vulkan.
 
I should check his examples. In the end I just turned it into a universal check for vulkan instead of a mac only thing. I am working on a branch that auto discovers vulkan SDK on mac so you don't have to run
Code
source ~/VulkanSDK/*/setup-env.sh && dotnet run
to run the application with vulkan.
I ended up instead loading Vulkan manually on MacOS and just pass that directly to glfw, so the renderer is the same for all three platforms but is only loaded once. I haven't tested Windows yet, but Linux and MacOS work great on my M2 Pro laptop at least.

On MacOS, Brutal.Vulkan (2026.10.2) asks .NET to load a native library called VulkanEx, which doesn’t exist on a normal machine. On Linux it asks for vulkan, which resolves to libvulkan.so, a file that only ships in -dev packages. Both fail with a DllNotFoundException wrapped in a TypeInitializationException the first time you touch the Vulkan API. This workaround needs no changes to BRUTAL:
C#
static readonly string[] Candidates = OperatingSystem.IsMacOS()
    ? ["libvulkan.1.dylib", "/opt/homebrew/lib/libvulkan.1.dylib", "/usr/local/lib/libvulkan.1.dylib"]
    : OperatingSystem.IsLinux() ? ["libvulkan.so.1"] : [];


public static unsafe bool TryLoad(out nint getInstanceProcAddr)
{
    // Only called after BRUTAL's own lookup has failed, and only for BRUTAL's Vulkan assembly.
    AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, name) =>
    {
        if (assembly != typeof(Vulkan).Assembly) return 0;
        foreach (var candidate in Candidates)
            if (NativeLibrary.TryLoad(candidate, out var handle)) return handle;
        return 0;
    };


    try
    {
        getInstanceProcAddr = (nint)Vulkan.GetInstanceProcAddr.Invoke;
        return true;
    }
    catch (TypeInitializationException e) when (e.InnerException is DllNotFoundException)
    {
        getInstanceProcAddr = 0;
        return false;
    }
}

// At startup, before Glfw.Init():
if (!VulkanLoader.TryLoad(out var gipa)) { /* no Vulkan loader installed */ }
Glfw.PInvoke.InitVulkanLoader(gipa);
Glfw.Init();
For MoltenVK, also call VulkanHelpers.AddPlatformRequiredExtensions on the instance extensions (portability enumeration) and VulkanHelpers.AddMandatoryIfSupportedDeviceExtensions on the device extensions (VK_KHR_portability_subset). Both do nothing elsewhere.

On MacOS, you can use brew to install the necessary dependencies:
Code
brew install vulkan-loader molten-vk
plus vulkan-validationlayers if you want validation. Homebrew’s layer manifest uses a bare library name, so run with DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib or the layer fails to load.
 
I ended up instead loading Vulkan manually on MacOS and just pass that directly to glfw, so the renderer is the same for all three platforms but is only loaded once. I haven't tested Windows yet, but Linux and MacOS work great on my M2 Pro laptop at least.

On MacOS, Brutal.Vulkan (2026.10.2) asks .NET to load a native library called VulkanEx, which doesn’t exist on a normal machine. On Linux it asks for vulkan, which resolves to libvulkan.so, a file that only ships in -dev packages. Both fail with a DllNotFoundException wrapped in a TypeInitializationException the first time you touch the Vulkan API. This workaround needs no changes to BRUTAL:
C#
static readonly string[] Candidates = OperatingSystem.IsMacOS()
    ? ["libvulkan.1.dylib", "/opt/homebrew/lib/libvulkan.1.dylib", "/usr/local/lib/libvulkan.1.dylib"]
    : OperatingSystem.IsLinux() ? ["libvulkan.so.1"] : [];


public static unsafe bool TryLoad(out nint getInstanceProcAddr)
{
    // Only called after BRUTAL's own lookup has failed, and only for BRUTAL's Vulkan assembly.
    AssemblyLoadContext.Default.ResolvingUnmanagedDll += (assembly, name) =>
    {
        if (assembly != typeof(Vulkan).Assembly) return 0;
        foreach (var candidate in Candidates)
            if (NativeLibrary.TryLoad(candidate, out var handle)) return handle;
        return 0;
    };


    try
    {
        getInstanceProcAddr = (nint)Vulkan.GetInstanceProcAddr.Invoke;
        return true;
    }
    catch (TypeInitializationException e) when (e.InnerException is DllNotFoundException)
    {
        getInstanceProcAddr = 0;
        return false;
    }
}

// At startup, before Glfw.Init():
if (!VulkanLoader.TryLoad(out var gipa)) { /* no Vulkan loader installed */ }
Glfw.PInvoke.InitVulkanLoader(gipa);
Glfw.Init();
For MoltenVK, also call VulkanHelpers.AddPlatformRequiredExtensions on the instance extensions (portability enumeration) and VulkanHelpers.AddMandatoryIfSupportedDeviceExtensions on the device extensions (VK_KHR_portability_subset). Both do nothing elsewhere.

On MacOS, you can use brew to install the necessary dependencies:
Code
brew install vulkan-loader molten-vk
plus vulkan-validationlayers if you want validation. Homebrew’s layer manifest uses a bare library name, so run with DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib or the layer fails to load.
I’m surprised you needed to do that much, I usually just do:

```
_ = Vulkan.GetInstanceProcAddr;
```

before any GLFW calls and Vulkan works for me on Mac.

We are looking at ways to improve the loader so we don’t need to do that, though. I’m actually surprised there was a InitVulkanLoader function on GLFW, don’t know how I missed that. I got this working at least, makes way more sense than what I was doing:

```
Glfw.InitVulkanLoader(Vulkan.GetInstanceProcAddr);
```
 
I’m surprised you needed to do that much, I usually just do:

```
_ = Vulkan.GetInstanceProcAddr;
```

before any GLFW calls and Vulkan works for me on Mac.

We are looking at ways to improve the loader so we don’t need to do that, though. I’m actually surprised there was a InitVulkanLoader function on GLFW, don’t know how I missed that. I got this working at least, makes way more sense than what I was doing:

```
Glfw.InitVulkanLoader(Vulkan.GetInstanceProcAddr);
```
@Terra Incognita I am disappointed the ``` didn't work 😭
 
I’m surprised you needed to do that much, I usually just do:

```
_ = Vulkan.GetInstanceProcAddr;
```

before any GLFW calls and Vulkan works for me on Mac.

We are looking at ways to improve the loader so we don’t need to do that, though. I’m actually surprised there was a InitVulkanLoader function on GLFW, don’t know how I missed that. I got this working at least, makes way more sense than what I was doing:

```
Glfw.InitVulkanLoader(Vulkan.GetInstanceProcAddr);
```
You probably have the dev packages installed? I opted to find a workaround that didn't require that, but I will test out your solution. I can recommend that upstream BRUTAL should instead resolve libvulkan.1.dylib and libvulkan.so.1 (or the Homebrew paths) by default instead of the VulkanEx and vulkan names.
 
You probably have the dev packages installed? I opted to find a workaround that didn't require that, but I will test out your solution. I can recommend that upstream BRUTAL should instead resolve libvulkan.1.dylib and libvulkan.so.1 (or the Homebrew paths) by default instead of the VulkanEx and vulkan names.
If you want to make your suggestion via an issue or PR, I can credit you for the contribution :)

I need another Mac that I don't have a dev environment installed on :ROFLMAO:
 
Back
Top