What's the state of the art in Zig ecosystem for Wayland+Vulkan without libc? 2

This is amazing! Thank you for sharing. If/when I get around to implementing this myself, would you mind if I wrote it up as a blog post with credit?

1 Like

This is BEYOND useful. Do you have a code repository somewhere with any of this? Even just a triangle example would be useful. If you don’t, that’s fine as this gave me MORE than enough breadcrumbs to go chasing down.

I have so much glop in my Vulkan programs just to handle all the idiocies around the fact that the swapchain handling functions only take binary sempahores instead of timeline ones.

Being able to use buffer device addresses and RBAR and timeline sempahores will allow me to delete ridiculous amounts of code.

Thank you very much for the post.

2 Likes

Of course, please do! This topic definitely needs more coverage. Many a barren search result trying to piece this together lol

You’re welcome! It has been such a breath of fresh air to get out from under this particular piece of the Vulkan API. Like, I respect the Vulkan devs’ efforts to abstract over what may be the most messy, platform-dependent system, but it really is so frustrating to work with.

I don’t have any public code available at the moment, but I’ll try to whip up a minimal repo sometime this week :slightly_smiling_face:

2 Likes

Does this mean you don’t get a native Wayland window? i.e. is this for full screen mode only? Or like when you run a program in DRM mode when you use Ctrl+Alt+F1 to switch to a different TTY, and then run a program that takes over the whole screen?

I’ll be super curious to tinker with the example you mentioned if you end up publishing it. Either way thanks for sharing!

My goto for stuff like this is toolbx/distrobox.

I have many of such containers on my system, 15 right now to be exact.

And it has the nice advantage that I can test my stuff easily across multiple distros (with the exceptions that they all share a kernel).

But then again, I’m also a Kinoite user, which makes using these tools kinda mandatory for my own sanity.

1 Like

I don’t think so, the compositor is still aware of the buffer and how it is synchronized. The DMA-BUF wayland extension lets you create wl_buffer that’s backed by dmabuf so that can still be attached to a xdg_surface and such. Someone correct me if I’m wrong.

1 Like

It’s because the top-level of lib namespace re-exports some stuff from the inner namespaces. Might be due to backwards compatiblity, not sure, nixpkgs is quite big repo with history :stuck_out_tongue:
https://github.com/NixOS/nixpkgs/blob/c00644f728f9d5669d3bed8ec07e583bba2b9b06/lib/default.nix#L322

It might be difficult to achieve this. Something you could try is the paths you get from /run/current-system/sw/bin/nix-store -q --requisites /run/current-system (regarding vulkan-loader for example), but I recommend showing a message that things may not work correctly if the detected system is nixos, I presume guix will have similar difficulties. It’s possible on nix/guix for programs to use different versions of vulkan-loader. The only thing that’s special on nix are the GPU drivers (living in /run/opengl-driver), as otherwise the package matrix would explode needing a package for each different GPU driver.

What @Cloudef said. In fact, I’d take it a step further. To my understanding, these Wayland extensions are what VK_KHR_wayland_surface and friends are using under the hood. See this snippet from wp_linux_drm_syncobj_manager_v1.get_surface:

Graphics APIs, like EGL or Vulkan, that manage the buffer queue and commits of a wl_surface themselves, are likely to be using this extension internally. If a client is using such an API for a wl_surface, it should not directly use this extension on that surface, to avoid raising a surface_exists protocol error.

And I’ve had no issues in my own experience. Windowed, fullscreen, decorations, resizing, scaling, etc., are all orthogonal to the wl_buffer (thank you Wayland designers)

3 Likes

Update: I’ve published what is hopefully a neat little repo (Zig 0.16): Wayland Vulkan Presentation From Scratch Example

  1. git clone https://codeberg.org/Daskie/presentation-example.git
  2. zig build -Dtarget=x86_64-linux-gnu
  3. zig-out/bin/test
  4. :eye: see a pretty rectangle :eye:

I will admit It’s more code than I expected. It’s almost like simple examples that cover a large surface area end up with the whole boilerplate for that surface area when written from scratch regardless of complexity :melting_face:

Anyway, there’s bunch in the readme, but in short

  • It should be a decorated window that can be manipulated like any other window (moved, resized, maximized, etc)
  • The whole window should slowly strobe colors (just doing the simplest possible thing each frame which is vkCmdClearColorImage)
  • You can make the window translucent
  • You can enable or disable v-sync
  • It will print the FPS and a bunch of info about the current and available DRM format+modifiers

Disclaimer: I have only tested this on my personal machine; Cosmic Desktop, AMD GPU. I give it a 50/50 of working with Nvidia. Eager to get this tightened up if anyone has issues and is so kind as to share them :slightly_smiling_face:

18 Likes

Hmm, on Sway (or rather SwayFX) I do get a window, but it’s transparent, nothing gets rendered into it. It’s laggy when I try to resize it, so I presume something is happening, but no real output.

Might be related to the first warning I get?

Program output
> ./zig-out/bin/test
warning(qce_vk_general): terminator_CreateInstance: Received return code -9 from call to vkCreateInstance in ICD /nix/store/v2isk5r5fzlriczi14ckn20hf45079di-mesa-26.1.2/lib/libvulkan_dzn.so. Skipping this driver.
info: Dmabuf feedback format+modifiers:
info: Tranche | Device | Scanout | Format               | Modifier           | Status

Lots of unsupported - deleted to that it fits in a Ziggit comment

info:       0 | main   |         | ABGR8888             | 0x020000001896BB03 | available
info:       0 | main   |         | ABGR8888             | 0x0200000018967B03 | available
info:       0 | main   |         | ABGR8888             | 0x0200000018937B03 | available
info:       0 | main   |         | ABGR8888             | 0x0200000018801B03 | available
info:       0 | main   |         | ABGR8888             | 0x0200000000801603 | available
info:       0 | main   |         | ABGR8888             | 0x0200000000000901 | available
info:       0 | main   |         | ABGR8888             | 0x0000000000000000 | available
info:       0 | main   |         | ABGR8888             | 0x00FFFFFFFFFFFFFF | unsupported
info:       0 | main   |         | XRGB8888             | 0x020000001896BB03 | unsupported
info:       0 | main   |         | XRGB8888             | 0x0200000018967B03 | unsupported
info:       0 | main   |         | XRGB8888             | 0x0200000018937B03 | unsupported
info:       0 | main   |         | XRGB8888             | 0x0200000018801B03 | unsupported
info:       0 | main   |         | XRGB8888             | 0x0200000000801603 | unsupported
info:       0 | main   |         | XRGB8888             | 0x0200000000000901 | unsupported
info:       0 | main   |         | XRGB8888             | 0x0000000000000000 | unsupported
info:       0 | main   |         | XRGB8888             | 0x00FFFFFFFFFFFFFF | unsupported
info:       0 | main   |         | XBGR8888             | 0x020000001896BB03 | available
info:       0 | main   |         | XBGR8888             | 0x0200000018967B03 | available
info:       0 | main   |         | XBGR8888             | 0x0200000018937B03 | available
info:       0 | main   |         | XBGR8888             | 0x0200000018801B03 | available
info:       0 | main   |         | XBGR8888             | 0x0200000000801603 | available
info:       0 | main   |         | XBGR8888             | 0x0200000000000901 | available
info:       0 | main   |         | XBGR8888             | 0x0000000000000000 | available

Lots of unsupported again

info: Swap image format+modifier set to xbgr8+0x020000001896BB03
2 Likes

I certainly don’t like that warning, but the lack of a panic is odd…

AMD or Nvidia? I’m assuming AMD, I forgot that the vendor is given in the top byte of the DRM modifier (Intel is 1, AMD is 2, Nvidia is 3)

Are you getting the FPS logs? If not, the program is hung, probably a semaphore issue.

If it’s not hung, try setting preferLinear to true in the window.init() call.

Also I just pushed a small commit that adds some better logging which might be helpful.

1 Like

Data point from NixOS 25.11.9840.a4bf06618f0b, KDE Plasma 6.5.6.

Using the following nix-shell (calling this one minimal-vulkan.nix on my computer):

{ pkgs ? import <nixpkgs> {} }:

pkgs.mkShell {
  hardeningDisable = [ "all" ];
  packages = with pkgs; [
    vulkan-loader
    vulkan-validation-layers
  ];

  VK_LAYER_PATH = "${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d";

  LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [
    pkgs.vulkan-loader
  ];
}
[nix-shell:~/src/presentation-example]$ ./zig-out/bin/test 
warning(vk_general): terminator_CreateInstance: Received return code -3 from call to vkCreateInstance in ICD /nix/store/i7my973ka8kddq8rg62znr6ckz1xa7wl-mesa-25.2.6/lib/libvulkan_dzn.so. Skipping this driver.
info(vulkan): Physical device name: "AMD Radeon RX 7900 XTX (RADV NAVI31)", type: discrete_gpu, API version: 1.4.318, driver version: 104865798
info(window): Dmabuf feedback format+modifiers:
info(window): Tranche | Device | Scanout | Format               | Modifier           | Status
thread 34238 panic: index out of bounds: index 69, len 0
/home/andy/src/presentation-example/window/window.zig:978:66: 0x119445a in _handleWaylandEvent (test)
                    const drmFormat = _dmabufFeedback.formatTable[i].format;
                                                                 ^
/home/andy/src/presentation-example/window/window.zig:611:28: 0x1192e81 in _readWaylandEvents (test)
        _handleWaylandEvent(header, data);
                           ^
/home/andy/src/presentation-example/window/window.zig:578:31: 0x11923f2 in _poll (test)
            _readWaylandEvents();
                              ^
/home/andy/src/presentation-example/window/window.zig:309:22: 0x1191a19 in poll (test)
            _ = _poll(true);
                     ^
/home/andy/src/presentation-example/test/test.zig:32:37: 0x118738e in main (test)
        const swapInfo = window.poll();
                                    ^
/home/andy/local/zig-0.16.0/lib/zig/std/start.zig:699:88: 0x11879c0 in callMain (test)
    if (fn_info.params[0].type.? == std.process.Init.Minimal) return wrapMain(root.main(.{
                                                                                       ^
3 Likes

Yes, AMD :slight_smile: AMD Radeon RX 6700 XT, if useful.

I don’t seem to be getting any more logs than what I’ve posted previously, so it’s hung, probably.

> ./zig-out/bin/test
warning(vk_general): terminator_CreateInstance: Received return code -9 from call to vkCreateInstance in ICD /nix/store/v2isk5r5fzlriczi14ckn20hf45079di-mesa-26.1.2/lib/libvulkan_dzn.so. Skipping this driver.
info(vulkan): Physical device name: "AMD Radeon RX 6700 XT (RADV NAVI22)", type: discrete_gpu, API version: 1.4.348, driver version: 109056002
...
info(window): Swap image format+modifier set to xbgr8+0x020000001896BB03
2 Likes

Thanks!

Okay, clearly there are problems when running in other environments, so I’m going to do what I probably should have done already and get a few different desktop environments available to test on locally. Hopefully I can reproduce these issues!

3 Likes

Do post updates! I’ll be watching this thread and try to help as much as I can :slight_smile:

1 Like

Hmm, just tried under upstream Sway (version 1.12) and it still shows an empty window, but—interestingly—also prints the FPS every second or so. Resizing is also smooth under Sway, not choopy like under SwayFX (version 0.5.3, based on sway 1.11).

Turns out KWin (kde’s compositor) sends the dmabuf feedback events in a slightly different order than other compositors :upside_down_face:

Pushed the simple fix. Hopefully that solves your issue

1 Like

assuming OPAQUE_FD == DRM syncobj works for mesa by coincidence?
But for nvidia it doesn’t fly.