Faster way to encode RenderTexture to png

So, I have an in-game camera the player can use, and I would like to be able to save the images instantly without noticing a lag. So far, I create render a camera into a RenderTexture and I feed it in this extension method:

public static void SaveToFile(this RenderTexture renderTexture, string name)
{
	RenderTexture currentActiveRT = RenderTexture.active;
	RenderTexture.active = renderTexture;
	Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height);
	tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
	var bytes = tex.EncodeToPNG();
	System.IO.File.WriteAllBytes(name, bytes);
	UnityEngine.Object.Destroy(tex);
	RenderTexture.active = currentActiveRT;
}

It does work, but ReadPixels is slow as hell and it creates a noticeable hiccup. I tried several ways to smooth out the performance spike created by it. First, I tried to call this method from another thread, but it has to be called in the main thread. Then, I tried to use renderTexture.GetNativeTexturePtr() with Marshal.Copy(), but I can’t find a way to do it. I guess the only other way is to make a Native plugin, but my knowledge in C/C++ is pretty limited. Anybody has any idea on this?

Have a look at Application.CaptureScreenshot, I believe it runs asynchronously, and handles all the file I/O for you as well.

More information on this Unity wiki page, which outlines several methods of capturing screenshots.

(This method wasn’t available back when the question was asked, but it’s still on the first page of google so)
The modern (2019+) method to do that is to read texture data using AsyncGPUReadback (Unity - Scripting API: AsyncGPUReadback) - it’s not fast, but it does not block the main thread at least; and then encode the data using ImageConversion.EncodeArrayToPNG (Unity - Scripting API: ImageConversion.EncodeArrayToPNG) or a similar method. This one blocks, but according to the docs it’s thread-safe.