# SetRenderTarget(null) clearing previous draw calls

I'm not sure if everything's working as it should be or whether I'm just not doing something properly, but I couldn't find anything that discussed this so I thought I'd ask here.

I'm using Monogame 3.2 for Windows.

In my game I'm drawing sprites to the back buffer, then I set a render target and draw to that, then I switch back to the back with SetRenderTarget(null) so I can draw my render target but I find that all the drawing I did before I set the render target the first time has been cleared. Is this just how it works or have I done something wrong?

EDIT: The pink rectangle is the render target.

Here is example code:

        // Render some stuff first
spriteBatch.Begin();
spriteBatch.Draw(mPixel, new Rectangle(10, 10, 500, 50), Color.Red);
spriteBatch.End();

// Render to target
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.Clear(Color.Pink);
spriteBatch.Begin();
spriteBatch.Draw(mPixel, new Rectangle(10, 10, 500, 50), Color.Blue);
spriteBatch.End();

// Render back to backbuffer
GraphicsDevice.SetRenderTarget(null);
spriteBatch.Begin();
spriteBatch.Draw(renderTarget, Vector2.Zero, Color.White);
spriteBatch.End();


Here is the result, I expected the first red rectangle to remain behind the render target:

• Haven't used XNA but DX, but shouldn't you set the rendertarget back to backbuffer and not null? This is what you do in DX at least or otherwise all the rendering is ignored – JarkkoL Sep 23 '14 at 0:25
• in XNA setting the render target to null sets it to the back buffer. It's more for setting it to custom render targets – Joseph Little Sep 23 '14 at 17:27
• It looks like it's not being cleared, but you're drawing over what you had previously draw when you draw the render target. – fastinvsqrt Sep 24 '14 at 20:30
• The pink rectangle is the render target, so since it doesn't physically cover the first rectangle I drew I thought it wouldn't affect anything. Or is this not the case? – Joseph Little Sep 25 '14 at 16:06

Having the exactly same issue here - the following code snipped works perfectly fine:

private void DoRenderSkybox (GameTime Time) {
this.Device.SetRenderTarget(this.GridTexture);
this.Device.SetRenderTarget(null);

// compute a temporary transformation matrix containing
// the combined world and projection transfromation
Matrix WorldViewProjection = this.Camera.View * this.Camera.Projection;

// set the render target to the back buffer in any case
this.Device.SetRenderTarget(null);

// assign the vertex - declaration and the vertex- and the index - buffer
this.Device.SetVertexBuffer(this.SkyboxVertices);
this.Device.Indices = this.SkyboxIndices;

// choose the appropriate technique for the current render pass
this.SceneEffect.CurrentTechnique = SceneEffect.Techniques["Skybox"];
this.SceneEffect.CurrentTechnique.Passes[0].Apply();
this.SceneEffect.Parameters["WorldViewProjection"].SetValue(WorldViewProjection);

// finally render the sykbox with disabled depth stencil buffering
this.Device.DepthStencilState = DepthStencilState.None;
this.Device.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, 36, 0, 12);
this.Device.DepthStencilState = DepthStencilState.Default;

//this.Device.SetRenderTarget(this.GridTexture);
//this.Device.SetRenderTarget(null);
}


However, if I assign (and right away unassign) the render target at the end of the function like so:

    private void DoRenderSkybox (GameTime Time) {
//this.Device.SetRenderTarget(this.GridTexture);
//this.Device.SetRenderTarget(null);

// compute a temporary transformation matrix containing
// the combined world and projection transfromation
Matrix WorldViewProjection = this.Camera.View * this.Camera.Projection;

// set the render target to the back buffer in any case
this.Device.SetRenderTarget(null);
this.Device.Clear(Color.Black);

// assign the vertex - declaration and the vertex- and the index - buffer
this.Device.SetVertexBuffer(this.SkyboxVertices);
this.Device.Indices = this.SkyboxIndices;

// choose the appropriate technique for the current render pass
this.SceneEffect.CurrentTechnique = SceneEffect.Techniques["Skybox"];
this.SceneEffect.CurrentTechnique.Passes[0].Apply();
this.SceneEffect.Parameters["WorldViewProjection"].SetValue(WorldViewProjection);

// finally render the sykbox with disabled depth stencil buffering
this.Device.DepthStencilState = DepthStencilState.None;
this.Device.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, 36, 0, 12);
this.Device.DepthStencilState = DepthStencilState.Default;

this.Device.SetRenderTarget(this.GridTexture);
this.Device.SetRenderTarget(null);
}


nothing is being rendered - I got a purple screen! Does that make any sense to you!

P.S. I know the sample doesn't make much sense (like assigning and right away unassigning a render target). The real scenario here is much more complicated but I was able to narrow down the essence of the problem to this strange behaviour, which I can demonstrate in this very simple example!

EDIT: Just found the solution by further examining the API: Adding Params.RenderTargetUsage = RenderTargetUsage.PreserveContents; into the PresentationParameter structure solves the problem.

It looks to me that the content of the backbuffer is - like with render targets being destroyed whenever you switch to another render target.

• Thanks! I've been using a work around for this for a long time now but I appreciate your answer :) – Joseph Little Jan 28 '15 at 13:38