From 9ee42d408a2d51150091481cbe1527638901f80d Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 27 May 2026 16:10:52 +0200 Subject: [PATCH] =?UTF-8?q?fix(render):=20Phase=20A8=20=E2=80=94=20invalid?= =?UTF-8?q?ate=20GL=20state=20caches=20at=20Render=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User report from second visual gate (Step 5 disabled, ColorMask fixed): "Cant see anything, flickering colors, sometimes I see textures and sometimes I see inside, the house is missing lots of walls. 10 FPS." Root cause: EnvCellRenderer._currentVao and _currentCullMode are STATIC caches that let SetCullMode / BindVertexArray skip redundant GL state changes when "already" in the right state. But other consumers (WbDrawDispatcher, terrain renderer, the Step 1+2 stencil pipeline) change the actual GL state without updating these caches. The cache lies, the per-batch SetCullMode in RenderModernMDIInternal skips its glCullFace call, and the cottage's mixed-cull-mode batches end up rendering with whatever stale cull state was leaked from the prior consumer. Walls with backface-only geometry vanish. The flicker is the state alternating depending on which Render call set the cache this frame. WB invalidates these caches at line 404-410 of EnvCellRenderManager.cs: CurrentVAO = 0; CurrentIBO = 0; CurrentAtlas = 0; CurrentInstanceBuffer = 0; CurrentCullMode = null; Our port missed this. Adding _currentVao = 0; _currentCullMode = null; at Render entry forces each Render call to re-establish the GL state it expects. (We only track Vao + CullMode in our minimal port; IBO/ Atlas/InstanceBuffer aren't cached in our class.) Build green. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Rendering/Wb/EnvCellRenderer.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs b/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs index cf713c0..4820f51 100644 --- a/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs +++ b/src/AcDream.App/Rendering/Wb/EnvCellRenderer.cs @@ -613,6 +613,26 @@ public sealed unsafe class EnvCellRenderer : IDisposable _shader.Use(); _poolIndex = snapshot.BatchedByCell.Count; // reset point (mirrors WB line 405) + // FIX 2026-05-28: invalidate static GL-state caches at start of Render. + // Mirrors WB EnvCellRenderManager.cs:404-410: + // CurrentVAO = 0; CurrentIBO = 0; CurrentAtlas = 0; + // CurrentInstanceBuffer = 0; CurrentCullMode = null; + // + // These caches let SetCullMode / BindVertexArray skip redundant GL + // calls when the state is already correct. BUT: between two Render() + // invocations, OTHER consumers (WbDrawDispatcher, terrain, the + // RenderInsideOutAcdream stencil pipeline) change the actual GL + // state without updating these caches. The cache then lies, and + // the per-batch SetCullMode in RenderModernMDIInternal skips its + // glCullFace call — leaving stale cull state from the prior + // consumer. For a cottage with mixed CullMode batches, half the + // walls end up culled and the user sees "missing walls". + // + // Forcing the cache to null/0 at entry guarantees each Render call + // re-establishes the GL state it expects. + _currentVao = 0; + _currentCullMode = null; + // WB EnvCellRenderManager.cs:406-409: uniform state setup. _shader.SetInt("uRenderPass", (int)renderPass); _shader.SetInt("uFilterByCell", 0);