👾

Common Lisp で Vulkan を書く準備

2023/03/04に公開

素敵なGIF
スプライトもUIも自前描画です。

こんにちは、Common Lisp大好きマンのcddadrです。
情報が少ない界隈なのでせっかくだし知見を残しておこうと思い筆を執っています。

TL;DR

  • Roswell + SBCL + Qlotな環境を作る。
  • vkとcl-glfw3を入れる。
    • vkのビルドのために処理系の動的メモリ上限を上げておく。
  • システム定義にpackage-inferred-systemを使う。

モチベーション

Common Lisp + VulkanでGUIアプリケーションフレームワークもといゲームエンジンを作っています。知見を共有したらワンチャンCL使いとかCL+Vulkanの情報増えてくれないかな…という清純な動機で記事を書いていきます。Common LispでもVulkanでグラフィックスプログラミングやれるんだ!と感じてもらえたら嬉しいです。
コードを書く片手間に文章化していくので小出しになると思いますが、あしからず。

対象読者

Common Lispは分からないけどLisp系言語を見たことがある・雰囲気を知っている人、あるいはグラフィックスプログラミング経験者。
やる気があったらCommon Lispの書き方も軽く説明を添えつつやっていこうと思います。Vulkanの基本的なことはVulkan Tutorialとかを読んだ方が早いです。

Vulkan について

オープンなグラフィックスAPI規格で、DirectXとかMetalみたいなやつの内の1つです。OpenGLと同じKhronos Groupが主に策定しています。OpenGLよりも低レベルなAPIで記述量が圧倒的に多いですが、色々と細かく制御出来るため痒いところに手が届くような印象です。またオープンなAPIなので動作プラットフォームを選ばないところも魅力です。

環境構築

  • macOSとLinuxは普通のやり方で動くはず。WindowsならMSYS2が良いです。Dockerはわからない。
  • 処理系管理と実行可能ファイル作成にはroswellを使います。
    • uiop:define-packageの新機能を使うためにインストール後はros install asdfでASDFを更新しておくことを推奨します。
    • そのうちRenderDocでデバッグするために実行可能ファイルを作ります。
  • Common Lisp処理系はSBCL(2.2.10)を前提に書きますが、多分CCLやECLでも動きます。
    • Android 対応は ECL が有力候補ですが、手元ではまだNDK込みでビルドを通せてないです。一応EQLという前例もあるので不可能ということは無いはず…
    • SBCLもTermux上での動作や共有ライブラリ化まではできているようなのでそろそろ誰かが動かしてくれそうな気配があります。
  • システム(外部ライブラリ)管理にはfukamachi/qlotを使います。Roswellと合わせて使うのが楽です。
  • VulkanSDKのインストールについてはLunarGのページ辺りを読んでください。

プロジェクト作成

何か適当なプロジェクト作成ツールを使っても良いですが、今回は全手動で作ります。
まずASDFのサーチパスが通ったディレクトリ下にプロジェクトのディレクトリを作成します。特に設定していなければ $HOME/common-lisp/ 以下に作ると良いはずです。サーチパスが通っていない場所に作成してしまうと正しくプロジェクトを読み込めないため注意してください。

- vkapp/
	- vkapp.asd
	- src/
		- package.lisp
		- app.lisp

上のような感じでディレクトリと空のファイルを作ったらシステム定義を vkapp.asd に記述します。システム定義クラスは package-inferred-system を採用します。これを使うとパッケージ定義からシステム依存関係を推測してくれるようになりメンテナンス性が高まりますが、ファイルパスとパッケージ名を一致させる必要があることに注意してください。

vkapp.asd
(asdf:defsystem #:vkapp
  :class :package-inferred-system
  :pathname "src/"
  :depends-on (#:vkapp/package))

一旦ここまで出来たらシステムが読み込めるか確認します。

ros run -- --eval "(require :vkapp)"

特に怒られなければ問題ないです。
怒られた場合はプロジェクトディレクトリを作った場所がマズいか vkapp.asd の書き方が間違っているので確認してください。

外部システム(ライブラリ)のインストール

前述の通りQlotを使って管理しますので、入っていなければ以下を叩いてインストールしてください。

ros install qlot
# パスを通すのもお忘れなく!
export PATH=$PATH:$HOME/.roswell/bin

qlotコマンドが使えるようになったら以下のシステムを入れていきます。

  • JolifantoBambla/vk: Vulkanバインディング。
  • AlexCharlton/cl-glfw3: GLFWバインディング。ウィンドウ管理と入力取得に使います。
  • cffi: FFIの処理系互換レイヤー。上2つの依存システムです。
  • alexandria: よく使うユーティリティ関数詰め合わせ。上2つの依存システムです。
    alexandria 以外はOS側でライブラリ入れたりが必要なのでそれぞれREADMEを読んでインストールしてください。一応 Ubuntu でのインストール例を載せておきます。ちなみに自分はArch Linuxユーザーです。
qlfile
ql alexandria
ql cffi
ql cl-glfw3
ql vk
# vulkan-sdkだけLunarGのPPAの追加が必要
sudo apt install vulkan-sdk vulkan-validationlayers libglfw3 libffi-dev
qlot install

インストールが出来たら一応それぞれのシステムのテストが通るか確認しておきましょう。Qlot でインストールしたシステムを使うために qlot exec ros run で REPL を起動します。補足ですが vk のビルドで動的メモリ上限まで食い潰す可能性が高いので SBCL なら --dynamic-space-size 4096 以上にしておくと吉です。

(asdf:test-system :cl-glfw3)
(asdf:test-system :vk)

問題ないことを確認したらシステム定義に依存システムを追記します。

vkapp.asd
(asdf:defsystem #:vkapp
  ...
  :depends-on (#:vk
               #:cl-glfw3
               
               #:vkapp/package))

これでCLでVulkanを書く準備が整いました。
長くなったので一旦ここまで。

Discussion