devcontainerでbevyのGUIをwslgを通して表示する

wsl2のvscodeのdevcontainerでRustのGUIアプリ(bevy)を作成する環境構築

VSCodeのリモートコンテナ(devcontainer)からRustでbevyなGUIアプリを表示することができたのでその構築のためのメモ

更新履歴

  • 2023/2: VSCodeのアップデート(v1.75.0)により、DISPLAY関連の環境変数とソケットのマウントが不要になったようなので、コメントを該当行の1行上に追加した。
  • 2023/2: audio再生についての記述を追加。こちらもそのうちマウントが不要になるかもしれない。
  • 2023/2: devcontainer.jsonfeaturesを活用すべきことを追記。

featuresを利用する

2023/2追記

GPUを使いたいならdevcontainer.jsonfeaturesに追記するだけでよさそうだ。下に書いたdevcontainer.jsonDockerfileは不要になる。

devcontainerの作成時に好きなのを選択したあと、.devcontainer/devcontainer.jsonに以下の項目を追記すればnvidia-smiは使える:

"features": {
    "ghcr.io/devcontainers/features/nvidia-cuda:1": {}
}

runArgsは必要だと思う。

環境

  • Windows10 22H2
  • nvidia GPU使用
  • wsl2 + wslg
  • wsl2で使うディストリビューション: debian(ubuntuでもいい)
  • VSCode 1.74.3
  • Rust rustc 1.67.0

ubuntu使用であれば適宜debianubuntuと読み替えてください。

wsl2とwslgについて

wslgwsl2からGUIアプリの実行を可能にしたもの。 2023/1の時点から過去1年以内くらいならWSL2をインストールしていればwslgも一緒にインストールされているはず。wslgやそのインストールについてはこちらを参照:

GitHub - microsoft/wslg: Enabling the Windows Subsystem for Linux to include support for Wayland and X server related scenarios
Enabling the Windows Subsystem for Linux to include support for Wayland and X server related scenarios - microsoft/wslg

wsl2debian上でsudo apt install -y x11-apps && xclockなど実行することでwslgの存在を確認できるかもしれない。wslgDISPLAY変数など用意していて、X11サーバなども動いてくれているようなので問題なくxclockがGUI付きで起動できるはず。起動しない場合は、上記リンクなどを見てwsl2をアップデートすればいい。

X11サーバはwindows側でなんとかしてくれるので、VcXsrvなども不要。

bevyについて

Rustで作られているゲームエンジン。詳細は以下:

Bevy Engine
Bevy is a refreshingly simple data-driven game engine built in Rust. It is free and open-source forever!

bevyのGetting StartedのDefaultPluginsを導入するとGUIが表示されるのだが、ここでdevcontainer上ではエラーになってしまっていた。最初はライブラリの不足だったが、最後にthread 'main' panicked at 'Unable to find a GPU! Make sure you have installed required drivers!'が表示されて詰まってしまった。これを何とかする。

ちなみにdevcontainer上でなくwsl2ubuntu上だとライブラリの不足を解決するとGUIが表示された。debianでは試していない。試行錯誤はubuntu上で行ったため。

bevyvulkanというグラフィック関連のAPIを使うらしく、xclockは表示できても、bevyのは表示されないということもあった。正直vulkanについてはよくわかってない。ドライバがあれば大丈夫だろうという認識。

本記事ではbevyを使っているが別にbevyでなくてもRustでなくても同じようにGUIの表示までできると思っている。

こうすればいい

要約と詳細で分けておく。今回のbevyを使うのであれば、詳細のほうをコピペすれば動く…はず。

要約

devcontainerのDockerイメージとして、nvidia/cuda:12.0.0-base-ubuntu22.04を指定すれば使える。

環境変数WAYLAND_DISPLAY=wayland-0 DISPLAY=:0の設定とwslgで使われているwsl2のX11のunixソケットをマウントすることを忘れずに。

あとは、使う言語などに関する設定をすればいい。

詳細

devcocntainerの設定で済む。.devcontainer/devcontainer.jsonはこのように:

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/rust
{
    "name": "Rust with gpu",
    // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
    // "image": "mcr.microsoft.com/devcontainers/rust:0-1-bullseye",
    "build": {
        "dockerfile": "./Dockerfile",
        "context": "."
    },
    "runArgs": [
        "--gpus=all"
    ],
    // mount wslg X11 socket, VSCode 1.75.0以降は不要
    "mounts": [
        "source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind,consistency=cached"
    ],
    // Features to add to the dev container. More info: https://containers.dev/features.
    "features": {
        "ghcr.io/devcontainers/features/common-utils:2": {
            "installZsh": "true",
            "username": "vscode",
            "userUid": "1000",
            "userGid": "1000",
            "upgradePackages": "true"
        },
        "ghcr.io/devcontainers/features/rust:1": "latest",
        "ghcr.io/devcontainers/features/git:1": {
            "version": "latest",
            "ppa": "false"
        }
    },
    // Configure tool-specific properties.
    "customizations": {
        // Configure properties specific to VS Code.
        "vscode": {
            // Set *default* container specific settings.json values on container create.
            "settings": {
                "lldb.executable": "/usr/bin/lldb",
                // VS Code don't watch files under ./target
                "files.watcherExclude": {
                    "**/target/**": true
                },
                "rust-analyzer.checkOnSave.command": "clippy"
            },
            // Add the IDs of extensions you want installed when the container is created.
            "extensions": [
                "vadimcn.vscode-lldb",
                "mutantdino.resourcemonitor",
                "rust-lang.rust-analyzer",
                "tamasfe.even-better-toml",
                "serayuzgur.crates"
            ]
        }
    },
    // Use 'forwardPorts' to make a list of ports inside the container available locally.
    // "forwardPorts": [],
    // Use 'postCreateCommand' to run commands after the container is created.
    "postCreateCommand": "sudo apt update && sudo apt-get install -y g++ pkg-config libx11-dev libudev-dev libxcursor-dev libasound2-dev libxrandr-dev libxi-dev libx11-xcb-dev libvulkan-dev",
    // Configure tool-specific properties.
    // "customizations": {},
    // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
    // "remoteUser": "root"
    "remoteUser": "vscode"
}

VSCodeのRust用devcontainerのテンプレートを参考に作っている:

https://github.com/devcontainers/images/tree/main/src/rust

runArgsmountsの設定を忘れないように。runArgsではGPUをDockerコンテナ内で使えるようにしている。mountsでのマウントはwslgのGUI用バックエンドを使うために渡している。mounts関連についてはこちらを参照:

Diagnosing "cannot open display" type issues with WSLg
Enabling the Windows Subsystem for Linux to include support for Wayland and X server related scenarios - microsoft/wslg

postCreateCommandではbevyの実行での不足分のライブラリのインストールをしている。

次にdevcontainerで使う.devcontainer/Dockerfileの中身:

FROM nvidia/cuda:12.0.0-base-ubuntu22.04

ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    RUST_VERSION=1.67.0

RUN apt update && export DEBIAN_FRONTEND=noninteractive; \
    apt install -y wget sudo; \
    apt-get purge -y imagemagick imagemagick-6-common;

RUN set -eux; \
    dpkgArch="$(dpkg --print-architecture)"; \
    case "${dpkgArch##*-}" in \
    amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='5cc9ffd1026e82e7fb2eec2121ad71f4b0f044e88bca39207b3f6b769aaa799c' ;; \
    armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='48c5ecfd1409da93164af20cf4ac2c6f00688b15eb6ba65047f654060c844d85' ;; \
    arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='e189948e396d47254103a49c987e7fb0e5dd8e34b200aa4481ecc4b8e41fb929' ;; \
    i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='0e0be29c560ad958ba52fcf06b3ea04435cb3cd674fbe11ce7d954093b9504fd' ;; \
    *) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
    esac; \
    url="https://static.rust-lang.org/rustup/archive/1.25.1/${rustArch}/rustup-init"; \
    wget "$url"; \
    echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
    chmod +x rustup-init; \
    ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host ${rustArch}; \
    rm rustup-init; \
    chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
    rustup --version; \
    cargo --version; \
    rustc --version;

# VSCode 1.75.0以降は不要
ENV WAYLAND_DISPLAY=wayland-0 DISPLAY=:0

CMD ["sleep", "infinity"]

RustのDockerイメージをほぼ流用させていただいている:

https://github.com/rust-lang/docker-rust/blob/286e5aa3ee6999e12f0e55f5edf7f8b29ea52fca/1.67.0/bullseye/Dockerfile

sudopostCreateCommandで使うので入れておく。まあsudoを使う必要もない気がするのでrootユーザで使っても問題ないと思う。

あとは環境変数の設定を忘れずにする。

備考

もしかしたらCUDAの設定をしないといけないかもしれない。(ubuntuではしたが、debianではした記憶がない。)

必要ならwsl2で以下を行う:

# cuda12の設定。
sudo apt-key del 7fa2af80
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/12.0.0/local_installers/cuda-repo-wsl-ubuntu-12-0-local_12.0.0-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-12-0-local_12.0.0-1_amd64.deb
sudo cp /var/cuda-repo-wsl-ubuntu-12-0-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt-get update
sudo apt-get -y install cuda

参考:

CUDA on WSL
The guide for using NVIDIA CUDA on Windows Subsystem for Linux.

オーディオ関連も設定

2023/2追記: WSLgで使われているPulseAudioを使って音声も再生できるので、それに関する設定もこの節に追記した。

.devcontainer/devcontainer.jsonmountscontainerEnvに追記する:

"mounts": [
    // mount wslg X11 socket(for old versions of vscode)
    // "source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind,consistency=cached",
    // mount PulseAudio server socket
    "source=/mnt/wslg/PulseServer,target=/tmp/PulseServer,type=bind,consistency=cached"
],
"containerEnv": {
    "PULSE_SERVER": "/tmp/PulseServer"
},

古いバージョンのためのX11の環境変数設定もcontainerEnvに追加すればよかったと若干後悔。

あとは、postCreateCommandsudo apt install -y pulseaudio alsa-utilsを入れておけばいい。後者のパッケージは不要かも。

おわり

DockerfileでRustイメージのまま使っていると、vulkan: No DRI3 support detected - required for presentation Note: you can probably enable DRI3 in your Xorg configといったエラーが出ていた。どうやってDRI3を有効にすればいいのか分からないので解決できていない。これが解決できればRustイメージのままできそうだ。

もしかしたら見当違いなことを書いたかもしれない。試行錯誤の記録をもっととるべきだったと反省している。

追記事項があれば書いていきたい。

以上です。

タイトルとURLをコピーしました