v0.4.0: Direct3D 11/12 backends, in-game renderer selection, per-run logging

- ra3.dx: D3D11 and D3D12 presentation backends (runtime HLSL via d3dcompiler);
  2D image blit and the GPU heightfield terrain raymarch, with the corner
  minimap/FPS overlays. Non-Windows builds link a null fallback.
- ra3.display: preferred backend plus ordered fallback (Vulkan/D3D11/D3D12/SDL);
  menu gains a Renderer option and the CLI gains --dx11/--dx12/--sdl, which the
  render command now honours too.
- vendor libenderlog (MIT): every run writes openra3.log next to the exe and
  archives the previous run's log; records at warn and above carry a call stack
  (native fallback, since libc++ has no <stacktrace>).
- Windows crash reporter writes openra3_crash.log (faulting module + backtrace);
  D3D/DXGI diagnostics are routed through the logger.
This commit is contained in:
EnderTheCoder
2026-09-28 13:03:37 +08:00
parent 59261868e1
commit 3caf18409b
16 changed files with 2815 additions and 70 deletions
+19 -4
View File
@@ -18,14 +18,16 @@ Ghidra.
## Status
OpenRA3 is at **v0.3.0**. The engine compiles and runs headless, and a **minimal
OpenRA3 is at **v0.4.0**. The engine compiles and runs headless, and a **minimal
skirmish** is playable: it reads a real multiplayer map out of your install,
recovers the player start waypoints, and simulates two sides building a base,
extracting ore and fighting until one side is wiped out. The balance is the
**retail Red Alert 3 balance**, pinned in `ra3.data` from EA's open RA3 XML:
damage types, `ArmorTemplate` percentages, weapon target masks, build costs and
the ore economy. Presentation is a **Vulkan** backend (`ra3.vulkan`) with a null
fallback; the software renderer still produces headless images. Terrain tiles
the ore economy. Presentation offers **Vulkan** (`ra3.vulkan`) and **Direct3D 11 / 12**
(`ra3.dx`) GPU backends with an SDL software blit and null fallbacks; the
backend is selectable from the in-game menu and the software renderer still
produces headless images. Terrain tiles
cross-fade the way the retail `Terrain.fx` does (a per-cell blend ramp plus a
gutter-padded atlas), so material boundaries are smooth instead of a grid of
hard lines. An in-window **menu** lists the maps by their localized name and
@@ -83,7 +85,7 @@ built-in test map so the project still builds and runs in CI.
| `src/core/ra3.core.cppm` | fundamental types, math, strings, random, message stream |
| `src/logic/ra3.logic.cppm` | objects, players, teams, spatial partition, game loop |
| `src/client/ra3.client.cppm` | `display` abstraction + shared interactive loops + client facade |
| `src/display/ra3.display.cppm` | picks the backend (Vulkan, then SDL) for the app |
| `src/display/ra3.display.cppm` | picks the backend (Vulkan/D3D11/D3D12, then SDL) for the app |
| `src/game/ra3.game.cppm` | RA3 sides, player templates, skirmish defaults |
| `src/data/ra3.data.cppm` | retail RA3 balance: damage types, armour, weapons, units, economy |
| `src/fs/ra3.fs.cppm` | `BIG4` archives, RefPack codec, local install locator |
@@ -93,6 +95,8 @@ built-in test map so the project still builds and runs in CI.
| `src/render/ra3.render.cppm` | ARGB framebuffer, TGA decode, BMP encode, map compositing, bitmap-font text |
| `src/ui/ra3.ui.*.cppm` | SDL3 window viewer and menu (null backend when SDL3 is absent) |
| `src/vulkan/ra3.vulkan.*.cppm` | Vulkan presentation backend and menu (null fallback without a loader) |
| `src/dx/ra3.dx.*.cppm` | Direct3D 11/12 presentation backend (runtime HLSL; null fallback off Windows) |
| `third_party/libenderlog/` | vendored C++26 module logger (`import ender.log;`, MIT) with a native stack fallback for libc++ |
| `src/ra3.cppm` | umbrella module re-exporting the SDK |
| `apps/openra3/main.cpp` | `menu` / `maps` / `skirmish` / `render` CLI |
| `tests/ra3_tests.cpp` | smoke tests (run via `ctest`) |
@@ -156,6 +160,17 @@ openra3.exe render --game-dir "C:\Red Alert 3" --vulkan
Vulkan is provided by **vendored volk + headers** (`third_party/`), resolved at
runtime, so neither image needs a Vulkan SDK.
## Logging
Every run writes `openra3.log` next to the executable through the vendored
[`libenderlog`](third_party/libenderlog) module (`import ender.log;`). A file
sink archives the previous log to `openra3.log.<YYYYmmdd-HHMMSS>` on open, so
each run gets its own file; the active file rotates at 4 MiB and the last 10
archives are kept. Records at **`warn` and above** carry a call stack (Windows
`CaptureStackBackTrace` / POSIX `execinfo`, because libc++ has no
`<stacktrace>`). A hard crash also writes `openra3_crash.log` with the faulting
module and a raw backtrace.
## Running a skirmish
```bash