ResolveBackBuffer and ResolveTexture2D in XNA Game Studio 4.0

ResolveBackBuffer and ResolveTexture2D in XNA Game Studio 4.0

  • Comments 10

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.

<digression>

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.

</digression>

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.

  • But, starting from GraphicsDevice where can I get the rendertarget in order to obtain the Texture2D ??

  • > But, starting from GraphicsDevice where can I get the rendertarget in order to obtain the Texture2D ??

    You create a rendertarget by calling the constructor: "new RenderTarget2D(...)"

    Then set it onto the device and draw into it.

  • The things you said here are true, but in fact when someone is trying to make some good C# code, using rendertarget instead of ResolveBackBuffer make more (and often dirty) code. Before that you were able to make some independant postprocessing components. Now... it's more hard

  • a full code example of how to resolve the backbuffer now would be great... not only theory :-)

  • I don't agree that "if you care about performance should always use rendertargets".

    Common bloom postprocessing scenario:

    1. Render scene to backbuffer

    2. Downsample from backbuffer to a smaller rendertarget

    3. Blur smaller rendertarget

    4. Add smaller rendertarget to backbuffer

    Unfortunately, this is impossible to do in XNA 4 (because step 2 is not allowed - cannot use backbuffer as a texture). Instead, this has to be done:

    1. Render scene to a full size render target

    2. Downsample fullsize rendertarget to a smaller rendertarget

    3. Blur smaller rendertarget

    4. Copy full size rendertarget to backbuffer

    5. Add smaller rendertarget to backbuffer

    This does 1 full size rendertarget copy more (at step 4) than the optimal approach - huge fillrate waste. Plus it needs one more full-size rendertarget - huge memory waste.

    We need ResolveBackBuffer back in XNA.

  • kaalus: your math is wrong.

    You forgot to account for the ResolveBackBuffer operation, which is itself a copy (and quite a slow copy on some hardware!) not to mention requiring a ResolveTexture2D surface to copy into.

    Memory usage is exactly the same for both versions.  In 3.1 using ResolveBackBuffer you would need backbuffer + resolve texture + small rendertarget.  In 4.0 you need backbuffer + rendertarget + small rendertarget.

    Now look at the amount of data copying. In 3.1:

    - Draw scene to backbuffer

    - Copy backbuffer to resolve target

    - Downsample resolve target to small rendertarget

    - Blur small rendertarget

    - Final shader pass combines resolve target + small rendertarget -> backbuffer

    In 4.0:

    - Draw scene to rendertarget

    - Downsample rendertarget to small rendertarget

    - Blur small rendertarget

    - Final shader pass combines rendertarget + small rendertarget -> backbuffer

    That's one less fullscreen copy = big GPU bandwidth saving.

  • Hi Shawn,

    I see, I didn't take into account that to use backbuffer as a texture you need to make a copy, even when not using multisampling.

    But before you can use fullsize rendertarget as a texture, you need to resolve it as well, which is a copy operation when multisampling is enabled. This is not accounted for in your bulletpoints. So it is not true that in 4.0 you can save a copy operation, or have I missed something again?

  • If you are multisampling the scene rendertarget then you will indeed need a resolve operation after drawing to it. But with the 4.0 approach, you will usually not need to multisample the backbuffer itself, so you can save a lot of bandwidth during the final bloom combine operation, and also save the final MSAA resolve that would otherwise occur during Present. A significant win for both bandwidth and memory usage.

    The only time the 4.0 approach is not more efficient than 3.1 is on Xbox, where the two are exactly identical behind the scenes.

  • I really stuck with this problem. I got a running code in 3.1 and i tried everything to get in run in 4.0... without luck. Everything what i can found on tutors or code samples are in 3.1 or older and wouldent work. I am really new in xna programming and would be happy to see a complete codesnippet how it works now with getting a screenshot. I done very well so far with my researches and converting my code into 4.1 but my screenshots are only black as black. I wrote in other forums before but nothing what i got as awnsers helped me very well. I hope i will find here a bit help.. Please..thx

  • Shawn, i'm so much loving the rendertargets i'm using them all day... they are so flexible

Page 1 of 1 (10 items)
Leave a Comment
  • Please add 4 and 4 and type the answer here:
  • Post