Closed Akz- closed 7 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
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.
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:
tglPresentBuffer()
before switching back to to on-screen framebuffer. But for dirtyrect it is much more complex, as each tglPresentBuffer()
call causes the current draw call list to become the previous frame's, breaking the assumption that calls are similar between frames. Restoring this assumption means moving previous call queue to per-framebuffer structure. Which pulls with it the linear vertex memory allocator. And probably also the current frame call queue, to simplify dirty rect comparison. And requires extending the list of draw call operations to include blitting of such buffers, which are different from existing bitmap-only blit operations.The first way will likely produce the shortest code, and I started poking at it.
The roulette players occasionally disappear in the casino with the TinyGL renderer.
7f560daf0475bab appears to be the first bad commit.