Не забивайте себе голову тем, что не имеет отношения к настоящему. В будущее надо ещё суметь попасть. Виктор Пелевин — Чапаев и Пустота.
Первая часть посвящена серверной стороне облачного гейминга, вторая часть — клиентской, а третья RDP :)
Эта статья состоит из трёх разделов: предыстория проблемы с RDP, подходы к решению проблемы и неожиданное решение.
Предыстория проблемы с RDP
С осени 2022 года в МГУ проводится курс Индустриальные исследования в искусственном интеллекте, ИИвИИ. В этом году я, как организатор курса, предложил слушателям выполнить задание по теме LLM-based Multi-Agents Systems, в котором необходимо при помощи LLM управлять персонажем в игровой среде Minecraft на карте МГУ. Поскольку я сторонник тонких клиентов, у меня возникла потребность запустить Minecraft в облаке.
Для запуска Minecraft необходима имплементация OpenGL. Конечно, можно использовать программную имплементацию, но она работает медленно. Поэтому лучше, чтобы была видеокарта.
В качестве тонкого клиента я выбрал RDP, поскольку он обладает собственным дисплеем, как можно видеть в сравнительной таблице в конце второй статьи. А поддержка RDP лучше всего реализована в Windows.
Таким образом, получилась связка GPU+Windows+RDP, дальше нужно было выбрать облако.
Важно отметить, что данный пост не является рекламным для облака Selectel, однако я выбрал именно это облако по двум причинам. Во-первых, в этом облаке доступна аренда виртуальной машины с Windows Server 2019 и GTX 1080 всего за 30 руб. в час. Во-вторых, в этом облаке доступна функция заморозки, когда виртуальная машина выключена, но GPU при этом не тарифицируется.
После установки на виртуальной машине с Windows Server 2019 простого советского драйвера для GPU 565.90-desktop-win10-win11-64bit-international-nsd-dch-whql.exe и удалённого подключения через RDP Minecraft запустился.
Но возникла проблема с камерой, точнее с мышкой...
Поиск показал, что данная проблема наиболее известна под названием Erratic mouse movement in 3D games over RDP with RemoteFX (эта ссылка является ключевой и далее я ссылаюсь на неё несколько раз). Оказывается, что в RDP есть два режима передачи положения курсора: absolute mouse movement и relative mouse movement. Про это даже написано в официальной документации от Microsoft. Говорят, что в играх якобы ради быстродействия нужно передавать относительное смещение курсора. Но лично мне кажется, что это сделано, чтобы по RDP не играли в игры...
Гипотеза о сговоре между Microsoft и Nvidia
RDP был выбран по той причине, что он обладает собственным виртуальным дисплеем.
Parsec, Moonlight и Steam подключаются к дисплею видеокарты. Но на не grid драйвере максимальное разрешение в этом случае составляет 1366x768.
А если устанавливать grid драйвер, то нужна будет лицензия. Подробнее о связи драйверов, лицензий и разрешений см. во второй статье.
Т.е. для 1080p либо Parsec/Moonlight/Steam и grid драйвер с лицензией от Nvidia
Либо RDP и проблемы с мышью от Microsoft
Совпадение?..
Подходы к решению проблемы
Выяснилось, что при подключении по RDP использовать мышь без relative режима крайне нетривиально. К слову, в Parsec'е есть автоматическое преобразование из relative в absolute. А вот с RDP всё гораздо сложнее...
Базовый подход через RemoteFX USB redirection
Основная идея решения по ключевой ссылке заключается в том, что мышь можно передавать через RDP как RemoteFX устройство. Эта процедура подходит для многих usb-устройств и называется RemoteFX USB redirection. В этом случае смещение курсора передаётся в режиме absolute mouse movement.
Попытки включить этот режим следуя руководству по ключевой ссылке не увенчались успехом, поскольку мышка не появилась в списке RemoteFX устройств в панели Локальные ресурсы в RDP. Отдельно отмечу, что руководство по ключевой ссылке апеллирует к официальной документации от Microsoft, где описан способ добавления устройства в список RemoteFX устройств через прописывание GUID в реестре.
Также на портале Microsoft в ответ на вопрос How to fix redirected USB mouse with RemoteFX not working over RDP? поинтересовались, является ли мышка беспроводной. Как ни странно, далее действительно будет выявлено различие в использовании мыши по RDP в зависимости от наличия провода.
Подводя итог по базовому подходу, добавлю, что я проверил, что этот подход не работает на одной машине с Windows 10 Home и другой машине с Windows 10 Pro. Оставлю без комментариев вариант, когда для того, чтобы заработало Remote FX USB redirection, рекомендуется обновить версию Windows до Enterprise.
Пробрасывание USB через сторонние решения
Следующим был рассмотрен вариант, когда мышь передается не через RDP, а через стороннее решение. Здесь уместна аналогия с передачей звука в Parsec'е через VB-Audio Virtual Cable. Я проверил следующие три решения для пробрасывания USB:
USB Network Gate
Интересно, что в конце страницы по ссылке сказано, что: You can’t allow RemoteFX to utilize USB devices while connecting to an RDP server if your Windows 10 HOME edition lacks gpedit.msc. Так что возможно в обновлении Windows до Enterprise есть смысл...VirtualHere
На мой взгляд это наиболее интересное решение. Нужно запустить на локальной машине VirtualHere USB Server. На виртуальной машине в облаке нужно отключить Windows Defender Firewall. Также в облаке нужно запустить VirtualHere USB Client. И затем останется подключиться к локальной машине через Reverse Clients.
Все три решения не сработали для моей мыши, она просто не пробросилась. Однако вспомнив про комментарий выше о том, является ли мышка беспроводной, я решил проверить эти решения для Bluetooth мыши, поскольку до этого проверки были для проводной мыши...
На удивление это сработало и с помощью VirtualHere мне удалось пробросить беспроводную мышку при подключении по RDP. Я понял, что пробрасывание сработало, поскольку случайно увидел, что курсор двигается в консоли виртуальной машины в облаке, но не двигается на мониторе локальной машины и на виртуальном дисплее RDP.
Я обратил внимание, что при подключении по RDP создаётся виртуальное устройство мыши, которое работает в виртуальном дисплее RDP. Таким образом, чтобы завершить анализ текущего подхода было необходимо:
- Научиться отключать RDP Desktop Mouse Device
- Научиться отключать консоль виртуальной машины в облаке
Возможно выполнение обоих этих действий привело бы к тому, что после пробрасывания беспроводной мыши, её курсор стал бы двигаться на виртуальном дисплее RDP, но я решил не проверять эту гипотезу. Однако я проверил гипотезу о подключении по RDP PS/2 мыши, поскольку обе проводная и беспроводная мыши до этого были usb-устройствами. К сожалению, при подключении по RDP PS/2 мыши проблема сохранилась.
Альтернативные подходы
Также мною были найдены следующие альтернативные подходы к решению проблемы:
Использовать в качестве тонкого клиента Chrome Remote Desktop
Создать виртуальный дисплей с помощью другого тонкого клиента, например, remote.it и затем подключиться к нему с помощью Parsec'а
Использовать геймпад либо стрелки на клавиатуре для управления камерой
Вариант со звёздочкой: для создания дисплея также можно использовать физическую заглушку, например, знакомый многим переходник HDMI-VGA, однако по какой-то причине облачные провайдеры не предоставляют такую услугу...
Я уже был готов начать рассматривать альтернативные подходы, когда неожиданно нашёл решение!
Неожиданное решение
Как сказал классик: реальность полна разочарований. Решение было обнаружено там, где я не надеялся его найти: на портале Microsoft'а...
Один архитектор в ковидные времена также столкнулся с той же проблемой и очень просил инженеров Microsoft её решить.
И в комментариях ему посоветовали обратить внимание на следующую ссылку: https://github.com/TKMAX777/RemoteRelativeInput
И у того же автора было ещё одно решение: https://github.com/TKMAX777/RDPRelativeInput
В некотором смысле автор решения реализовал плагин для RDP, который позволяет при подключении использовать мышь без relative режима, что и было нужно для Minecraft'а!
Послание себе
Таким образом, проблема с доступностью курсора в игре при подключении по RDP из второй статьи решена. И теперь RDP также подходит для облачного гейминга. Осталось только разобраться с Horizon'ом...