Page MenuHome

BGE: Save screenshots in a different thread
ClosedPublic

Authored by Sybren A. Stüvel (sybren) on Sep 7 2015, 11:34 AM.

Details

Summary

This patch allows the game engine to keep running while performing things like PNG compression and disk I/O.

As an example, my crowd simulation rasterizer saves a screenshot for every frame. This now takes up 13 msec per frame, which was 31 msec before this patch. Effectively, it allows the simulation to save every frame and still run at 60 FPS.

Diff Detail

Repository
rB Blender

Event Timeline

Sybren A. Stüvel (sybren) retitled this revision from to BGE: Save screenshots in a different thread.
Sybren A. Stüvel (sybren) updated this object.
Sybren A. Stüvel (sybren) set the repository for this revision to rB Blender.

Demo blend file

. Press [P] to start.

Without this patch: logic takes approximately 30 msec per frame, with a 30 FPS frame rate.
With this patch: logic takes approximately 16 msec per frame, with a 60 FPS frame rate.

Porteries Tristan (panzergame) requested changes to this revision.Sep 8 2015, 11:48 AM
Porteries Tristan (panzergame) edited edge metadata.

Blender player doesn't use that, why ? Can you share this move this code in RAS_ICanvas to share it for blender player ?

source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
96

Add BLI_task_pool_free(m_taskpool); because it create a memory leak.

This revision now requires changes to proceed.Sep 8 2015, 11:48 AM
Sybren A. Stüvel (sybren) edited edge metadata.
Sybren A. Stüvel (sybren) updated this object.

Moved common code to RAS_ICanvas, using it from both Blender and Player.
Solved memory leak.

Sybren A. Stüvel (sybren) edited edge metadata.

Removed some unnecessary includes and whitespace changes.

source/gameengine/Rasterizer/RAS_ICanvas.h
288 ↗(On Diff #5038)

you should use camelcase, no ?

291 ↗(On Diff #5038)

it's better to rename it : save_screenshot_thread_func like for animation task function ?

source/gameengine/Rasterizer/RAS_ICanvas.h
288 ↗(On Diff #5038)

Renamed function to save_screenshot_thread_func

Overall, looks good to me; just some style preferences for more defensive programming. Have you made sure to test for new memory errors with something like Valgrind? I'm guessing you've also tested both the embedded player and the Blenderplayer?

source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp
351

I would add a comment here stating that save_screenshot frees dumprect.

source/gameengine/GamePlayer/common/GPC_Canvas.cpp
165 ↗(On Diff #5041)

I would add a comment here stating that save_screenshot frees dumprect.

source/gameengine/Rasterizer/RAS_ICanvas.h
63 ↗(On Diff #5041)

Maybe this struct and the static function (if it does not remain as a member function) should be moved to the source file. I don't see much need to make them part of a public interface. In other words, limit the scope of the threading helper data/functions to only the file that needs it.

291 ↗(On Diff #5041)

Does this need to be a member function of RAS_ICanvas? I think it could just be a static function in the source file. At the moment any derived class could call this function directly, which seems odd.

Sybren A. Stüvel (sybren) edited edge metadata.

Moved save_screenshot_thread_func and ScreenshotTaskData out of
RAS_ICanvas class. And yes, I checked with Valgrind, no new leaks are
found. Plenty of other stuff is reported though.

Added comments and a declaration.

Sybren A. Stüvel (sybren) marked 5 inline comments as done.Sep 10 2015, 9:25 AM

Something that we'll need to think about as we use BLI_task in more and more places in the BGE, is how we want to instantiate the task scheduler and pools. Should there be a mostly global location (like KX_KetsjiEngine) where we do this, or should individual components be responsible for their own schedulers? In this case, I'm okay with the canvas having it's own since it doesn't need to manage task dependencies. It's really just using BLI_task as a higher-level threading API to launch one thread.

source/gameengine/Rasterizer/RAS_ICanvas.cpp
61 ↗(On Diff #5048)

I don't know how useful it is to forward declare this function, but I guess it doesn't hurt either.

In this case, I did it to prevent a dependency cycle between KX_KetsjiEngine and the canvas. The canvas is created first, so getting it to use the engine's task pool would become hairy.

I agree that it may be a good idea to have some globally-available task scheduler. However, creating one with proper task scheduling isn't trivial, but at least a global BLI_task may be a good start.

source/gameengine/Rasterizer/RAS_ICanvas.cpp
61 ↗(On Diff #5048)

It was useful enough to silence a gcc compiler warning about an undeclared function. I didn't know it was something warning about, but didn't want to introduce new warnings either.

Mitchell Stokes (moguri) edited edge metadata.

Testing with Valgrind (memcheck) and Helgrind would be nice. Otherwise, looks good to me.

This revision is now accepted and ready to land.Nov 14 2015, 12:13 AM
This revision was automatically updated to reflect the committed changes.