Windows で OpenGL/Vulkan アプリを動かして画面をイントラネットで VNC などで転送したいメモ

## 背景

* OpenGL/Vulkan を使う Windows 10 グラフィックスアプリの画面を Linux PC などに転送したい
* 同じ部屋や, 異なる部屋にある PC 間で, イントラネットで使う(インターネットで外から繋ぐなどはしない)
* RDP だと OpenGL 2.x(?) までなので使えない.
  * 追記: OpenGL/Vulkan 機能使えました. おまけ参照. 
* Chrome Remote Desktop だと, 拡張入れるのが気になるし, 認証で一度 Google サーバに繋がないといけないのでめんどい.

VNC を試します.

VNC は, free(OSS) は 3 種類ほどあります(TightVNC, UltraVNC, TigerVNC)

まず, TigerVNC は今回の用途では使ってはいけません. **とっても遅いです**. これは実装上しょうがないようです(Java だから?).
私も試しましたが, 使い物になりませんでした. 

TigerVNC 1.6.0 on Windows 10 running as a Service is unbearably slow and does not work in user mode. [$200]
https://github.com/TigerVNC/tigervnc/issues/277

$200 のバウンティがついていますが, 誰もやりそうにないですね...
(issue が上がったのが 2016 年なので, 1 BTC にしておけばワンチャンあったかも?)

## Ultra VNC

UltraVNC を使います(ダウンロード URL が, 何やら amazon へのリンクが入っていてややあやしい. 気になるひとはソースコードからビルドするのがいいかもです). 

最近だと mirror driver がデフォで有効になっていました.

UltraVNCにmirror driverはもういらない
https://kulog.org/pc/software/k9067/

Windows 10 側で, 5900, 5901 あたりのポートを開放しておく必要があると思います.


## VNC client

VNC client は jpeg 圧縮しないのを選べるものを使いましょう. jpeg 圧縮すると画面の彩度が落ちてしまいます.

tighervnc の viewer(Ubuntu で apt で入る)は jpeg off にできました.
 
Ubuntu Desktop 標準(?) の Remmina では設定できないようでした.
 

## 10 GbE/IB ?

1 GbE だと, 2.5K で 3~4 fps(全描画)という感じです. ネットワーク転送量は 500kb/s くらいで, viewer 側の圧縮率を下げてもあまり変わりはありませんでしたので, どこか CPU あたりでボトルネックがあるのかもしれません..

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">UltraVNC で転送の場合のラグと fps はこんな感じです <a href="https://t.co/BR8pnTPZKx">pic.twitter.com/BR8pnTPZKx</a></p>&mdash; Syoyo Fujita 🌸 レイトラ 🐯 2 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1259465303949373446?ref_src=twsrc%5Etfw">May 10, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

10 GbE など高速ネットワーク + 完全非圧縮転送だと, より fps が稼げるかもしれません.


## WebRTC, zoom や VDI?

昨今では, 仮想で動かして PCI-ex の画面データ(?)を転送する方法があるようですね(VDI?). ただ, 基本サーバーとか向けのようです.

zoom(これも WebRTC?) やらゲーム配信で, 画面のストリーミング方法も出てきているので, 画面転送はこれらで, マウスやキーボードなどは VNC や Synergy など経由などでやるという手がありそうです.
(nomachine とか?)

自宅サーバのデスクトップへブラウザからアクセスできるように「noVNC」を設える
https://qiita.com/knaka/items/b61e0cb0b5d07d2527b2

Stream a remote screen with WebRTC
https://viscarra.dev/post/webrtc-remote-screen/

noVNC あたりで画面は websocket で非圧縮転送, というのがイントラネット向けではいいかも?

(伝統的な) RDP, VNC を使って画面転送, リモートデスクトップというというのは廃れていくのかもしれません.

## Parsec

**優秀な仮想化若人さま**から, Parsec(Haskell PEG parser library ではない)を教えていただきました.

アカウントなどでの認証でインターネットアクセス(Parsec ログイン)必要になります.
一応, LAN のみで画面転送できるようですが,

https://support.parsecgaming.com/hc/en-us/community/posts/115003261871-Restrict-streaming-only-to-LAN

設定パラメータがなくなっていたりするので, 最近はどうなのか不明です.

ただ, Linux クライアントは, 対応する GPU を搭載していても nvenc(h264/h265)未対応のようで, SW デコード(?)で jpeg 系圧縮オンリーでした.

jpeg 系だとやはり彩度がいくらか落ちてしまいます. LAN モードでは非圧縮転送オプションとかほしいですね.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ねんがんの Parsec(not Haskell PEG Parser)での, (たぶん)LAN 上でのぬるぬるリモートデスクトップ(画面転送)に成功したぞ!!!! 🎉🎉🎉🎉🎉🎉🥳🥳🥳しかし jpeg あたりで圧縮だからかやはり彩度など落ちるぬる感じあります. jpeg 画像から機械学習でリアルタイム彩度復元機能欲しくなりますね. <a href="https://t.co/JkLzaiAAnt">pic.twitter.com/JkLzaiAAnt</a></p>&mdash; Syoyo Fujita 🌸 レイトラ 🐯 2 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1259716996268044288?ref_src=twsrc%5Etfw">May 11, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

## 自前でつくりたい...!?

画面キャプチャ自体は, Windows の標準機能(or Chrome/Electron) などで取得できるようなので, 
LAN 用途であれば仕組み的にはそれほど難しくないと想像できます.

リアルタイム画面取得 + 非圧縮(zstd でリアルタイム圧縮/展開)で Websocket or IB RDMA 転送するツールを作りたくなってきますね!

## RDP

RDP でも, OpenGL/Vulkan 有効にできました(NVIDIA だけ, 制限がかかていた(が, 最近開放するパッチ(?)が出た. しばらくは使えそう?))

OpenGLを使えるリモートデスクトップを構成する
https://blog.techlab-xe.net/enable-opengl-rdp-nvidia/

OpenGLを使えるリモートデスクトップ その2
https://blog.techlab-xe.net/check-opengl-rdp-intel-amd/

ありがとうございます.

VK_NV_ray_tracing も使えましたのでレイトレ開発がバリバリできますね!


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Win 10 Pro アップグレードして RDP + RemoteFX + OpenGL 対応 RDP 設定 <a href="https://t.co/5mzNvR42xu">https://t.co/5mzNvR42xu</a> + Linux クライアントで OpenGL 4.6/Vulkan 1.1(VK_NV_ray_tracing 対応)で視覚的には圧縮気にならずぬるぬる 20 ~ 30 fps いけました!(2.5K フル描画リフレッシュだとさすがに 10 fps くらい) <a href="https://t.co/8NLgIdgWTy">pic.twitter.com/8NLgIdgWTy</a></p>&mdash; Syoyo Fujita 🌸 レイトラ 🐯 2 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1260465652260896768?ref_src=twsrc%5Etfw">May 13, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

### Alacritty Terminal を使う

GPU が使えるので, 爆速ターミナル Alacritty も動きます.

Windows の Terminal を変えた
https://qiita.com/kikuchi_kentaro/items/040aa16979eab9ae0af6

RDP で非圧縮相当(ロスレス or YUV444?)であれば, テキストくっきりでかなりいい感じに動きます.
(レイテンシは macOS Terminal くらいあります) Linear スイッチキーボードなど, 反応はやいキーボードと組み合わせするとよりベター.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">RDP ロスレス(に近い?) + Alacritty + リモート GPU enabled で, 多少遅延あるがテキストくっきり + 概ね手元 Terminal と同じ速度でリモート Windows でターミナル作業できてよい!(TODO: ターミナルカラーを変える) <a href="https://t.co/xgstwn03DR">pic.twitter.com/xgstwn03DR</a></p>&mdash; Syoyo Fujita 🌸 レイトラ 🐯 2 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1265175184207605762?ref_src=twsrc%5Etfw">May 26, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


### 10 GbE で非圧縮転送.

TP Link の激安 8 port 4 万円スイッチ + 10 GbE カードで 10 GbE 接続ためしました.

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ねんがんの GeForce Windows 10 + 10 GbE 接続 RDP RemoteFX 非圧縮転送で 2.5K 解像度ヌルサク 24 fps OpenGL 画面転送に成功したぞ!!!!!! タイルで転送しているようなのでタイル上のティアリングありますが許容範囲でしょうか. 4 万円激安 TP-Link 10 GbE スイッチ利用. iperf は 6 Gbps/s でした. <a href="https://t.co/HdwFsq5fJa">pic.twitter.com/HdwFsq5fJa</a></p>&mdash; Syoyo Fujita 🌸 レイトラ ® 🐯 3 周年 🎉 (@syoyo) <a href="https://twitter.com/syoyo/status/1378635954332729352?ref_src=twsrc%5Etfw">April 4, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

iperf での実測は 6 Gbps でしたので実質 5 GbE くらいでしょうか.
(スイッチ的にはノンブロッキングっぽいのですが, ジャンボフレーム使わないとフルスピード出ないとかですかね)

上記 https://blog.techlab-xe.net/enable-opengl-rdp-nvidia/ を参考に RemoteFX(32bit) + 非圧縮設定にしました.

タイルで画像転送しているためか, タイル状アーティファクトありますがまあ慣れれば問題ないでしょうか.
2.5K 解像度でも 24 fps くらいで転送できており, 圧縮によるノイズや彩度低下がなくて非常に快適です.

## TODO

* [ ] TightVNC を試す(ひとまず UltraVNC の速度で満足してしまったので試していません)
* [ ] UltraVNC の zstd 圧縮を試す.
* [x] 少なくとも, 10 fps くらいは出せるようにして, Blender などをそこそこいい感じに動くようにしたい
  * [x] 10 GbE でいい感じに動きました. 
  * [x] RDP で非圧縮モード(?) RemoteFX or True Color(32bit) でいけました