4

I'd like to change my RenderTargets between SpriteBatch.Begin and SpriteBatch.End. I already know this works:

GraphicsDevice.SetRenderTarget(target1);
SpriteBatch.Begin()
SpriteBatch.Draw(...)
SpriteBatch.End()
GraphicsDevice.SetRenderTarget(target2);
SpriteBatch.Begin()
Spritebatch.Draw(...)
SPriteBatch.End()

But I'd really like to make this work:

SpriteBatch.Begin()
GraphicsDevice.SetRenderTarget(target1);
SpriteBatch.Draw(...)
GraphicsDevice.SetRenderTarget(target2);
Spritebatch.Draw(...)
SpriteBatch.End()

I've ever seen anybody doing this, but I didn't find any reason why.

EDIT: a little more about why I want to do this:

In my project, I use SpriteSortMode.Immediate (to be able to change the BlendState when I want), and I simply iterate through a sorted list of sprites, and draw them all. But now I want to apply mutli passes shader on some sprites, but not all! I'm quite new to shaders, but from what I understood, I have to draw my sprite on an intermediate one using first pass, and the draw the intermediate sprite on the final render target using the second pass. (I'm using a gaussian blur pixel shader). That's why I'd like to draw on the target I want, using the desired shader, without having to make a new begin/end.

s0ubap
  • 267
  • 3
  • 8
  • Well, does the second code piece work? And if it does, is it as fast as the first one? – user1306322 Mar 01 '13 at 15:19
  • @user1306322 no it doesn't work... the result is kind of weird, it's like my first draw call finally draws on the current RenderTarget anyway – s0ubap Mar 01 '13 at 15:21
  • Then you found the reason why it doesn't work. When you call `SptireBatch.End()` the whole batch of sprites accumulated from the `Begin` call until now is sent to the current render target. Suppose it's expected to work like that. – user1306322 Mar 01 '13 at 15:23
  • @user1306322 Ok, but even when I'm using SpriteSortMode.Immediate? Shouldn't it instantly draw on the render target at each draw call? – s0ubap Mar 01 '13 at 15:25
  • 1
    `Immediate` will send each sprite separately, after setting appropriate render states in `Begin`. It is the only sort mode that does not batch (doing everything in `End`). – Andrew Russell Mar 01 '13 at 16:09

1 Answers1

3

The question is: Why do you want to change the render target there?

You won't have any performance improvements, since the batch would have to be split anyways when the render target (or any other render state) changes.

SpriteBatch tries to group the sprites by common attributes, for example the texture when SpriteSortMode.Texture is used. That means sprites sharing a texture will be drawn in the same draw call (batch). Having less batches can improve performance. But you can't change the GPU state during a draw call. So when you change the render target you are bound to use two draw calls anyways.

Ergo, even if the second example would work, the number of batches would be the same.

Lucius
  • 3,705
  • 2
  • 22
  • 41
  • Thanks for the answer. I've just edited my post, and tried to explain why I want to do this. – s0ubap Mar 01 '13 at 17:43
  • Okay, now I get where you are coming from. Have you done any profiling on that matter? Did you test what performance cost you have by calling `Begin` again? I think on the long run you should consider switching from `SpriteSortMode.Immediate` to something like `SpriteSortMode.Texture`. With *immediate* every sprite you draw will issue its own draw call, which is probably a waste of batches. If it's only the blend state that is changing, consider sorting beforehand and having a `Begin` / `End` block *per* BlendState. But you would have to profile the changes to be sure. – Lucius Mar 02 '13 at 15:38