Appendix B Renderer Registry, Capabilities, and Evidence
CNA exposes 50 public renderer identities / 46 implementation families at the pinned revision. The four-count difference is exact: five EasyGL profiles share one implementation family, while every other identity has its own family. This appendix derives the registry from docs/renderer-registry.md and the source-owned factory paths, then reports a narrow set of capabilities from reachable implementation behavior. It does not copy the older central feature matrix, whose names and cells predate the current registry.
B.1 Canonical public identities
| Cluster | Accepted CNA_GRAPHICS_RENDERER values | Count |
|---|---|---|
| OpenGL fixed function | OPENGLES1, OPENGL1, TINYGL | 3 |
| OpenGL programmable / portable | OPENGLES2, OPENGLES3, OPENGL33, WEBGL1, WEBGL2, OPENGL2, OPENGL4, PORTABLEGL | 8 |
| Native modern GPU | VULKAN, WEBGPU, SDL_GPU, METAL, IGL | 5 |
| Abstraction layers | BGFX, MAGNUM, LLGL, DILIGENT, SOKOL, WICKED, FNA3D | 7 |
| DirectX 1–3 / free-direct | DIRECTX1, DIRECTX2, DIRECTX3, FREEDIRECT | 4 |
| Retro ladder | DIRECTX5, DIRECTX6, DIRECTX7, DIRECTX8, GLIDE | 5 |
| Modern Direct3D | DIRECTX9, DIRECTX10, DIRECTX11, DIRECTX12 | 4 |
| Windows 2D | DIRECT2D, GDI | 2 |
| 2D / vector rasterizers | SDL_RENDERER, SKIA, BLEND2D, OPENVG, NANOVG | 5 |
| Web / DOM | CANVAS, HTML_DOM, SVG_DOM, PIXIJS | 4 |
| Diagnostic / non-GPU | HEADLESS, SOFTWARE, STUB | 3 |
| Total | 50 identities / 46 families | 50 |
ASCII is no longer a renderer identity; its reusable work lives in CNA::Graphics::AsciiPostProcessEffect. EASYGL, DX3, D3D9, D3D11, and D3D12 are not accepted selectors. FREEDIRECT selects the free-direct-backed family; DIRECTX3 selects the genuine DirectX 3 family. Defaults are WEBGL2 under Emscripten, OPENGLES3 on Linux, and SDL_RENDERER elsewhere.
B.2 Four implementation questions across all 46 families
The next matrix deliberately asks only four questions that can be answered uniformly from the pinned source. “Native” means the family owns both ordinary effect-aware Draw*Ex routes; it does not promise complete stock-effect fidelity. “Fallback–reject” means the shared parameter-dropping fallback reaches an explicit 3D refusal. “Hybrid” means a renderer-owned route still has a bounded coloured fallback. “Conditional” names a real profile/device/extension dependency. “Claims yes” exposes a public capability answer that contradicts the reachable factory or operation.
| Family | Public identity / identities | Effect-aware draw | RT2D | MRT | Occlusion query |
|---|---|---|---|---|---|
| bgfx | BGFX | native | yes | yes | conditional |
| blend2d | BLEND2D | fallback–reject | yes | no | no |
| canvas | CANVAS | fallback–reject | yes | no | no |
| diligent | DILIGENT | native | yes | yes | conditional |
| direct2d | DIRECT2D | fallback–reject | yes | no | no |
| directx1 | DIRECTX1 | fallback–reject | yes | no | no |
| directx2 | DIRECTX2 | native fixed | yes | no | no |
| directx3 | DIRECTX3 | native fixed | yes | no | no |
| directx5 | DIRECTX5 | native fixed | yes | no | no |
| directx6 | DIRECTX6 | native fixed | yes | no | no |
| directx7 | DIRECTX7 | native fixed | yes | no | no |
| directx8 | DIRECTX8 | native fixed | yes | no | no |
| directx9 | DIRECTX9 | native | yes | yes | yes |
| directx10 | DIRECTX10 | fallback–coloured | yes | yes | no |
| directx11 | DIRECTX11 | native | yes | yes | yes |
| directx12 | DIRECTX12 | native | yes | yes | yes |
| easygl | OPENGLES2, OPENGLES3, OPENGL33, WEBGL1, WEBGL2 | native | yes | profile | profile |
| fna3d | FNA3D | native | yes | yes | yes |
| freedirect | FREEDIRECT | fallback–reject | yes | no | no |
| gdi | GDI | reject | yes | no | no |
| glide | GLIDE | native fixed | throws | no | no |
| headless | HEADLESS | trace | trace | trace | trace; not a GPU query |
| html-dom | HTML_DOM | fallback–reject | yes | no | no |
| igl | IGL | native | yes | yes | no |
| llgl | LLGL | native | yes | yes | yes |
| magnum | MAGNUM | native | yes | conditional | yes |
| metal | METAL | native | yes | no | no |
| nanovg | NANOVG | fallback–reject | no | no | no |
| opengl1 | OPENGL1 | native fixed | conditional | no | conditional |
| opengl2 | OPENGL2 | native | yes | conditional | conditional |
| opengl4 | OPENGL4 | hybrid | yes | yes | yes |
| opengles1 | OPENGLES1 | hybrid fixed | yes | no | no |
| openvg | OPENVG | fallback–reject | no | no | no |
| pixijs | PIXIJS | fallback–reject | yes | no | no |
| portablegl | PORTABLEGL | native CPU | no | no | no |
| sdl-gpu | SDL_GPU | hybrid | yes | yes | no; claims yes |
| sdl-renderer | SDL_RENDERER | fallback–reject | yes | no | no |
| skia | SKIA | reject | yes | no | no |
| software | SOFTWARE | native CPU | yes | no | no; claims yes |
| sokol | SOKOL | native | yes | yes | GL build only |
| stub | STUB | fallback–no-op | no | no | no |
| svg-dom | SVG_DOM | fallback–reject | yes | no | no |
| tinygl | TINYGL | native CPU fixed | no | no | no |
| vulkan | VULKAN | native | yes | yes | yes |
| webgpu | WEBGPU | hybrid | yes | no; claims yes | no; claims yes |
| wicked | WICKED | native | yes | yes | yes |
The table is a routing audit, not runtime certification. It is mechanically checked to contain 46 families; EasyGL contributes the remaining four public identities. New alpha.1 families IGL, NanoVG, PixiJS, and TinyGL are explicit rows rather than being inferred from their native libraries. Inherited refusal, deliberate no-op, CPU fixed-function, trace-only and hybrid colored-tail routes remain different outcomes even when the public method exists.
B.3 Capability answers require operation-level proof
GraphicsDevice::SupportsCapability is a useful preflight query, but its shared default is permissive. At the pin, WEBGPU reports MRT while rejecting every multi-target set. SDL_GPU, WEBGPU, and SOFTWARE report occlusion-query support while inheriting a null factory; HEADLESS returns a bookkeeping object with a constant pseudo-count rather than a real GPU query. These are tracked defects, not support.
Conversely, a false or absent high-level bit can hide a narrower usable path. Profile-gated GL queries, driver-gated wrapper capabilities, fixed-function rendering, CPU rasterization, and trace validation all need their own labels. The safe decision sequence is:
-
1.
filter by platform/dependency admissibility and the exact public selector;
-
2.
inspect the factory/resource operation and the draw route for the required feature;
-
3.
require renderer-owned tests or a retained host artifact at the needed evidence tier;
-
4.
use a second structurally independent family as a localization control;
-
5.
retain skips, refusals, and capability/reporting contradictions in the result.
Appendix G defines the evidence vocabulary. The renderer chapters own the narrower state, shader, texture, readback, and platform qualifications that cannot fit in this compact matrix.