-
-
Notifications
You must be signed in to change notification settings - Fork 841
VI. Emulator Design [Devs]
I believe that the best way of learning a program's flow is by reading its code. Though I can see there's people who still want to know yet don't have enough skill to understand the code, so it's true that it'd be great to have documentation on that. But to sum it up quickly:
- Main eboot (game executable) is loaded.
- System libraries are loaded.
- Start running the eboot. We lose 'control' of the thread now.
- The guest runs its code. (e.g. load game assets, initialize systems, game UI, etc.)
- The guest calls system functions (they can be LLE or HLE).
- The guest starts sending GPU command buffers.
- The emulator receives said command buffers and does proper rendering (shader compilation, rendering).
- Repeat on step 4.
Things worth noting:
- We don't emulate the CPU - any guest code is executed natively, which is why the emulator is currently only available for x86_64 CPUs (excluding ARM Mac computers with the Rosetta recompiler).
- We act as a compatibility layer by doing a reimplementation of the system libraries.
- Certain system libraries run with LLE, so we're part LLE and HLE.
- We're also an emulator since the GPU has to be fully emulated. The GPU is the only portion of the PS4's hardware that is emulated.
[...] Where is the render loop at?
The emulator does not have a render loop. We do rendering when the guest wants to. The guest fills command buffers to send to the GPU. We also fill command buffers with a reimplementation of the GnmDriver system library [1].
Once the game finishes filling the GPU command buffers, it submits them and they're received by the emulator. This is where the GPU emulation starts. It works by going over the submitted PM4 packets; these can reset, set GPU registers, make draw and dispatch calls, move data over DMA, and so on.
Once a draw call packet is encountered, the graphics pipeline is compiled (if needed), and a Vulkan draw call is done. If the guest does not submit command buffers, none of the above happens.
You can find the relevant code here:
- https://github.com/shadps4-emu/shadPS4/tree/main/src/video_core/amdgpu
- https://github.com/shadps4-emu/shadPS4/tree/main/src/video_core/renderer_vulkan
I hope I explained everything you wanted to know. Let me know if you have any other questions.
[1] Gnm is the name of the PS4's graphics API. It is similar to DirectX 11.
Raw version, extracted from here, by Polybius