GraphicsDevice.GetBackBufferData is sloooow

Hi all! So what I’ve been working on is a thing that records gameplay, and then at the end of the game compresses it to an animated gif, which the player can then share on social media. It’s coming along great and it’s nearly there, but I’ve ran into a few wrinkles…

The way I’m currently recording gameplay is by grabbing a screenshot using GraphicDevice.GetBackBufferData(). It works great on desktop because there is horsepower to spare, but on android/iOS the performance is in the toilet. As soon as I turn the recorder on, I get a janky frame everytime it calls GetBackBufferData. I tried to cheat and wrap it in Task.Run to pitch to a separate task, which fixes the performance issue but on opengl platforms it grabs a blank screen.

My next step is to try spinning up a dedicated BackgroundWorker to grab screenshots, maybe that will work but I don’t really have my hopes up. Does anyone have a better idea? Is there some other technique that would be better than GetBackBufferData? Is there a way to speed it up?

You can check it out here if you want:
https://github.com/dmanning23/MonogameScreenTools

and here is a full-blown example game for windows, android, & ios:
https://github.com/dmanning23/MonogameScreenToolsExample

Cheers!

idunno, I might just bail on this whole project and just create a Xamarin binding library for Megacool.co :confused:
Just feels like quitting though :wink:

It’s possible to make the GL.ReadPixels (GraphicsDevice.GetBackBufferData) call faster by using PBO’s (PixelBufferObjects).

I roughly described that in this post:

Here is the technical description:
http://www.songho.ca/opengl/gl_pbo.html

However we need to implement some missing things in the MonoGame.Framework first like the GL_PIXEL_UNPACK_BUFFER buffer target.


To get around the performance issue in your current solution you could work with intervalls.

if you look at PlatformGetBackBufferData() you see that it has to flip the buffer up/down.
it uses 3 copies for each pair of rows. you can make it 2/3 times faster (1 copy per row + a full size tmpBuffer), but I assume that’s not good enough.

Edit
possibly you want a custom build of MG or use reflection to get the flipped backbuffer and save it.
then correct it in post processing.

I never tried to do anything like that but im thinking that getting the back buffer would be slow for other reasons then the ones stated. Primarily because i think that a call to the backbuffer is actually interacting with more then just monogame in reality its also dealing with the os calls so i think its more like a hardware interrupt though im not sure this is even remotely true anymore.

Wouldn’t it be faster to rendertarget it then cast to texture2d then set data or save as png it ?
Anyways didn’t someone around here already write a gif creator ?

Yeah I started from a fork of jmoral4’s work. His code used GDI for gif creation though, so it couldn’t be ported to platforms other than windows. I refactored it to use ImageSharp so there are a lot more image manipulation options available, ported to android and iOS, did a bunch of optimization to get .gif creation under 10 seconds on a phone, and pushed up in a nuget package. It’s pretty much production ready, just a little janky right now while recording gameplay. The screenshot capability works perfectly though :slight_smile: It’ll even ask for the correct Android permissions and save to external storage :open_mouth:

I think your rendertarget idea will probably solve the jankiness problem. I’m going to try and get this Megacool binding library working first, it’d be nice to get the social sharing and link-tracking out of the box.

Thanks again! Cheers!

Ok Megacool was a bust, I got the whole binding library working and found out that their native Android implementation just dumps the main view to a buffer. They haven’t finished OpenGL screen capturing yet, so it doesn’t work on MonoGame. (I think their main focus is Unity developers, not native iOS and Android)

The good news is the rendertarget thing worked perfectly! This thing is ready to go… I feel like I’m living on the edge by using the ImageSharp prerelease package in production, but whatever this app has like 10 downloads total :wink:

Cheers!

2 Likes

ImageSharp is doing really well, getting close to RC1 apparently. A lot of people use the bleeding edge builds, so don’t worry too much :wink:

1 Like

Yeah, it is incredibly stable for prerelease software.

1 Like