I need to investigate a sample failure
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. Read at 009d40f5; cna-samples, the gallery and cna-examples are cited only at their pinned revisions and are not TARGET evidence; nothing was built or run, and the sweep and oracle results quoted are CNA's own records.
A sample that crashes, renders wrongly or behaves differently from the original is CNA's most convincing bug report and also its most ambiguous one: the fault can sit in CNA, in the C++ translation, in the compiled content, in the build configuration or in the host. This recipe is the triage flow for deciding which, and for reducing the failure to something a maintainer can fix and test. It uses the sample repositories as evidence for their own pinned revisions, never as statements about the TARGET snapshot 009d40f5. Everything was read from source, plans and pinned repository revisions; nothing was built or run.
The sample ecosystem and what each part proves
| Source | What it is | Pin used here | It is evidence for |
|---|---|---|---|
libcna/cna-samples | C++ ports of Microsoft's XNA Game Studio 4.0 samples, built against a sibling CNA checkout. Its plan.md inventories 153 upstream sample directories; 87 are marked complete (native OpenGL ES 3 run, real-browser WebGL 2 run and a zero-workaround audit), 49 await owner decisions, 14 are documented non-ports, and Racing Game is tracked separately | 4da98a0fc24520d8ff9f9b462f8f78d47fc23fbe, 2026-09-20 | CNA next on that date, four days before TARGET; the relation to TARGET is unverified |
| samples.libcna.com | The public gallery: 40 prebuilt Release, WEBGL2, non-threaded bundles (GitHub Pages cannot send the COOP/COEP headers pthreads need) | 736b8aa3199e07cb8ce4d174c7290d6db2c8c4aa, 2026-09-20 | Liveness of a bundle; the bundle does not record which CNA revision built it |
libcna/cna-examples | One app with 13 areas, 79 categories and 249 demo screens, each calling a real XNA or CNA API; --list-demos is its authoritative list | ea33c9a29eb4cd02bc44ed3890efd4e3777a04e8, 2026-09-13 | API behaviour at that CNA revision. Some screens catch their own exceptions, so a clean screenshot does not prove a pass |
tools/xna-sample-sweep (in tree) | Rebuilds the content of the real Microsoft samples through cna-content and compares each .xnb with the one genuine XNA 4.0 produced | TARGET | Content-pipeline parity, not runtime behaviour; the sample sources and genuine .xnb files it reads are a local collection that is not part of the repository |
tools/xna-oracle (in tree) | 39 declarative scenes and their reference PNGs from real XNA 4.0 under Wine with DXVK on Linux | TARGET | Pixel behaviour of the scenes it covers, on the renderer that was run |
module examples (in tree) | Standalone *_test.cpp programs registered beside each module (879 across the tree) | TARGET | The template for a minimal repro |
The sample counts above are the pinned repository's own; they are not CNA facts and change as the plan is edited. The user-facing summary and its caveats are on the XNA compatibility and verification pages.
Find the owner: sample, content, CNA, configuration or host
The sample repository's working rules (rules.md at the pin) state the ownership principle a maintainer should copy: a sample may not compensate for a CNA defect, so a faithful translation that fails is either a translation or content fault (fix it in the sample) or a framework fault (fix it generally in CNA, with a test, never with a sample-name special case). Use the table to decide which.
| Observation | Likely owner | First evidence to gather |
|---|---|---|
| Same source line disagrees with the original C# (constant, order, lifecycle call) | Sample translation | Line-by-line diff against the original; the sample's missing.md audit |
A NotSupportedException naming the profile, or MRT, occlusion, 32-bit indices, volume or float targets | Profile mismatch between sample and original | The original's GraphicsProfile; the profile section |
Asset loads but looks wrong, or the load throws ContentLoadException | Content, or the reader | The .xnb header (target platform, readers), byte comparison with the reference, the content section |
| An effect refuses or renders wrongly, one colour channel off | Compiled-effect path (CNA) or the effect blob | The error guide in fx-compiled-effects.md; the same effect on a second compiled-effect renderer |
| Same build behaves differently on two renderers | A renderer translation layer | The capability profile and a second backend (Fix a renderer bug) |
| Fails only in the browser | Web platform, storage or a renderer restriction | The axes section; Tutorial 124 |
| Fails only on one machine or driver, or only under Wine | Host | Another host, the private-display and Xvfb notes in What to test after changing X |
| Passes in the sample's build, fails at TARGET | A CNA regression between the two revisions | Bisect the CNA revision (next section) |
Reproduce with the sample's CNA revision
- Record three revisions. The sample commit, the CNA commit and the sharp-runtime commit. cna-samples builds against sibling checkouts
../cnaand../sharp-runtime, both on thenextbranch, withCNA_SHARP_RUNTIME_ROOTselecting the runtime andCNA_SAMPLES_CNA_ROOTnaming an equivalent explicit CNA checkout; its rules require the configured path to be recorded in the sample's evidence. It does not pin CNA, so the CNA commit has to be recovered from the sample's audit or by date. - Use the campaign's reference configuration first. Native builds use
CNA_GRAPHICS_RENDERER=OPENGLES3; browser builds useWEBGL2under Emscripten (OPENGLES3is refused there). A failure on another renderer is a different question (Renderer selection internals). - Build one sample. From the sample repository:
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DCNA_SAMPLES_ONLY=PrimitivesSamplethencmake --build build --target PrimitivesSample_cna_samples, as its README states at the pin. Do not treat a published gallery bundle as a reproduction: it is a Release WebGL 2 artifact of unrecorded CNA revision. - Reproduce at the sample's CNA revision, then at TARGET. If it fails at both, it is not a regression and the cause is in one of the layers below. If it passes at the older revision and fails at TARGET, bisect CNA between them with a fixed sample commit; the C++ change list is the input to Change public XNA behaviour.
- Write down the configuration that failed: the platform, audio and renderer axes, the profile, the compiled-effects options, whether content is pregenerated
.xnbor built bycna-content, and the host.
Profile: Reach versus HiDef
The default project profile is Reach (ProjectGraphicsProfile.cpp initialises it to GraphicsProfile::Reach), and TARGET enforces the profile ceilings in the shared device layer on every renderer. Samples written for XNA 4.0 that use these features set HiDef in the original; a port that does not is a translation fault, and a port that does and still throws is a CNA fault. Messages read at TARGET:
| Feature under Reach | What happens | Where |
|---|---|---|
32-bit IndexBuffer or 32-bit user indices | NotSupportedException: “Thirty-two-bit index buffers are not supported by the Reach graphics profile.” | IndexBuffer.cpp, GraphicsDevice.cpp |
| A draw above 65,535 primitives (HiDef: 1,048,575) | NotSupportedException naming the limit | GraphicsDevice.cpp |
OcclusionQuery | Constructor throws: “not supported by the active graphics profile and renderer” (HiDef also needs the renderer capability) | OcclusionQuery.cpp |
| More than one render target | SetRenderTargets throws naming the profile's maximum (Reach 1, HiDef 4) | GraphicsDevice.cpp |
Texture3D | “GraphicsProfile.Reach does not support volume (3D) textures at all” | Texture3D.cpp |
Non-power-of-two Texture2D with mips or DXT; sampled with non-Clamp addressing; separate alpha blend | NotSupportedException (“Reach requires Clamp addressing for non-power-of-two Texture2D resources.”) | Texture2D.cpp, GraphicsDevice.cpp |
| Float, HDR and packed formats; some render-target formats | Refused for Texture2D; a RenderTarget2D may silently fall back to Color | Texture.cpp |
Read the profile a device actually has with getGraphicsProfileProperty(), set it with GraphicsDeviceManager::setGraphicsProfileProperty(GraphicsProfile::HiDef) before device creation (or CNA::SetProjectGraphicsProfileEXT), and read renderer answers with GraphicsDevice::GetRendererCapabilityProfileEXT().GetEnglishReport() (Tutorial 152, Tutorial 133). A device that reports a feature as unsupported after HiDef is requested is then a renderer question. Many alpha.1-era tutorials omit the profile, so an old snippet that throws is not evidence against CNA.
Renderer and platform axes
Platform, audio device, renderer and target OS are independent choices (the four axes). To learn which renderers a build actually contains and which one was selected, run cna_demo_renderer_selection (graphics examples), which reports what the build contains instead of assuming. Selection precedence is the API call, then the CNA_GRAPHICS_RENDERER environment variable (in a browser the page property Module.cnaPreferredRenderer, at the environment variable's precedence), then the compiled default; a name that is not compiled in throws rather than being ignored (GraphicsRendererSelection.cpp, rules). Selection latches on first device creation.
- A window-free control.
CNA_GRAPHICS_RENDERER=HEADLESSwithCNA_HEADLESS_MODE=Tracevalidates the sample's calls and records a structured call log without pixels, which separates a state or API-misuse fault from a rendering fault (Headless renderer internals); it cannot show shader output. - Fault injection.
CNA_DEBUG_UNAVAILABLE_RENDERERSandCNA_DEBUG_FAIL_RENDERER_INITmake listed renderers fail their probe or initialisation, to exercise fallback chains. - Browser. Only the Emscripten renderer identities are selectable; saves do not persist across a reload (below);
VideothrowsNotSupportedException; a blockingGame::Run()needs Asyncify in the final link (Tutorial 124). - Sample-defined host differences. A gallery bundle is non-threaded by construction; a sample that genuinely uses
System.Threadingneeds the threaded configuration and COOP/COEP headers that Pages cannot send.
Content pipeline and effects
The samples use official pregenerated .xnb files where the original pipeline output is available, keeping the original Content.Load<T>() contract; otherwise content is built by cna-content. Runtime CNA loads XNB, CNB or loose files (ContentManager); it does not compile .fx source. Effects are compiled-bytecode only: an XNA/FNA Direct3D 9 Effect Framework binary is accepted on the renderers that enable it (FNA3D always; nine default-OFF build options), MonoGame MGFX is rejected by name, and cna-content compiles .fx at build time through an external legacy fxc discovered from the CNA_FXC environment variable, the baked CNA_FXC_EXECUTABLE or PATH (EffectCompilerService.hpp). Its equivalence to Microsoft's compiler is unverified.
The error guide in fx-compiled-effects.md distinguishes the kinds of fault a maintainer needs to separate: ArgumentException means the bytes are wrong; NotSupportedException means the format, renderer or profile is wrong; a parser diagnostic as std::runtime_error means plausible but corrupt content; ContentLoadException wraps any of them with the asset name. A worked example of a sample finding a real defect: PerPixelLightingSample rendered with red and green matching the original and only blue different, where blue would exceed 1, which traced to Direct3D 9 clamping vertex colours before interpolation where GL ES clamps after it; CNA restores the clamp at the end of the generated shader for the ES profiles with a MojoShader patch in cmake/patches. The tell was a one-channel mismatch that appeared only above 1.
- Is the asset the same bytes as the reference? The in-tree sweep (
sweep.py, thenclassify.pyandtaxonomy.py) rebuilds each mapped project through a frozencna-contentand compares by bytes; its classes separate identical, semantically identical (for example the same payload under two conforming LZX encoders), an accepted difference (a rasteriser, a block compressor, a compiler version string), a custom pipeline component defined by the sample that CNA cannot load, and environment gaps (a font this host lacks). CNA's plan records the sweep's results at its own runs; the collection it reads is not in the repository, so treat those figures as CNA's records. - Does a sample define its own processor? A processor no XNA assembly defines is the sample's own and cannot be loaded into CNA; that is a documented gap, not a defect in either side.
- Is the target platform right? XNB readers and headers are platform-specific; an Xbox 360 or Windows Phone target in the header is a content question before it is a reader question (Content pipeline internals).
Storage, persistence and audio
- Storage. The root is chosen from the first applicable of Android's private directory,
XDG_DATA_HOME,LOCALAPPDATA,HOME(with Apple'sLibrary/Application Support) and finally the working directory, below<app>, which is the literalgameunlessStorageDevice::SetAppNameEXTis called.Begin*completes before it returns, so start atEnd*. In a browser the root lives in Emscripten's in-memory file system and CNA mounts no persistent one, so a save is written and reported successful but is gone after a reload. A failed root resolution latches an empty root (source-read, not exercised), which turns later saves into working-directory writes (Storage internals, Tutorial 141). - Audio. A build with no usable audio device throws
NoAudioHardwareExceptionon effect construction under SDL3;SDL_AUDIODRIVER=dummyand the NULL audio implementation give a device-free control, andCNA_AUDIO_DEVICEsteers the ALSA device. High-level playback exists only for the SDL3 and ALSA audio selections (Audio engine internals, environment variables).
Separating a CNA defect from a sample, content or host problem
Run each control below to change one variable, and stop at the first that flips the result.
- Same sample, HEADLESS renderer with
CNA_HEADLESS_MODE=Trace. AHeadlessValidationExceptionnaming a rule points at the API sequence (sample or CNA state handling); a clean trace points at rendering. - Same sample, HiDef if the original was HiDef. Flips: the port omitted the profile.
- Same content, built by
cna-contentversus the pregenerated.xnb. Flips: content generation. - Same sample, a second renderer that supports what it uses. Flips: a renderer translation layer, not shared logic.
- Same CNA revision, a second host or driver. Flips: host.
- Older CNA revision, same sample. Flips: regression, so bisect.
- Original C# sample under real XNA. See below.
Do not paper over a CNA gap in the sample. The cna-samples rules forbid sample-local workarounds (backend helpers, raw loaders in place of Content.Load, invented controls) and mark a sample with a workaround as not complete. A fix that is valid only for one sample name is not a CNA fix.
Extract a minimal repro
- Remove content first: replace loaded assets with a procedural
Texture2Dor a colour clear. If the failure survives, it is not content. - Strip the game to one
Game, oneGraphicsDeviceManagerand the single call sequence that fails, with the same profile, renderer and platform. - Prefer an existing declarative or standalone form: an oracle scene (
tools/xna-oracle/README.mdlists the keys) for stock effects, SpriteBatch and primitives, or a module example in the style ofmodules/graphics/examples. Register a new example in that directory'sCMakeLists.txt(a target-existence gate tests equality withCNA_GRAPHICS_RENDERER, a resource-availability gate may test membership) and, if it needs a window, give itsadd_testthe private-display environment. - Turn the repro into a regression test with the narrowest assertion that fails (Add a regression test); a passing sample is not a test.
When to compare against real XNA
Compare when the question is what XNA does, not what CNA does: a pixel difference on a stock effect, SpriteBatch or primitive draw, a default value, an exception type, or a byte-level content difference. The oracle corpus covers only its 39 scenes; the DIRECTX9 identity is recorded pixel-exact on all 39 through Wine and DXVK, while other renderers are measured against it and mostly not gated, and no workflow runs the whole corpus (Using the XNA oracle as evidence, Tutorial 161). For a whole sample the sample repository's own order of authority is the original C# source, then a real XNA 4.0 build of that unchanged source, then FNA, then Microsoft documentation, and other ports only as supplemental evidence. For content, the byte comparison above is the oracle. A CNA result that matches FNA but not the XNA reference is worth recording rather than resolving silently.
Review checklist
- The three revisions (sample, CNA, sharp-runtime), the axes and the profile are recorded, and a reproduction exists at more than one CNA revision or the reason it does not is stated.
- The owner was decided by a control that flipped the result, not by inspection of the crash site.
- The fix is in the owning layer with a regression test that does not need the sample; no sample-specific branch was added to CNA.
- External counts and results are cited with their pins and are not restated as TARGET facts; anything that was not run is said so.
Related: Debugging cookbook, Tutorial 79, How to understand code you did not write, Modify the Content Pipeline and Change build configuration.
Deep dives on this topic
Long-form pages that explain the exact semantics, invariants and evidence behind this subject.
- Migrating an XNA game to CNA: a process that keeps every mismatch attributable — A porting process for XNA and FNA games at this snapshot: freeze a baseline, translate mechanically, map assets and shaders to real routes, pick renderers by evidence and verify in rungs.
- Porting case studies: the Blupi games, the official samples and the example catalogue — What real ports around CNA teach: free-direct's call-site audits of two Blupi games, a native-CNA port plan, the Speedy Blupi 2013 port, cna-samples and cna-examples, each pinned.
Related pages
The same subsystem is explained at four altitudes. These are the neighbouring pages at each one.
- User guide
- XNA compatibility · Verification: the XNA oracle corpus · Tutorial 152: Reach vs HiDef · Tutorial 124: WebAssembly gotchas
- Architecture
- Graphics architecture · Content architecture
- Internals
- Renderer selection internals · Headless renderer internals · Content pipeline internals · Storage internals
- Maintainer workflow
- Using the XNA oracle as evidence · How to understand code you did not write · Debugging cookbook · Fix a renderer bug
- Tests and validation
- Add a regression test
- Reference
- Selection axes index