| Summary: | Tabbing in/out of SDL2 app really quick leads to visible texture corruption | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Ellie <etc0de> |
| Component: | render | Assignee: | Sylvain <sylvain.becker> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | sylvain.becker |
| Version: | HG 2.0 | ||
| Hardware: | ARM | ||
| OS: | Android (All) | ||
| Attachments: |
Texture corruption that happens when tabbing in/out often & fast enough
patch test modified version of block_on_pause=0 test-case |
||
Sorry I forgot to specify, I've tested hg revision a34ab2e5ddcf. However, I've also seen this happen on 2.0.9 stable so it doesn't seem to be a recent regression Another detail I forgot: I set to SDL_ANDROID_BLOCK_ON_PAUSE to 0, so that may also be needed to reproduce this This is one of the reason of block_on_pause, you can't use the opengles context while you're in background. As soon as you enter pause state, you shouldn't use the sdl renderer, and resume when you go back into foreground. Interesting, that extends to all non-drawing actions like SDL_CreateTexture or SDL_DestroyTexture as well I assume? The garbage collector could actually trigger SDL_DestroyTexture while things are in background, so maybe that is the cause. Very interesting! I'll dive into things, seems like this is likely to be my own mistake then Yup, I refactored my destructor to not call SDL_DestroyTexture but queue up the deletions and clean them in a safe spot when in foreground, and now the problem is gone. So this was my own fault / caused by accessing SDL_Renderer while in background thanks for the help! Sylvain, is there any way we can do this internally inside SDL? This seems like a reasonable thing that we could protect against. For what it's worth, it was 99% SDL_DestroyTexture at fault, and I fixed it by manually delaying it with an internal queue until a point where I know the context is safe to use. It would be admittedly really cool if SDL2 just did that internally without requiring me to do it, but I understand if that is too complex to do Created attachment 3730 [details]
patch test modified version of block_on_pause=0
Not sure if this make sense and even if this is possible to be really robust with this. They are also probably differences between devices and android versions.
BTW, it's still possible to use block_on_pause=1, and have another thread that still run in bg.
But, I may see an issue in the non_blocking event loop:
It doesn't acknowledge that the app has read the event SDL_WILL_ENTER_BACKGROUND before actually doing the egl context backup.
It receives the java pause and immediately backup the context.
SDL_WILL_ENTER_BACKGROUND should be a warning that the context will be backed up, then, on the next pollEvent, the context is actually backed-up
Here's a modified version of block_on_pause=0. It became more similar to block_on_pause=1, but totally un-tested. To be tried ...
I did speak too soon and I am still seeing corruption, just way more rarely. And indeed, when getting SDL_WILLENTERBACKGROUND I do still touch the context in many cases, so that could be part of the reason :-O I am still trying to figure out what causes it. But there isn't much else in my code that could be it at this point since I gated all the drawing and texture creation/destruction operations with a global access lock Created attachment 3748 [details] test-case I've pushed the fix: https://hg.libsdl.org/SDL/rev/f6c7e5e03f60 And here's a test-case to see it. Without that fix, it remains black after background/foreground. In non-blocking mode: - we wait that the user application fetch SDL_APP_DIDENTERBACKGROUND before backup-ing the context. So that it's the same behavior as for the blocking mode. I've tested with rev. f6c7e5e03f60 for a while (no additional patches) and so far everything looks fine, even when tabbing out during the occasional hangs. Thanks once more for the great work! I'll still test further to be more certain this time, but it seems like the new wait for SDL_APPDIDENTERBACKGROUND fetch fixed it! It looks like this is fixed, thanks guys! |
Created attachment 3729 [details] Texture corruption that happens when tabbing in/out often & fast enough If you write a test SDL2 android app that uses: 1. Only SDL_Renderer in accelerated mode with SDL_Texture (no direct OpenGL access) 2. ... and does nothing special on app pause & resume, especially not dump/recreate the renderer 3. ... redraws its SDL_Textures continuously and has a bunch of them Then if you tab in/out of the app quickly enough and often enough, it appears that suddenly a big bunch of the textures suffers major corruption! (see attached screenshot) I have also noticed once this happens the CPU-side seems to be fine (no misbehaving that would make me guess system memory corruption, no crashes) but suddenly rectangles are sometimes the wrong color, or elements are plain missing even of new textures, so on the GPU side something big seems to have broken down Since this is quite central to an app working correctly when it runs a little longer and the user has it in the background and tabs in/out, it would be neat if that could be fixed