Эмулятор RISC-V в форме пиксельного шейдера, позволивший запустить Linux в VRChat

Опубликованы результаты эксперимента по организации запуска Linux внутри виртуального 3D-пространства многопользовательской online-игры VRChat, допускающей загрузку 3D-моделей со своими шейдерами. Для реализации задуманной идеи был создан эмулятор архитектуры RISC-V, выполняемый на стороне GPU в виде пиксельного (фрагментного) шейдера (VRChat не поддерживает вычислительные шейдеры и UAV). Код эмулятора опубликован под лицензией MIT.

В основе эмулятора заложена реализация на языке Си, при создании которой, в свою очередь, использованы наработки минималистичного эмулятора riscv-rust, развиваемого на языке Rust. Подготовленный Си-код транслируется в пиксельный шейдер на языке HLSL, пригодный для загрузки в VRChat. В эмуляторе предоставляется полная поддержка архитектуры набора команд rv32imasu, блок управления памятью SV32 и минимальный набор периферийных устройств (UART и таймер). Подготовленных возможностей достаточно для загрузки ядра Linux 5.13.5 и базового окружения командной строки BusyBox, с которым можно взаимодействовать напрямую из виртуального мира VRChat.




Эмулятор реализован в шейдере в форме собственной динамической текстуры (Unity Custom Render Texture), дополненной предоставляемыми для VRChat скриптами Udon, задействованными для управления эмулятором во время его выполнения. Содержимое оперативной памяти и состояние процессора эмулируемой системы сохраняется в форме текстуры, размером 2048×2048 пикселей. Эмулируемый процессор работает с частотой 250 kHz.
Помимо Linux в эмуялторе также может быть запущен Micropython.


Для организации постоянного хранения данных с поддержкой чтения и записи применяется трюк, связанный с использованием объекта Camera, привязанного к прямоугольной области, генерируемой шейдером, и направлением вывода отрисовываемой текстуры на вход шейдера. Таким образом любой пиксель, записанный в процессе выполнения пиксельного шейдер. Особенностью пиксельных шейдеров является то, что для каждого пикселя текстуры параллельно запускается отдельный экземпляр шейдера.

Данная особенность существенно усложняет реализацию и требует отдельной координации состояния всей эмулируемой системы и сопоставления позиции обрабатываемого пикселя с закодированными в нём состоянием CPU или содержимым ОЗУ эмулируемой системы (каждый пиксель может кодировать 128 бит информации). Код шейдера при этом требует включения огромного числа проверок, для упрощения реализации которых был задействован perl-препроцессор perlpp.



Release. Ссылка here.