mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Turn off the Vulkan thread when switching away from the app.
This commit is contained in:
parent
b66f7ea909
commit
aa3256f4e8
5 changed files with 75 additions and 39 deletions
|
@ -1,4 +1,5 @@
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
#import "ViewControllerCommon.h"
|
||||||
#import "ViewController.h"
|
#import "ViewController.h"
|
||||||
#import "ViewControllerMetal.h"
|
#import "ViewControllerMetal.h"
|
||||||
#import "iOSCoreAudio.h"
|
#import "iOSCoreAudio.h"
|
||||||
|
@ -119,6 +120,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) applicationWillResignActive:(UIApplication *)application {
|
-(void) applicationWillResignActive:(UIApplication *)application {
|
||||||
|
INFO_LOG(G3D, "willResignActive");
|
||||||
|
|
||||||
|
[self.viewController willResignActive];
|
||||||
if (g_Config.bEnableSound) {
|
if (g_Config.bEnableSound) {
|
||||||
iOSCoreAudioShutdown();
|
iOSCoreAudioShutdown();
|
||||||
}
|
}
|
||||||
|
@ -127,11 +131,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) applicationDidBecomeActive:(UIApplication *)application {
|
-(void) applicationDidBecomeActive:(UIApplication *)application {
|
||||||
|
INFO_LOG(G3D, "didBecomeActive");
|
||||||
if (g_Config.bEnableSound) {
|
if (g_Config.bEnableSound) {
|
||||||
iOSCoreAudioInit();
|
iOSCoreAudioInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
System_PostUIMessage(UIMessage::GOT_FOCUS);
|
System_PostUIMessage(UIMessage::GOT_FOCUS);
|
||||||
|
[self.viewController didBecomeActive];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||||
|
|
|
@ -238,6 +238,14 @@ extern float g_safeInsetBottom;
|
||||||
[self shutdown];
|
[self shutdown];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)willResignActive {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)didBecomeActive {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
- (void)shutdown
|
- (void)shutdown
|
||||||
{
|
{
|
||||||
if (sharedViewController == nil) {
|
if (sharedViewController == nil) {
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
- (void)startVideo:(int)width height:(int)height;
|
- (void)startVideo:(int)width height:(int)height;
|
||||||
- (void)stopVideo;
|
- (void)stopVideo;
|
||||||
|
|
||||||
|
// Forwarded from the AppDelegate
|
||||||
|
- (void)didBecomeActive;
|
||||||
|
- (void)willResignActive;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
extern id <PPSSPPViewController> sharedViewController;
|
extern id <PPSSPPViewController> sharedViewController;
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "Core/HLE/sceUsbCam.h"
|
#include "Core/HLE/sceUsbCam.h"
|
||||||
#include "Core/HLE/sceUsbGps.h"
|
#include "Core/HLE/sceUsbGps.h"
|
||||||
|
|
||||||
|
// ViewController lifecycle:
|
||||||
|
// https://www.progressconcepts.com/blog/ios-appdelegate-viewcontroller-method-order/
|
||||||
|
|
||||||
// TODO: Share this between backends.
|
// TODO: Share this between backends.
|
||||||
static uint32_t FlagsFromConfig() {
|
static uint32_t FlagsFromConfig() {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
@ -178,33 +181,7 @@ bool IOSVulkanContext::InitAPI() {
|
||||||
info.app_name = "PPSSPP";
|
info.app_name = "PPSSPP";
|
||||||
info.app_ver = gitVer.ToInteger();
|
info.app_ver = gitVer.ToInteger();
|
||||||
info.flags = FlagsFromConfig();
|
info.flags = FlagsFromConfig();
|
||||||
VkResult res = g_Vulkan->CreateInstance(info);
|
if (!g_Vulkan->CreateInstanceAndDevice(info)) {
|
||||||
if (res != VK_SUCCESS) {
|
|
||||||
ERROR_LOG(G3D, "Failed to create vulkan context: %s", g_Vulkan->InitError().c_str());
|
|
||||||
VulkanSetAvailable(false);
|
|
||||||
delete g_Vulkan;
|
|
||||||
g_Vulkan = nullptr;
|
|
||||||
state_ = GraphicsContextState::FAILED_INIT;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int physicalDevice = g_Vulkan->GetBestPhysicalDevice();
|
|
||||||
if (physicalDevice < 0) {
|
|
||||||
ERROR_LOG(G3D, "No usable Vulkan device found.");
|
|
||||||
g_Vulkan->DestroyInstance();
|
|
||||||
delete g_Vulkan;
|
|
||||||
g_Vulkan = nullptr;
|
|
||||||
state_ = GraphicsContextState::FAILED_INIT;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_Vulkan->ChooseDevice(physicalDevice);
|
|
||||||
|
|
||||||
INFO_LOG(G3D, "Creating Vulkan device (flags: %08x)", info.flags);
|
|
||||||
if (g_Vulkan->CreateDevice() != VK_SUCCESS) {
|
|
||||||
INFO_LOG(G3D, "Failed to create vulkan device: %s", g_Vulkan->InitError().c_str());
|
|
||||||
System_Toast("No Vulkan driver found. Using OpenGL instead.");
|
|
||||||
g_Vulkan->DestroyInstance();
|
|
||||||
delete g_Vulkan;
|
delete g_Vulkan;
|
||||||
g_Vulkan = nullptr;
|
g_Vulkan = nullptr;
|
||||||
state_ = GraphicsContextState::FAILED_INIT;
|
state_ = GraphicsContextState::FAILED_INIT;
|
||||||
|
@ -228,6 +205,7 @@ static std::atomic<bool> exitRenderLoop;
|
||||||
static std::atomic<bool> renderLoopRunning;
|
static std::atomic<bool> renderLoopRunning;
|
||||||
static bool renderer_inited = false;
|
static bool renderer_inited = false;
|
||||||
static std::mutex renderLock;
|
static std::mutex renderLock;
|
||||||
|
static std::thread g_vulkanRenderLoopThread;
|
||||||
|
|
||||||
@interface PPSSPPViewControllerMetal () {
|
@interface PPSSPPViewControllerMetal () {
|
||||||
ICadeTracker g_iCadeTracker;
|
ICadeTracker g_iCadeTracker;
|
||||||
|
@ -258,7 +236,7 @@ static std::mutex renderLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be very similar to the Android one, probably mergeable.
|
// Should be very similar to the Android one, probably mergeable.
|
||||||
void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLayer, int desiredBackbufferSizeX, int desiredBackbufferSizeY) {
|
void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLayer) {
|
||||||
SetCurrentThreadName("EmuThread");
|
SetCurrentThreadName("EmuThread");
|
||||||
|
|
||||||
if (!graphicsContext) {
|
if (!graphicsContext) {
|
||||||
|
@ -278,6 +256,9 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||||
// This is up here to prevent race conditions, in case we pause during init.
|
// This is up here to prevent race conditions, in case we pause during init.
|
||||||
renderLoopRunning = true;
|
renderLoopRunning = true;
|
||||||
|
|
||||||
|
int desiredBackbufferSizeX = g_display.pixel_xres;
|
||||||
|
int desiredBackbufferSizeY = g_display.pixel_yres;
|
||||||
|
|
||||||
//WARN_LOG(G3D, "runVulkanRenderLoop. desiredBackbufferSizeX=%d desiredBackbufferSizeY=%d",
|
//WARN_LOG(G3D, "runVulkanRenderLoop. desiredBackbufferSizeX=%d desiredBackbufferSizeY=%d",
|
||||||
// desiredBackbufferSizeX, desiredBackbufferSizeY);
|
// desiredBackbufferSizeX, desiredBackbufferSizeY);
|
||||||
|
|
||||||
|
@ -328,6 +309,45 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||||
WARN_LOG(G3D, "Render loop function exited.");
|
WARN_LOG(G3D, "Render loop function exited.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (bool)runVulkanRenderLoop {
|
||||||
|
if (!graphicsContext) {
|
||||||
|
ERROR_LOG(G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_vulkanRenderLoopThread.joinable()) {
|
||||||
|
ERROR_LOG(G3D, "runVulkanRenderLoop: Already running");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAMetalLayer *metalLayer = (CAMetalLayer *)self.view.layer;
|
||||||
|
g_vulkanRenderLoopThread = std::thread(VulkanRenderLoop, graphicsContext, metalLayer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)requestExitVulkanRenderLoop {
|
||||||
|
if (!renderLoopRunning) {
|
||||||
|
ERROR_LOG(SYSTEM, "Render loop already exited");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_assert_(g_vulkanRenderLoopThread.joinable());
|
||||||
|
exitRenderLoop = true;
|
||||||
|
g_vulkanRenderLoopThread.join();
|
||||||
|
_assert_(!g_vulkanRenderLoopThread.joinable());
|
||||||
|
g_vulkanRenderLoopThread = std::thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
// These two are forwarded from the appDelegate
|
||||||
|
- (void)didBecomeActive {
|
||||||
|
// Spin up the emu thread. It will in turn spin up the Vulkan render thread
|
||||||
|
// on its own.
|
||||||
|
[self runVulkanRenderLoop];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)willResignActive {
|
||||||
|
[self requestExitVulkanRenderLoop];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)loadView {
|
- (void)loadView {
|
||||||
INFO_LOG(G3D, "Creating metal view");
|
INFO_LOG(G3D, "Creating metal view");
|
||||||
|
|
||||||
|
@ -356,15 +376,11 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||||
_assert_msg_(false, "Failed to init Vulkan");
|
_assert_msg_(false, "Failed to init Vulkan");
|
||||||
}
|
}
|
||||||
|
|
||||||
int desiredBackbufferSizeX = g_display.pixel_xres;
|
|
||||||
int desiredBackbufferSizeY = g_display.pixel_yres;
|
|
||||||
|
|
||||||
if ([[GCController controllers] count] > 0) {
|
if ([[GCController controllers] count] > 0) {
|
||||||
[self setupController:[[GCController controllers] firstObject]];
|
[self setupController:[[GCController controllers] firstObject]];
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(G3D, "Detected size: %dx%d", desiredBackbufferSizeX, desiredBackbufferSizeY);
|
INFO_LOG(G3D, "Detected size: %dx%d", g_display.pixel_xres, g_display.pixel_yres);
|
||||||
CAMetalLayer *layer = (CAMetalLayer *)self.view.layer;
|
|
||||||
|
|
||||||
cameraHelper = [[CameraHelper alloc] init];
|
cameraHelper = [[CameraHelper alloc] init];
|
||||||
[cameraHelper setDelegate:self];
|
[cameraHelper setDelegate:self];
|
||||||
|
@ -378,11 +394,6 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||||
[mBackGestureRecognizer setEdges:UIRectEdgeLeft];
|
[mBackGestureRecognizer setEdges:UIRectEdgeLeft];
|
||||||
[[self view] addGestureRecognizer:mBackGestureRecognizer];
|
[[self view] addGestureRecognizer:mBackGestureRecognizer];
|
||||||
|
|
||||||
// Spin up the emu thread. It will in turn spin up the Vulkan render thread
|
|
||||||
// on its own.
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
||||||
VulkanRenderLoop(graphicsContext, layer, desiredBackbufferSizeX, desiredBackbufferSizeY);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow device rotation to resize the swapchain
|
// Allow device rotation to resize the swapchain
|
||||||
|
@ -397,10 +408,16 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated {
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
[super viewWillAppear: animated];
|
[super viewWillAppear:animated];
|
||||||
|
INFO_LOG(G3D, "viewWillAppear");
|
||||||
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
|
self.view.contentScaleFactor = UIScreen.mainScreen.nativeScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewWillDisappear:(BOOL)animated {
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
INFO_LOG(G3D, "viewWillDisappear");
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidDisappear:(BOOL)animated {
|
- (void)viewDidDisappear:(BOOL)animated {
|
||||||
[super viewDidDisappear: animated];
|
[super viewDidDisappear: animated];
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,6 +392,7 @@ void System_Notify(SystemNotification notification) {
|
||||||
bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) {
|
bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SystemRequestType::EXIT_APP:
|
case SystemRequestType::EXIT_APP:
|
||||||
|
// NOTE: on iOS, this is considered a crash and not a valid way to exit.
|
||||||
exit(0);
|
exit(0);
|
||||||
// The below seems right, but causes hangs. See #12140.
|
// The below seems right, but causes hangs. See #12140.
|
||||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
|
Loading…
Add table
Reference in a new issue