residualvm / residualvm

ResidualVM main repository
GNU General Public License v2.0
396 stars 110 forks source link

GRIM: Roulette players disappear with TinyGL renderer #1042

Closed Akz- closed 7 years ago

Akz- commented 10 years ago

The roulette players occasionally disappear in the casino with the TinyGL renderer.

casino

7f560daf0475bab appears to be the first bad commit.

aquadran commented 9 years ago

I can confirm issue with 0.3.0 branch, but it's gone after revert to more stable state of tinygl on branch 0.2.0

vpelletier commented 9 years ago

I could reproduce this accidentally by repeatedly switching between opengl shaders and tinygl (to re-parse shaders as I modify them). From what I could see, this happens when the save/load is done while players are animated: after load, they finish their current animation and disappear. Then the croupier gets stuck when he waits for players to finish their animation.

vpelletier commented 7 years ago

I investigated this issue.

The problem starts with an optimisation deep in GRIM lua scripts for these scenes: there are many actors in these, so when the game detects software rendering, instead of rendering all polygons of all actors on each frame, it renders several actors to a framebuffer and blits that to screen on ever frame instead. This is done by selecting an off-screen buffer, issuing draw calls, then selecting the default (on-screen) buffer again for subsequent calls. Once the actor is expected by game scripts to have been rendered to such off-screen buffer, it unbinds the actor from the scene so it does not get rendered anymore. Until it decides it wants that actor to move, and re-adds it to the scene.

7f560daf0475bab1e387f39daa47ce0acbb58b19 is the first bad commit because in that commit, rendering does not happens at glIssueDrawCall time anymore, so nothing actually gets rendered to the off-screen buffer.

Such draw postponing is the first requirement toward dirty rectangle support, which basically extends the freeze principle to the whole scene: detect which calls diverge from previous frame, and only draw the area they cover, often updating tiny parts of the screen only. So it needs to have the list of rendering operations for later comparison and execution.

Because GRIM uses the same lua API function to manage the "Hardware Accelerated" menu option and this freeze/thaw system, the proper fix is not just to fake always being hardware-accelerated (although it is very efficient, and incidentally a nice way to stress-test dirty rectangle mechanism with these heavy scenes).

I see a few ways:

The first way will likely produce the shortest code, and I started poking at it.