I guess textures don't implement ICloneable
for a good reason: it would be too easy to accidentally cause a FPS sink. One might think, XNA stores texture resources in the managed memory pool, so when someRt.GetData()
gets called, texture data seems to be already there for locking, which should be fast, right? Not really, since getting actual data requires the driver to flush all commands in queue, wait for GPU to process them, and then send fresh data back for reading.
Chances are, if you're going to do your thing on a per-frame basis, it will be better to just render twice. But if you want to clone a texture once in while, a simple way of deep cloning is to walk through mipmap levels and clone them one by one:
static RenderTarget2D CloneRenderTarget(RenderTarget2D target)
{
var clone = new RenderTarget2D(target.GraphicsDevice, target.Width,
target.Height, target.LevelCount > 1, target.Format,
target.DepthStencilFormat, target.MultiSampleCount,
target.RenderTargetUsage);
for (int i = 0; i < target.LevelCount; i++)
{
double rawMipWidth = target.Width / Math.Pow(2, i);
double rawMipHeight = target.Height / Math.Pow(2, i);
// make sure that mipmap dimensions are always > 0.
int mipWidth = (rawMipWidth < 1) ? 1 : (int)rawMipWidth;
int mipHeight = (rawMipHeight < 1) ? 1 : (int)rawMipHeight;
var mipData = new Color[mipWidth * mipHeight];
target.GetData(i, null, mipData, 0, mipData.Length);
clone.SetData(i, null, mipData, 0, mipData.Length);
}
return clone;
}