Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Khronos Vulkan Samples not running #85817

Closed
bryanhonof opened this issue Apr 22, 2020 · 6 comments
Closed

Khronos Vulkan Samples not running #85817

bryanhonof opened this issue Apr 22, 2020 · 6 comments

Comments

@bryanhonof
Copy link
Member

Describe the bug
I am able to build the Khronos Vulkan Samples but not run them.
I get an error: [error] [build/linux/app/main.cpp:75] Failed to initialize volk.

To Reproduce

  1. Download and follow the build instruction form the Khronos Vulkan Sample repo
  2. Run one of the examples as described in the build guide

Expected behavior
With a simple sample application like hello_triangle a multi colored triangle is supposed to show up in a window accelerated by Vulkan.

Additional context
I am extremely new to nix and nixos, I literally installed it yesterday.
So I am extremely sorry if I am posting this issue in the wrong place.
Please do correct me and I will move my question elsewhere.

I used to use Arch Linux before and I was able to get the samples to run on there.

I checked on the volk github page and it says that if it fails to find a vulkan loader it will throw that error.

I am trying to build it in a separate nix-shell with a default.nix:

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
        buildInputs = [
                pkgs.gcc
                pkgs.cmake
                pkgs.mesa
                pkgs.vulkan-headers
                pkgs.vulkan-loader
                pkgs.vulkan-tools
                pkgs.vulkan-validation-layers
                pkgs.glfw2
                pkgs.libGLU
                pkgs.python3
                pkgs.xorg.libX11
                pkgs.xorg.libXcursor
                pkgs.xorg.libXrandr
                pkgs.xorg.libXinerama
                pkgs.xorg.libXi
                pkgs.xorg.libXext
        ];
}

I also tried installing the vulkan-* packages directly into my system packages but nothing changed.

I read a previous issue #57770 and tried setting the environment variable VK_ICD_FILENAMES and deleting the files in ~/.cache/ but that also did not fix the problem.

Metadata

 - system: `"x86_64-linux"`
 - host os: `Linux 5.6.5, NixOS, 20.09pre222244.22a3bf9fb9e (Nightingale)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3.4`
 - channels(root): `"nixos-20.09pre222244.22a3bf9fb9e"`
 - channels(bryan): `"nixpkgs-20.09pre221814.10100a97c89"`
 - nixpkgs: `/home/bryan/.nix-defexpr/channels/nixpkgs`
@bryanhonof
Copy link
Member Author

I ran the program trough strace and noticed a lot of these errors:

uname({sysname="Linux", nodename="nixos", ...}) = 0
poll([{fd=3, events=POLLIN|POLLOUT}], 1, -1) = 1 ([{fd=3, revents=POLLOUT}])
writev(3, [{iov_base="\22\0\10\0\3\0 \1\375\0\0\0\4\0\0\0 \0\1\0\2\0\0\0\373\0\0\0\n\1\0\0"..., iov_len=464}, {iov_base=NULL, iov_len=0}, {iov_base="", iov_len=0}], 3) = 464
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\34\0C\0\3\0 \1\375\0\0\0y\300\270\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 288
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\34\0L\0\3\0 \1$\0\0\0y\300\270\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 64
poll([{fd=3, events=POLLIN|POLLOUT}], 1, -1) = 1 ([{fd=3, revents=POLLOUT}])
writev(3, [{iov_base="\22\0\7\0\3\0 \1\374\0\0\0\37\0\0\0\10\0\1\0\1\0\0\0C\0\0\0\22\0\n\0"..., iov_len=108}, {iov_base=NULL, iov_len=0}, {iov_base="", iov_len=0}], 3) = 108
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\34\0N\0\3\0 \1\374\0\0\0z\300\270\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 32
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\34\0O\0\3\0 \1\10\1\0\0z\300\270\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 64
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)

These messages happen right before it prints out the line [error] [build/linux/app/main.cpp:75] Failed to initialize volk..

I also tried running it in gdb, it crashes with the following message:

(gdb) file ./build/linux/app/bin/Release/x86_64/vulkan_samples 
Reading symbols from ./build/linux/app/bin/Release/x86_64/vulkan_samples...
(gdb) run hello_triangle
Starting program: /home/bryan/Downloads/Vulkan-Samples/build/linux/app/bin/Release/x86_64/vulkan_samples hello_triangle
warning: File "/nix/store/jy89v2q2zv074mvw91jgqcvkmk7yqx69-gcc-9.3.0-lib/lib/libstdc++.so.6.0.28-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load:/nix/store/ihr026g1ijgmjiqn4xn39bk5rr1w379j-gcc-9.3.0-lib".
To enable execution of this file add
	add-auto-load-safe-path /nix/store/jy89v2q2zv074mvw91jgqcvkmk7yqx69-gcc-9.3.0-lib/lib/libstdc++.so.6.0.28-gdb.py
line to your configuration file "/home/bryan/.gdbinit".
To completely disable this security protection add
	set auto-load safe-path /
line to your configuration file "/home/bryan/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
	info "(gdb)Auto-loading safe path"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/nix/store/v9j0bsl1bv7ngijmvnvnj9h3qrb1p3mf-glibc-2.30/lib/libthread_db.so.1".
[info] Logger initialized
[info] Window created
[info] Initializing vulkan instance.
[error] [build/linux/app/main.cpp:75] Failed to initialize volk.
[info] Closing App (Runtime: 0.0)

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) backtrace 
#0  0x0000000000000000 in ?? ()
#1  0x00000000004a261b in HelloTriangle::teardown(HelloTriangle::Context&) ()
#2  0x00000000004a2901 in HelloTriangle::~HelloTriangle() ()
#3  0x00000000004a2a19 in HelloTriangle::~HelloTriangle() ()
#4  0x0000000000507f2a in vkb::Platform::terminate(vkb::ExitCode) ()
#5  0x000000000040f159 in main.cold ()
#6  0x00007ffff797fd8b in __libc_start_main () from /nix/store/an6bdv4phxsz14q2sk57iscl2dc7bnj1-glibc-2.30/lib/libc.so.6
#7  0x000000000047f32a in _start () at ../sysdeps/x86_64/start.S:120

@bryanhonof
Copy link
Member Author

I was able to get the hello triangle to run from vulkan-tutorial.
So I am assuming this is a problem with either volk or the Khronos Vulkan Samples themselves.
I will take this issue over there.

Screenshot from 2020-04-24 01-20-46

@bryanhonof
Copy link
Member Author

bryanhonof commented Apr 24, 2020

OK, I am posting one last update since I figured out what was wrong.
I am also tagging the vulkan-loader package maintainer @Ralith, since I am not sure if this is intended to work like this.

So, volk opens a vulkan loader with dlopen in this line:

void* module = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);

but since the libvulkan.so file it is looking for is not included in dlopen's (or ld's) search path it fails.

I first got around this by replacing said line with:

void* module = dlopen("/nix/store/xxxx-vulkan-loader-1.2.131.2/lib/libvulkan.so", RTLD_NOW | RTLD_LOCAL);

But that is a little bit too hacky in my opinion, and if the nix store path changes or disappears, it'll break the program again. so I tried editing my default.nix to this:

with import <nixpkgs> {};
stdenv.mkDerivation rec {
        name = "Vulkan-Samples";
        buildInputs = [
                pkgs.gcc
                pkgs.cmake
                pkgs.mesa
                pkgs.vulkan-headers
                pkgs.vulkan-loader
                pkgs.vulkan-tools
                pkgs.vulkan-validation-layers
                pkgs.glfw
                pkgs.glm
                pkgs.libGLU
                pkgs.python3
                pkgs.xorg.libX11
                pkgs.xorg.libXcursor
                pkgs.xorg.libXrandr
                pkgs.xorg.libXinerama
                pkgs.xorg.libXi
                pkgs.xorg.libXext
                pkgs.xorg.libXrender
                pkgs.xorg.libXxf86vm
                pkgs.xorg.libXdmcp
                pkgs.xorg.libXau
                pkgs.xorg.libxcb
                pkgs.gnutls
                pkgs.xorg.libpthreadstubs
                pkgs.llvm_10
                pkgs.clang_10
                pkgs.pkg-config
        ];
        
        LD_LIBRARY_PATH="${pkgs.vulkan-loader}/lib";

        shellHook = "echo ${pkgs.vulkan-loader}";
}

I know there probably is a bunch of packages in there right now I do not actually need but those are worries for another time.
The important line here is LD_LIBRARY_PATH="${pkgs.vulkan-loader}/lib";.
When changing to a shell with this default.nix the program builds and runs without any errors or warnings.

Running the hello_triangle sample produces the correct triangle this time :D.
Screenshot from 2020-04-24 13-40-28

Now I am wondering if this is the correct way to dynamically link with vulkan-loader or if there is an option that I did not see.

@bryanhonof bryanhonof reopened this Apr 24, 2020
@Ralith
Copy link
Contributor

Ralith commented Apr 24, 2020

You'll frequently run into this problem when using dlopen with nix-packaged libraries. You have a few different reasonable options to address it:

  1. Place the library in LD_LIBRARY_PATH in the runtime environment, as you've done. This is easy, and convenient when initially experimenting with someone else's code, but impermanent, and an ugly hack if you distribute your software that way.
  2. Add the library to the rpath embedded in the binary, either after the fact with patchelf or by telling your linker to do so when building. Because it avoids a wrapper script, this is the preferred approach in nixpkgs when the dlopen can't be avoided, e.g. for proprietary software.
  3. Replace the use of dlopen with conventional dynamic linking. This will allow Nix's usual mechanisms to Just Work, and should be preferred whenever possible.

@bryanhonof
Copy link
Member Author

Place the library in LD_LIBRARY_PATH in the runtime environment, as you've done. This is easy, and convenient when initially experimenting with someone else's code, but impermanent, and an ugly hack if you distribute your software that way.

I think I will stick with this solution for now since my own application will be statically linked, so that shouldn't be a problem.

I am however going to looking into point 2 and 3, just to broaden my knowledge :).

Thanks for the reply, I will close this issue.

@Ralith
Copy link
Contributor

Ralith commented Apr 26, 2020

You shouldn't statically link the vulkan loader; it's specifically designed to be upgraded independent of applications, for compatibility with future drivers and layers. It's also impossible to have a 100% statically linked application that uses vulkan at all, because video drivers are dynamically loaded, which requires a dynamically linked libc.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants