The bad news:
If you had a program using
rendertargets that worked with the XNA Framework 1.0, it might not
still work with 2.0.
The good news:
Things are actually much more consistent now, honest!
Let me
explain...
How rendertargets used to work (1.0)
On Windows:
- Each rendertarget lives in a
separate piece of video memory
- After you select the
rendertarget, you can draw onto that video memory
- When you are
done drawing, you call GetTexture to reuse that same area of video
memory as a texture
- You can draw onto the same rendertarget as
many times as you like, and its contents will always remain valid
On Xbox:
- All rendertargets share a single
special piece of EDRAM memory
- This means only one of them can
physically exist at a time
- When you finish drawing to a
rendertarget, the GraphicsDevice.ResolveRenderTarget method copies from
EDRAM to a separate area of texture memory
- You can then use
this texture in any way you like
- But EDRAM is now being reused
by some other rendertarget!
- This won't work like you expect:
- Draw to backbuffer (EDRAM contains what you just drew)
- Switch to rendertarget
- Draw to rendertarget (EDRAM
contains what you just drew)
- Resolve rendertarget (RenderTarget.GetTexture()
contains a copy of what you drew)
- Switch back to
backbuffer (problem! the act of selecting a different rendertarget
has overwritten what you previously drew to the backbuffer, so the EDRAM
no longer contains that backbuffer image)
- The rules
in summary:
- Any time you change rendertarget, the contents
of EDRAM are overwritten, so all previous rendertargets (including the
backbuffer) are clobbered
- Rendertarget data which was resolved
into the associated texture remains valid, however
- This is ok:
- Draw to rendertarget A
- Draw to rendertarget B
- Draw
textures from rendertargets A and B onto rendertarget C
- But
this is not:
- Draw to rendertarget A
- Draw to
rendertarget B
- Switch back to A and continue drawing over the
top of it
Problem with the 1.0 behavior:
It was far too easy to write a program that worked fine on one
platform, but then rendered incorrectly when you run it on the other!
How rendertargets work now (2.0)
By
default:
- You get what used to be the Xbox behavior
- On Xbox, it works exactly the same as before
- On Windows,
we automatically clear your rendertargets at the right times to emulate
the Xbox behavior
- This is fast on both platforms (Clear is very
cheap)
If you don't like that default:
- You
can specify a different RenderTargetUsage
- RenderTarget2D
constructor parameter
- To change it for the backbuffer, use the
GraphicsDeviceManager.PreparingDeviceSettings event to alter
GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage
- Specify RenderTargetUsage.PreserveContents to get what used to be
the Windows behavior
- Works exactly the same as before on
Windows
- On Xbox, we automatically copy data back from the
resolved texture into EDRAM to restore its contents when you change
rendertarget
- This is not cheap! Use it if you must, but be
aware of the performance penalty
- Specify
RenderTargetUsage.PlatformContents to get the exact same behavior as
1.0, which is different on Xbox versus Windows
Shawn
recommends:
- If at all possible, use the default
RenderTargetUsage.DiscardContents mode. This gives good performance and
consistent behavior on both platforms.
Other good
stuff:
- In 2.0, you no longer need to call the
GraphicsDevice.ResolveRenderTarget method. In fact you can't, because we
removed it. We now do this automatically when you switch away from the
rendertarget.
- In 2.0, we now support multiple simultaneous
rendertargets (MRT) on Xbox.