Files
t5de-renderer/docs/architecture.md
T
dhkatzandClaude Opus 5.5 a04dba18c1 Draw particles, match the client's fog, and measure frame delay
Particles (point sprites) are drawn as instanced camera-facing squares sized like Direct3D 9's. Fog is by depth buffer value, as Direct3D 9 does with IMVU's projections. At most one frame is queued for display, frames carry the adapter's timestamp so the renderer process logs the delay to presenting, and the log's lines from several processes no longer mix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 06:11:51 -07:00

61 lines
4.0 KiB
Markdown

# Architecture
The renderer is two programs:
- **The adapter**, `t5deRenderEngine.dll` (32-bit, `adapter/`): a renderer plugin IMVU Classic loads in place of its
OpenGL renderer (selected by the `t5de-renderer` patch in the `t5de` repository). It implements IMVU's
`PiRenderEngine` interface (`include/t5de/imvu/`, `docs/interface.md`) and passes what the client draws to the
renderer process. It stays thin: IMVU's process is 32-bit (4 GB of address space shared with Python, Gecko and
IMVU's own code) and tied to Visual C++ 2010's ABI.
- **The renderer process**, `t5de-renderer.exe` (64-bit, `renderer/`): draws, with
[Diligent Engine](https://github.com/DiligentGraphics/DiligentCore) (Apache-2.0). Being 64-bit and separate, it can
use any modern API and library, isn't limited by the client's address space, and can crash without taking the
client down.
Why Diligent: one API over Direct3D 11 (every Windows PC, and software rendering on machines without a graphics
driver), Direct3D 12 and Vulkan (ray tracing, mesh shaders), and WebGPU (browsers, for a possible future client).
It's built with CMake and fetched by `FetchContent`, pinned to a commit (`renderer/CMakeLists.txt`); only the
Direct3D 11 backend is built for now.
## How they talk
`include/t5de/protocol/` is shared by both builds, so it uses fixed-size fields only. For each engine the client
creates (each 3D view, and again on room changes), the adapter:
1. creates a shared memory channel (`Local\t5de-renderer-<pid>-<n>`) holding IMVU's window handle and a frame
count, and an event set after each frame;
2. starts `t5de-renderer.exe --channel <name> --parent <pid>` from its own folder;
3. sets the event at each `endRendering`, and sets `closing` when the engine is destroyed.
The renderer process draws into a child window it creates inside the client's window: window handles are valid in
every process, and Windows allows child windows across processes (Chrome's GPU process works this way). The child
is disabled so mouse input goes to the client's window under it, and the adapter gives the client's window
`WS_CLIPCHILDREN` so the client's own drawing stays out of it. The process exits when the engine is destroyed or the
client exits.
## Status
The renderer process draws the client's whole scene, over the right half of the 3D view, beside the client's own
Direct3D renderer on the left (the adapter still forwards everything to it): `T5DE_RENDERER_VIEW=full` or `off`
changes that. Checked in rooms: the halves match, particles included.
- The command stream (`include/t5de/protocol/commands.hpp`) carries state, transforms, lights, fog, textures,
buffers (copied when created or updated) and draws, in chunks through the channel; the adapter waits for each to
be taken, and gives up on a renderer process that stops taking them (the client's renderer carries on).
- The renderer process reproduces IMVU's Direct3D 9 setup (`renderer/shaders/fixed_function.hlsl`), particles
included (point sprites, drawn as instanced squares), with a pipeline per combination of states.
- Speed: on the development VM (software rendering) a room frame takes 8 to 60 ms to draw; the time from the
client finishing a frame to ours being presented averages about 60 ms. The renderer process draws only the
newest frame when it falls behind, and keeps at most one frame queued. Over Remote Desktop, the half drawn by the
renderer process (another process's window, composited by Windows) visibly trails the client's half by more
than that; that delay comes after presenting, and is to be checked on a real graphics card and display.
Next: render targets (offscreen frames are skipped), the renderer process drawing the whole view in place of the
client's renderer, and one renderer process for all of a client's views.
## Building
Two presets, one per architecture: `cmake --workflow --preset adapter` (32-bit, with the tests) and
`cmake --workflow --preset renderer` (64-bit; the first configure fetches and builds Diligent). Both programs go in
the client's folder.