Skip to content

Fix GL calls WebGL rejects (black lit surfaces) + probe for the freeze - #24

Merged
matthewcodergamer merged 3 commits into
masterfrom
render360/iphone-baseline-lowmem
Oct 14, 2026
Merged

matthewcodergamer merged 3 commits into
masterfrom
render360/iphone-baseline-lowmem

Conversation

@matthewcodergamer

@matthewcodergamer matthewcodergamer commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Black lit surfaces

The GL probe named the calls WebGL rejects in game:

  • texImage2D(GL_RGB8, …, GL_RGBA) → INVALID_OPERATION. D3DFMT_X8R8G8B8 is 4-byte BGRX data stored in a 3-channel GL_RGB8 texture. GLES 3 / WebGL 2 don't allow that pairing, so every such texture had no image and sampled black. That covers normal maps and the engine's 1×1 white/grey/black fallback textures.
    • On web, X8R8G8B8 is now reported unsupported, so the material system converts those images to R8G8B8 when it loads them.
    • convert_texture also promotes RGB8 to RGBA8 whenever 4-channel data arrives, so no texture is left without an image.
  • GL_TEXTURE_BORDER_COLOR, the GL_CLAMP_TO_BORDER wrap mode and GL_FRAMEBUFFER_SRGB → INVALID_ENUM every frame. WebGL has none of these. On web the border colour is skipped, wrapping clamps to edge instead, and the sRGB write stays in the shader (the web build already does this).

Probe for the freeze

Frames stopped about 12 s into the first chamber. The probe now logs:

  • frames slower than 1.5 s, with their draws, uploads and GPU buffer read-backs
  • GPU buffer read-backs, also counted in the heartbeat
  • the framebuffer status on INVALID_FRAMEBUFFER_OPERATION errors
  • (from the page) when the render thread stops presenting frames, and when it resumes

The first commit added the original probe: an error hunt, texture-upload samples and the heartbeat.

Checks

  • em++ -fsyntax-only (Emscripten 4.0.9) passes on cglmtex.cpp, dxabstract.cpp and glmgr.cpp.
  • node --check emscripten/pre.js passes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qy5DKdwTqGQqScWvJyNcft


Generated by Claude Code

The probe showed the in-game trails are gone (frames are cleared), but a
GL error (0x500, INVALID_ENUM) every frame, lit world surfaces rendering
black, and a freeze after the first chamber loads. Extend it so the next
diagnostics pin all three down:

- Error hunt: for three short windows (frames 6-8, 200-203, 450-453)
  every WebGL call is followed by glGetError and the rejected calls are
  logged with their arguments. The wrappers are installed only for the
  window and removed after, so normal frames pay nothing.
- Texture uploads: the first texSubImage2D/texImage2D calls are logged
  with size, format, UNPACK_ROW_LENGTH and a sample of their bytes (mean,
  share of non-zero), to see whether lightmap data reaches WebGL.
- Heartbeat: an "alive" line with frame count and fps about every 10 s,
  so a freeze shows as the moment the lines stop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qy5DKdwTqGQqScWvJyNcft
…robe

The GL probe named the calls WebGL rejects in game:

- texImage2D(GL_RGB8 internal format, GL_RGBA data) -> INVALID_OPERATION.
  D3DFMT_X8R8G8B8 is 4-byte BGRX data kept in a 3-channel GL_RGB8 texture,
  a pairing GLES 3 / WebGL 2 do not allow, so every such texture (normal
  maps, the engine's 1x1 white/grey/black fallback textures) had no image
  and sampled black. On web X8R8G8B8 is reported unsupported, so the
  material system converts those images to R8G8B8 when it loads them;
  convert_texture also promotes RGB8 to RGBA8 whenever 4-channel data
  arrives, so no texture is left without an image.
- texParameter(GL_TEXTURE_BORDER_COLOR), the GL_CLAMP_TO_BORDER wrap mode
  and enable/disable(GL_FRAMEBUFFER_SRGB) -> INVALID_ENUM every frame.
  WebGL has none of them: skip the border colour, clamp to edge instead,
  and leave the sRGB write to the shader (as the web build already does).

Freeze: frames stopped about 12 s into the first chamber. The probe now
logs frames slower than 1.5 s with their draws, uploads and GPU buffer
read-backs, counts read-backs in the heartbeat, adds the framebuffer
status to INVALID_FRAMEBUFFER_OPERATION errors, and the page logs when
the render thread stops presenting frames and when it resumes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qy5DKdwTqGQqScWvJyNcft
@matthewcodergamer matthewcodergamer changed the title GL probe: name the failing GL call, check lightmap data, heartbeat for freezes Fix GL calls WebGL rejects (black lit surfaces) + probe for the freeze Oct 10, 2026
…ndows

The probe showed clears and draws failing with framebuffer status 0x8CD9
(FRAMEBUFFER_INCOMPLETE_DIMENSIONS): WebGL 2 still requires every
attachment of a framebuffer to have the same size, while Source renders
into smaller targets (1024x512, 292x135, ...) with the full-screen
1168x540 depth buffer bound, as D3D9 allows. Everything drawn into those
framebuffers was lost. On web such a framebuffer now gets a private depth
buffer of the colour target's size (created once per size); those passes
only touch the top-left of the big depth buffer and clear depth anyway.

The menu also ran at 6-12 s per frame in the last run. Add profile windows
(frames 11-13, 60-63, 240-243, or up to a slow frame) that count WebGL
calls by name and time spent inside them versus the whole frame, so the
next diagnostics show whether the time goes to WebGL or to the engine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qy5DKdwTqGQqScWvJyNcft
@matthewcodergamer
matthewcodergamer merged commit 97f8f77 into master Oct 14, 2026
2 checks passed

This branch was successfully deployed

1 active deployment
portal-iphone-staging — a1c21181 Deployed Oct 14, 2026 by matthewcodergamer via Deploy iPhone staging page #334
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants