A RISC-V emulator in the form of a pixel shader that made it possible to run Linux in VRChat

The results of an experiment on organizing the launch of Linux inside the virtual 3D space of the multiplayer online game VRChat, which allows loading 3D models with their own shaders, have been published. To implement the conceived idea, a RISC-V architecture emulator was created, which runs on the GPU side in the form of a pixel (fragment) shader (VRChat does not support compute shaders and UAV). The emulator code is published under the MIT license.

The emulator is based on the implementation in the C language, which, in turn, uses the developments of the minimalistic riscv-rust emulator developed in the Rust language. The prepared C-code is translated into a pixel shader in HLSL, suitable for loading into VRChat. The emulator provides full support for the rv32imasu instruction set architecture, an SV32 memory management unit, and a minimal set of peripherals (UART and timer). The prepared features are enough to boot the Linux 5.13.5 kernel and the basic BusyBox command line environment, which can be interacted with directly from the VRChat virtual world.

A RISC-V emulator in the form of a pixel shader that made it possible to run Linux in VRChat
A RISC-V emulator in the form of a pixel shader that made it possible to run Linux in VRChat

The emulator is implemented in the shader in the form of its own dynamic texture (Unity Custom Render Texture), supplemented by Udon scripts provided for VRChat, used to control the emulator during its execution. The contents of RAM and the state of the processor of the emulated system are stored in the form of a texture, sized 2048Γ—2048 pixels. The emulated processor runs at 250 kHz. In addition to Linux, the emulator can also run Micropython.

A RISC-V emulator in the form of a pixel shader that made it possible to run Linux in VRChat

To organize persistent data storage with support for reading and writing, a trick is used associated with using a Camera object attached to a rectangular area generated by the shader and directing the output of the rendered texture to the input of the shader. Thus, any pixel written during the execution of the pixel shader can be read during the processing of the next frame.

When applying pixel shaders, a separate instance of the shader is run in parallel for each pixel of the texture. This feature significantly complicates the implementation and requires separate coordination of the state of the entire emulated system and comparison of the position of the processed pixel with the state of the CPU encoded in it or the contents of the RAM of the emulated system (each pixel can encode 128 bits of information). In this case, the shader code requires the inclusion of a huge number of checks, to simplify the implementation of which the perl preprocessor perlpp was used.



Source: opennet.ru

Add a comment