felixdoerre/primus_vk

Unable to compile on Sabayon (Gentoo)

mahalay opened this issue · 26 comments

Hello,

Seems like the ebuild described in this issue is already outdated, so I followed the installation instruction.

However, during make libprimus_vk.so libnv_vulkan_wrapper.so I get the following:

c++  --std=gnu++11 -g3 -I/usr/include/vulkan -shared -fPIC primus_vk.cpp -o libprimus_vk.so -Wl,-soname,libprimus_vk.so.1 -ldl -lpthread 
In file included from primus_vk.cpp:3:
/usr/include/vulkan/vk_layer_dispatch_table.h:389:5: error: ‘PFN_vkGetDeviceGroupSurfacePresentModes2EXT’ does not name a type; did you mean ‘PFN_vkGetDeviceGroupSurfacePresentModesKHR’?
     PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT;
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     PFN_vkGetDeviceGroupSurfacePresentModesKHR
make: *** [Makefile:19: libprimus_vk.so] Error 1

On my system, the required dependencies (as far as I can understand) have the following versions installed:

vulkan-headers-1.1.114
vulkan-layers-1.1.125-r2
nvidia-drivers-440.44-r1
bumblebee-3.2.1_p20170130
primus-20150328

Hi, what version is your vk_layer_dispatch_table.h? It does not seem to match the upstream version in any of the mentioned versions: https://github.com/KhronosGroup/Vulkan-Loader/blob/v1.1.125/loader/generated/vk_layer_dispatch_table.h#L641
I would expect PFN_vkGetDeviceGroupSurfacePresentModes2EXT to be wrapped inside #ifdef VK_USE_PLATFORM_WIN32_KHR, which is true in the upstream version, but your line numbers seem to be way off..... could you please provide your version of /usr/include/vulkan/vk_layer_dispatch_table.h?

Regarding the ebuild: I don't see why you couldn't just update the version numbers and it should work. By the way, you should probably bump media-libs/vulkan-layers-1.1.106 to media-libs/vulkan-layers-1.1.108.

Hi, what version is your vk_layer_dispatch_table.h? It does not seem to match the upstream version in any of the mentioned versions: https://github.com/KhronosGroup/Vulkan-Loader/blob/v1.1.125/loader/generated/vk_layer_dispatch_table.h#L641
I would expect PFN_vkGetDeviceGroupSurfacePresentModes2EXT to be wrapped inside #ifdef VK_USE_PLATFORM_WIN32_KHR, which is true in the upstream version, but your line numbers seem to be way off..... could you please provide your version of /usr/include/vulkan/vk_layer_dispatch_table.h?

Just managed to get into my computer just now, sorry but I think I may have given you an incorrect version for vulkan_layers (I'm using two package manager - entropy (Sabayon for its pre-built binaries) and portage for other packages non-existent in Sabayon. What's installed in my system is 1.1.106. I'll do another rebuild later. Thank you so much for the effort. Highly appreciated.

Regarding the ebuild: I don't see why you couldn't just update the version numbers and it should work. By the way, you should probably bump media-libs/vulkan-layers-1.1.106 to media-libs/vulkan-layers-1.1.108.

Unfortunately it's not straightforward. Paths are different on my distro - after reading the guide. Howver, I'll give it another try to see what we get.

Hello @felixdoerre

I manage to compile from source, but had to make changes as described below. However, I am getting this error: [ 5625.241684] vulkaninfo[6459]: segfault at 0 ip 0000000000000000 sp 00007fff88be98b8 error 14 in x86_64-pc-linux-gnu-vulkaninfo[561a7c1e9000+3000] whenever I do $ optirun primus_vk_diag. Can you spot if there's anything I've missed?

diff --git a/Makefile b/Makefile
index 86ab89e..f5bb2e9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,20 @@
 DESTDIR      ?=
-PREFIX        = $(DESTDIR)/usr/local
+PREFIX        = $(DESTDIR)/usr
 INSTALL       = /usr/bin/install
 override INSTALL += -D
 MSGFMT        = /usr/bin/msgfmt
 SED           = /bin/sed
 LN            = /bin/ln
+RM            = /bin/rm
 bindir        = $(PREFIX)/bin
-libdir        = $(PREFIX)/lib
+libdir        = $(PREFIX)/local/lib
 sysconfdir    = $(PREFIX)/etc
 datarootdir   = ${PREFIX}/share
 datadir       = ${datarootdir}
 
 override CXXFLAGS += --std=gnu++11 -g3
 
-all: libprimus_vk.so libnv_vulkan_wrapper.so
+all: libprimus_vk.so libnv_vulkan_wrapper.so primus_vk_diag
 
 libprimus_vk.so: primus_vk.cpp
 	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I/usr/include/vulkan -shared -fPIC $^ -o $@ -Wl,-soname,libprimus_vk.so.1 -ldl -lpthread $(LDFLAGS)
@@ -33,7 +34,7 @@ primus_vk_diag: primus_vk_diag.o
 	$(CXX) -g3 -o $@ $^ -lX11 -lvulkan -ldl $(LDFLAGS)
 
 clean:
-	rm -f libnv_vulkan_wrapper.so libprimus_vk.so
+	rm -f libnv_vulkan_wrapper.so libprimus_vk.so primus_vk_diag primus_vk_diag.so
 
 install: all
 	$(INSTALL) "libnv_vulkan_wrapper.so" "$(libdir)/libnv_vulkan_wrapper.so.1"
@@ -43,3 +44,7 @@ install: all
 	$(INSTALL) -m644 "primus_vk.json" -t "$(datadir)/vulkan/implicit_layer.d/"
 	$(INSTALL) -m644 "nv_vulkan_wrapper.json" -t "$(datadir)/vulkan/icd.d/"
 	$(INSTALL) -m755 "pvkrun.in.sh" "$(bindir)/pvkrun"
+	$(INSTALL) -m755 "primus_vk_diag" "$(bindir)/primus_vk_diag"
+
+uninstall: all
+	$(RM) "$(libdir)/libnv_vulkan_wrapper.so.1" "$(libdir)/libnv_vulkan_wrapper.so" "$(libdir)/libprimus_vk.so.1" "$(libdir)/libprimus_vk.so" "$(datadir)/vulkan/implicit_layer.d/primus_vk.json" "$(datadir)/vulkan/icd.d/nv_vulkan_wrapper.json" "$(bindir)/pvkrun" "$(bindir)/primus_vk_diag"
diff --git a/nv_vulkan_wrapper.cpp b/nv_vulkan_wrapper.cpp
index b186aac..e2b4022 100644
--- a/nv_vulkan_wrapper.cpp
+++ b/nv_vulkan_wrapper.cpp
@@ -8,7 +8,7 @@ extern "C" VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersi
 
 
 #ifndef NV_DRIVER_PATH
-#define NV_DRIVER_PATH "/usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.1"
+#define NV_DRIVER_PATH "/usr/lib64/opengl/nvidia/lib/libGL.so.1"
 #endif
 
 class StaticInitialize {
diff --git a/primus_vk.cpp b/primus_vk.cpp
index ba5a69e..31254a3 100644
--- a/primus_vk.cpp
+++ b/primus_vk.cpp
@@ -1,6 +1,7 @@
 #include "vulkan.h"
 #include "vk_layer.h"
 #include "vk_layer_dispatch_table.h"
+#include "vk_layer_utils.h"
 
 #include <cassert>
 #include <cstring>
diff --git a/primus_vk.json b/primus_vk.json
index 7b0771c..6c0977e 100644
--- a/primus_vk.json
+++ b/primus_vk.json
@@ -3,7 +3,7 @@
   "layer" : {
     "name": "VK_LAYER_PRIMUS_PrimusVK",
     "type": "GLOBAL",
-    "library_path": "libprimus_vk.so",
+    "library_path": "/usr/local/lib/libprimus_vk.so",
     "api_version": "1.1.0",
     "implementation_version": "1",
     "description": "Primus-vk - https://github.com/felixdoerre/primus_vk",

Sorry, but the error message [ 5625.241684] vulkaninfo[6459]: segfault at 0 ip 0000000000000000 sp 00007fff88be98b8 error 14 in x86_64-pc-linux-gnu-vulkaninfo[561a7c1e9000+3000] is not helpful for me. To be able to understand this error, you need to install debug symbols (at least for libvulkan.so.1 and for vulkaninfo) and run e.g. vulkaninfo with gdb to get a useful stack trace.

So you could run ENABLE_PRIMUS_LAYER=1 pvkrun gdb vulkaninfo in a terminal and then start the program with run, and when gdb detects a segfault, please provide a stacktrace with the command bt.

I'm unable to get a backtrace but did find error messages that may help:

Starting program: /usr/bin/vulkaninfo 
warning: File "/lib64/libthread_db-1.0.so" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
	add-auto-load-safe-path /lib64/libthread_db-1.0.so
line to your configuration file "/home/anton/.gdbinit".
To completely disable this security protection add
	set auto-load safe-path /
line to your configuration file "/home/anton/.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"
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
primus: fatal: failed to load any of the libraries: /usr/lib64/opengl/nvidia/lib/libGL.so.1:/usr/lib32/opengl/nvidia/lib/libGL.so.1:/usr/lib/opengl/nvidia/lib/libGL.so.1
libGLX.so.0: cannot open shared object file: No such file or directory
/usr/lib32/opengl/nvidia/lib/libGL.so.1: wrong ELF class: ELFCLASS32
libGLX.so.0: cannot open shared object file: No such file or directory
[Inferior 1 (process 13075) exited with code 01]

Do you have libGLX.so.0 installed? On debian the dependency chain is: primus->primus-libs->libgl1->libgl0.

Yes, it's provided by this package x11-drivers/nvidia-userspace-430.26.

I tried switching the systems OpenGL implementation to nvidia instead of xorg-x11, I now have the backtrace (see below). As you may have already noticed my nvidia-drivers is a bit old, i.e., 430.26. I'm not sure if that matters - I'm gonna try upgrading it next.

#0  0x0000000000000000 in ?? ()
#1  0x00007ffff11713c0 in vk_icdNegotiateLoaderICDInterfaceVersion (pSupportedVersion=0x7fffffffc3a4) at nv_vulkan_wrapper.cpp:85
#2  0x00007ffff7b7de91 in loader_icd_scan () from /usr/lib64/libvulkan.so.1
#3  0x00007ffff7b82cd8 in terminator_EnumerateInstanceExtensionProperties () from /usr/lib64/libvulkan.so.1
#4  0x00007ffff7b86603 in vkEnumerateInstanceExtensionProperties () from /usr/lib64/libvulkan.so.1
#5  0x000055555559c5f1 in AppInstance::AppGetGlobalLayerExtensions(char*) ()
#6  0x000055555559de00 in AppInstance::AppInstance() ()
#7  0x0000555555561837 in main ()

This error likely means that the library, you provided ( e.g. /usr/lib64/opengl/nvidia/lib/libGL.so.1) is not loadable or does not have a symbol named: vk_icdNegotiateLoaderICDInterfaceVersion. Ultimately the real_dlsym here must have returned nullptr: https://github.com/felixdoerre/primus_vk/blob/master/nv_vulkan_wrapper.cpp#L50

Can you verify that this library is loadable (e.g. ldd /usr/lib64/opengl/nvidia/lib/libGL.so.1 show not missing libraries) and contains that symbol ( e.g. nm -D /usr/lib64/opengl/nvidia/lib/libGL.so.1 | grep vk_icdNegotiateLoaderICDInterfaceVersion show that symbol)?

Hey @felixdoerre,

Sorry took me a while to respond. It appears to be a driver issue.

Output of $ optirun ldd /usr/lib64/opengl/nvidia/lib/libGL.so.1

$ optirun ldd /usr/lib64/opengl/nvidia/lib/libGL.so.1
	linux-vdso.so.1 (0x00007fffc69f4000)
	libdlfaker.so => /usr/lib64/VirtualGL/libdlfaker.so (0x00007f6df5d99000)
	libvglfaker.so => /usr/lib64/VirtualGL/libvglfaker.so (0x00007f6df5cc9000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f6df5c25000)
	libGLX.so.0 => /usr/lib64/opengl/nvidia/lib/libGLX.so.0 (0x00007f6df59f5000)
	libGLdispatch.so.0 => /usr/lib64/opengl/nvidia/lib/libGLdispatch.so.0 (0x00007f6df5722000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f6df554c000)
	libturbojpeg.so.0 => /usr/lib64/libturbojpeg.so.0 (0x00007f6df54b6000)
	libXv.so.1 => /usr/lib64/libXv.so.1 (0x00007f6df52b0000)
	libX11.so.6 => /usr/lib64/libX11.so.6 (0x00007f6df516f000)
	libXext.so.6 => /usr/lib64/libXext.so.6 (0x00007f6df5159000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6df5136000)
	libssl.so.1.1 => /usr/lib64/libssl.so.1.1 (0x00007f6df50a6000)
	libcrypto.so.1.1 => /usr/lib64/libcrypto.so.1.1 (0x00007f6df4ded000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f6df4ca3000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f6df6049000)
	libxcb.so.1 => /usr/lib64/libxcb.so.1 (0x00007f6df4a72000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f6df4a58000)
	libXau.so.6 => /usr/lib64/libXau.so.6 (0x00007f6df4a52000)
	libXdmcp.so.6 => /usr/lib64/libXdmcp.so.6 (0x00007f6df4a48000)
	libbsd.so.0 => /usr/lib64/libbsd.so.0 (0x00007f6df482f000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f6df4825000)

No output for $ optirun nm -D /usr/lib64/opengl/nvidia/lib/libGL.so.1 | grep vk_icdNegotiateLoaderICDInterfaceVersion which suggests it's a driver issue right?

I'm using nvidia-drivers-430.26, do you think upgrading the driver will help? (e.g., nvidia-drivers-440.44)

Whatever currently is under /usr/lib64/opengl/nvidia/lib/libGL.so.1 is not a vulkan driver. I have downloaded the package x11-drivers/nvidia-userspace-430.26 and checked what library is registered as vulkan driver and in /etc/vulkan/icd.d/nvidia_icd.json, the registered file is libGLX_nvidia.so.0.
So I suggest, that you use this as NV_DRIVER_PATH. When installing nv_vulkan_wrapper.json I would recommend, that you install it into /etc/vulkan/icd.d/nv_vulkan_wrapper.json and remove /etc/vulkan/icd.d/nvidia_icd.json.

$ optirun vulkaninfo yields:

ERROR: [Loader Message] Code 0 : /usr/lib32/libvulkan_radeon.so: wrong ELF class: ELFCLASS32
ERROR: [Loader Message] Code 0 : /usr/lib32/libvulkan_intel.so: wrong ELF class: ELFCLASS32
INTEL-MESA: warning: Haswell Vulkan support is incomplete
/var/tmp/portage/dev-util/vulkan-tools-1.1.124/work/Vulkan-Tools-119e7c3bbae122f6cc5d778d068fb91e0e85d6a9/vulkaninfo/vulkaninfo.h:810: failed with ERROR_INITIALIZATION_FAILED

FYI, there are intel_icd*.json and radeon_icd*.json in /usr/share/vulkan/icd.d/ folder which belongs to media-libs/mesa-19.3.1 package. Should I remove those?

Here are my changes for your reference: https://pastebin.com/vsTrTDmF

The error is (kind of) ok. This is the nvidia driver acting confused about the new surface, that it sees from the intel driver.
The json files from the media-libs/mesa-19.3.1 are ok, and required for primus_vk to work.

Can you please try ENABLE_PRIMUS_LAYER=1 optirun vulkaninfo? This should work now.

OMG! It f***ing works!

Output of ENABLE_PRIMUS_LAYER=1 optirun vulkaninfo

PrimusVK: Searching for display GPU:
PrimusVK: 0x55e86efdb110: 
PrimusVK: Got integrated gpu!
PrimusVK: Device: Intel(R) Haswell Mobile
PrimusVK:   Type: 1
PrimusVK: Searching for render GPU:
PrimusVK: 0x55e86efdb110.
PrimusVK: 0x55e86f1d1c20.
PrimusVK: Got discrete gpu!
PrimusVK: Device: GeForce GTX 970M
PrimusVK:   Type: 2
PrimusVK: fetching dispatch for 0x55e86f3d1d30
PrimusVK: Creating display device finished!: 0
PrimusVK: fetching dispatch for 0x55e86f311ef0
PrimusVK: CreateDevice done

Glxspheres64 works too using ENABLE_PRIMUS_LAYER=1 optirun glxspheres64

I'm closing this issue now.

If you ever visit the Philippines, let me know, I owe you a bucket of beer! 👍

Hello @felixdoerre,

Had to make changes in pvkrun.in.sh

Here's the new diff. I'll try if this allows me to run Wine using DXVK.

Steam won't run: $ pvkrun steam:

Running Steam on sabayon 1.0.0.59-r3 64-bit
STEAM_RUNTIME is enabled by the user
Pins up-to-date!
/home/anton/.local/share/Steam/ubuntu12_32/steam
Installing breakpad exception handler for appid(steam)/version(1576550254)
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Installing breakpad exception handler for appid(steam)/version(1576550254)
Installing breakpad exception handler for appid(steam)/version(1576550254)

(steam:89942): Gtk-WARNING **: 23:57:50.399: Unable to locate theme engine in module_path: "adwaita",

(steam:89942): Gtk-WARNING **: 23:57:50.399: Unable to locate theme engine in module_path: "adwaita",
/usr/share/themes/Arc/gtk-2.0/main.rc:1090: error: unexpected identifier 'direction', expected character '}'
/usr/share/themes/Arc/gtk-2.0/apps.rc:91: error: unexpected identifier 'direction', expected character '}'
Gtk-Message: 23:57:50.446: Failed to load module "pk-gtk-module"
Steam: An X Error occurred
X Error of failed request:  GLXBadContext
Major opcode of failed request:  150
Serial number of failed request:  86
xerror_handler: X failed, continuing
Steam: An X Error occurred
X Error of failed request:  BadValue (integer parameter out of range for operation)
Major opcode of failed request:  150
Value in failed request:  0x0
Serial number of failed request:  85
xerror_handler: X failed, continuing
assert_20200107235745_1.dmp[89978]: Uploading dump (out-of-process)
/tmp/dumps/assert_20200107235745_1.dmp
/home/anton/.local/share/Steam/steam.sh: line 722: 89942 Segmentation fault      (core dumped) $STEAM_DEBUGGER "$STEAMROOT/$STEAMEXEPATH" "$@"
assert_20200107235745_1.dmp[89978]: Finished uploading minidump (out-of-process): success = yes
assert_20200107235745_1.dmp[89978]: response: CrashID=bp-8f2867bf-e40b-41fd-8f2c-fc9df2200107
assert_20200107235745_1.dmp[89978]: file ''/tmp/dumps/assert_20200107235745_1.dmp'', upload yes: ''CrashID=bp-8f2867bf-e40b-41fd-8f2c-fc9df2200107''

I'm not sure if it's due to this line: Gtk-Message: 23:57:50.446: Failed to load module "pk-gtk-module"

Question, the game I'm trying to run in Wine is 32 bit. Does that mean, I need to compile for 32 bit as well? Is it possible to compile for both 32 bit and 64 bit?

Btw, the GTK error still appears if I launch steam without pvkrun so I think that shouldn't be a problem.

Yes, for a 32-bit application (as steam also would be one) you will need a 32-bit graphics driver and a 32-bit primus_vk.

Just compile the nv_vulkan_wrapper and the libprimus_vk.so with 32-bit as well (e.g. with make CXXFLAGS=-m32 libprimus_vk.so libnv_vulkan_wrapper.so) and place them in the appropriate locations. (Note, that you will also need to adjust the NV_DRIVER_PATH or just use a non-absolute library name here and let ld.so figure it out).
The json configuration files can be duplicated (vulkan will skip drivers and layers where the bitness doesn't match) or you can just use a non-absolute path and let ld.so figure it out and find the right variant.

On my system I leave it all to ld.so to figure out bitness:

$ grep -H library_path /usr/share/vulkan/icd.d/nv_vulkan_wrapper.json /usr/share/vulkan/implicit_layer.d/primus_vk.json
/usr/share/vulkan/icd.d/nv_vulkan_wrapper.json:        "library_path": "libnv_vulkan_wrapper.so.1",
/usr/share/vulkan/implicit_layer.d/primus_vk.json:    "library_path": "libprimus_vk.so.1",
$ ls -als /usr/lib/{x86_64,i386}-linux-gnu/lib{primus_vk,nv_vulkan_wrapper}.so.1 
 9 -rw-r--r-- 1 root root  13628 Nov 20 11:01 /usr/lib/i386-linux-gnu/libnv_vulkan_wrapper.so.1
61 -rw-r--r-- 1 root root 116080 Nov 20 11:01 /usr/lib/i386-linux-gnu/libprimus_vk.so.1
 9 -rw-r--r-- 1 root root  14264 Nov 20 11:01 /usr/lib/x86_64-linux-gnu/libnv_vulkan_wrapper.so.1
57 -rw-r--r-- 1 root root 116744 Nov 20 11:01 /usr/lib/x86_64-linux-gnu/libprimus_vk.so.1

Cool, I'll explore this further tomorrow.

After some digging, I found out that media-libs/mesa-19.3.1 do not have the vulkan use flag - at least on Sabayon which probably explains why vk_* symbols can't be found on /usr/lib/libGL.so but on libGLX_nvidia.so.0.

Furthermore, it appears that by default it uses xorg-x11 opengl implementation which removes paths to Nvidia's lib files from LDPATH variable. Switching to nvidia adds the paths into LDPATH variable but will result to my DE not loading.

I guess, I'll have to hint the compiler or even hardcode the nvidia lib paths relative to preferred bitness.

Hey @felixdoerre,

In nv_vulkan_wrapper.cpp, would like to ask about these lines:

#ifndef NV_DRIVER_PATH
#define NV_DRIVER_PATH "/usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.1"
#endif

I'm under the impression that this constant (apparently called macro), can be changed on pre-compile time. I can't seem to do so by passing an argument like -DNV_DRIVER_PATH="/usr/lib32/opengl/nvidia/lib/libGLX_nvidia.so".

Apologies for my ignorance, I'm not really a C/C++ programmer - it's my first time to tinker with an existing code.

Yes, that should work. When you want to pass this argument through make, you need to escape it properly: make CPPFLAGS='-DNV_DRIVER_PATH=\"/usr/lib32/opengl/nvidia/lib/libGLX_nvidia.so\"' CXXFLAGS=-m32 libnv _vulkan_wrapper.so

You need one layer of escaping for the shell you invoke make in (i used single quotes) and one for the shell g++ is invoked in (i used backslashes) so that the quotes end up inside the macro.

Hey @felixdoerre,

I was able to compile both 32 bit and 64 bit libs. However my system cannot see the 32-bit lib perhaps due to vulkan flags being disabled in Sabayon. 64-bit titles works just fine though.

Closing this issue, I'll try it on vanilla Gentoo next time.