去年末にLinuxでHDR表示を有効にしてゲームをする方法について記事を書いたんですが、年明けでまた状況が変わってきたので追加の記事を書いておこうと思う。
HyprlandのHDR対応
元々、KDE PlazmaデスクトップだけHDR表示に対応しているという状況だったのが、今年になってからリリースされたHyprland-0.47.0からHDR表示に対応した。🎉
という訳で、experimentalな機能ながらWaylandでタイル型のウインドウマネージャーを使いたかった自分の様な人間にも道が開けてきた。
では、実際にはどうやって利用するのか。
Hyprland-0.47.0では以下の様な設定を追加する。
experimental {
wide_color_gamut = true
xx_color_management_v4 = true
# debug的な用途でディスプレイ表示を強制的にHDRモードに切り替える
# hdr = true
}
monitor=DP-1, 3840x2160@120, 0x0, 1, bitdepth, 10
また、Hyprlandのgitのmasterでは既に設定方法が変わっており、その場合は以下の様にする。次のバージョンではこの設定になるだろう。(これも変わるかもしれないが)
render {
cm_fs_passthrough = true # defaultでtrueなのでHDRを利用するだけならモニターを10bit表示にしておくだけで良い。
}
monitor=DP-1, 3840x2160@120, 0x0, 1, bitdepth, 10
# monitor=DP-1, 3840x2160@120, 0x0, 1, bitdepth, 10, cm, hdr # 強制的にHDRモードに切り替えるならこう
そして、モニターの色深度を10bitにしておく。いわゆる10億色表示のことで、通常は8bitカラーなので1670万色表示。 ちゃんと設定できていると、amdgpuなら以下の様なコマンドで確認できる。
sudo cat /sys/kernel/debug/dri/0/crtc-0/amdgpu_current_bpc Current: 10
(ただ、amdgpuだとここにバグがあったのでHyprlandのレンダリングライブラリをgit版に更新しないと駄目かもしれない)
こんな感じで出力できていれば概ねOK。
ここからHDRを有効にして画面表示をするなら、frog-color-management-v1 か xx-color-management-v4 に対応したクライアントが必要になる。
具体的なツールとしては、以前の記事で紹介した gamescope と VK_hdr_layer がある。
gamescopeはDXVK_HDR=1 gamescope -f --hdr-enabled -- %command%の様な感じでゲームを起動すれば、中のゲームがHDRに対応していればディスプレイがHDRモードに切り替わる。強制的にそうするオプションもある(詳しくはhelp参照)。DXVK_HDR=1にしておかないとゲーム側がHDRに対応していることを認識できない。
HyprlandがHDR対応する前は、コンソールから直接起動するembedded modeでしかHDR切り替えは動作しなかったが、Hyprlandの対応のおかげで通常のwaylandデスクトップからでも切り替えられる様になっている。🎉
mpvなどを利用して動画を見る場合はVK_hdr_layerを使う。vulkanの表示レイヤーにHDR表示のためのcolor management切り替え処理を行うレイヤーを追加するものだ。
これをインストールした上でENABLE_HDR_WSI=1 mpv --vo=gpu-next --target-colorspace-hint --gpu-api=vulkan --gpu-context=waylandvk "filename"の様にしてmpvを起動しフルスクリーンにすると画面がHDR表示モードに切り替わるはず。
target-colorspace-hintはインプットの動画ファイルのカラースペースをディスプレイ表示のカラースペースとしてそのまま利用する設定だ。基本的にHDR動画は色深度が10bitでBT.2020という色域でマスタリングされているが、それを画面表示にそのまま利用することになる。 この設定をしない場合は、BT.709と8bit colorで表示される様にmpvが調整して、その上でtone-mappingという機能で色域を補正していたのでそこまでおかしな表示にはなってなかったはずだが、tone-mappingをoffにするとめちゃくちゃ彩度が高く見えるはず。ちなみに、target-colorspace-hintを有効にした上でディスプレイの表示がHDRモードになっていない場合は、逆にディスプレイ側の表示色域が足りてないのでHDR動画の彩度がめちゃくちゃ低く見えると思う。
mpvでHDR表示をする際には、追加で以下の様な設定を入れても良い。
[hdr] target-colorspace-hint=yes target-prim=bt.2020 target-trc=pq target-peak=800 target-contrast=1000000 fullscreen=yes hdr-compute-peak=yes tone-mapping=bt.2446a inverse-tone-mapping=yes hdr-contrast-recovery=0.2
特に影響が大きいのはtarget-peakとinverse-tone-mappingの設定になる。target-peakはディスプレイの明るさのターゲットを指定するもので、自分の感覚では使ってるディスプレイの最大輝度よりちょっと大きいぐらいを指定しておくのが良さそうに思う。inverse-tone-mappingは名前の通り逆向きのtone-mappingでSDR画質(つまり通常の動画)の色域をHDRに拡張する。実際、そう都合よく綺麗になる訳ではないが、HDR表示モードでSDRの動画を見るとこれまた彩度がめちゃくちゃ高くなってしまってヤバイ表示になるのを何とかしてくれる。
基本的にこれらの機能はフルスクリーンでしか機能しない。そもそもディスプレイが画面全体をHDR表示モードにするかSDR表示モードにするかしかコントロールできないので、画面の一部だけHDRとかを上手いことやるのは難しいだろう。
という訳で、Linuxでも設定さえちゃんとやってしまえば普通にHDR表示が出来る、ぐらいまでは到達した様に思う。まあ、そもそもコンテンツが余り無いのだが……。配信作品とかはブラウザがそもそもそういう表示に対応してないので当分無理だろうし……。現状はLG辺りが出してるデモムービーぐらいしか無い。やはり現状で一番有用なのはPCゲームである。
HDR表示しているゲーム画面をキャプチャする
Linuxでゲーム画面をキャプチャしたい場合は、obsとobs-vkcaptureというプラグインを使うと良い。obs-vkcaptureはデスクトップ表示からキャプチャするのではなくゲーム画面をレンダリングするvulkanのレイヤーにキャプチャ層を追加して直接obsに流すことで低遅延かつ高画質でキャプチャできる様にしてくれるプラグインだ。
obs-vkcaptureはHDR表示に対応していてHDR表示されている場合は、その色域をちゃんとobsまで流してくれる。
obs側では詳細設定の項目から、カラーフォーマットをP010、色空間をRec.2100 (PQ) に設定し、HEVCからAV1を使ってキャプチャする様に設定してからキャプチャを開始すれば、HDR出力をそのままHDR動画としてキャプチャできる。
現実的に今それなりの解像度と60fpsをリアルタイムでキャプチャ可能なのはHEVCのハードウェアエンコードぐらいだと思う。AV1は自分が持ってるGPUが対応してないのでハードウェアエンコードでどれぐらいパフォーマンス出るのか分からんが、HEVCより遅いという話は聞く。今のところパテントフリーなので応援はしているが。
そして、amdgpuのVAAPIを利用したハードウェアエンコードはぶっちゃけ画質が余り良くないので、そこそこの画質で出力しようとすると普通に30Mbpsぐらい必要になる。録画なら良いが配信だと結構良い回線が必要である。