CNA-BUG-110: Stock-effect state is captured at draw time, so a property changed after EffectPass::Apply() affects the next draw, unlike XNA
Evidence basis: source-verified at the pinned commit. 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.
GraphicsDevice calls currentEffect_->FillGpuDrawParams() inside every draw, reading the stock effect's current World, colours and so on; XNA commits effect state at Apply() and a later property change only marks the effect dirty for the next Apply.
- Identifier
CNA-BUG-110- Category
- Bug
- Subsystem
- Graphics & renderers
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- None
- Affected contract
- BasicEffect and the other stock effects' properties between EffectPass::Apply() and GraphicsDevice::Draw*Primitives
Expected behaviour
In XNA 4.0 (IL) a stock-effect setter such as BasicEffect.set_World stores the value and sets dirty flags; EffectPass.Apply runs OnApply and commits the parameters, so the draw uses the values current at Apply. Compiled effects in CNA already synchronise at Apply.
Actual behaviour at TARGET
Every draw overload in GraphicsDevice.cpp builds a GpuDrawParams with currentEffect_->FillGpuDrawParams(p) at the draw call. The sequence effect.World = A; pass.Apply(); effect.World = B; Draw(); draws with B in CNA and with A in XNA.
Source locations
modules/graphics/src/Xna/GraphicsDevice.cpp— GraphicsDevice::DrawPrimitives and DrawIndexedPrimitives (FillGpuDrawParams at draw time)modules/graphics/src/Xna/Effect.cpp— Effect::ApplyPassInternal / SyncCompiledParameters for compiled effects
Evidence
Checked by reading the named sources at 009d40f5; nothing was built or executed for this entry. XNA behaviour from the genuine XNA 4.0 Graphics IL (setter stores + dirty flags; Apply commits). The site's effect object model page already describes the draw-time capture.
Focused reproduction
// Illustrative; not compiled or run for this entry.
effect.setWorldProperty(worldA);
effect.getCurrentTechniqueProperty()->getPassesProperty()[0]->Apply();
effect.setWorldProperty(worldB); // e.g. preparing the next object too early
device.DrawIndexedPrimitives(...); // XNA draws with worldA, CNA with worldB
Current tests
No test changes a stock-effect property between Apply and a draw.
Regression test
A HEADLESS test that records the GpuDrawParams world matrix of a draw after such a change and expects the Apply-time value.
Blast radius
Code that mutates stock effects between Apply and Draw (batching helpers, shared effects across objects); the usual set-then-Apply-then-Draw order is unaffected.
Workaround
Set all properties before Apply and do not touch the effect until the draw.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Deep dives
- Effect object model: draw-time capture
- Known issues
- Bug index