CNA-BUG-244: README.md's Usage Example does not compile (nonexistent Graphics/GraphicsDeviceManager.hpp include, unqualified CornflowerBlue) and presents every frame twice
Evidence basis: source-verified at the pinned commit; executed for this entry (the Evidence section names exactly what was run); 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 README's game skeleton includes a nonexistent header path, writes CornflowerBlue without Color::, and calls device.Present() in Draw although EndDraw() already presents, so the copied program fails to compile and, once repaired, presents twice per frame.
- Identifier
CNA-BUG-244- Category
- Bug
- Subsystem
- Documentation & release tooling
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Medium (a triage suggestion, not a project priority)
- Evidence basis
- Reproduced: executed for this entry (the Evidence section names exactly what was run)
- Tests touching this area
- Yes: see Current tests
- Affected contract
- README.md section 10 (Usage Example): the minimal Game skeleton; Microsoft/Xna/Framework/GraphicsDeviceManager.hpp, Color::CornflowerBlue and the Game::Draw / EndDraw presentation contract
Expected behaviour
The README's “Minimal XNA-style game skeleton” is the first program most users copy. It should compile against the public headers and follow the frame contract CNA shares with XNA: Game::Tick calls BeginDraw(), Draw() and EndDraw(), and GraphicsDeviceManager::EndDraw presents, so a Draw override never calls Present() itself. CNA's own stub_smoke_test.cpp states exactly that rule (“No explicit Present() here”).
Actual behaviour at TARGET
At 009d40f5 the example in README.md:
- includes
Microsoft/Xna/Framework/Graphics/GraphicsDeviceManager.hpp; the only such header isMicrosoft/Xna/Framework/GraphicsDeviceManager.hppand no forwarding header exists anywhere in the tree; - calls
device.Clear(CornflowerBlue)with onlyusing namespace Microsoft::Xna::FrameworkandMicrosoft::Xna::Framework::Graphicsin effect, butCornflowerBlueis the static memberColor::CornflowerBlue(Color.hpp) and no namespace-scope name exists; - ends
Drawwithdevice.Present().Game::Tickthen callsEndDraw(),GraphicsDeviceManager::EndDrawcallsGraphicsDevice::Present()again, andGraphicsDevice::Presenthas no once-per-frame guard, so the renderer'sPresent()runs twice every frame.
The overrides also skip Game::Update and Game::Draw, which update and draw registered components and call FrameworkDispatcher::Update(); harmless in this component-free skeleton, but it drops the base-call pattern of the XNA template. The rest of the example (GraphicsDeviceManager(Game*), the CNAEXT Texture2D(path, device) constructor and SpriteBatch::Draw(texture, x, y)) matches the headers.
Source locations
README.md— section 10, Usage Examplemodules/runtime/include/Microsoft/Xna/Framework/GraphicsDeviceManager.hpp— the only GraphicsDeviceManager headermodules/math/include/Microsoft/Xna/Framework/Color.hpp— static const Color CornflowerBluemodules/runtime/src/GraphicsDeviceManager.cpp— GraphicsDeviceManager::EndDraw presents after every successful BeginDrawmodules/runtime/src/Game.cpp— Game::Tick draw sequence; Game::Update and Game::Draw base behaviourmodules/graphics/src/Xna/GraphicsDevice.cpp— GraphicsDevice::Present, no per-frame guardmodules/renderers/stub/examples/stub_smoke_test.cpp— StubSmokeTest::Draw comment: no explicit Present()
Evidence
Read at 009d40f5: README section 10, the header tree, Color.hpp, GraphicsDeviceManager::EndDraw, Game::Tick, Game::Update, Game::Draw and GraphicsDevice::Present. Executed: the README code block was extracted verbatim and syntax-checked with g++ -std=c++23 -fsyntax-only -DCNA_RENDERER_SDL_RENDERER -DCNA_PLATFORM_SDL3 against every TARGET modules/*/include root and a sharp-runtime next checkout at 41b918c9 (a sibling revision not pinned by TARGET). The verbatim block stops with “Microsoft/Xna/Framework/Graphics/GraphicsDeviceManager.hpp: No such file or directory”; with the include corrected it stops with “‘CornflowerBlue’ was not declared in this scope”; with Color::CornflowerBlue as well it compiles. The double present is established by reading; nothing was linked or run, so what the second present shows on each renderer was not observed. README.md last changed in 9a42a7e82 and still carries the example at TARGET.
Focused reproduction
Executed (syntax check only), from a scratch directory, with the README block saved as readme.cpp:
T=/path/to/cna-target; SR=/path/to/sharp-runtime
INC=$(for d in $T/modules/*/include $SR/modules/*/include; do printf ' -I%s' "$d"; done)
g++ -std=c++23 -fsyntax-only -DCNA_RENDERER_SDL_RENDERER -DCNA_PLATFORM_SDL3 $INC readme.cpp
# fatal error: Microsoft/Xna/Framework/Graphics/GraphicsDeviceManager.hpp: No such file or directory
# after fixing the include: error: 'CornflowerBlue' was not declared in this scope
Current tests
No CNA test compiles README snippets; the documentation-labelled CTests (for example CnaXnbPlanStatusConsistency) check plan tables, not examples. stub_smoke_test.cpp and the other renderer examples demonstrate the correct Draw without Present(), but nothing counts presents per Tick.
Regression test
A documentation gate that extracts the README's C++ block and syntax-checks it against the public headers with the flags above; optionally a HEADLESS or STUB example that counts renderer Present() calls per Tick and asserts one. The fix: include Microsoft/Xna/Framework/GraphicsDeviceManager.hpp, write Color::CornflowerBlue, drop device.Present(), and end the overrides with Game::Update(gameTime) / Game::Draw(gameTime).
Blast radius
Every user who starts from CNA's README: the example fails at its first include; a user who repairs the two compile errors gets a program that presents twice per frame. No library code is affected, and the other CNA examples do not repeat the pattern.
Workaround
Start from the corrected skeleton of the first-game walkthrough: #include "Microsoft/Xna/Framework/GraphicsDeviceManager.hpp", device.Clear(Color::CornflowerBlue), no Present() in Draw.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Getting started · Game loop: Draw
- Internals
- Frame internals: the draw sequence
- Known issues
- Bug index