Skip to content
The CNA BibleCNA 0.1.0-alpha.1 Edition

Chapter 32 Non-GPU and Diagnostic Renderers

HEADLESS, SOFTWARE, and STUB all run without a GPU, but they answer three different questions. Headless asks whether calls and lifetimes form a valid trace. Software asks what a bounded CPU rasterizer would draw. Stub asks whether framework code can survive a renderer that intentionally does almost nothing.

Identity Observable Extended route RT / MRT / query
HEADLESS validation, trace, counters validate and trace trace target / no / constant bookkeeping
SOFTWARE real CPU pixels native bounded raster yes / no / no
STUB no pixels or bookkeeping inherited no-op no / no / no

32.1 HEADLESS: behavior without an image

Headless builds resource objects, validates arguments and sequencing, records state and draw events, and exposes counters and a trace log. Its extended primitive methods do not rasterize; they validate and describe the call. A render target is likewise a bookkeeping target whose bind/unbind transitions can be inspected.

This makes the renderer valuable for deterministic unit tests, servers, and API misuse checks. It can prove that a draw used the expected primitive count, target, texture, or state sequence. It cannot prove coverage, interpolation, sampling, blending, depth, or final color.

32.1.1 A query result that is not an occlusion measurement

The Headless query object returns a constant pixel count of one. That value keeps control-flow tests moving; it is not derived from geometry. Treat it as validation scaffolding, never as an oracle for visibility or sample count.

The capability switch currently falls through to true for MRT and occlusion queries even though setting more than one target throws and the query is trace-only. These are default-true contract contradictions recorded in the audit. Callers requiring real feature behavior must not infer it from the bit.

32.2 SOFTWARE: bounded CPU rasterization

Software is a renderer, not a recorder. It rasterizes sprites and a bounded 3D subset into CPU buffers: triangle lists, depth/stencil, complete per-stream vertex fetch, texture/sampler state, the five stock-effect packet shapes, cube storage and environment-map sampling, and the public blend-factor/equation surface all have real CPU paths. The fixed shader logic remains deliberately narrower than a programmable renderer: stock lighting and fog flags are still outside the v1 surface, and accepting source text into SoftwareEffectRenderer does not execute that source as a custom shader.

Both extended draw methods are native CPU paths, and RenderTarget2D produces real pixels. Plain TextureCube has every declared mip/face stored and can feed the bounded environment-map path, but RenderTargetCube, Texture3D, instancing, MRT and occlusion queries remain outside v1. The capability switch explicitly returns false for Texture3D and instancing and true for multistream input, but its default branch still overclaims MRT and queries — the same default-policy shape as Headless, with a real rasterizer beneath other operations.

That distinction matters for test design. A Software screenshot is genuine pixel evidence for the bounded CPU algorithm. It is not evidence for GPU precision, driver shader compilation, MSAA resolve, or a programmable effect path.

32.2.1 A useful reference with known semantic limits

Software’s deterministic memory buffers make it a strong local oracle for geometry ordering, stream offsets, texture/cube sampling, target usage, depth/stencil and blending. When another renderer differs, first check that the scene stays inside Software’s declared subset. A lit, fogged, instanced, custom-shader or render-target-cube scene cannot use the CPU result as an XNA-exact ground truth.

32.3 STUB: the smallest terminal implementation

Stub intentionally keeps no rendering state worth observing. It creates no targets, records no trace, and its inherited extended draw path ends in a no-op. Its capability method returns false for every flag, avoiding the default-true trap entirely.

The family is useful as an architectural teaching device. It shows which renderer hooks must exist for the framework to construct and run even when their bodies have no presentation work. It can also expose accidental assumptions in code that should be renderer-independent, such as unconditional dereferences of optional resource factories.

Stub must not be called a headless rasterizer. It supplies neither Headless validation nor Software pixels. A passing Stub lifecycle test proves only that the surrounding framework did not demand more than the deliberately minimal contract.

32.4 Choosing the right non-GPU test double

Use Headless when the assertion concerns call shape, order, counters, lifetime, or validation. Use Software when the assertion concerns pixels within its bounded raster vocabulary. Use Stub when the assertion concerns framework survival in the absence of rendering behavior.

Question Best identity Invalid inference
Was the target bound before the draw? HEADLESS that the target contains correct pixels
Did a simple textured triangle produce this color? SOFTWARE that a GPU shader or MSAA path agrees
Can the game loop run with no rendering facilities? STUB that resource or draw semantics were validated
Did an occlusion query count visible samples? none of these Headless’s constant or Software’s null factory is a measurement

32.5 Capability discipline

The cluster illustrates all three outcomes of the renderer contract’s default policy. Stub overrides everything false. Software implements substantial behavior but accidentally overclaims features it does not own. Headless intentionally supplies validation objects yet lets their interface presence look like pixel capability.

Documentation and tests should therefore name the observable, not only the method. A target can be a trace object or a pixel buffer; a query can be a control-flow token or a sample count; a draw can be a log record, a CPU rasterization, or a no-op. The same C++ signature does not make those results equivalent.

Type at least three characters. Results are ranked by how often and where the words occur.