Assuming you have Vulkan compatible hardware you can enable it on /compat/linux by creating a new "linux" service script (or edit the existing /etc/rc.d/linux service file, just replace linux_vlk with linux) with the following:
Please note that there are several gotchas with this solution:
Because I wanted Vulkan support on /compat/linux and linsysfs does not do it yet (see bug 278363, drm-kmod issue 290 and review D26836).
Also note that due to the version of mesa on rocky (25.0.7) at least for AMD cards you might have better performance with the proprietary driver: https://amdgpu-install.readthedocs.io/en/latest/
Disclaimer
This script is given as is, I've tested it on my machine and it works, but that's it. If you find this useful feel free to contribute/share and help with the relevant issues.
Bash:
#!/bin/sh
#
#
# PROVIDE: linux
# REQUIRE: kldxref zfs
# KEYWORD: nojail
. /etc/rc.subr
name="linux_vlk"
desc="Enable Linux ABI"
rcvar="linux_vlk-enable"
start_cmd="${name}_start"
stop_cmd=":"
linux_mount() {
local _fs _mount_point
_fs="$1"
_mount_point="$2"
shift 2
if ! mount | grep -q "^$_fs on $_mount_point ("; then
mkdir -p "$_mount_point"
mount "$@" -t "$_fs" "$_fs" "$_mount_point"
fi
}
enable_vulkan()
{
# this will change to /compat/linux/sys/.sys
ROOT_PATH="$(sysctl -n compat.linux.emul_path)"
# Note, as this has to be, by force, a simple SH script we will have to stick with a single card
mkdir -p ${ROOT_PATH}/sys/class/drm;
mkdir -p ${ROOT_PATH}/sys/dev/char;
cd $ROOT_PATH/sys
# we only handle one card for now
for card_dir in .sys/class/drm/card*; do
uevent=$(cat "${card_dir}/device/uevent")
pci_id=$(echo $uevent | sed -e "s/.*PCI_ID=//g" | sed -e "s/ .*//")
ln -s ../../.sys/class/drm/card0 class/drm/card0
# corresponding char device
mkdir -p ${ROOT_PATH}/sys/dev/char/226:0
echo "1" > ${ROOT_PATH}/sys/dev/char/226:0/boot_display
echo "226:0" > ${ROOT_PATH}/sys/dev/char/226:0/dev
ln -s ../../../.sys/class/drm/card0/device dev/char/226:0/device
ln -s ../../../.sys/class/drm dev/char/226:0/subsystem
cat <<EOF > dev/char/226:0/uevent
MAJOR=226
MINOR=0
DEVNAME=dri/card0
DEVTYPE=drm_minor
EOF
# also create the renderD node
mkdir -p ${ROOT_PATH}/sys/class/drm/renderD128
echo "1" > ${ROOT_PATH}/sys/class/drm/renderD128/boot_display
echo "226:128" > ${ROOT_PATH}/sys/class/drm/renderD128/dev
cat <<EOF > ${ROOT_PATH}/sys/class/drm/renderD128/uevent
MAJOR=226
MINOR=128
DEVNAME=dri/renderD128
DEVTYPE=drm_minor
EOF
# link the device
ln -s ../../drm class/drm/renderD128/subsystem
ln -s ../card0/device class/drm/renderD128/device
# corresponding char device
mkdir -p ${ROOT_PATH}/sys/dev/char/226:128
echo "1" > ${ROOT_PATH}/sys/dev/char/226:128/boot_display
echo "226:128" > ${ROOT_PATH}/sys/dev/char/226:128/dev
ln -s ../../../.sys/class/drm/card0/device dev/char/226:128/device
ln -s ../../../.sys/class/drm dev/char/226:128/subsystem
cat <<EOF > ${ROOT_PATH}/sys/dev/char/226:128/uevent
MAJOR=226
MINOR=128
DEVNAME=dri/renderD128
DEVTYPE=drm_minor
EOF
# assign the rw permissions for everyone
# TODO figure out if we want to instead just assign the render group
chmod 666 ${ROOT_PATH}/dev/dri/renderD128
break
done
# Link other class and sys directories
cd class
for path in ../.sys/class/*; do
dname=$(basename ${path})
if [ ! -d ./${dname} ]; then
ln -s $path $dname;
fi;
done
cd ..
for path in ./.sys/*; do
dname=$(basename ${path})
if [ ! -d ./${dname} ]; then
ln -s $path $dname;
fi;
done
}
linux_start()
{
local _emul_path _tmpdir
case `sysctl -n hw.machine_arch` in
aarch64)
load_kld -e 'linux64elf' linux64
;;
amd64)
load_kld -e 'linuxelf' linux
load_kld -e 'linux64elf' linux64
;;
i386)
load_kld -e 'linuxelf' linux
;;
esac
_emul_path="$(sysctl -n compat.linux.emul_path)"
if [ -x ${_emul_path}/sbin/ldconfigDisabled ]; then
_tmpdir=`mktemp -d -t linux-ldconfig`
${_emul_path}/sbin/ldconfig -C ${_tmpdir}/ld.so.cache
if ! cmp -s ${_tmpdir}/ld.so.cache ${_emul_path}/etc/ld.so.cache; then
cat ${_tmpdir}/ld.so.cache > ${_emul_path}/etc/ld.so.cache
fi
rm -rf ${_tmpdir}
fi
# Linux uses the pre-pts(4) tty naming scheme.
load_kld pty
# Explicitly load the filesystem modules; they are usually required,
# even with linux_mounts_enable="NO".
load_kld fdescfs
load_kld linprocfs
load_kld linsysfs
# Handle unbranded ELF executables by defaulting to ELFOSABI_LINUX.
if [ `sysctl -ni kern.elf64.fallback_brand` -eq "-1" ]; then
sysctl kern.elf64.fallback_brand=3 > /dev/null
fi
if [ `sysctl -ni kern.elf32.fallback_brand` -eq "-1" ]; then
sysctl kern.elf32.fallback_brand=3 > /dev/null
fi
if checkyesno linux_mounts_enable; then
linux_mount linprocfs "${_emul_path}/proc" -o nocover
if checkyesno linux_vulkan_enable; then
# make sure we have our fake sys directory
mkdir -p "${_emul_path}/sys/.sys"
linux_mount linsysfs "${_emul_path}/sys/.sys" -o nocover
else
linux_mount linsysfs "${_emul_path}/sys" -o nocover
fi
linux_mount devfs "${_emul_path}/dev" -o nocover
linux_mount fdescfs "${_emul_path}/dev/fd" -o nocover,linrdlnk
linux_mount tmpfs "${_emul_path}/dev/shm" -o nocover,mode=1777
fi
# enable vulkan
if checkyesno linux_vulkan_enable; then
enable_vulkan;
fi
}
load_rc_config $name
# doesn't make sense to run in a svcj: kernel modules and FS-mounting
linux_svcj="NO"
run_rc_command "$1"
Please note that there are several gotchas with this solution:
- Only tested on FreeBSD 15 (amd64), and in any case centos7 would have subpar support for more recent cards
- Only one card supported (the first being exposed), so for multiple cards feel free to replicate what is done in the enable_vulkan function, renderD devices start with 128+n, where n is the id of the associated card
- Not tested with NVIDIA cards and will probably not work as is
- You will need to install at least linux-rl9-vulkan-loader, linux-rl9-dri
- To avoid issues, you need to set linux_mounts_enable="YES" and linux_vulkan_enable="YES" on /etc/rc.conf
- If you are using this ad an alternative linux service remember to disable the default with linux_enable="NO" in /etc/rc.conf
- The /dev/dri/renderD128 node will have 666 permissions (there are other solutions, like changing the group to "render" but that needs to be aligned with the FreeBSD groups so...)
Because I wanted Vulkan support on /compat/linux and linsysfs does not do it yet (see bug 278363, drm-kmod issue 290 and review D26836).
Also note that due to the version of mesa on rocky (25.0.7) at least for AMD cards you might have better performance with the proprietary driver: https://amdgpu-install.readthedocs.io/en/latest/
Disclaimer
This script is given as is, I've tested it on my machine and it works, but that's it. If you find this useful feel free to contribute/share and help with the relevant issues.