Repository navigation
Expand file tree
/
Copy patharchitecture.html
More file actions
594 lines (539 loc) · 57.1 KB
/
Copy patharchitecture.html
File metadata and controls
594 lines (539 loc) · 57.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Architecture - CNA</title>
<meta name="description" content="CNA snapshot c1c316b9 architecture: XNA-compatible APIs over independent target-OS, platform, renderer and audio axes, a 23-module layout, 14 renderer identities in 12 families behind a descriptor registry with latched runtime selection, and a build-time content pipeline kept outside the runtime link closure.">
<meta property="og:type" content="website">
<meta property="og:site_name" content="CNA">
<meta property="og:url" content="https://libcna.com/architecture.html">
<meta property="og:title" content="Architecture - CNA">
<meta property="og:description" content="CNA snapshot c1c316b9 architecture: XNA-compatible APIs over independent target-OS, platform, renderer and audio axes, a 23-module layout, 14 renderer identities in 12 families behind a descriptor registry with latched runtime selection, and a build-time content pipeline kept outside the runtime link closure.">
<link rel="stylesheet" href="css/style.css">
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="canonical" href="https://libcna.com/architecture.html">
<link rel="stylesheet" href="css/prism-tomorrow.min.css">
<script>(function(){try{var t=localStorage.getItem("cna-theme");if(t==="light"||t==="dark")document.documentElement.setAttribute("data-theme",t);}catch(e){}})();</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Architecture - CNA",
"url": "https://libcna.com/architecture.html",
"description": "CNA snapshot c1c316b9 architecture: XNA-compatible APIs over independent target-OS, platform, renderer and audio axes, a 23-module layout, 14 renderer identities in 12 families behind a descriptor registry with latched runtime selection, and a build-time content pipeline kept outside the runtime link closure.",
"dateModified": "2026-10-09"
}
</script>
</head>
<body>
<a class="skip-link" href="#main-content">Skip to content</a>
<nav class="nav">
<div class="nav-container">
<a href="index.html" class="nav-brand">CNA</a>
<button class="nav-toggle" aria-label="Toggle navigation" aria-expanded="false">
<span></span><span></span><span></span>
</button>
<div class="nav-menu">
<a href="index.html" class="nav-link">Home</a>
<a href="about.html" class="nav-link">About</a>
<a href="features.html" class="nav-link">Features</a>
<a href="architecture.html" class="nav-link">Architecture</a>
<a href="documentation.html" class="nav-link">Documentation</a>
<a href="development/index.html" class="nav-link">Development</a>
<a href="deep-dives/index.html" class="nav-link">Deep Dives</a>
<a href="tutorials.html" class="nav-link">Tutorials</a>
<a href="demos.html" class="nav-link">Demos</a>
<a href="showcase.html" class="nav-link">Showcase</a>
<a href="videos.html" class="nav-link">Videos</a>
<a href="roadmap.html" class="nav-link">Roadmap</a>
<a href="contact.html" class="nav-link">Contact</a>
<a href="network.html" class="nav-link">Network</a>
<a href="search.html" class="nav-link">Search</a>
<a href="https://github.com/libcna/cna" class="nav-link nav-link--github" target="_blank" rel="noopener">GitHub</a><a href="https://blog.libcna.com/" class="nav-link nav-link--blog" target="_blank" rel="noopener">Blog</a>
<a href="https://www.youtube.com/@libcna" class="nav-link nav-link--youtube" target="_blank" rel="noopener">YouTube</a>
<a href="https://discord.gg/vrnc4n6DaE" class="nav-link nav-link--discord" target="_blank" rel="noopener">Discord</a>
</div>
<button class="theme-toggle" type="button" aria-label="Switch to light theme" title="Switch to light theme">
<svg class="theme-icon-light" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 17a5 5 0 1 1 0-10 5 5 0 0 1 0 10zm0-2a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.5 4.9l1.4-1.4 2.1 2.1-1.4 1.4L3.5 4.9zm13.5 13.5l1.4-1.4 2.1 2.1-1.4 1.4-2.1-2.1zM19.1 3.5l1.4 1.4-2.1 2.1-1.4-1.4 2.1-2.1zM5.6 17l1.4 1.4-2.1 2.1-1.4-1.4L5.6 17zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></svg>
<svg class="theme-icon-dark" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12.3 22a10 10 0 0 1-1.6-19.9c.6-.1 1 .5.8 1a7.9 7.9 0 0 0 9.7 10.6c.5-.2 1 .3.9.8A10 10 0 0 1 12.3 22z"/></svg>
</button>
</div>
</nav>
<main id="main-content">
<div class="page-header">
<div class="container">
<span class="section-label">Architecture</span>
<h1>How CNA is structured</h1>
<p>CNA is organised into four clear, strictly separated layers - from high-level game code down to hardware-specific renderers - over four independent build axes: target OS, platform, renderer and audio.</p>
</div>
</div>
<section class="section">
<div class="container">
<!-- ASCII diagram -->
<span class="section-label">Overview Diagram</span>
<h2 id="layer-overview">Layer overview</h2>
<div class="arch-diagram">
<pre>
┌─────────────────────────────────────────────────────────────────┐
│ Game / Application Code │
│ Uses: Microsoft::Xna::Framework API │
│ Example: MyGame extends Game, calls SpriteBatch::Draw() │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ XNA-Compatible Public API Layer │
│ modules/*/include/Microsoft/Xna/Framework/... │
│ Game · GraphicsDevice · SpriteBatch · Texture2D · Color │
│ Vector2/3/4 · Matrix · Input · Audio · Media · Content · Net │
│ Opt-in: CNAEXT extensions · Design · Phone · C ABI │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ CNA Internal Abstraction Layer (sharp-runtime support) │
│ modules/graphics/include/CNA/Internal/Renderers/Common/ │
│ IGraphicsRenderer · ISpriteBatchRenderer · ITextureRenderer │
│ Descriptors · Registry · GraphicsRendererSelection (core) │
└─────────┬──────────────────────┬──────────────────────┬─────────┘
│ │ │
▼ ▼ ▼
┌───────────────────┐ ┌─────────────────────┐ ┌───────────────────┐
│ EasyGL family (3) │ │ Native GPU APIs (7) │ │ 2D/CPU/none (4) │
│ OPENGLES3 │ │ VULKAN · SDL_GPU │ │ SDL_RENDERER │
│ OPENGL33 │ │ DIRECTX9 · 11 │ │ SOFTWARE │
│ WEBGL2 │ │ METAL · WEBGPU │ │ HEADLESS · STUB │
│ │ │ FNA3D │ │ │
└─────────┬─────────┘ └──────────┬──────────┘ └─────────┬─────────┘
│ │ │
└──────────────────────┴──────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Independent host and audio services (build axes) │
│ CNA_PLATFORM: SDL3 · HEADLESS · TERMINAL │
│ (SDL3 reaches Windows, X11, Wayland, macOS, iOS, │
│ Android and the web through its video drivers) │
│ CNA_AUDIO_PLATFORM: SDL3 · NULL · ALSA │
│ CNA_ENABLE_SDL: AUTO | ON | OFF (OFF = windowless, no SDL) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Build-time and optional pieces │
│ cna-content · content-pipeline · CNB / XNB writers │
│ Opt-in: Inspector · C ABI (libcna_c_api) · Design │
│ Diagnostics is compiled out when CNA_DIAGNOSTICS=OFF │
└─────────────────────────────────────────────────────────────────┘
</pre>
</div>
<p style="margin-top:1rem;">Every renderer family publishes a descriptor and namespaced factory into a generated runtime registry. A normal build emits one entry; <code>CNA_GRAPHICS_RENDERER</code> picks the default and <code>CNA_GRAPHICS_RENDERERS</code> can emit a compatible set. This snapshot exposes <strong>14 public identities over 12 implementation families</strong>: three GL profiles (<code>OPENGLES3</code>, <code>OPENGL33</code>, <code>WEBGL2</code>) share the single EasyGL family. The host and audio services below the renderers are independent build axes, not part of any renderer. See the <a href="docs/rendering-backends.html">renderer reference</a>, and the <a href="docs/releases.html">release notes</a> for what changed since alpha.1.</p>
<!-- Visual diagram -->
<span class="section-label">Visual Diagram</span>
<h2 id="diagram">Detailed architecture diagram</h2>
<div style="background:#ffffff; border-radius:var(--radius-lg); padding:1.5rem; margin-top:1.5rem; overflow-x:auto;">
<img src="mermaid-diagram.png" alt="CNA architecture at snapshot c1c316b9: the runtime flow, the XNA-shaped Framework API, renderer selection and the IGraphicsRenderer interface, the 14 renderer identities in three groups, the platform and audio implementations chosen independently, and the target operating systems. A text alternative follows." style="max-width:100%; height:auto; display:block; margin:0 auto;">
</div>
<div class="callout callout--info" style="margin-top:1.5rem;">
<span class="callout-icon">📌</span>
<p><strong>Regenerated for this snapshot.</strong> The diagram earlier on this page was drawn for an early development stage and no longer matched the code, so it has been redrawn: it now shows the 14 renderer identities in three groups, the independent platform (<code>CNA_PLATFORM</code>) and audio (<code>CNA_AUDIO_PLATFORM</code>) selections, the sprite draw flow and the build-time selection options. It is generated by <code>scripts/make_architecture_diagram.py</code>; an <a href="img/architecture-diagram.svg">SVG version</a> scales without loss.</p>
</div>
<h3 style="margin-top:1.5rem;">Text alternative to the diagram</h3>
<ul>
<li><strong>Runtime flow:</strong> <code>main</code> → <code>Game::Run</code> → <code>Initialize</code> → <code>LoadContent</code> → the <code>Update</code>/<code>Draw</code> loop → <code>Present</code> (in <code>Game::EndDraw</code>).</li>
<li><strong>Sprite draw flow:</strong> <code>SpriteBatch::Begin</code> → <code>Draw</code> → <code>End</code> → <code>GraphicsDevice</code> → the selected <code>IGraphicsRenderer</code> → a GPU API, the CPU or the browser.</li>
<li><strong>Build-time choice:</strong> <code>CNA_GRAPHICS_RENDERER</code> decides which family (or, with <code>CNA_GRAPHICS_RENDERERS</code>, which set of families) is compiled; <code>GraphicsRendererSelection</code> decides among the compiled families at run time.</li>
<li><strong>Services:</strong> the renderer obtains its window, GL context, Vulkan surface or native handle from the selected <code>CNA_PLATFORM</code> implementation; audio comes from <code>CNA_AUDIO_PLATFORM</code>; siblings (<code>sharp-runtime</code>, plus <code>easy-gl</code>/<code>meta-gl</code> for the GL renderers) sit beside the CNA tree.</li>
</ul>
<!-- Build axes -->
<span class="section-label" style="margin-top:3rem; display:block;">Build Axes</span>
<h2 id="build-axes">The four build axes</h2>
<p>CNA keeps four concerns apart, plus one switch. They are selected independently, with a small set of hard exclusions that fail at configure time with a named reason and never fall back silently.</p>
<div class="table-wrap">
<table>
<thead>
<tr><th scope="col">Axis</th><th scope="col">Question it answers</th><th scope="col">Selected by</th><th scope="col">Values at this snapshot</th></tr>
</thead>
<tbody>
<tr><td>1. Target operating system</td><td>Which ABI and toolchain is the binary for?</td><td>The CMake toolchain and host; reported at run time by <code>CNA::TargetPlatform</code> (<code>Desktop</code>, <code>Android</code>, <code>iOS</code>, <code>Web</code>)</td><td>Linux, Windows (MSVC or MinGW-w64), macOS, iOS, Android, Emscripten</td></tr>
<tr><td>2. Platform implementation</td><td>Who owns windows, events, input, timing and host services?</td><td><code>CNA_PLATFORM</code> (default <code>SDL3</code>)</td><td><code>SDL3</code>, <code>HEADLESS</code>, <code>TERMINAL</code>; <code>SDL12</code> and <code>EMSCRIPTEN</code> are reserved and refused</td></tr>
<tr><td>3. Graphics renderer</td><td>Who turns draw calls into pixels?</td><td><code>CNA_GRAPHICS_RENDERER</code> (per-host default) and optionally <code>CNA_GRAPHICS_RENDERERS</code></td><td>14 public identities in 12 families</td></tr>
<tr><td>4. Audio implementation</td><td>Who opens playback and capture, and for two values mixes?</td><td><code>CNA_AUDIO_PLATFORM</code> (default <code>SDL3</code>)</td><td><code>SDL3</code>, <code>NULL</code>, <code>ALSA</code>; <code>OPENAL</code> and <code>WASAPI</code> are reserved and refused</td></tr>
<tr><td>Switch: SDL availability</td><td>Is SDL configured at all?</td><td><code>CNA_ENABLE_SDL</code> = <code>AUTO</code> (default), <code>ON</code>, <code>OFF</code></td><td><code>OFF</code> refuses every selection that needs SDL: the SDL3 platform, SDL3 audio and the <code>SDL_RENDERER</code>, <code>SDL_GPU</code> and <code>FNA3D</code> renderers</td></tr>
</tbody>
</table>
</div>
<p style="margin-top:1rem;"><strong>Hard exclusions:</strong> <code>TERMINAL</code> accepts only the CPU renderers <code>SOFTWARE</code>, <code>HEADLESS</code> and <code>STUB</code>; <code>TERMINAL</code> is non-Windows-only (reserved and refused on Windows); <code>ALSA</code> is Linux-only. The platform and audio defaults are <code>SDL3</code> on every OS; only the renderer default varies (Emscripten <code>WEBGL2</code>, Linux <code>OPENGLES3</code>, everything else <code>SDL_RENDERER</code>). See <a href="docs/platforms.html">Platform Support</a> and <a href="docs/native-platforms.html">Native platforms</a>.</p>
<!-- Layer descriptions -->
<span class="section-label" style="margin-top:3rem; display:block;">Layers</span>
<h2 id="layers">Layer descriptions</h2>
<div class="arch-layer arch-layer--app">
<div class="arch-layer-label">Layer 1 - Highest</div>
<h4>Game / Application Code</h4>
<p>Your game logic. Subclasses <code>Game</code>, overrides <code>LoadContent()</code>, <code>Update()</code>, <code>Draw()</code>. Calls XNA-style APIs exclusively. Has zero knowledge of which renderer is in use - this is the contract CNA enforces. Games written against this layer are portable across renderers; the renderer-dependent parts (capabilities, the default <code>Reach</code> graphics profile) are queried through the public API rather than by renderer name.</p>
</div>
<div class="arch-layer arch-layer--api">
<div class="arch-layer-label">Layer 2 - Public API</div>
<h4>XNA-Compatible API Layer</h4>
<p>Lives under each module's <code>include/Microsoft/Xna/Framework/</code> tree. This is the surface that game code touches. Class names, namespaces, and method signatures mirror the original XNA 4.0 API as faithfully as practical in C++. No renderer-specific code leaks into this layer. Includes: <code>Game</code>, <code>GraphicsDevice</code>, <code>GraphicsDeviceManager</code>, <code>SpriteBatch</code>, <code>Texture2D</code>, <code>Color</code>, all math types, input surfaces, <code>GameTime</code>, <code>GameComponent</code>, etc. Beside it sit the opt-in extensions: the <code>CNA::Graphics</code> extensions (<code>CNA_CNAEXT</code>), <code>CNA::Design</code> converters, <code>Microsoft::Phone</code> and the C ABI adapter.</p>
</div>
<div class="arch-layer arch-layer--internal">
<div class="arch-layer-label">Layer 3 - Internal Abstractions</div>
<h4>CNA Internal Layer & sharp-runtime Support</h4>
<p>Lives under <code>modules/graphics/include/CNA/Internal/Renderers/Common/</code>, in the <code>CNA::Internal::Renderers</code> namespace. It defines the renderer interfaces (<code>IGraphicsRenderer</code> with <code>ISpriteBatchRenderer</code>, <code>ITextureRenderer</code> and the other resource interfaces) plus the descriptor/registry contract used before a device exists (<code>GraphicsRendererDescriptor</code>, <code>GraphicsRendererRegistry</code>). The public <code>GraphicsRendererSelection</code> API lives in the core module: it resolves the compiled default or an explicit runtime choice and then dispatches through the selected family's namespaced factory.</p>
</div>
<div class="arch-layer arch-layer--renderer">
<div class="arch-layer-label">Layer 4 - Lowest</div>
<h4>Renderer, platform and audio implementations</h4>
<p>Concrete renderers live under <code>modules/renderers/<family>/</code>: 12 implementation families carrying 14 identities (plus shared <code>common/d3d</code> and <code>common/mojoshader</code> helper targets, which are not families). Platform implementations separately implement <code>CNA::Platform::IPlatform</code> under <code>modules/platform/src/<Backend></code>; audio implementations separately implement the audio device surface under <code>modules/audio/src/Platform</code> and <code>Backend</code>. The target OS is a fourth concern, reported by <code>CNA::TargetPlatform</code>.</p>
<h5 style="margin-top:1rem; margin-bottom:0.5rem;">SDL3, Headless and Terminal</h5>
<p>SDL3 is the default platform and audio selection, and CNA’s one windowing implementation: Windows, X11, Wayland, macOS, iOS, Android and the browser are reached through SDL’s own video drivers. Headless and POSIX Terminal avoid a graphical host, and <code>CNA_ENABLE_SDL=OFF</code> configures such a windowless build without SDL at all. Audio-device code may independently be SDL3, Null or ALSA; SDL3 (SDL3_mixer) and ALSA (CNA's own <code>CnaMixer</code>) define <code>SOUND_ENABLED</code> and supply the high-level playback and decoding engine.</p>
<ul>
<li><strong>SDL3_mixer</strong> uses the <code>MIX_Mixer</code> model with track-based, per-mixer channels.</li>
<li><strong>SDL3_image</strong> is used for texture/image loading.</li>
<li>All three libraries (<code>SDL</code>, <code>SDL_image</code>, <code>SDL_mixer</code>) are vendored as Git submodules under <code>third_party/</code>, and SDL3 is built at configure time into a persistent <code>.sdl-prebuilt-*</code> cache. No system SDL install is required by default; pass <code>-DCNA_USE_SYSTEM_SDL=ON</code> to use system packages instead.</li>
</ul>
<p>The platform service contract (a 32-flag <code>PlatformCapabilities</code> set, where a missing capability refuses deterministically) covers:</p>
<ul>
<li><strong>Windowing</strong> — window creation and management (<code>SDL_Window</code>, on whichever video driver SDL uses)</li>
<li><strong>Event loop</strong> — cross-platform event pumping</li>
<li><strong>Input</strong> — keyboard, mouse, gamepad and touch/pen state (SDL input; the Terminal platform reads the TTY)</li>
<li><strong>Audio</strong> — not part of <code>IPlatform</code>: audio is a separate axis (<code>CNA_AUDIO_PLATFORM</code>) implemented in <code>cna_audio</code></li>
<li><strong>OpenGL context creation</strong> — used by the EasyGL renderers (created by SDL3 for its window)</li>
<li><strong>Vulkan surface creation</strong> — used by the VULKAN renderer (created by SDL3 for its window)</li>
<li><strong>Native window handles</strong> — used by the WEBGPU renderer and the Direct3D and Metal families: the SDL3 window’s <code>HWND</code>, X11 <code>Display*</code> and window, Wayland <code>wl_display*</code> and <code>wl_surface*</code>, or Cocoa/UIKit window, delivered as a <code>NativeWindowHandle</code></li>
<li><strong>CPU surface presentation</strong> — hands a finished software frame to the window or terminal (used by the Terminal platform with <code>SOFTWARE</code>)</li>
<li><strong>Clipboard, drag-and-drop, message boxes, file dialogs, tray</strong> — host services, each capability-gated per backend</li>
<li><strong>Android JNI Activity layer</strong> — Android platform integration</li>
<li><strong>Emscripten main loop</strong> — WebAssembly/browser event scheduling</li>
</ul>
<p style="margin-top:1rem;">A renderer asks for narrow services such as a native surface, GL context or Vulkan surface. Headless and Terminal applications can still choose a full audio engine (SDL3 or ALSA); graphical applications can select Null to remove it, with the resulting no-playback boundary documented explicitly. See <a href="docs/platforms.html">Platform Support</a> for valid combinations.</p>
</div>
<!-- Module layout -->
<span class="section-label" style="margin-top:3rem; display:block;">Modules</span>
<h2 id="modules">Module layout</h2>
<p>Every subsystem physically owns <code>modules/<name>/{CMakeLists.txt, include/, src/, tests/, examples/}</code>; consumer include spelling is unchanged because each module's <code>include/</code> root reproduces the public <code>Microsoft/...</code> and <code>CNA/...</code> paths. The root <code>CMakeLists.txt</code> composes the modules with <code>add_subdirectory(modules)</code>, and a configure-time validator fails the build if a production source file sits outside a declared module.</p>
<div class="table-wrap">
<table>
<thead>
<tr><th scope="col">Module</th><th scope="col">Role</th><th scope="col">CMake target</th><th scope="col">In the <code>CNA</code> umbrella?</th></tr>
</thead>
<tbody>
<tr><td><code>audio</code></td><td>XNA audio and XACT; the audio device implementations (SDL3, Null, ALSA) and mixers</td><td><code>CNA::Audio</code></td><td>Yes</td></tr>
<tr><td><code>c-api</code></td><td>Experimental C ABI 0.46.0 adapter over the C++ aggregate (the base of the C# binding CNA.NET) (<code>libcna_c_api</code>)</td><td><code>CNA::CApi</code></td><td>No; separate shared library, <code>CNA_BUILD_C_API</code> (default OFF)</td></tr>
<tr><td><code>content</code></td><td><code>ContentManager</code>, XNB readers and writers, CNB codecs, the canonical pipeline engine</td><td><code>CNA::Content</code></td><td>Yes</td></tr>
<tr><td><code>content-pipeline</code></td><td>Build-time XNA Content Pipeline API, FreeType font route, FFmpeg media importers, effect-compiler service</td><td><code>CNA::ContentPipelineBuild</code></td><td>No; linked only by the content compiler</td></tr>
<tr><td><code>core</code></td><td>Base types, <code>TargetPlatform</code>, the renderer identities and <code>GraphicsRendererSelection</code>, capability enums</td><td><code>CNA::Core</code></td><td>Yes</td></tr>
<tr><td><code>design</code></td><td><code>Microsoft::Xna::Framework::Design</code> type converters</td><td><code>CNA::Design</code></td><td>No; opt-in</td></tr>
<tr><td><code>devices</code></td><td><code>Microsoft::Devices</code> sensors and vibration</td><td><code>CNA::Devices</code></td><td>Yes</td></tr>
<tr><td><code>devices-ext</code></td><td><code>CNA::Devices</code>: camera, clipboard, dialogs, tray, power, locale, URL launcher</td><td><code>CNA::DevicesExt</code></td><td>Yes; its code compiles only with <code>CNA_DEVICES</code></td></tr>
<tr><td><code>diagnostics</code></td><td>Counters, gauges, zones, frame history, trace export</td><td><code>CNA::Diagnostics</code></td><td>Yes; does nothing when <code>CNA_DIAGNOSTICS=OFF</code></td></tr>
<tr><td><code>gamer-services</code></td><td>GamerServices, Guide, Avatar, local persistence</td><td><code>CNA::GamerServices</code></td><td>No; linked explicitly, built with <code>CNA_ENABLE_NET</code> (default ON)</td></tr>
<tr><td><code>graphics</code></td><td>The XNA graphics API plus renderer interfaces, descriptors and the registry</td><td><code>CNA::GraphicsCore</code></td><td>Yes</td></tr>
<tr><td><code>graphics-ext</code></td><td>The opt-in CNAEXT extensions (<code>CNA::Graphics</code>, 11 public headers: retro effects, debug drawing, shader packages; see <a href="docs/cnaext-extensions.html">CNAEXT extensions</a>)</td><td><code>CNA::GraphicsExt</code></td><td>Yes; its code compiles only with <code>CNA_CNAEXT</code></td></tr>
<tr><td><code>input</code></td><td>Keyboard, mouse, gamepad, touch panel and gestures</td><td><code>CNA::Input</code></td><td>Yes</td></tr>
<tr><td><code>inspector</code></td><td>In-process agent, the <code>cna-inspector</code> bridge and its browser UI</td><td><code>CNA::Inspector</code></td><td>No; <code>CNA_BUILD_INSPECTOR</code>, link explicitly</td></tr>
<tr><td><code>math</code></td><td>Vectors, matrices, quaternions, colours, bounding volumes, curves (a compiled module)</td><td><code>CNA::Math</code></td><td>Yes</td></tr>
<tr><td><code>media</code></td><td><code>MediaPlayer</code>, <code>MediaLibrary</code> and the <code>Video</code>/<code>VideoPlayer</code> surface, link-complete without FFmpeg</td><td><code>CNA::Media</code></td><td>Yes</td></tr>
<tr><td><code>net</code></td><td><code>Microsoft::Xna::Framework::Net</code> over ENet</td><td><code>CNA::Net</code></td><td>No; linked explicitly, built with <code>CNA_ENABLE_NET</code></td></tr>
<tr><td><code>phone</code></td><td><code>Microsoft::Phone</code> shell and push notifications</td><td><code>CNA::Phone</code></td><td>No; linked when a game names it</td></tr>
<tr><td><code>platform</code></td><td><code>IPlatform</code> and its six implementations</td><td><code>CNA::Platform</code></td><td>Yes</td></tr>
<tr><td><code>renderers</code></td><td>12 implementation families (plus shared <code>common/d3d</code> and <code>common/mojoshader</code> helpers)</td><td>One <code>cna_renderer_<family></code> per family</td><td>The selected family, or the selected set</td></tr>
<tr><td><code>runtime</code></td><td><code>Game</code>, <code>GameWindow</code>, <code>GraphicsDeviceManager</code>, components, the project graphics profile</td><td><code>CNA::Runtime</code></td><td>Yes</td></tr>
<tr><td><code>storage</code></td><td><code>StorageDevice</code> and <code>StorageContainer</code> with path containment</td><td><code>CNA::Storage</code></td><td>Yes</td></tr>
<tr><td><code>video-ffmpeg</code></td><td>Optional FFmpeg decoding backend, selected by <code>CNA_ENABLE_VIDEO</code></td><td><code>CNA::VideoFfmpeg</code></td><td>No; linked into <code>media</code> only when enabled</td></tr>
</tbody>
</table>
</div>
<p style="margin-top:1rem;">A few dependency cycles are intentional and inherited from XNA's own semantics: graphics ↔ input (the device updates touch and mouse binding), audio ↔ media (the dispatcher pumps <code>MediaPlayer</code>, which plays through the mixer) and graphics ↔ the selected renderer (the factory edge). The <code>CNA</code> umbrella is an interface target that composes the runtime modules and the selected renderer; on native ELF GNU/Clang builds with CMake 3.27 or newer <code>CNA_SHARED_LIBRARY</code> defaults to ON, so executables link one <code>libcna.so</code> instead of each carrying a static copy of the engine.</p>
<!-- Registry -->
<span class="section-label" style="margin-top:3rem; display:block;">Renderer Registry</span>
<h2 id="renderer-registry">Renderer registry, descriptors and selection</h2>
<div class="cards cards--2 mt-3">
<div class="card">
<span class="card-icon">📋</span>
<h3>Descriptors before devices</h3>
<p>Each family publishes one <code>GraphicsRendererDescriptor</code>: everything <code>GraphicsDevice</code> must know <em>before</em> a renderer object exists — the window kind it needs (none, plain, OpenGL, Vulkan or Metal), whether a window or video subsystem is required, pre-window GL framebuffer attributes, adapter-level queries, declared maturity and category, and the factory. This replaces <code>#ifdef</code> chains inside <code>GraphicsDevice</code>. Every availability probe is unconditional, so “available” means “compiled in”; real failures arrive as initialization errors.</p>
</div>
<div class="card">
<span class="card-icon">🔨</span>
<h3>Generated registry and the descriptor gate</h3>
<p>The build generates a registry listing the linked families with the default first; tests receive <code>CNA_RENDERER_PRESENT_<IDENTITY></code> for each compiled-in family, and <code>CNA_MULTI_RENDERER</code> is defined when more than one is linked. The descriptor gate (<code>CNA_BUILD_RENDERER_DESCRIPTOR_GATE</code>, default ON) compiles every registered family's descriptor in every configuration, so a family nobody configured cannot silently rot (the Windows-SDK-bound Direct3D families are compiled by their own targets).</p>
</div>
<div class="card">
<span class="card-icon">🔢</span>
<h3>One list of 25, kept in sync mechanically</h3>
<p>The identity list lives in five places — the CMake identity list, the C++ enum, the registry map, the C ABI header and the C ABI table — and <code>scripts/check_renderer_identities.py</code> (a CTest) holds them together. Names are exact; there are no aliases. A name outside the 14 is a configure-time error that names the offending route, never a silent fallback. C ABI values are sparse and stable, whereas the C++ enum ordinals are dense and explicitly not a contract.</p>
</div>
<div class="card">
<span class="card-icon">🔒</span>
<h3>Selection and latching</h3>
<p>At run time <code>GraphicsRendererSelection</code> resolves, in order, an explicit <code>SetPreferred()</code>, the <code>CNA_GRAPHICS_RENDERER</code> environment variable (or the Emscripten <code>Module.cnaPreferredRenderer</code> property), then the build default. The selection <strong>latches</strong> when the first <code>GraphicsDevice</code> has successfully created a renderer; a failed attempt does not latch, so a game can catch the error and retry. Fallback is off by default; an opt-in chain or automatic fallback records every skipped renderer and why in <code>GetFallbackHistory()</code>, and a candidate that needs a different window kind makes CNA recreate a window it owns.</p>
</div>
<div class="card">
<span class="card-icon">⚖</span>
<h3>One combination rule</h3>
<p>A multi-renderer build is checked at configure time: identities from different platform partitions — Windows-only, Emscripten-only, macOS-only — cannot mix, because one toolchain cannot target both. See <a href="docs/runtime-renderer-selection.html">Runtime renderer selection</a>.</p>
</div>
<div class="card">
<span class="card-icon">📡</span>
<h3>Capabilities, not names</h3>
<p>Because renderers differ, code asks the device: <code>GraphicsDevice::SupportsCapability()</code> answers 19 capabilities, and <code>GetRendererCapabilityProfileEXT()</code> adds 32 features, 22 limits and per-format usage. The renderer descriptors also carry CNA's own maturity (Production, Supported, Experimental) and category (Native, TranslationLayer, Software, Web, Diagnostic) per identity.</p>
</div>
</div>
<!-- Build-time pieces -->
<span class="section-label" style="margin-top:3rem; display:block;">Build-time Tools</span>
<h2 id="build-time">Build-time pieces outside the runtime closure</h2>
<p>Some of the largest pieces of CNA are deliberately kept out of a shipped game's link closure.</p>
<div class="arch-layer arch-layer--internal" style="margin-top:1.5rem;">
<div class="arch-layer-label">Content pipeline</div>
<h4>The build-time content pipeline</h4>
<p><code>modules/content</code> holds what a game needs to <em>load</em> content and also the canonical pipeline engine (importers, processors, writers), the XNB writer and the CNB codecs (<a href="docs/cnb-format.html">CNB format</a>). <code>modules/content-pipeline</code> holds the parts that must never ship: FreeType for <code>.spritefont</code>, FFmpeg-based media importers, FBX and <code>.x</code> readers, the external <code>fxc</code> service and the XNA <code>Content.Pipeline</code> facade (107 headers). Only <code>cna_content_compiler</code> (alias <code>CNA::ContentCompiler</code>) links it, and the <code>cna-content</code> executable is a tiny <code>main</code> over that library. The tool itself is built by default; only its optional inputs are switchable. See <a href="docs/content-pipeline.html">Content Pipeline</a> and <a href="docs/tools.html">Command-line tools</a>.</p>
</div>
<div class="arch-layer arch-layer--api" style="margin-top:1.5rem;">
<div class="arch-layer-label">Optional development pieces</div>
<h4>Diagnostics, Inspector, Design and the C ABI</h4>
<p><code>CNA::Diagnostics</code> is in the umbrella but compiles its instrumentation to nothing when <code>CNA_DIAGNOSTICS=OFF</code> (the default). <code>CNA::Inspector</code> and the <code>cna-inspector</code> bridge are built only with <code>CNA_BUILD_INSPECTOR=ON</code>, are refused on Emscripten, Android and iOS, and are linked explicitly by the games that start an agent. <code>CNA::Design</code> is a design-time facility that a game links only if it wants converter registration. The C ABI is a separate shared library over the C++ aggregate and needs <code>CNA_BUILD_C_API=ON</code> and <code>CNA_ENABLE_NET=ON</code>. See <a href="docs/diagnostics.html">Diagnostics</a>, <a href="docs/inspector.html">Inspector</a>, <a href="docs/design-converters.html">Framework.Design</a> and <a href="docs/c-api.html">C API</a>.</p>
</div>
<!-- Sibling Libraries -->
<span class="section-label" style="margin-top:3rem; display:block;">Sibling Libraries</span>
<h2 id="siblings">Required sibling repositories</h2>
<p>CNA depends on sibling C++ libraries that must be cloned adjacent to the CNA repository: <code>sharp-runtime</code> for every build, and <code>easy-gl</code> (with <code>meta-gl</code>) only for the GL renderers. They are not vendored inside CNA — they live at predictable relative paths and are discovered by CMake automatically. For this snapshot clone CNA and <code>sharp-runtime</code> on their <code>apple/m4-stabilization</code> branches; <code>easy-gl</code> and <code>meta-gl</code> use their default branch.</p>
<div class="arch-layer arch-layer--internal" style="margin-top:1.5rem;">
<div class="arch-layer-label">Sibling — clone at <code>../sharp-runtime/</code> (branch <code>apple/m4-stabilization</code>)</div>
<h4>sharp-runtime</h4>
<p><code>sharp-runtime</code> is a C++ library that provides .NET-style type primitives for C++23. It allows CNA code to closely mirror XNA C# code structure without a managed runtime. Clone it at <code>../sharp-runtime/</code> relative to the CNA repo root, on branch <code>apple/m4-stabilization</code>: this snapshot requests the <code>Resources</code> and <code>Xml.Serialization</code> components, which the default branch does not contain.</p>
<p><strong>Integer aliases:</strong></p>
<ul>
<li><code>bytecs</code> — alias for <code>uint8_t</code></li>
<li><code>shortcs</code> — alias for <code>int16_t</code></li>
<li><code>intcs</code> — alias for <code>int32_t</code></li>
<li><code>longcs</code> — alias for <code>int64_t</code></li>
<li><code>ushortcs</code>, <code>uintcs</code>, <code>ulongcs</code> — unsigned variants</li>
</ul>
<p><strong>Other primitives:</strong></p>
<ul>
<li><code>Single</code> — alias for <code>float</code></li>
<li><code>String</code> — <code>std::string</code> wrapper</li>
<li><code>IDisposable</code> — virtual <code>Dispose()</code> interface</li>
<li><code>IEquatable<T></code> — <code>Equals</code> method interface</li>
<li><code>IComparable<T></code> — comparison interface</li>
<li><code>EventHandler<TArgs></code> — multicast delegate-style callbacks</li>
<li><code>List<T></code>, <code>Dictionary<K,V></code> — collection wrappers</li>
<li>I/O primitives</li>
<li>Components CNA now requests beyond these: Collections, Threading, Text, Globalization, <code>ComponentModel</code> (for <code>CNA::Design</code>), Storage, <code>Security.Cryptography</code>, <code>Xml</code>, <code>Resources</code> and, off Windows, <code>Xml.Serialization</code></li>
</ul>
</div>
<div class="arch-layer arch-layer--renderer" style="margin-top:1.5rem;">
<div class="arch-layer-label">Sibling — clone at <code>../easy-gl/</code> (the three GL identities only)</div>
<h4>easy-gl</h4>
<p><code>easy-gl</code> wraps OpenGL, OpenGL ES and WebGL for CNA's EasyGL family, which serves <code>OPENGLES3</code>, <code>OPENGL33</code> and <code>WEBGL2</code>. Clone it at <code>../easy-gl/</code> relative to the CNA repo root; it needs its own sibling <code>../meta-gl/</code>. It is required <strong>only</strong> for those three identities — not needed for <code>SDL_RENDERER</code>, <code>VULKAN</code>, <code>WEBGPU</code>, <code>SDL_GPU</code>, <code>METAL</code>, <code>FNA3D</code>, <code>HEADLESS</code>, <code>SOFTWARE</code>, <code>STUB</code>, <code>DIRECTX9</code> or <code>DIRECTX11</code>.</p>
<ul>
<li>Abstracts GLSL shader compilation, linking, and uniform binding</li>
<li>Manages VAOs, VBOs, FBOs, textures, and renderbuffers</li>
<li>Supplies the GL/GLES/WebGL function layer for desktop and for WebGL 2 (via Emscripten); the GL context itself comes from the SDL3 platform</li>
</ul>
</div>
<p style="margin-top:1rem;">Everything else CNA needs is fetched at configure time when the matching renderer or option is selected (FNA3D with MojoShader, wgpu-native, SDL_shadercross) or vendored in the tree (ENet, stb, dr_libs, cgltf).</p>
<!-- Renderer Selection Guide -->
<span class="section-label" style="margin-top:3rem; display:block;">Renderer Selection</span>
<h2 id="which-renderer">Which renderer should I choose?</h2>
<p>Select your renderer at configure time with <code>-DCNA_GRAPHICS_RENDERER=<NAME></code>. Use the table below to pick the best fit for your target platform and requirements; it lists all 14 identities.</p>
<div class="table-wrap">
<table>
<thead>
<tr><th>Renderer</th><th>Best for</th><th>Scope</th><th>Platform</th></tr>
</thead>
<tbody>
<tr><td><code>OPENGLES3</code></td><td>Most Linux games</td><td>2D + 3D</td><td>Native GL hosts (default on Linux)</td></tr>
<tr><td><code>OPENGL33</code></td><td>Desktop GL 3.3 core through EasyGL</td><td>2D + 3D</td><td>Native GL hosts</td></tr>
<tr><td><code>WEBGL2</code></td><td>Browser games with 3D</td><td>2D + 3D</td><td>Emscripten only (the web default)</td></tr>
<tr><td><code>SDL_RENDERER</code></td><td>Pure 2D, maximum portability</td><td>2D only</td><td>Anywhere SDL3 runs (default off Linux and the web, iOS included)</td></tr>
<tr><td><code>VULKAN</code></td><td>Low-level GPU control and the broadest modern feature set</td><td>2D + 3D</td><td>Any Vulkan-capable target</td></tr>
<tr><td><code>SDL_GPU</code></td><td>SDL3's GPU API, with SDL’s Direct3D 12 and Metal drivers via SDL_shadercross where enabled</td><td>2D + 3D</td><td>Any host SDL3's GPU API supports; needs SDL3</td></tr>
<tr><td><code>WEBGPU</code></td><td>Experimenting with WebGPU, natively or in the browser</td><td>2D + 3D</td><td>Linux, macOS, Windows (wgpu-native) and Emscripten</td></tr>
<tr><td><code>DIRECTX11</code></td><td>Native Windows 3D</td><td>2D + 3D</td><td>Windows only</td></tr>
<tr><td><code>DIRECTX9</code></td><td>XNA pixel authenticity</td><td>2D + 3D</td><td>Windows only</td></tr>
<tr><td><code>FNA3D</code></td><td>Running any compiled XNA effect binary (<code>.fxb</code>)</td><td>2D + 3D</td><td>Any FNA3D + SDL3 host; cannot run <code>ShaderEffect</code> source</td></tr>
<tr><td><code>METAL</code></td><td>Native Apple GPU access on macOS and iOS</td><td>2D + 3D</td><td>macOS and iOS</td></tr>
<tr><td><code>SOFTWARE</code></td><td>Deterministic pixels with no GPU</td><td>2D + 3D</td><td>Any; off-screen (displayed by the Terminal platform)</td></tr>
<tr><td><code>HEADLESS</code></td><td>Fast CI of game logic</td><td>no output</td><td>Any; renders nothing by design</td></tr>
<tr><td><code>STUB</code></td><td>Builds and tests that need no rendering at all</td><td>no output</td><td>Any; all capabilities false</td></tr>
</tbody>
</table>
</div>
<p style="margin-top:1rem;">The table is a starting point, not a verdict: this snapshot exposes <strong>14 identities across 12 families</strong>, and CNA itself says a renderer earns a place only with meaningful platform coverage, compatibility value, architectural value, or a capability the set does not otherwise cover. Judge a renderer by the scope, dependencies and platform it actually claims; see the <a href="docs/rendering-backends.html">renderer reference</a> and the <a href="features.html">feature overview</a> for per-renderer capabilities.</p>
<!-- Principles -->
<span class="section-label">Design Principles</span>
<h2 id="decisions">Key architectural decisions</h2>
<div class="cards cards--2 mt-3">
<div class="card">
<span class="card-icon">🔒</span>
<h3>Interface/Implementation separation</h3>
<p>Public API headers (<code>Microsoft/Xna/Framework/...</code>) never include renderer headers. Renderer code never bleeds into game-facing APIs. This boundary is enforced by directory and include structure, and checked by per-module minimal-link probes in CTest.</p>
</div>
<div class="card">
<span class="card-icon">⚙</span>
<h3>Compact default, opt-in runtime selection</h3>
<p><code>CNA_GRAPHICS_RENDERER</code> keeps single-renderer builds small. <code>CNA_GRAPHICS_RENDERERS</code> opts into a compatible registry and selects before the first device, with hard failure by default and explicit fallback when requested.</p>
</div>
<div class="card">
<span class="card-icon">📦</span>
<h3>Vendored dependencies</h3>
<p>SDL3, SDL3_image, and SDL3_mixer are vendored as Git submodules and built once into a persistent prebuilt cache. No system SDL packages needed. Renderer dependencies are pinned and fetched only when their renderer is selected (FNA3D with MojoShader, wgpu-native with a checked SHA-256, SDL_shadercross), and the sibling repositories are checked at configure time. This ensures reproducible builds across environments.</p>
</div>
<div class="card">
<span class="card-icon">🧬</span>
<h3>XNA namespace mirroring</h3>
<p>C++ namespaces mirror XNA's hierarchy: <code>Microsoft::Xna::Framework</code>, <code>Microsoft::Xna::Framework::Graphics</code>, <code>Microsoft::Xna::Framework::Input</code>, etc. Reduces conceptual migration cost from XNA/MonoGame experience. Non-XNA members are marked <code>CNAEXT</code>, and the opt-in CNAEXT extensions live in their own <code>CNA::Graphics</code> namespace.</p>
</div>
<div class="card">
<span class="card-icon">📝</span>
<h3>sharp-runtime support layer</h3>
<p>The <code>sharp-runtime</code> library provides utility and runtime support primitives that CNA's internals depend on. It builds cleanly on all supported platforms with no external dependencies of its own, and CNA links only the components it requests rather than the whole library.</p>
</div>
<div class="card">
<span class="card-icon">🔁</span>
<h3>Independent axes, hard exclusions</h3>
<p>Target OS, platform, renderer and audio are chosen separately, and <code>CNA_ENABLE_SDL</code> can remove SDL altogether. Impossible combinations fail at configure time with a named reason instead of half-working, and reserved values are refused rather than silently substituted.</p>
</div>
<div class="card">
<span class="card-icon">🧰</span>
<h3>Build-time pipeline outside the runtime closure</h3>
<p>Content compilation, FreeType, FFmpeg importers and the external effect compiler live in <code>content-pipeline</code>, which only the <code>cna-content</code> compiler links. A shipped game links the loaders, never the pipeline.</p>
</div>
<div class="card">
<span class="card-icon">✂</span>
<h3>A curated renderer set</h3>
<p>Renderer count is not a goal. CNA maintains 14 public identities over 12 families, held together by an identity registry with stable, never-reused C ABI values, and a name outside that list is a configure error rather than an alias.</p>
</div>
</div>
<!-- C++23 Features -->
<span class="section-label" style="margin-top:3rem; display:block;">C++ Features (C++23 floor)</span>
<h2 id="cpp23-features">Key C++ features used in CNA (built as C++23)</h2>
<p>CNA targets C++23 as a compiler floor, not a feature list: the modern standard library and language features it uses to mirror XNA's C# semantics cleanly without a managed runtime are C++17 and C++20 ones, and a text search of the module sources finds no C++23-only facility (see <a href="deep-dives/foundations/language-conventions.html#cpp-dialect">The C++ dialect</a>).</p>
<div class="arch-layer arch-layer--api" style="margin-top:1.5rem;">
<div class="arch-layer-label">Standard Library & Language Features</div>
<ul>
<li><code>std::optional<T></code> — replaces XNA nullable types (<code>Nullable<T></code>) for missing or unset values.</li>
<li><code>std::span<T></code> — provides buffer views in <code>GetData()</code>/<code>SetData()</code> without copying data.</li>
<li><code>std::string_view</code> — zero-copy string parameters wherever a string is read but not owned.</li>
<li><code>std::unique_ptr<T></code> / <code>std::shared_ptr<T></code> — RAII resource management, replacing C# <code>using</code> blocks and <code>IDisposable</code> patterns.</li>
<li><strong>Ranges and concepts</strong> (where available) — type-safe template constraints replacing unconstrained templates.</li>
<li><code>[[nodiscard]]</code> attributes — applied to <code>Load<T>()</code>, <code>Begin()</code>, and similar factory/guard calls to catch accidentally discarded return values.</li>
<li><strong>Structured bindings</strong> — used for returning multiple values from internal helpers without heavyweight output-parameter patterns.</li>
<li><code>if constexpr</code> — compile-time template branching in <code>PackedVector</code> implementations and format-dispatch helpers.</li>
<li><strong>Inline variables</strong> — for static constants defined directly in header-only types without requiring a separate <code>.cpp</code> definition.</li>
<li><code><format></code> — used unconditionally in the always-built content code, which is why the build effectively needs libstdc++ 13, a current libc++ or MSVC 2022.</li>
</ul>
</div>
<div class="callout callout--info" id="go-deeper">
<span class="callout-icon">🔬</span>
<p><strong>Go deeper.</strong> This page is the user-facing map of the layers. For the maintainer view — how the layers relate in the source, who owns what, and how each subsystem behaves from construction to teardown — see the <a href="development/architecture/overview.html">Architecture maps</a>, the <a href="development/repository/module-graph.html">physical module dependency map</a>, the <a href="development/internals/index.html">Internals</a> source tours (runtime, <a href="development/internals/graphics/selection.html">renderer selection</a>, <a href="development/internals/platforms/index.html">platform backends</a>, <a href="development/internals/audio/engine.html">audio</a>, <a href="development/internals/content/runtime.html">content</a>) and the generated <a href="development/reference/selection-axes.html">selection axes index</a>.</p>
</div>
<!-- File layout -->
<span class="section-label">Source Layout</span>
<h2 id="directory-structure">Directory structure</h2>
<pre><code>cna/
├── modules/ ← every source file lives in a module (23 modules)
│ ├── core/ ← base types, renderer identities, GraphicsRendererSelection
│ ├── math/
│ ├── graphics/ ← the XNA graphics API + renderer interfaces
│ │ ├── include/
│ │ │ ├── Microsoft/Xna/Framework/Graphics/ ← public XNA API
│ │ │ │ ├── GraphicsDevice.hpp
│ │ │ │ ├── SpriteBatch.hpp
│ │ │ │ └── Texture2D.hpp
│ │ │ └── CNA/Internal/Renderers/Common/ ← renderer interfaces and registry
│ │ │ ├── IGraphicsRenderer.hpp ← also ISpriteBatchRenderer, ITextureRenderer
│ │ │ ├── GraphicsRendererDescriptor.hpp
│ │ │ └── GraphicsRendererRegistry.hpp
│ │ ├── src/
│ │ ├── tests/
│ │ └── examples/
│ ├── platform/ ← IPlatform; src/ Sdl3 Headless Terminal (Windows, X11, Wayland via SDL3)
│ ├── audio/ ← XNA audio; src/Platform: Sdl3 Alsa Null; src/Backend: Sdl3Mixer CnaMixer
│ ├── input/ media/ storage/ runtime/
│ ├── content/ ← ContentManager, XNB reader and writer, CNB codecs
│ ├── content-pipeline/ ← build-time only: XNA Content.Pipeline API, FreeType, FFmpeg importers
│ ├── video-ffmpeg/ ← optional FFmpeg backend (CNA_ENABLE_VIDEO)
│ ├── devices/ devices-ext/ phone/ gamer-services/ net/
│ ├── graphics-ext/ ← CNAEXT extensions (-DCNA_CNAEXT=ON)
│ ├── design/ ← Framework.Design converters (opt-in)
│ ├── diagnostics/ inspector/ ← optional observation layer and viewer
│ ├── c-api/ ← experimental C ABI 0.46.0 (-DCNA_BUILD_C_API=ON)
│ └── renderers/ ← 12 families, 14 public identities
│ ├── easygl/ ← OPENGLES3, OPENGL33, WEBGL2
│ ├── vulkan/ sdl-gpu/ webgpu/ metal/ fna3d/
│ ├── directx9/ directx11/ ← Windows-only
│ ├── sdl-renderer/ ← 2D over SDL3
│ ├── software/ headless/ stub/ ← no GPU required
│ └── common/ ← shared d3d and mojoshader helpers (not families)
│
├── third_party/ ← SDL, SDL_image, SDL_mixer, draco, enet, stb, dr_libs, cgltf
├── vendor/ ← googletest
├── tools/ ← content (cna-content), gltf_to_cnj, gltf_to_cnb, cnj_to_cnb,
│ source_to_cnb, cnb_info, xna-oracle, reference dumpers
├── cmake/ ← renderer/platform/audio selection, registry, third-party helpers
├── examples/ tests/ docs/ scripts/
└── CMakeLists.txt</code></pre>
</div>
</section>
</main>
<footer>
<div class="footer-inner">
<div class="footer-top">
<div class="footer-brand">
<div class="footer-brand-name">CNA</div>
<p>Documentation snapshot for CNA commit c1c316b9 (9 October 2026), a post-alpha.1 development snapshot. CNA exposes 14 renderer identities across 12 implementation families; APIs may change before 1.0.</p>
</div>
<div class="footer-col">
<h4>Project</h4>
<ul>
<li><a href="about.html">About</a></li>
<li><a href="features.html">Features</a></li>
<li><a href="architecture.html">Architecture</a></li>
<li><a href="roadmap.html">Roadmap</a></li>
<li><a href="network.html">CNA Network</a></li>
</ul>
</div>
<div class="footer-col">
<h4>Docs</h4>
<ul>
<li><a href="docs/getting-started.html">Getting Started</a></li>
<li><a href="docs/building.html">Building</a></li>
<li><a href="docs/platforms.html">Platforms</a></li>
<li><a href="docs/rendering-backends.html">Renderers</a></li>
<li><a href="docs/faq.html">FAQ</a></li>
<li><a href="deep-dives/index.html">Deep Dives</a></li>
<li><a href="known-issues/index.html">Known Issues</a></li>
</ul>
</div>
<div class="footer-col">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/libcna/cna" target="_blank" rel="noopener">GitHub</a></li>
<li><a href="https://discord.gg/vrnc4n6DaE" target="_blank" rel="noopener">Discord</a></li>
<li><a href="demos.html">Demos</a></li>
<li><a href="videos.html">Videos</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>CNA is not affiliated with or endorsed by Microsoft Corporation. XNA is a trademark of Microsoft. Licensed under the Microsoft Public License (Ms-PL).</p>
<div class="footer-links">
<a href="https://github.com/libcna/cna/blob/c1c316b9c7a846ce8002809c151fcd1af14942c9/LICENSE" target="_blank" rel="noopener">License</a>
<a href="contact.html">Contact</a>
</div>
</div>
</div>
</footer>
<script src="js/main.js"></script>
<script src="js/prism/prism.min.js" defer></script>
<script src="js/prism/prism-cpp.min.js" defer></script>
<script src="js/prism/prism-glsl.min.js" defer></script>
<script src="js/prism/prism-json.min.js" defer></script>
<script src="js/prism/prism-bash.min.js" defer></script>
<script src="js/prism/prism-cmake.min.js" defer></script>
</body>
</html>