Overview
A few people on the forum including myself are having issues with Vital having a black screen and/or crashing from it. After doing some debugging I think I have found the root cause.
This is caused because the bgfx library’s setRenderContextSize function is receiving corrupted height and width dimensions due to outdated memory mapping.
Workaround by Discord member Slart at the bottom.
Error
/home/runner/work/vital/vital/plugin_framework/third_party/bgfx.cmake/bgfx/src/glcontext_egl.cpp (425): BGFX FATAL 0x00000002: Failed to create surface.
Test Parameters
- Vital Standalone & VST3 (Reaper)
- Vital Version 1.6.4
- Fedora 44
- Wayland
- NVIDIA GPU
- Mesa 26.X+
- GDB Debugger
Technical Breakdown
Looking at the backtrace, we can see the application reaches this point before crashing:
#5 0x0000555555c0b1b9 in bgfx::fatal(char const*, unsigned short, bgfx::Fatal::Enum, char const*, ...) ()
#6 0x0000555555c94031 in bgfx::gl::RendererContextGL::setRenderContextSize(unsigned int, unsigned int, unsigned int) ()
By inspecting Frame 6, we can see the canvas dimensions being passed to the graphics engine.
On Wayland, the function receives:
232298
233343
Upon further investigation, it appears these values are actually the PID and LWP ID’s (as shown in the thread exit logs below), rather than actual pixel dimensions.
On the other hand, if we attempt to force X11 at the application/window layer with GDK_BACKEND=x11 we get:
140736884377728
0
These are a memory address (0x7fffdc000880) and a null pointer.
In either scenario the values are invalid for a canvas size, causing the application or VST to crash.
The Reason
The reason it’s receiving these values is because Vital is expecting to receive this information in a specific structure in memory, but due to using outdated tools, the structure is not matching with what the host is providing.
Vital expects to receive an X11 Window Struct but the host is providing a Wayland/EGL Surface struct. From my limited understanding X11 provides the width and height in the first bytes, while Wayland provides the PID & LWP.
The reason forcing X11 didn’t work is because the bgfx library bypasses XWayland and talks to the lower level graphics layers directly. So the resulting values are what the XWayland translation layer is giving, that is also incorrectly mapped.
Further Proof
As shown in the next sections workaround, you can directly override the use of Wayland by forcing X11 at a lower graphic level by specifying the use of an older Mesa configuration. The fact that forcing these low-level driver rules completely solves the crash proves that Vital’s interface stabilizes once the underlying memory maps are forced back into a legacy layout.
Workaround Scripts (By Slart on Discord)
To fix the crash, you must target the Graphics API and Hardware Driver layers directly, forcing the entire rendering pipeline to drop back to legacy X11 memory mapping layouts where the variables align correctly.
You can implement this by creating a custom launcher script for your Standalone application or your DAW host (e.g., Reaper).
NOTE: You may need to change the path to your DAW and the mesa.json version (see below for how to find your version).
#!/bin/sh
export __GL_THREADED_OPTIMIZATIONS=0
export EGL_PLATFORM=x11
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json
unset WAYLAND_DISPLAY
exec "/usr/bin/reaper" "$@"
Your distribution may use a different priority value for your Mesa configuration, to check; run and replace the __EGL_VENDOR_LIBRARY_FILENAMES if necessary:
ls /usr/share/glvnd/egl_vendor.d/
For Flatpaks you can run the following command (replace com.bitwig.BitwigStudio with your specific DAW’s Flatpak ID):
flatpak override --user \
--env=__GL_THREADED_OPTIMIZATIONS=0 \
--env=EGL_PLATFORM=x11 \
--env=__EGL_VENDOR_LIBRARY_FILENAMES=/run/host/usr/share/glvnd/egl_vendor.d/50_mesa.json \
--unset-env=WAYLAND_DISPLAY \
com.bitwig.BitwigStudio
And use this to undo it at a later point:
flatpak override --user --reset com.bitwig.BitwigStudio
Full Backtrace
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1 0x00007ffff79168d3 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:89
#2 0x00007ffff78bb48e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007ffff78a27b3 in __GI_abort () at abort.c:77
#4 0x0000555555c8d90b in bgfx::CallbackStub::fatal(char const*, unsigned short, bgfx::Fatal::Enum, char const*) ()
#5 0x0000555555c0b1b9 in bgfx::fatal(char const*, unsigned short, bgfx::Fatal::Enum, char const*, ...) ()
#6 0x0000555555c94031 in bgfx::gl::RendererContextGL::setRenderContextSize(unsigned int, unsigned int, unsigned int) ()
#7 0x0000555555c49ce0 in bgfx::gl::RendererContextGL::init(bgfx::Init const&) ()
#8 0x0000555555c49be8 in bgfx::gl::rendererCreate(bgfx::Init const&) ()
#9 0x0000555555c12383 in bgfx::rendererCreate(bgfx::Init const&) ()
#10 0x0000555555c12ede in bgfx::Context::rendererExecCommands(bgfx::CommandBuffer&) ()
#11 0x0000555555c0f279 in bgfx::Context::renderFrame(int) ()
#12 0x0000555555c0f86e in bgfx::Context::renderThread(bx::Thread*, void*) ()
#13 0x0000555555cb8a6a in bx::ThreadInternal::threadFunc(void*) ()
#14 0x00007ffff7914759 in start_thread (arg=<optimized out>) at pthread_create.c:454
#15 0x00007ffff799890c in __GI___clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
Exit Threads
[Thread 0x7ffff5e006c0 (LWP 232334) exited]
[Thread 0x7ffff7d29c80 (LWP 232298) exited]