The results of an experiment on organizing the launch of Linux inside the virtual 3D space of the online multiplayer game VRChat , which allows loading 3D models with their own shaders, have been published. To implement the conceived idea, an emulator of the RISC-V architecture was created, executed on the GPU side in the form of a pixel (fragment) shader (VRChat does not support computational 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, was created using the developments of the minimalist emulator riscv-rust , developed in the Rust language. The prepared C code is translated into a pixel shader in the HLSL language, suitable for loading into VRChat. The emulator provides full support for the rv32imasu instruction set architecture, SV32 memory control unit and a minimum set of peripherals (UART and timer). The prepared capabilities are enough to load the Linux 5.13.5 kernel and the basic BusyBox command line environment, with which you can interact directly from the virtual world of VRChat.
The emulator is implemented in the shader in the form of its own dynamic texture (Unity Custom Render Texture), supplemented by the Udon scripts provided for VRChat, which are used to control the emulator at runtime. The contents of the main memory and the state of the processor of the emulated system are saved in the form of a texture with a size of 2048×2048 pixels. The emulated processor runs at 250 kHz. In addition to Linux, Micropython can also be run in the emulator .
To organize persistent data storage with support for reading and writing, a trick is used that involves using a Camera object bound to a rectangular area generated by the shader and directing the output of the rendered texture to the shader’s input. Thus, any pixel written during the execution of a pixel shader can be read during the next frame.
When pixel shaders are applied, a separate instance of the shader is launched in parallel for each pixel in 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 CPU state or the contents of the RAM of the emulated system encoded in it (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 .