Add Android Vulkan swapchain support - #109
Conversation
| return nullptr; | ||
| mainWindow = owner; | ||
| return reinterpret_cast<SystemApi::Window*>(app->window); | ||
| return reinterpret_cast<SystemApi::Window*>(&app->window); |
There was a problem hiding this comment.
is app persistent? Any risk that NDK might destroy it sporadically, like window?
There was a problem hiding this comment.
It stays alive until android_main returns. The NDK glue waits for android_app_destroy to signal completion before freeing it; TERM/INIT_WINDOW only replace its window field. The handle now points to our own static nativeWindow instead of app->window.
|
Just noting: I have only limited amount of time on this week, but will do my best to get into review by Friday/weekend. There are still some things that look suspicious in PR. There are several places that look-like you assuming |
|
Checked, yes, in the current Android backend they are effectively the same thread. So the Your I think surface-loss recovery should be deferred until control returns to the event loop, then recreate after pending window events are processed. But, I'm on vacation until Monday too, so I can't introduce any fixes until then. |
|
The example now performs initial creation and reset in the render callback, after Android has processed window events. Android swapchain creation reports recoverable failures instead of retrying internally, so each retry returns through the event loop. Surface-query failures are handled too, and VK_INCOMPLETE enumeration results are retried. The acquire check is removed. The present check is retained to detect a window replacement between frames; the pointer does not change during rendering. |
cf20dfb to
5263484
Compare
|
Understood - changing createSwapchain() to throw SwapchainSuboptimal broke the existing recovery contract. Keeping recovery internal means Android must process pending window events during the retry. The normal event path can re-enter rendering, and even polling native events directly can dispatch resize and recursively call reset(). Would you prefer to settle #110 first and adapt this PR afterward, or keep the current API and add an internal Android lifecycle-processing path that defers application callbacks during recovery? |
|
I've experimented a bit with current state of the path. I don;t think it can work. Swapchain s(device, hwnd); // constructor
...
// s.acquire(); - not in api but hidden i constructor and present
device.present(s);
s.reset();
...
// getters
uint32_t w() const;
uint32_t h() const;
uint32_t currentImage() const;
uint32_t imageCount() const;and use-case in frame: try {
...
device.present(s); // can throw
}
catch(SwapchainSuboptimal&) {
s.reset(); // recovery cant throw!
}If Android allows asynchronous failure, everywhere, but does not allow recovery until event loop make progress - we stuck.
Note on any new top-level api. |
|
At this point option 2 (and flags to keep activity alive) is probably best of the worst. |
|
Implemented option 2. Surface loss is now fatal; creation/reset retry only out-of-date/suboptimal swapchains. Removed deferred recovery and the surface-loss state, and expanded the example's configChanges flags. Checked this revision on-device: rendering continued after background/resume, rotation and screen off/on. Exit/reopen also worked, with no crashes. |
|
@Solessfir Also, |
|
Checked your cleanup on Android. Removed the cached native window and double pointer, and made Rendering and rotation work. Home and screen locking destroy the surface on this device, so the example now exits and reopens cleanly. Repeated shutdown testing caught a JIT-thread SIGSEGV during |
Pff... Android being android :D |
|
Great work @Solessfir , merged! |
Adds Vulkan rendering to the Android window backend introduced in #108.
The example manifest handles screen, input and UI-mode configuration changes without recreating the Activity. Android may still destroy the window when backgrounded or locked, ending the application.
Input and audio remain separate work.