CNA-GAP-016: Several live GraphicsDevices share process-wide window and input slots with last-writer semantics
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. Nothing on this page was executed unless the Evidence section says so.
The window-to-renderer registry is a static, unsynchronised map with no ownership check, and TextInputEXT and Mouse keep one process-wide window slot, so two devices overwrite each other's registry entries and input target.
- Identifier
CNA-GAP-016- Category
- Functional gap
- Subsystem
- Graphics & renderers
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- IGraphicsRenderer::RegisterForWindow/UnregisterForWindow/GetForWindow; TextInputEXT and Mouse window binding with more than one GraphicsDevice
Expected behaviour
CNA allows several devices and caller-provided (borrowed) windows; each device's input routing and window lookup should stay correct while the others live.
Actual behaviour at TARGET
RegisterForWindow in IGraphicsRenderer.hpp does windowRegistry()[window] = renderer and UnregisterForWindow erases by window id, with no owner check and no lock; two devices attached to one borrowed window overwrite each other, and destroying either removes the survivor's entry (used by Mouse and the input bridge). GraphicsDevice.cpp's createOrAttachWindow sets the process-wide TextInputEXT and Mouse window slots to its window, and destroyNativeResources clears them only if they still point at it, so the last device created owns input. XNA's own Mouse.WindowHandle is also a single static slot.
Source locations
modules/graphics/include/CNA/Internal/Renderers/Common/IGraphicsRenderer.hpp— RegisterForWindow, UnregisterForWindow, GetForWindow, windowRegistrymodules/graphics/src/Xna/GraphicsDevice.cpp— createOrAttachWindow and destroyNativeResources input-slot handlingmodules/graphics/tests/CNA/Internal/Renderers/Common/IGraphicsRendererWindowRegistryTests.cpp— distinct-window and replace-on-register tests
Evidence
Checked by reading the named sources at 009d40f5; nothing was built or executed for this entry.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
IGraphicsRendererWindowRegistryTests.cpp pins distinct windows and replacement; SDL_GPU's constructor-exception test covers unregistration after a failed construction. Nothing covers two devices on one window, concurrent lookup, or two devices' input slots.
Regression test
A test with two devices on one borrowed window (destroy one, the other stays registered) and a test of input routing with two live devices.
Blast radius
Tools and editors that host several devices or share one window between devices; single-device games are unaffected.
Workaround
Use one GraphicsDevice per window and create input-owning devices last.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Deep dives
- Presentation: the window registry
- Known issues
- Functional gap index