As of version 4.0, XNA Game Studio no longer supports the ResolveBackBuffer API and associated ResolveTexture2D class.
This API did basically the same thing as RenderTarget2D (draw using the GPU, with the result ending up in a texture), just in a slightly different way. Overlap isn’t always a bad thing, but exact duplication is rarely sensible!
One way to judge whether there are good reasons for overlapping functionality is to answer the question: “what should we tell customers who are trying to choose between the two options?” If the verdict comes out as “always prefer A over B”, or “it doesn’t matter, either way works fine”, then we don’t need both.
Here is the guidance we came up with:
- Rendertargets are more flexible. You can only use ResolveBackBuffer if the image you are trying to capture has the same size and format as the backbuffer.
- ResolveBackBuffer is useful if you want to capture something that was drawn by code you do not control, so you had no chance to redirect this drawing into a rendertarget.
- There is no significant difference in memory usage.
- The performance implications are somewhat complex:
Rendertarget ResolveBackBuffer Windows Fast Slower when not multisampling. Same as rendertargets when multisampling is enabled. Xbox 360 Fast Same as rendertargets. Windows Phone Fast Same as rendertargets for portrait mode games. Order of magnitude slower for landscape games.
An obvious conclusion is that if you care about performance, you should always use rendertargets. Depending on the situation, ResolveBackBuffer may be the same speed or slower, but it is never faster.
The compatibility implication of performance difference is a complex topic. Clearly, we cannot expect all platforms to have identical performance! (phones are fundamentally slower than Xbox 360 consoles). We cannot even expect all platforms to have the same relative performance (a game which is CPU bound on one PC may well be GPU bound on another). But it would be going too far to say that performance differences can never count as a compatibility break. For instance:
Alice writes a tutorial on how to implement the Flobydryglap rendering algorithm. As an Xbox developer, Alice sees no performance difference between rendertargets and ResolveBackBuffer. She arbitrarily chooses ResolveBackBuffer.
Bob tries to implement Alice’s tutorial on his Windows Phone device, but is disappointed by the poor performance. His friend Charlie takes a look, and says this is because his game happens to be running in landscape mode. He can make it several times faster by changing the code to use rendertargets.
Technically, this code did 'work', but the performance difference meant it was not directly portable from one platform to another.
What about people who do not care about performance? Are there times when it is useful to read from the backbuffer, regardless of how long that takes? We could think of exactly two such situations:
- Capturing screenshots
- Unit tests that verify rendering results
Both involve copying backbuffer data all the way back to the CPU, not just into a texture on the GPU. So here’s what we decided to do:
- Remove ResolveBackBuffer and ResolveTexture2D
- Add a new GraphicsDevice.GetBackBufferData API, which does the same thing as what used to be ResolveBackBuffer immediately followed by ResolveTexture2D.GetData
GetBackBufferData does a CPU readback, so it is never exactly fast on any platform. Handy for screenshots and unit tests, but not fast enough for anyone to be tempted to use it in performance sensitive code, and thus no danger of cross platform performance differences causing unpleasant surprises.
That was the plan, anyway…
Late in the day, we discovered some subtle issues with interactions between the D3D runtime, system compositor, and image scaler, which are not particularly interesting to explain in detail, but meant it was not possible to make GetBackBufferData (or ResolveBackBuffer, for that matter) work reliably on Windows Phone.
So, reluctantly, we removed GetBackBufferData from the Reach profile. Game Studio 4.0 still supports it, but only for HiDef games on Windows and Xbox. This is a software problem rather than hardware limitation, so it is possible we may be able to add GetBackBufferData back into Reach in some future version, but right now we are busy with other higher priority work, so this didn’t make the cut for the 4.0 release.