LoginSignup
3
2

Vulkan Extension Layer を使う Android アプリを RenderDoc でデバッグする

Last updated at Posted at 2024-02-12

今回の結果の git コミット

fork した RenderDoc のリポジトリにコミットを追加してある.

後述の手順でビルドを行うと, VEL の *.so がパッケージングされた org.renderdoc.renderdoccmd.arm64.apk が生成される.

この APK を下記の手順で RenderDoc が使用するようにすると, VEL を使った RenderDoc キャプチャのリプレイが可能になる.

更新履歴

日付 内容
2024-02-20 追記: APK の外部に存在する layer としての使用について

導入

Vulkan Extension Layer (VEL)

Android に限らず Vulkan アプリで, ドライバがネイティブで対応していない拡張を用いるために,
polyfill layer である Vulkan Extension Layer (VEL) を用いることができる.

これらはドライバのアップデートをあまり期待できない Android において特に重宝し,
中でも VK_KHR_synchronization2VK_KHR_timeline_semaphore のものを使いたい場合が多い.

VEL と RenderDoc キャプチャ

ただし Android でこれら VEL を用いるアプリを RenderDoc でデバッグしたいとき,
キャプチャを取るまでは問題ないが, 実際にそのキャプチャをリプレイ(i.e 開く)する際には,
デバイスが該当の拡張に対応していない旨のエラーが表示され, 続行することができない.

Current replaying hardware unsupported or incompatible with captured hardware
☝️ Adreno 650 のドライバ 512.444.0 がネイティブで VK_KHR_synchronization2 に対応していないため, キャプチャをリプレイすることができない.

クロスプラットフォームな Vulkan アプリを開発する際,
VK_KHR_synchronization2VK_KHR_timeline_semaphore は是非使用したいところだが,
その際ドライバの新しくない Android 端末にも対応する場合にはこれら VEL を使うことが必須になる.
ただしそのときこれら端末では, RenderDoc によるGPUデバッグが行えないことになる.

今回はこの問題を解決したい.

Android における RenderDoc キャプチャのリプレイ

Android での RenderDoc キャプチャを開く際, 実際に行われるのは,
シリアライズされたグラフィクスAPIのコマンド列を Android 端末上の RenderDoc のアプリに送信して,
端末でそれらグラフィクスAPIのコマンド列を再実行(リプレイ)させることである.

この Android 端末上でのリプレイに用いられるアプリが,
org.renderdoc.renderdoccmd.arm64org.renderdoc.renderdoccmd.arm32 であり,
初回に Remote Context に接続した際に端末にインストールされる, お馴染みの画面のアプリになる.

Honeyview_screen.png
☝️ org.renderdoc.renderdoccmd.arm64 アプリ

org.renderdoc.renderdoccmd.arm64 と VEL

リプレイ時に, キャプチャされたグラフィクスAPIのコマンド列を実行しているのは実機上の org.renderdoc.renderdoccmd.arm64 なので,
VEL の *.so を利用できる必要があるのは当然, このアプリということになる.

つまり, 自分のアプリで VEL を使用するときにように, VEL の *.sorenderdoccmd の APK の lib/arm64-v8a にパッケージング12してしまうのが手っ取り早い:

lib/arm64-v8a/libVkLayer_khronos_synchronization2.so
lib/arm64-v8a/libVkLayer_khronos_timeline_semaphore.so

まずは基本的な renderdoccmd の Android 向けのビルドの手順を確認してから,
VEL の *.so のこの APK へのパッケージングができるようにしていく.

APK の外部に存在する layer としての使用について

*.so に対して org.renderdoc.renderdoccmd.arm64run-as を使用する方法3だが,
これはうまくいかない.

run-as した *.so を認識させるには adb shell setprop debug.vulkan.layers など設定を行う必要があるが,
これらの設定を, RenderDoc は Android 端末の Remote Context の確立時に, 消去してしまう:

renderdoc/renderdoc/android/android.cpp
Android::adbExecCommand(deviceID, "shell setprop debug.vulkan.layers :", ".", true);
Android::adbExecCommand(deviceID, "shell settings delete global enable_gpu_debug_layers", ".",
                          true);
Android::adbExecCommand(deviceID, "shell settings delete global gpu_debug_app", ".", true);
Android::adbExecCommand(deviceID, "shell settings delete global gpu_debug_layer_app", ".", true);
Android::adbExecCommand(deviceID, "shell settings delete global gpu_debug_layers", ".", true);
Android::adbExecCommand(deviceID, "shell settings delete global gpu_debug_layers_gles", ".", true);

Android 向けの renderdoccmd のビルドと使用

Windows で行いたかったが, 公式ドキュメントの推奨に従って, 今回は WSL 上の Ubuntu で行う.

Android の開発環境の用意

Android SDK, Android NDK, Java Development Kit をインストールする.
公式ドキュメントの該当部分に従う.

Android 向けのビルド

公式ドキュメントの該当部分に従っていく.

Ninja をインストール:

sudo apt update
sudo apt-get -y install ninja-build

クローンした RenderDoc のディレクトリへ移動:

cd renderdoc

ビルド:

mkdir build-android
cd build-android
cmake -DBUILD_ANDROID=On -DANDROID_ABI=arm64-v8a -G "Ninja" ..
ninja -j 8

ncurses5 が足りないようなことを言われたらインストール:

sudo apt-get -y install libncurses5

org.renderdoc.renderdoccmd.arm64.apk が, renderdoc/build-android/bin に生成されているはず.

使用

既に古い org.renderdoc.renderdoccmd.arm64 が Android 端末に入っている場合, アンインストールしておく:

adb uninstall org.renderdoc.renderdoccmd.arm64

RenderDoc のインストールディレクトリの plugins/android に,
標準の org.renderdoc.renderdoccmd.arm64 が存在するので, 新しいものをこれに上書きする.
これで, Remote Context 接続の際にインストールされるリプレイ用アプリが, 今回ビルドしたものになる.

renderdoccmd に VEL の *.so がパッケージングされるようにする

renderdoc/renderdoccmd/android に, ABI ごとのディレクトリに *.so を入れたフォルダ vel を用意する:

renderdoc/renderdoccmd
renderdoccmd/
├── 3rdparty/
├── android/
│   ├── AndroidManifest.xml
│   ├── Loader.java
│   ├── icon.png
│   ├── vel/ 👈🆕
│   │   ├── arm64-v8a/
│   │   │   ├── libVkLayer_khronos_synchronization2.so
│   │   │   └── libVkLayer_khronos_timeline_semaphore.so
│   │   └── armeabi-v7a/
│   │       ├── libVkLayer_khronos_synchronization2.so
│   │       └── libVkLayer_khronos_timeline_semaphore.so
│   └── wrap.sh
├── apple/
├── ...

renderdoc/renderdoccmd/CMakeLists.txt に, これら *.so をパッケージングするための記述を追加する:

renderdoc/renderdoccmd/CMakeLists.txt
# Copy in android package files, replacing the package name with the architecture-specific package name
configure_file(android/Loader.java ${CMAKE_CURRENT_BINARY_DIR}/src/org/renderdoc/renderdoccmd/Loader.java)
configure_file(android/AndroidManifest.xml ${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml)
configure_file(android/icon.png ${CMAKE_CURRENT_BINARY_DIR}/res/drawable/icon.png COPYONLY)
+ configure_file(android/vel/${ANDROID_ABI}/libVkLayer_khronos_synchronization2.so ${CMAKE_CURRENT_BINARY_DIR}/vel/${ANDROID_ABI}/libVkLayer_khronos_synchronization2.so COPYONLY)
+ configure_file(android/vel/${ANDROID_ABI}/libVkLayer_khronos_timeline_semaphore.so ${CMAKE_CURRENT_BINARY_DIR}/vel/${ANDROID_ABI}/libVkLayer_khronos_timeline_semaphore.so COPYONLY)

add_custom_command(OUTPUT ${APK_FILE}
                   DEPENDS renderdoc
                   DEPENDS renderdoccmd
                   DEPENDS ${KEYSTORE}
                   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
                   COMMAND ${CMAKE_COMMAND} -E make_directory libs/lib/${ANDROID_ABI}
                   COMMAND ${CMAKE_COMMAND} -E make_directory obj
                   COMMAND ${CMAKE_COMMAND} -E make_directory bin
                   COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:renderdoc> libs/lib/${ANDROID_ABI}/$<TARGET_FILE_NAME:renderdoc>
                   COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:renderdoccmd> libs/lib/${ANDROID_ABI}/$<TARGET_FILE_NAME:renderdoccmd>
+                  COMMAND ${CMAKE_COMMAND} -E copy vel/${ANDROID_ABI}/libVkLayer_khronos_synchronization2.so libs/lib/${ANDROID_ABI}/libVkLayer_khronos_synchronization2.so
+                  COMMAND ${CMAKE_COMMAND} -E copy vel/${ANDROID_ABI}/libVkLayer_khronos_timeline_semaphore.so libs/lib/${ANDROID_ABI}/libVkLayer_khronos_timeline_semaphore.so
                   )

この変更の上で上記の手順でビルドを行うと, *.so がパッケージングされた APK が生成される.

org.renderdoc.renderdoccmd.arm64.apk
org.renderdoc.renderdoccmd.arm64.apk/
├── AndroidManifest.xml
├── META-INF/
│   ├── MANIFEST.MF
│   ├── RDOCANDR.RSA
│   └── RDOCANDR.SF
├── classes.dex
├── lib/
│   └── arm64-v8a/
│       ├── libVkLayer_GLES_RenderDoc.so
│       ├── libVkLayer_khronos_synchronization2.so 👈🆕
│       ├── libVkLayer_khronos_timeline_semaphore.so 👈🆕
│       ├── librenderdoccmd.so
│       └── wrap.sh
├── res/
│   └── drawable/
│       └── icon.png
└── resources.arsc

この APK を上記の手順で RenderDoc が使用するようにすると, VEL を使った RenderDoc キャプチャのリプレイが可能になる.

  1. APK にパッケージ化された検証レイヤを使用する - Android の Vulkan 検証レイヤ  |  Android NDK  |  Android Developers

  2. Package contents - apk (file format) - Wikipedia

  3. Load a validation layer binary from your device’s local storage - Vulkan validation layers on Android  |  Android NDK  |  Android Developers

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2