|
1 | 1 | # Metal Debug Iteration Log |
2 | 2 |
|
3 | 3 | ## Current Status |
4 | | -- Last iteration: 11 |
5 | | -- Commit: (pending) |
6 | | -- Shaders: 89/89(+5 grass), Draw calls: 19idx+11, FPS: 54.3, PSO fails: 2 (cached) |
| 4 | +- Last iteration: 12 |
| 5 | +- Commit: 1ad1171218 |
| 6 | +- Shaders: 87, Draw calls: 19idx+11, FPS: 54.6, PSO fails: 2 (cached) |
7 | 7 | - Exit: **CLEAN EXIT (code 0)**, Errors: **12** |
8 | | -- Visual: **UNITS + SKY + GRASS PIPELINE READY** — all grass infrastructure on Metal |
9 | | -- **Grass rendering fully enabled on Metal** — shaders compile, GL_QUADS→Triangles conversion, |
10 | | - GLAD extension bypass, BAR Lua override patching. Test map has no grass data (0/24576 squares). |
| 8 | +- Visual: **FULL-SCREEN TERRAIN + UNITS + SKY** — no black rectangle, no blinking |
| 9 | +- **Terrain covers entire 800x600** — previously only top-left ~25% showed ground. |
| 10 | + Root cause was Metal FBO Bind() no-op leaking Lua/MiniMap/RmlUi draws to screen. |
11 | 11 |
|
12 | 12 | ## Priority Queue |
13 | | -1. Terrain rendering diagnostic — only top-left ~25% of screen shows detailed terrain, |
14 | | - other 3/4 render units/effects but no ground. Viewport/frustum investigation needed. |
| 13 | +1. Widget off-screen textures — `gl.RenderToTexture()` stale on Metal (scissor-clipped workaround) |
15 | 14 | 2. Shadow pass verification — shadow shader variants compile, need to verify FBO + shadow map pipeline |
16 | 15 | 3. BumpWater — requires `[[clip_distance]]` across all water-affected shaders. Water=0 anyway. |
17 | 16 | 4. Last 2 PSO failures — both cached, non-crashing. Quick investigation. |
18 | 17 | 5. Info textures (Combiner) — requires FFP builtin removal from Lua info shaders. |
19 | 18 | 6. Tier 5: CI pipeline, macOS app bundle, final audit |
20 | 19 |
|
21 | | -## Confirmed Working (Post-Phase 38) |
| 20 | +## Confirmed Working (Post-Iteration 12) |
| 21 | +- **Full-screen terrain** — terrain covers entire 800x600, no black rectangle or blinking |
| 22 | +- **Units + particle effects** — commanders, infantry, battle smoke, construction sparks |
| 23 | +- **Atmospheric sky** — ModernSky gradient rendering (Sky-0/Sky-1 shaders) |
| 24 | +- **Grass pipeline** — all infrastructure ready, test map has 0 grass data |
22 | 25 | - **Clean shutdown** — Metal device destroyed, all Kill[] stages complete, exit code 0 |
23 | | -- **Game simulation** — forcestart works, gf=0→43 in 300 frames |
| 26 | +- **Game simulation** — forcestart works, gf=189 in 600 frames, ~54.6 FPS |
24 | 27 | - **SIGABRT recovery** — Metal abort() during PSO creation caught + cached via sigsetjmp |
25 | 28 | - **Vertex output padding** — PadMissingVertexOutputs adds zero-initialized dummy outputs |
26 | 29 | - **PSO failure caching** — both NSError and SIGABRT failures cached, logged once per shader |
27 | | -- **27 PSOs created OK** — up from ~8 before padding fix |
28 | 30 | - Viewport: 800x600, drawable matches, contentsScale=1.0 |
29 | 31 | - SPIRV-Cross texture remapping: GL unit → Metal [[texture(N)]] index per shader stage |
30 | 32 | - Terrain shader: SMFShaderGLSL-Forward-Adv with correct texture bindings |
31 | | -- ROAM patch visibility: 2/24 patches visible at steep camera angle — geometrically correct |
32 | | -- Drawable: 800x600 matches viewport, present works correctly |
33 | 33 | - Clear(): mid-pass clears properly handled via fullscreen quad |
34 | 34 | - Screenshots: ReadPixels with Y-flip works correctly |
35 | 35 | - Loading screen: "Loading..." text renders with fonts |
|
309 | 309 | Far billboard path enters Draw() with 59 blocks but all have empty grassMap data. |
310 | 310 | Near grass blade VBO created, DrawIndexed(Triangles) path ready. |
311 | 311 | - Next: Terrain rendering diagnostic (top-left quadrant issue), shadow pass verification. |
| 312 | + |
| 313 | +### Iteration 12 — 2026-03-01 (Black rectangle fix + full-screen terrain) ★ FULL SCREEN |
| 314 | +- Run: 20260301_181211 |
| 315 | +- Commit: 1ad1171218 |
| 316 | +- Metrics: shaders=87 draws=19idx+11 fps=54.6 pso_fails=2(cached) exit=0 gf=189 errors=12 |
| 317 | +- Visual: **TERRAIN FILLS ENTIRE 800x600 SCREEN** — no black rectangle, no alternating black |
| 318 | + frames. Units with battle smoke, particle effects, atmospheric sky all visible. |
| 319 | +- Root cause: **Metal FBO Bind() is a no-op** — three subsystems called FBO::Bind() expecting |
| 320 | + rendering to redirect to off-screen textures, but on Metal all draws went to the screen: |
| 321 | + 1. **LuaOpenGL::RenderToTexture** — Lua widgets called `gl.RenderToTexture()` which set viewport |
| 322 | + to texture size (400x300 = half screen) and drew to screen, producing the black rectangle. |
| 323 | + 2. **MiniMap::UpdateTextureCache** — `FBO::IsSupported()` returns true on Metal (line 36-37 of |
| 324 | + FBO.cpp), so `renderToTexture=true`, causing minimap to render at reduced viewport to screen. |
| 325 | + 3. **RmlUi layer compositing** — `BeginFrame`/`PushLayer`/`CompositeLayers` used FBO Bind()+Clear() |
| 326 | + which cleared the screen each frame, causing alternating black frames ("blinking"). |
| 327 | +- Failed approaches: |
| 328 | + - **Render pass break** (EndRenderPass→BeginRenderPass(FBO)→EndRenderPass→BeginDefaultRenderPass): |
| 329 | + Terrain became invisible even with LoadAction::Load for both color and depth. Draw counts normal |
| 330 | + (128+) but fragments didn't render. Root cause unclear — possibly Metal Store→Load within same |
| 331 | + command buffer doesn't preserve correctly. |
| 332 | + - **Clear FBO to transparent** (LoadAction::Clear with 0,0,0,0): Same terrain disappearance. |
| 333 | +- Fix: Three targeted workarounds (11 files, 127 insertions, 42 deletions): |
| 334 | + 1. **LuaOpenGL.cpp**: Scissor-clip RenderToTexture on Metal — set 1x1 scissor rect before Lua |
| 335 | + function execution, restore after. Lua code runs (no crash) but draws are invisible. |
| 336 | + 2. **MiniMap.cpp**: Force `renderToTexture=false` on Metal — uses direct rendering path instead |
| 337 | + of broken FBO texture cache. |
| 338 | + 3. **RmlUi_Renderer_GL3_Recoil.cpp**: Guard all FBO operations with `IsMetalBackend()` checks — |
| 339 | + BeginFrame, EndFrame, PushLayer, CompositeLayers, PopLayer all skip FBO paths on Metal. |
| 340 | + 4. **MTLContext.mm**: Support explicit depth LoadAction in BeginDefaultRenderPass (for future |
| 341 | + render pass resume support). |
| 342 | + 5. **WorldDrawer.cpp**: Viewport restore at start of Draw(), ClearColor alpha 1.0 (was 0.0). |
| 343 | + 6. **Supporting**: ModernSky CullMode::None, DepthBufferCopy Metal skip, MTLDevice opaque=YES, |
| 344 | + SMFRenderState clipPlane2 default, NetCommands sync logging. |
| 345 | +- Known limitation: Widget off-screen textures not updated on Metal (stale via scissor workaround). |
| 346 | + Widgets that depend on RenderToTexture will have empty/stale textures. Proper fix requires |
| 347 | + solving the render pass break terrain issue. |
| 348 | +- Next: Widget texture rendering, shadow pass verification. |
0 commit comments