CNA-BUG-249: misc/CNAEXT.md's 'Renderer shader coverage for PBR' table omits OPENGL4 and METAL and still says WebGPU has no SkinnedPbrEffect path
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.
The table lists six rows covering seven renderers (EasyGL, Vulkan, SdlGpu, WebGPU, D3D11, D3D9/D3D12) plus a fallback row, but OPENGL4 and METAL implement both PBR effects, WebGPU implements skinned PBR, and FNA3D and PORTABLEGL refuse PBR draws by name; the table shows none of this.
- Identifier
CNA-BUG-249- Category
- Bug
- Subsystem
- Documentation & release tooling
- Status
- Open
- 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
- misc/CNAEXT.md section 3.1, 'Renderer shader coverage for PBR' (PbrEffect / SkinnedPbrEffect per renderer)
Expected behaviour
The table states, for the current renderer set, which renderers draw PbrEffect and SkinnedPbrEffect, which fall back and which refuse.
Actual behaviour at TARGET
CNAEXT.md lists EasyGL, Vulkan, SdlGpu, WebGPU ('unskinned', 'no skinning path yet'), D3D11, D3D9/D3D12 and a fallback row naming SDL_Renderer, Software, Canvas, FreeDirect and Headless. At TARGET: OPENGL4 builds StockProgramShape::Pbr and StockProgramShape::PbrSkinned stock programs (OpenGL4StockDraw.cpp); METAL carries PbrEffect and SkinnedPbrEffect shader paths (METAL-81, METAL-82 in MetalRenderer.mm); WebGPU creates and draws skinned PBR (CreateSkinnedPbrResources, DrawFamily::SkinnedPbr, IssueSkinnedPbrDraw in WebGPURenderer.cpp), so the 'no skinning path yet' cell is stale; FNA3D refuses a PBR draw through RequirePbrShadingSupportEXT (Fna3dDraw.cpp) and PORTABLEGL refuses PbrEffect by name (PortableGLRenderer.cpp), a third behaviour, refusal rather than fallback, that appears nowhere in the table. The table was last edited in the 2026-09-17 renderer-set pass, which removed the row of a retired renderer, so it is maintained as current support rather than a dated snapshot. FUTURE.md says 15 of 17 PBR renderers apply COLOR_0 and the other 2 refuse such a draw by name, far more renderers than the table shows.
Source locations
misc/CNAEXT.md— Renderer shader coverage for PBR tablemodules/renderers/opengl4/src/OpenGL4StockDraw.cpp— StockProgramShape::Pbr and PbrSkinnedmodules/renderers/metal/src/MetalRenderer.mm— PbrEffect (METAL-81) and SkinnedPbrEffect (METAL-82) layouts and shadersmodules/renderers/webgpu/src/WebGPURenderer.cpp— CreateSkinnedPbrResources, IssueSkinnedPbrDraw, DrawFamily::SkinnedPbrmodules/renderers/webgpu/src/WebGPURendererModern.cpp— DrawFamily::SkinnedPbr indirect commandsmodules/renderers/fna3d/src/Fna3dDraw.cpp— Fna3dRenderer::DrawPrimitivesEx refuses PBR via RequirePbrShadingSupportEXTmodules/renderers/portablegl/src/PortableGLRenderer.cpp— refuse(PbrEffect)misc/FUTURE.md— Phase 5 row: 15 of 17 PBR renderers apply COLOR_0
Evidence
Checked by reading at 009d40f5; not executed. The per-renderer statements rest on the named symbols; whether each route produces correct PBR pixels is a separate, per-renderer evidence question that this entry does not decide, and the table's “Verification” column was not re-checked. The document last changed in 1321ca346 and is identical at TARGET.
Independent re-verification: Checked by reading at 009d40f5; not executed. The per-renderer statements rest on the named symbols; whether each route produces correct PBR pixels is a separate, per-renderer evidence question that this entry does not decide, and the table's Verification column was not re-checked. The 2026-09-17 renderer-set pass edited this very table (it removed the row of a retired renderer) and left the WebGPU cell and the missing rows as they are. Tests exist for the WebGPU, OpenGL4 and Metal PBR paths (WebGPU_SkinnedPbr3D, OpenGL4_PbrEffect, the Metal policy suites), but nothing checks the table.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
Nothing checks the table against the renderer tree; the document's own glTF section already follows the rule “derive the table from the tree” for import capabilities.
Regression test
Regenerate the table from the renderer registry (all 25 identities, with implemented / reduced / refused per effect), or replace it with a pointer to a generated capability table.
Blast radius
Readers choosing a renderer for PBR content from CNA's extension document: OPENGL4 and METAL look unsupported, WebGPU looks unable to skin, and FNA3D/PORTABLEGL look like silent fallbacks. No runtime behaviour is affected.
Workaround
Use the per-identity coverage table in the PBR materials tutorial.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Backends: OpenGL4 and EasyGL
- Deep dives
- Effect object model
- Known issues
- Bug index