はじめに
なんとなく、Raspberry Pi 4 で Vulkan を試すと同様のことをPokyでもやってみた。
使用するのはラズベリーパイ4
動かすデモプログラムはSaschaWillems/Vulkan。これはVulkanのデモとしては有名なものらしい。
run_crops.sh(余談)
gistに置いた。
実行権限をつけてPATHの通ったところに置いておく。
$ chmod +x ./run_crops.sh
Pokyの作成
作業場所は~/work/yocto/rpi_honister_vulkan
とする。
$ mkdir -p ~/work/yocto/rpi_honister_vulkan && cd ~/work/yocto/rpi_honister_vulkan
Pokyの取得
まずはPoky一式を取得する。
$ git clone git://git.yoctoproject.org/poky.git -b honister
meta-raspberrypiの取得
meta-raspberrypiをbitbake-layers layerindex-fetch
で取得する。
$ run_crops.sh bitbake-layers layerindex-fetch meta-raspberrypi
local.confの修正
build/conf/local.conf
に下記の内容を追加する。
MACHINE = "raspberrypi4-64" DL_DIR ?= "${TOPDIR}/../downloads" # enable uart ENABLE_UART = "1" # systemd DISTRO_FEATURES:append = " systemd pam" VIRTUAL-RUNTIME_init_manager = "systemd" DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" VIRTUAL-RUNTIME_initscripts = ""
core-image-x11をビルド
今回はGUIを使用するのでcore-image-x11をビルドする。
$ run_crops.sh bitbake core-image-x11
これが作業の土台となる。
ラズパイ向けのVulkanドライバ
下記コマンドでmesaのdevshellに入る。
$ run_crops.sh bitbake mesa -c devshell
Vulkanドライバがビルドされているかを確認する。
sh-4.4# ls -lha ../packages-split/mesa-vulkan-drivers total 8.0K drwxrwxrwx 2 root root 4.0K Oct 14 19:59 . drwxr-xr-x 30 root root 4.0K Oct 14 19:59 ..
この時点でなにも生成されてないことがわかる。
devshellはexit
コマンドで抜けられる。
mesaのレシピ
poky/meta/recipes-graphics/mesa/mesa.inc
の以下の部分を確認する。
# Vulkan drivers need dri3 enabled # amd could be enabled as well but requires gallium-llvm with llvm >= 3.9 VULKAN_DRIVERS = "" VULKAN_DRIVERS:append:x86:class-target = ",intel" VULKAN_DRIVERS:append:x86-64:class-target = ",intel" VULKAN_DRIVERS:append ="${@bb.utils.contains('PACKAGECONFIG', 'freedreno', ',freedreno', '', d)}" PACKAGECONFIG[vulkan] = "-Dvulkan-drivers=${@strip_comma('${VULKAN_DRIVERS}')}, -Dvulkan-drivers='',"
ラズパイ向けのVulkanドライバをビルドするには、mesaのビルド時点で-Dvulkan-drivers=broadcom
という設定が必要になるらしい。
この定義を見ていると、VULKAN_DRIVERS
に",broadcom"が設定されていれば良さそう。
手早く確認するためにbuild/conf/local.conf
に下記の1行を追加してみる。
VULKAN_DRIVERS:append:rpi:pn-mesa = ",broadcom"
Override Syntaxが_
から:
に変わっているので、この辺りの表現はわかりやすくなっている。
この状態でmesaのレシピをビルドしてみる。
$ run_crops.sh bitbake mesa -f
再度devshellを起動してmeta-vulkan-drivers
の内容を確認する。
sh-4.4# ls -lha ../packages-split/mesa-vulkan-drivers total 12K drwxrwxrwx 3 root root 4.0K Oct 14 19:59 . drwxr-xr-x 30 root root 4.0K Oct 14 19:59 .. drwxr-xr-x 4 root root 4.0K Oct 14 19:59 usr
usrディレクトリが生成されている。
sh-4.4# find ../packages-split/mesa-vulkan-drivers -type f ../packages-split/mesa-vulkan-drivers/usr/share/vulkan/icd.d/broadcom_icd.aarch64.json ../packages-split/mesa-vulkan-drivers/usr/lib/libvulkan_broadcom.so
ドライバとjsonファイルが生成されていることがわかる。
ここまででラズベリーパイ向けのVulkanドライバがビルドできた。
Vulkanデモプログラム
デモプログラムはSaschaWillems/Vulkanを使用する。
いつもの三角形や歯車が実装されている。
レイヤの作成
デモプログラムをPokyに組み込むためにレシピを作成することになるが、そのレシピを組み込むためのレイヤを作成する。
$ run_crops.sh bitbake-layers create-layer meta-vulkan-demo $ rm -rf ./build/meta-vulkan-demo/recipes-example $ rm -rf ./build/meta-vulkan-demo/recipes-recipetool $ mkdir -p ./build/meta-vulkan-demo/recipes-graphics/vulkan $ mv ./build/meta-vulkan-demo ./poky $ run_crops.sh bitbake-layers add-layer $(pwd)/poky/meta-vulkan-demo
レシピの作成
recipetoolを使用してデモプログラムのレシピを作成する。
$ run_crops.sh recipetool create https://github.com/SaschaWillems/Vulkan.git -o $(pwd)/poky/meta-vulkan-demo/recipes-graphics/vulkan/vulkan-demo_git.bb
do_configureでエラー
試しにビルドすると下記のようなエラーが発生した。
(...snip...) | CMake Error at CMakeLists.txt:46 (find_library): | Could not find Vulkan_LIBRARY using the following names: vulkan (...snip...) ERROR: Task (/home/mickey/work/yocto/rpi_honister_vulkan/poky/meta-vulkan-demo/recipes-graphics/vulkan/vulkan-demo_git.bb:do_configure) failed with exit code '1' NOTE: Tasks Summary: Attempted 773 tasks of which 771 didn't need to be rerun and 1 failed. Summary: 1 task failed: /home/mickey/work/yocto/rpi_honister_vulkan/poky/meta-vulkan-demo/recipes-graphics/vulkan/vulkan-demo_git.bb:do_configure Summary: There was 1 ERROR message shown, returning a non-zero exit code.
vulkan関連のモジュールが見つからないのでdo_configureタスクに失敗している。
diff --git a/recipes-graphics/vulkan/vulkan-demo_git.bb b/recipes-graphics/vulkan/vulkan-demo_git.bb index c173b4f..a837a5d 100644 --- a/recipes-graphics/vulkan/vulkan-demo_git.bb +++ b/recipes-graphics/vulkan/vulkan-demo_git.bb @@ -35,7 +35,7 @@ S = "${WORKDIR}/git" # NOTE: unable to map the following CMake package dependencies: Wayland Vulkan DirectFB # NOTE: the following library dependencies are unknown, ignoring: vulkan-1 vulkan # (this is based on recipes that have previously been built and packaged) -DEPENDS = "libxcb wayland-protocols" +DEPENDS = "libxcb wayland-protocols vulkan-loader" inherit cmake pkgconfig
ビルド時の依存関係にvulkan-loader
を追加すると、do_configureは成功し、do_compile以降の処理が実行されるようになる。
do_installのエラー
do_installタスクで下記のエラーが発生した。cmakeでのビルドプロセスにinstall
ターゲットが存在しないとなっている。
... (snip) ... | ninja: error: unknown target 'install' ... (snip) ...
SaschaWillems/Vulkanの作業例ではmake install
的なコマンドは見当たらなかった。
インストールプロセスをまともに実装していないのかもしれない。
その場合は自分でdo_install
タスクを作成する。
devshellでビルド結果を確認してみる。
sh-4.4# find ../build -type f | less (...snip...) ../build/bin/indirectdraw ../build/bin/texturearray ../build/bin/computenbody ../build/bin/gltfscenerendering ../build/bin/deferredshadows ../build/.ninja_lo
必要そうなものはbuild/bin
以下に固まっているようだ。なのでとりあえず下記のようなdo_install
タスクを実装する。
do_install() { install -d ${D}${bindir} install -m 0755 ${B}/bin/* ${D}${bindir} }
よく使用される変数
do_installタスクを実装する際にだいたい必要になることが多い変数を下記にまとめる。
変数 | 概要 | ディレクトリ |
---|---|---|
WORKDIR | bitbake中のレシピの作業ディレクトリ | (..snip..)/vulkan-demo/1.0+gitAUTOINC+821a0659a7-r0 |
S | bitbake中のソースディレクトリ | ${WORKDIR}/git |
D | bitbake中のinstall先 | ${WORKDIR}//build |
B | bitbake中のビルドディレクトリ | ${WORKDIR}//image |
bindir | ルートFS中の実行ファイルインストール先 | /usr/bin |
datadir | ルートFS中のデータインストール先 | /usr/share |
WORKDIRは通常、bitbake時のbuild/tmp/work/CPUアーキ/レシピ/バージョン
となる。
これらの変数の実際の値は下記のように確認することができる。
$ run_crops.sh bitbake "レシピ名" -e | grep '^変数名=' # vulkan-demoでDを確認したい場合は下記のようにする。 $ run_crops.sh bitbake vulkan-demo -e | grep '^D=' D="/home/mickey/work/yocto/rpi_honister_vulkan/build/tmp/work/cortexa72-poky-linux/vulkan-demo/1.0+gitAUTOINC+821a0659a7-r0/image"
デモプログラムの実行
bitbakeが通るようになったので、vulkan-demoを組み込んだイメージを作成する。
local.confに下記の一行を追加する。
IMAGE_INSTALL:append = " vulkan-demo"
core-image-x11を作成し、ラズパイ上でデモプログラムであるgears
を実行する。
すると下記のようなエラーが発生する。
root@raspberrypi4-64:~# gears Error: Could not find asset path in /home/mickey/work/yocto/rpi_honister_vulkan/build/tmp/work/cortexa72-poky-linux/vulkan-demo/1.0+gitAUTOINC+821a0659a7-r0/git/data/
エラー自体はデモプログラムの実行に必要なアセットと呼ばれるデータファイルが見つからないというもの。 このエラーの問題点は下記の2つ
- ルートFSにアセットが含まれていない
- デモプログラムがアセットを読み出すパスがプログラムのビルド時のホストPC上のディレクトリを指している
アセットの取得
SaschaWillems/Vulkanの Assets の項にアセットを取得する方法が記載してある。
python download_assets.py
vulkan-demoのレシピにこの処理を追加してやれば良さそう。
do_compile:append() { cd ${S} ./download_assets.py } do_install() { install -d ${D}${bindir} install -m 0755 ${B}/bin/* ${D}${bindir} install -d ${D}${datadir}/Vulkan/data cp -r ${S}/data ${D}${datadir}/Vulkan } FILES:${PN} += "${datadir}/Vulkan/data"
do_compileタスクに処理を追加し、download_assets.py
を実行する。
次に、取得したアセットがビルドしたパッケージに含まれるようにインストールする。
最後に、インストールされたデータがきちんとパッケージに反映されるようにFILES
に追加する。
この修正後にbitbakeしてdevshellでpackages-split/vulkan-demoディレクトリを確認してみる。
$ run_crops.sh bitake vulkan-demo $ run_crops.sh bitake vulkan-demo -c devshell sh-4.4# cd ../packages-split/vulkan-demo/usr/share sh-4.4# ls Vulkan
packages-split/vulkan-demo/usr/share
以下にVulkan
ディレクトリがあれば、
アセットはルートFSに含まれるようになっている。
アセットのロードパスの変更
アセットがルートFSに含まれるようになったが、問題はデモプログラムがアセットを読み込むパスを変更する必要があるということ。 このパスはどのように決定されているのだろうか。
ソースコードにエラーメッセージの一部の文字列でgrepしてみる。
$ run_crops.sh bitbake vulkan-demo -c devshell $ grep -r 'Could not find asset path in' . base/vulkanexamplebase.cpp: std::cerr << "Error: Could not find asset path in " << getAssetPath() << "\n";
getAssetPath()
の実装を確認する。外部関数として実装されているのはbase/VulkanTools.cpp
のみのようだ。
const std::string getAssetPath() { #if defined(VK_USE_PLATFORM_ANDROID_KHR) return ""; #elif defined(VK_EXAMPLE_DATA_DIR) return VK_EXAMPLE_DATA_DIR; #else return "./../data/"; #endif }
VK_EXAMPLE_DATA_DIR
が定義されていればその内容が展開されreturnされるようだ。
VK_EXAMPLE_DATA_DIR
がどのように定義されているかを確認する。
$ grep -r VK_EXAMPLE_DATA_DIR . ./CMakeLists.txt: add_definitions(-DVK_EXAMPLE_DATA_DIR=\"${RESOURCE_INSTALL_DIR}/\") ./CMakeLists.txt: add_definitions(-DVK_EXAMPLE_DATA_DIR=\"${CMAKE_SOURCE_DIR}/data/\")
CMakeLists.txtで定義されているようだ。
if(RESOURCE_INSTALL_DIR) add_definitions(-DVK_EXAMPLE_DATA_DIR=\"${RESOURCE_INSTALL_DIR}/\") install(DIRECTORY data/ DESTINATION ${RESOURCE_INSTALL_DIR}/) else() add_definitions(-DVK_EXAMPLE_DATA_DIR=\"${CMAKE_SOURCE_DIR}/data/\") endif()
内容を確認すると、RESOURCE_INSTALL_DIRが定義されている場合はその内容がVK_EXAMPLE_DATA_DIRに代入されるように見える。
RESOURCE_INSTALL_DIRはレシピ中のEXTRA_OECMAKE
で定義することができる。
レシピに下記の行を変更する。
EXTRA_OECMAKE = "-DRESOURCE_INSTALL_DIR=${datadir}/Vulkan/data"
vulkan-demo_git.bb完成形
vulkan-demo_git.bbの完成形を以下に示す。
LICENSE = "MIT & Unknown" LIC_FILES_CHKSUM = "file://LICENSE.md;md5=dcf473723faabf17baa9b5f2207599d0 \ file://external/glm/util/conan-package/lib_licenses/LICENSE1.txt;md5=37ffc29490b4cf57fd7e5ffba4c1b185 \ file://external/glm/util/conan-package/lib_licenses/LICENSE2.txt;md5=f7f57caa96a29810aa62259f274b374b \ file://external/tinygltf/LICENSE;md5=82f6e601fc2fd27cbf55d6f5f176d017 \ file://external/imgui/LICENSE.txt;md5=f3c4ae64ab2a23f1b8734609e1a2d48a \ file://external/ktx/LICENSE.md;md5=654c86a2bade5bb7fbcde45788f98a61" SRC_URI = "gitsm://github.com/SaschaWillems/Vulkan.git;protocol=https;branch=master" PV = "1.0+git${SRCPV}" SRCREV = "821a0659a76131662b1fc4a77c5a1ee6a9a330d8" S = "${WORKDIR}/git" DEPENDS = "libxcb wayland-protocols vulkan-loader" inherit cmake pkgconfig EXTRA_OECMAKE = "-DRESOURCE_INSTALL_DIR=${datadir}/Vulkan/data" do_compile:append() { cd ${S} ./download_assets.py } do_install() { install -d ${D}${bindir} install -m 0755 ${B}/bin/* ${D}${bindir} install -d ${D}${datadir}/Vulkan/data cp -r ${S}/data ${D}${datadir}/Vulkan } FILES:${PN} += "${datadir}/Vulkan/data"
gitリポジトリにサブモジュールが含まれている場合、
recipetool createによってSRC_URIのfetcherがgitsm://
になっている。
このようにできる範囲で最適なfetcherを選択してくれる。
動作画面
ラズパイ4でgearsが動いた。
まとめ
ラズパイ4でVulkanのデモプログラムを動かしてみた。
デフォルト設定ではvulkanドライバが作成されないので、VULKAN_DRIVERS
に",broadcom"
を追加する必要がある。
recipetoolを使って新規にレシピを作成する方法もざっと紹介した。
ラズパイ4のVulkanは結構ヌルヌル動いた。