Release the GIL when performing SDL_GL_SwapWindow call. #8025
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Maintainer merge checklist
Component: xxx
label.api-deprecation
orapi-break
label.release-highlight
label to be highlighted in release notes.versionadded
,versionchanged
as needed.TL;DR; On Android,
SDL
implemented an Activity lock guard (SDL_LockMutex(Android_ActivityMutex);
), and that does not fit well with Python GIL ( for a specific reason).This change is not needed with the current
python-for-android
release, but it will be needed when upgrading to a newer SDL2 version: kivy/python-for-android#2673.Thanks to the SDL team who helped with the debugging, I found a deadlock condition that was causing the app to freeze.
Preface:
We use
SDL_SetEventFilter
so we can catch some events before they are added to the queue. (And that may need some rework)kivy/kivy/core/window/_window_sdl2.pyx
Line 259 in fd12906
The callback passed to
SDL_SetEventFilter
requires the GIL.kivy/kivy/core/window/_window_sdl2.pyx
Lines 27 to 28 in fd12906
Analysis:
On SDL side, the
onNativeTouch
callback is called, butAndroid_ActivityMutex
is already locked byAndroid_GLES_SwapWindow
(from a different thread), so it waits untilAndroid_ActivityMutex
gets unlocked.The
Android_GLES_SwapWindow
finishes and unlocksAndroid_ActivityMutex
soonNativeTouch
can now lockAndroid_ActivityMutex
. The touch event then gets pushed viaSDL_PushEvent
, wherethe
SDL_EventOK.callback
(which as said before requires the GIL on the Python side), gets called but looks stuck.Why? Well, meanwhile on thread
5386
ourflip
method, which is callingSDL_GL_SwapWindow
have the GIL locked, and can't release it asAndroid_GLES_SwapWindow
is stuck onSDL_LockMutex(Android_ActivityMutex);
, waiting foronNativeTouch
to unlock theAndroid_ActivityMutex
.Ouch. deadlocked.
For more info, see: libsdl-org/SDL#3679
Results after these changes:
Why you resurrected an old test app from issue kivy/python-for-android#2002 ? (https://github.com/jere-botes/KivyBench)
Well looks like we previously reverted a PR (Original: #4219, Reverts it: #6578) that added
nogil
when callingSDL_GL_SwapWindow
, so I was afraid to re-introduce an issue.From my tests, the
nogil
onSDL_GL_SwapWindow
does not create any performance drop. (Tested onSamsung S10e Android 12
andAndroid Emulator (arm64): Pixel 6 Pro API 33
(even with 200 widgets runs at 60fps).Before these changes (freeze):
Screen.Recording.2022-10-02.at.09.33.31.mov
After these changes (no freeze and 60fps with 200 widgets):
Screen.Recording.2022-10-02.at.09.42.01.mov