How do I save a large PNG async?

I really have 2 questions, and I think answering question #2 would negate the need for question 1. I’m working on a 2D game.

Question 1:
I have a FOW texture that is quite large, and in order to persist it, I’m saving it as a PNG as follows:

RenderTexture.active = FOWRenderTexture;
                
Texture2D texture = new Texture2D(FOWRenderTexture.width, FOWRenderTexture.height, TextureFormat.RGB24, false);

texture.ReadPixels(new Rect(0, 0, FOWRenderTexture.width, FOWRenderTexture.height), 0, 0);
texture.Apply();
                
byte[] bytes = texture.EncodeToPNG();
                
File.WriteAllBytes(filePath, bytes);
                
// Clean up
RenderTexture.active = null;
Destroy(texture);

This works well, except that it is a heavy process and hangs the game.

I tried pushing the save off the main thread using await Task.Run, but most of the saving function is required to be on the main thread (throws an error if inside the await). I can push the File.WriteAllBytes to a different thread, but apparently that’s not the heavy part, since it still hangs.

Any ideas for how to push this whole chunk off the main thread?

Question 2:
Alternatively, instead of saving the actual texture, I think it might be smarter to save some sort of simple set of map coordinates that can translate to and from the actual texture. So as the player walks around, maybe every time they enter a new 10x10 chunk, a simple representation of that chunk gets added to an array. Then I can just save and load the array, and when the game loads it uses the array to clear fog over chunks that have been entered.

Does this make more sense? I’m trying to figure out how to actually implement this.

Thanks for any thoughts.

EncodeToPng and/or ReadPixels are likely the time sink (use Profiler to verify).

Writing bytes to disk is already cached by the OS on fixed drives and thus returns even before everything is guaranteed to be physically written. Only on ejectable media write-cache is disabled (on Window at least, and by default).

As the ReadPixels method needs to load the texture data from the GPU onto main memory, this is also likely very slow as the manual indicates. The page also offers suggestions for alternatives.

Yeah it looks like you’re right.

I clearly need to learn how to use the profiler better.

I also think despite figuring this out, I’m better off storing either a List or if I can figure it out a HashSet and then using that to remake the fog clearance.

Thanks for the tips.