CNA-BUG-255: EasyGL family: ClearColorAndStencil leaves the stencil write mask forced to all ones, so a later draw ignores StencilWriteMask
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
GraphicsDevice::Clear with Target and Stencil reaches EasyGLRenderer::ClearColorAndStencil, which forces the GL stencil mask open and never restores it, unlike the other EasyGL clears (REMED-GFX-237). A later StencilWriteMask-limited draw is not limited.
- Identifier
CNA-BUG-255- Category
- Bug
- Subsystem
- Graphics & renderers
- Status
- Narrowed (partially fixed; describes only what survives)
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- GraphicsDevice::Clear(ClearOptions::Target | ClearOptions::Stencil, ...) on the EasyGL renderer family (EasyGLRenderer::ClearColorAndStencil)
Expected behaviour
XNA's Clear ignores StencilWriteMask but does not change the device's DepthStencilState, so a draw after the clear obeys the state the game assigned. EasyGL's own rule (REMED-GFX-237, stated in EasyGLRenderer.hpp and in OpenGL4Renderer.cpp) is that every clear puts back the write masks it forced open, because a game need not reassign its DepthStencilState before the next draw.
Actual behaviour at TARGET
EasyGLRenderer::ClearColorAndDepth, ClearDepth, ClearStencil, ClearDepthAndStencil and ClearColorDepthAndStencil all call RestoreWriteMasksAfterClear. ClearColorAndStencil sets the stencil mask to all ones, clears, and restores only the colour mask and the scissor. After GraphicsDevice::Clear(ClearOptions::Target | ClearOptions::Stencil, ...) the GL stencil write mask stays 0xFFFFFFFF until ApplyDepthStencilState runs again, so a later draw can write stencil bits its StencilWriteMask forbids until the depth/stencil state is applied again. OpenGL4Renderer::ClearColorAndStencil carries a comment that EasyGL's twin of this route does not put the mask back. The restore check in easygl_graphicsdevice_clear_stencil_test.cpp (Check D) uses ClearOptions::Stencil only.
Source locations
modules/renderers/easygl/src/EasyGLRenderer.cpp— ClearColorAndStencil has no RestoreWriteMasksAfterClear; ClearStencil and ClearColorDepthAndStencil domodules/renderers/easygl/include/CNA/Internal/Renderers/EasyGL/EasyGLRenderer.hpp— REMED-GFX-237 rule and RestoreWriteMasksAfterClearmodules/renderers/opengl4/src/OpenGL4Renderer.cpp— ClearColorAndStencil comment naming EasyGL's twin routemodules/renderers/easygl/examples/easygl_graphicsdevice_clear_stencil_test.cpp— Check D covers the ClearOptions::Stencil route onlymodules/graphics/src/Xna/GraphicsDevice.cpp— Clear dispatches Target plus Stencil to ClearColorAndStencil
Evidence
Read at 009d40f5; nothing executed. The routine serves all five EasyGL-family identities (OPENGLES2, OPENGLES3, OPENGL33, WEBGL1, WEBGL2). Scope is narrow: it needs an explicit Target plus Stencil clear and a later draw that relies on a limited StencilWriteMask without reassigning its DepthStencilState. Stencil-clear tests exist for the other routes, none for this one.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
easygl_graphicsdevice_clear_stencil_test.cpp (Check D) verifies that the stencil write mask is restored after a clear, but only for ClearOptions::Stencil; no test clears colour and stencil together and then draws through a state with a restricted StencilWriteMask.
Regression test
Extend that check to ClearOptions::Target | ClearOptions::Stencil: clear, then draw through a DepthStencilState with StencilWriteMask 0 and expect the stencil buffer unchanged. The fix is to end ClearColorAndStencil with RestoreWriteMasksAfterClear(false, true) like its siblings.
Blast radius
EasyGL-family renderers only (OPENGLES2/3, OPENGL33, WEBGL1/2 and the other EasyGL identities); games that clear colour and stencil in one call and then rely on StencilWriteMask. OpenGL4 restores its masks on the same route.
Workaround
Clear colour and stencil with two calls (ClearOptions::Target, then ClearOptions::Stencil), or re-apply the depth/stencil state after the combined clear.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Graphics state: DepthStencilState
- Internals
- EasyGL renderer internals
- Deep dives
- EasyGL state and resource semantics
- Known issues
- Bug index