SwiftShader Vulkan software renderer on Haiku


Yet another Vulkan related post!

Screenshot 1

Screenshot 2

I spent the weekend porting SwiftShader to Haiku to figure out how much work it would be to get something that resembles the VulkanSDK working. Short version: components of the Vulkan SDK can most likely be built individually as packages. Getting the Vulkan SDK working intact on Haiku will take some doing. Anyway, that can be sorted out later.

Okay, so what’s going on here?

What you’re looking at are two screenshots from a framework that I use to test Vulkan, D3D12, and D3D12 implementations on various platforms. The first screenshot shows a cube map render. The second screenshot shows a PBR-ish material render. You can see from the screenshot that the framerate is not too shabby for a software renderer using a 5+ year old CPU. And yes, both programs are interactive.

The framework itself sits on top of GLFW and uses ImGui for all the nice graphics wigets you’re seeing.

What I did was took the source from the existing GLFW package in HaikuPorts and added Vulkan support in it. The existing implementation had all the right facilities and just need some small additions. For instance, I added a function called glfwGetHaikuView to return a pointer to the BView that the GLFW window creates. The BView is passed onto the Vulkan create surface function and later used by the swapchain. More below.

I’ll put the changes into a repo later this week when I havesome more time.

Works as is - no modifications needed. The framework I had already had all the routing code for ImGui and GLFW and so it all kinda just worked.

Part of porting SwiftShader meant getting SPIRV-Tools to compile. The changes to this were pretty minimal. You can see the changes here: https://github.com/chaoticbob/swiftshader/tree/haiku/third_party/SPIRV-Tools.

SPIRV-Tools is pretty essential to having a working Vulkan ecosystem on a platform. It’s the backbone of so many Vulkan related tools.

This took some doing and at some point I almost gave up because there was a use of static thread_local that gave me a headache just thinking about it. PulkoMandy was nice enough to let me know that static TLS isn’t supported on Haiku yet. After more thinking about it and writing a sample program to test out the pattern that SwiftShader had - it didn’t seem like the static thread_local would matter for simple cases - so thread_local was removed.

You can check out the changes I made here: https://github.com/chaoticbob/swiftshader/tree/haiku

WSI Integreation
As mentioned earlier, a BView is used for surface creation and gets fed an image swapchain for presentation. The BView is retried from the GLFW Window and passed to vkCreateHaikuSurfaceEXT. The surface class implementation creates a bitmap that gets used as apart of the presentation.

Here’s what the implementation looks like:

Yeah…it looks a lot like GLFW HaikuPlatformtView class. One question that did come up was is there a way to get the exact pixel dimensions of a BView? BRect returns floats and I’m not entirely sure if what I’m doing to approximate the size is correct.

Addtionally, it was necessary to create all the Vulkan platform WSI bits - so I went ahead and created vulkan_haiku.h for all this. The surface extension is tagged as an EXT - hopefully that wasn’t too presumptious (or eagerly hopefully).

You can see what that looks like here:

What’s Next?

  • Vulkan-Loader and Validation Layers need to be ported - I have Vulkan-Loader compiling but it spins out when it tries to scan for the ICDs. This shouldn’t be too hard to fix.
  • Shader compilers - both glslang and DXC should compile and run on Haiku since they both work on Linux and MacOS. IIRC there isn’t anything egregious in their code base that would prevent this.
  • More samples?
  • Wait for a Vulkan hardware driver to show :slight_smile:

Anyway enjoy - and feel free to ask any questions.


Nice work!
How is this related to @X512 's work on Vulkan rendering?

Official Vulkan samples from Khronos:

This Git repo also has a very comprehensive set of samples:

SwiftShader is a different Vulkan software renderer from Lavapipe, which is part of Mesa. That being said, both efforts could share quite a lot such as the WSI, SPIRV-Tools, GLFW, etc.


BRect uses floats but for an on-screen view you will only find integer values there. However you need to add 1 to the rect width and height to get the number of covered pixels.

Some explanations are provided in the Be Book:



I ran into a weird case at 1280x720 where adding 1 to Width() and Height() put me over where I was suppose to be. It’s most likely a bug somewhere in my logic but it was odd that it worked with other resolutions beforehand. I’ll investigate more later.

Build instructions if you want to play along at home:


You make it look so easy!

1 Like