mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
More app lifecycle work. Switching between Vulkan and OpenGL now works.
This commit is contained in:
1 parent
9a93a478d1
commit
f864f52b64
7 files changed
+142
-84
No files matched your search
@@ -348,6 +348,9 @@ void GLRenderManager::BeginFrame(bool enableProfiling) {
|
||||
curProgram_ = nullptr;
|
||||
#endif
|
||||
|
||||
// Shouldn't call BeginFrame unless we're in a run state.
|
||||
_dbg_assert_(runCompileThread_);
|
||||
|
||||
int curFrame = GetCurFrame();
|
||||
|
||||
FrameTimeData &frameTimeData = frameTimeHistory_.Add(frameIdGen_);
|
||||
@@ -368,10 +371,6 @@ void GLRenderManager::BeginFrame(bool enableProfiling) {
|
||||
frameData.readyForFence = false;
|
||||
}
|
||||
|
||||
if (!runCompileThread_) {
|
||||
WARN_LOG(G3D, "BeginFrame while !run_!");
|
||||
}
|
||||
|
||||
insideFrame_ = true;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1289,7 +1289,7 @@ void MainScreen::CreateViews() {
|
||||
}
|
||||
|
||||
rightColumnChoices->Add(new Spacer(25.0));
|
||||
#if !PPSSPP_PLATFORM(IOS_APP_STORE) || defined(_DEBUG)
|
||||
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
|
||||
// Officially, iOS apps should not have exit buttons. Remove it to maximize app store review chances.
|
||||
rightColumnChoices->Add(new Choice(mm->T("Exit")))->OnClick.Handle(this, &MainScreen::OnExit);
|
||||
#endif
|
||||
|
||||
@@ -112,6 +112,7 @@ enum class EmuThreadState {
|
||||
STOPPED,
|
||||
};
|
||||
|
||||
// OpenGL emu thread
|
||||
static std::thread emuThread;
|
||||
static std::atomic<int> emuThreadState((int)EmuThreadState::DISABLED);
|
||||
|
||||
@@ -1549,7 +1550,7 @@ static void ProcessFrameCommands(JNIEnv *env) {
|
||||
}
|
||||
}
|
||||
|
||||
std::thread g_vulkanRenderLoopThread;
|
||||
std::thread g_renderLoopThread;
|
||||
|
||||
static void VulkanEmuThread(ANativeWindow *wnd);
|
||||
|
||||
@@ -1563,7 +1564,7 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runVulkanRenderLoo
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_vulkanRenderLoopThread.joinable()) {
|
||||
if (g_renderLoopThread.joinable()) {
|
||||
ERROR_LOG(G3D, "runVulkanRenderLoop: Already running");
|
||||
return false;
|
||||
}
|
||||
@@ -1577,7 +1578,7 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runVulkanRenderLoo
|
||||
return false;
|
||||
}
|
||||
|
||||
g_vulkanRenderLoopThread = std::thread(VulkanEmuThread, wnd);
|
||||
g_renderLoopThread = std::thread(VulkanEmuThread, wnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1586,11 +1587,11 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeActivity_requestExitVulkanR
|
||||
ERROR_LOG(SYSTEM, "Render loop already exited");
|
||||
return;
|
||||
}
|
||||
_assert_(g_vulkanRenderLoopThread.joinable());
|
||||
_assert_(g_renderLoopThread.joinable());
|
||||
exitRenderLoop = true;
|
||||
g_vulkanRenderLoopThread.join();
|
||||
_assert_(!g_vulkanRenderLoopThread.joinable());
|
||||
g_vulkanRenderLoopThread = std::thread();
|
||||
g_renderLoopThread.join();
|
||||
_assert_(!g_renderLoopThread.joinable());
|
||||
g_renderLoopThread = std::thread();
|
||||
}
|
||||
|
||||
// TODO: Merge with the Win32 EmuThread and so on, and the Java EmuThread?
|
||||
|
||||
+6
-2
@@ -126,6 +126,8 @@
|
||||
- (void)restart:(const char*)restartArgs {
|
||||
INFO_LOG(G3D, "Restart requested: %s", restartArgs);
|
||||
[self.viewController willResignActive];
|
||||
[self.viewController shutdown];
|
||||
self.window.rootViewController = nil;
|
||||
self.viewController = nil;
|
||||
|
||||
// App was requested to restart, probably.
|
||||
@@ -136,12 +138,14 @@
|
||||
// TODO: Ignoring the command line for now.
|
||||
// Hoping that overwriting the viewController works as expected...
|
||||
[self launchPPSSPP:0 argv:nullptr];
|
||||
[self.viewController didBecomeActive];
|
||||
}
|
||||
|
||||
-(void) applicationWillResignActive:(UIApplication *)application {
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
INFO_LOG(G3D, "willResignActive");
|
||||
|
||||
[self.viewController willResignActive];
|
||||
|
||||
if (g_Config.bEnableSound) {
|
||||
iOSCoreAudioShutdown();
|
||||
}
|
||||
@@ -149,7 +153,7 @@
|
||||
System_PostUIMessage(UIMessage::LOST_FOCUS);
|
||||
}
|
||||
|
||||
-(void) applicationDidBecomeActive:(UIApplication *)application {
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
INFO_LOG(G3D, "didBecomeActive");
|
||||
if (g_Config.bEnableSound) {
|
||||
iOSCoreAudioInit();
|
||||
|
||||
+81
-48
@@ -26,6 +26,7 @@
|
||||
#include "Common/System/OSD.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Common/Input/InputState.h"
|
||||
@@ -81,8 +82,9 @@ private:
|
||||
GLRenderManager *renderManager_;
|
||||
};
|
||||
|
||||
static bool threadEnabled = true;
|
||||
static bool threadStopped = false;
|
||||
static std::atomic<bool> exitRenderLoop;
|
||||
static std::atomic<bool> renderLoopRunning;
|
||||
static std::thread g_renderLoopThread;
|
||||
|
||||
id<PPSSPPViewController> sharedViewController;
|
||||
|
||||
@@ -90,7 +92,7 @@ id<PPSSPPViewController> sharedViewController;
|
||||
ICadeTracker g_iCadeTracker;
|
||||
TouchTracker g_touchTracker;
|
||||
|
||||
GraphicsContext *graphicsContext;
|
||||
IOSGLESContext *graphicsContext;
|
||||
LocationHelper *locationHelper;
|
||||
CameraHelper *cameraHelper;
|
||||
}
|
||||
@@ -145,6 +147,59 @@ extern float g_safeInsetBottom;
|
||||
}
|
||||
}
|
||||
|
||||
// The actual rendering is NOT on this thread, this is the emu thread
|
||||
// that runs game logic.
|
||||
void GLRenderLoop(IOSGLESContext *graphicsContext) {
|
||||
SetCurrentThreadName("EmuThreadGL");
|
||||
renderLoopRunning = true;
|
||||
|
||||
// graphicsContext->StartThread();
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
INFO_LOG(SYSTEM, "Emulation thread starting\n");
|
||||
while (!exitRenderLoop) {
|
||||
NativeFrame(graphicsContext);
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "Emulation thread shutting down\n");
|
||||
NativeShutdownGraphics();
|
||||
|
||||
// Also ask the main thread to stop, so it doesn't hang waiting for a new frame.
|
||||
INFO_LOG(SYSTEM, "Emulation thread stopping\n");
|
||||
|
||||
exitRenderLoop = false;
|
||||
renderLoopRunning = false;
|
||||
}
|
||||
|
||||
- (bool)runGLRenderLoop {
|
||||
if (!graphicsContext) {
|
||||
ERROR_LOG(G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_renderLoopThread.joinable()) {
|
||||
ERROR_LOG(G3D, "runVulkanRenderLoop: Already running");
|
||||
return false;
|
||||
}
|
||||
|
||||
_dbg_assert_(!renderLoopRunning);
|
||||
_dbg_assert_(!exitRenderLoop);
|
||||
|
||||
g_renderLoopThread = std::thread(GLRenderLoop, graphicsContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)requestExitGLRenderLoop {
|
||||
if (!renderLoopRunning) {
|
||||
ERROR_LOG(SYSTEM, "Render loop already exited");
|
||||
return;
|
||||
}
|
||||
_assert_(g_renderLoopThread.joinable());
|
||||
exitRenderLoop = true;
|
||||
g_renderLoopThread.join();
|
||||
_assert_(!g_renderLoopThread.joinable());
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
[self hideKeyboard];
|
||||
@@ -201,24 +256,7 @@ extern float g_safeInsetBottom;
|
||||
[mBackGestureRecognizer setEdges:UIRectEdgeLeft];
|
||||
[[self view] addGestureRecognizer:mBackGestureRecognizer];
|
||||
|
||||
// Was previously DISPATCH_QUEUE_PRIORITY_HIGH.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NativeInitGraphics(graphicsContext);
|
||||
|
||||
INFO_LOG(SYSTEM, "Emulation thread starting\n");
|
||||
while (threadEnabled) {
|
||||
NativeFrame(graphicsContext);
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "Emulation thread shutting down\n");
|
||||
NativeShutdownGraphics();
|
||||
|
||||
// Also ask the main thread to stop, so it doesn't hang waiting for a new frame.
|
||||
INFO_LOG(SYSTEM, "Emulation thread stopping\n");
|
||||
graphicsContext->StopThread();
|
||||
|
||||
threadStopped = true;
|
||||
});
|
||||
INFO_LOG(G3D, "Done with viewDidLoad. Next up, OpenGL");
|
||||
}
|
||||
|
||||
- (void)handleSwipeFrom:(UIScreenEdgePanGestureRecognizer *)recognizer
|
||||
@@ -238,31 +276,24 @@ extern float g_safeInsetBottom;
|
||||
[self shutdown];
|
||||
}
|
||||
|
||||
- (void)willResignActive {
|
||||
|
||||
- (void)didBecomeActive {
|
||||
INFO_LOG(SYSTEM, "didBecomeActive begin");
|
||||
[self runGLRenderLoop];
|
||||
INFO_LOG(SYSTEM, "didBecomeActive end");
|
||||
}
|
||||
|
||||
- (void)didBecomeActive {
|
||||
|
||||
- (void)willResignActive {
|
||||
INFO_LOG(SYSTEM, "willResignActive begin");
|
||||
[self requestExitGLRenderLoop];
|
||||
INFO_LOG(SYSTEM, "willResignActive end");
|
||||
}
|
||||
|
||||
- (void)shutdown
|
||||
{
|
||||
if (sharedViewController == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
iOSCoreAudioShutdown();
|
||||
|
||||
if (threadEnabled) {
|
||||
threadEnabled = false;
|
||||
while (graphicsContext->ThreadFrame()) {
|
||||
continue;
|
||||
}
|
||||
while (!threadStopped) {}
|
||||
graphicsContext->ThreadEnd();
|
||||
}
|
||||
INFO_LOG(SYSTEM, "shutdown GL");
|
||||
|
||||
_dbg_assert_(graphicsContext);
|
||||
_dbg_assert_(sharedViewController != nil);
|
||||
sharedViewController = nil;
|
||||
|
||||
if (self.context) {
|
||||
@@ -276,19 +307,15 @@ extern float g_safeInsetBottom;
|
||||
|
||||
self.gameController = nil;
|
||||
|
||||
if (graphicsContext) {
|
||||
graphicsContext->Shutdown();
|
||||
delete graphicsContext;
|
||||
graphicsContext = NULL;
|
||||
}
|
||||
|
||||
NativeShutdown();
|
||||
graphicsContext->StopThread();
|
||||
graphicsContext->Shutdown();
|
||||
delete graphicsContext;
|
||||
graphicsContext = nullptr;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
INFO_LOG(SYSTEM, "dealloc");
|
||||
[self shutdown];
|
||||
INFO_LOG(SYSTEM, "dealloc GL");
|
||||
}
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
@@ -298,8 +325,14 @@ extern float g_safeInsetBottom;
|
||||
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
||||
{
|
||||
if (!renderLoopRunning) {
|
||||
INFO_LOG(G3D, "Ignoring drawInRect");
|
||||
return;
|
||||
}
|
||||
INFO_LOG(G3D, "drawInRect start");
|
||||
if (sharedViewController)
|
||||
graphicsContext->ThreadFrame();
|
||||
INFO_LOG(G3D, "drawInRect end");
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
||||
|
||||
+41
-22
@@ -152,8 +152,6 @@ void IOSVulkanContext::Resize() {
|
||||
INFO_LOG(G3D, "IOSVulkanContext::Resize end (final size: %dx%d)", g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
||||
}
|
||||
|
||||
extern const char *PPSSPP_GIT_VERSION;
|
||||
|
||||
bool IOSVulkanContext::InitAPI() {
|
||||
INFO_LOG(G3D, "IOSVulkanContext::Init");
|
||||
init_glslang();
|
||||
@@ -203,9 +201,7 @@ bool IOSVulkanContext::InitAPI() {
|
||||
|
||||
static std::atomic<bool> exitRenderLoop;
|
||||
static std::atomic<bool> renderLoopRunning;
|
||||
static bool renderer_inited = false;
|
||||
static std::mutex renderLock;
|
||||
static std::thread g_vulkanRenderLoopThread;
|
||||
static std::thread g_renderLoopThread;
|
||||
|
||||
@interface PPSSPPViewControllerMetal () {
|
||||
ICadeTracker g_iCadeTracker;
|
||||
@@ -237,7 +233,8 @@ static std::thread g_vulkanRenderLoopThread;
|
||||
|
||||
// Should be very similar to the Android one, probably mergeable.
|
||||
void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLayer) {
|
||||
SetCurrentThreadName("EmuThread");
|
||||
SetCurrentThreadName("EmuThreadVulkan");
|
||||
INFO_LOG(G3D, "Entering EmuThreadVulkan");
|
||||
|
||||
if (!graphicsContext) {
|
||||
ERROR_LOG(G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context.");
|
||||
@@ -281,14 +278,8 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||
// Gonna be in a weird state here..
|
||||
}
|
||||
graphicsContext->ThreadStart();
|
||||
renderer_inited = true;
|
||||
|
||||
while (!exitRenderLoop) {
|
||||
{
|
||||
std::lock_guard<std::mutex> renderGuard(renderLock);
|
||||
NativeFrame(graphicsContext);
|
||||
}
|
||||
// Here Android processes frame commands.
|
||||
NativeFrame(graphicsContext);
|
||||
}
|
||||
INFO_LOG(G3D, "Leaving Vulkan main loop.");
|
||||
} else {
|
||||
@@ -297,7 +288,6 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||
|
||||
NativeShutdownGraphics();
|
||||
|
||||
renderer_inited = false;
|
||||
graphicsContext->ThreadEnd();
|
||||
|
||||
// Shut the graphics context down to the same state it was in when we entered the render thread.
|
||||
@@ -310,44 +300,73 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||
}
|
||||
|
||||
- (bool)runVulkanRenderLoop {
|
||||
INFO_LOG(G3D, "runVulkanRenderLoop");
|
||||
|
||||
if (!graphicsContext) {
|
||||
ERROR_LOG(G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_vulkanRenderLoopThread.joinable()) {
|
||||
if (g_renderLoopThread.joinable()) {
|
||||
ERROR_LOG(G3D, "runVulkanRenderLoop: Already running");
|
||||
return false;
|
||||
}
|
||||
|
||||
CAMetalLayer *metalLayer = (CAMetalLayer *)self.view.layer;
|
||||
g_vulkanRenderLoopThread = std::thread(VulkanRenderLoop, graphicsContext, metalLayer);
|
||||
g_renderLoopThread = std::thread(VulkanRenderLoop, graphicsContext, metalLayer);
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)requestExitVulkanRenderLoop {
|
||||
INFO_LOG(G3D, "requestExitVulkanRenderLoop");
|
||||
|
||||
if (!renderLoopRunning) {
|
||||
ERROR_LOG(SYSTEM, "Render loop already exited");
|
||||
return;
|
||||
}
|
||||
_assert_(g_vulkanRenderLoopThread.joinable());
|
||||
_assert_(g_renderLoopThread.joinable());
|
||||
exitRenderLoop = true;
|
||||
g_vulkanRenderLoopThread.join();
|
||||
_assert_(!g_vulkanRenderLoopThread.joinable());
|
||||
g_vulkanRenderLoopThread = std::thread();
|
||||
g_renderLoopThread.join();
|
||||
_assert_(!g_renderLoopThread.joinable());
|
||||
}
|
||||
|
||||
// These two are forwarded from the appDelegate
|
||||
- (void)didBecomeActive {
|
||||
INFO_LOG(G3D, "didBecomeActive GL");
|
||||
|
||||
// Spin up the emu thread. It will in turn spin up the Vulkan render thread
|
||||
// on its own.
|
||||
[self runVulkanRenderLoop];
|
||||
}
|
||||
|
||||
- (void)willResignActive {
|
||||
INFO_LOG(G3D, "willResignActive GL");
|
||||
[self requestExitVulkanRenderLoop];
|
||||
}
|
||||
|
||||
- (void)shutdown
|
||||
{
|
||||
INFO_LOG(SYSTEM, "shutdown VK");
|
||||
|
||||
_dbg_assert_(sharedViewController != nil);
|
||||
sharedViewController = nil;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
self.gameController = nil;
|
||||
|
||||
if (graphicsContext) {
|
||||
graphicsContext->Shutdown();
|
||||
delete graphicsContext;
|
||||
graphicsContext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
INFO_LOG(SYSTEM, "dealloc VK");
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
INFO_LOG(G3D, "Creating metal view");
|
||||
|
||||
@@ -393,14 +412,12 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||
UIScreenEdgePanGestureRecognizer *mBackGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:) ];
|
||||
[mBackGestureRecognizer setEdges:UIRectEdgeLeft];
|
||||
[[self view] addGestureRecognizer:mBackGestureRecognizer];
|
||||
|
||||
}
|
||||
|
||||
// Allow device rotation to resize the swapchain
|
||||
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator {
|
||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||
// TODO: Handle resizing properly.
|
||||
// demo_resize(&demo);
|
||||
}
|
||||
|
||||
- (UIView *)getView {
|
||||
@@ -424,7 +441,9 @@ void VulkanRenderLoop(IOSVulkanContext *graphicsContext, CAMetalLayer *metalLaye
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
INFO_LOG(G3D, "viewDidAppear");
|
||||
[self hideKeyboard];
|
||||
INFO_LOG(G3D, "viewDidAppearDone");
|
||||
}
|
||||
|
||||
- (BOOL)prefersHomeIndicatorAutoHidden {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "Common/System/Request.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Profiler/Profiler.h"
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Common/Log.h"
|
||||
#include "UI/DarwinFileSystemServices.h"
|
||||
@@ -550,6 +551,7 @@ void System_Vibrate(int mode) {
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// SetCurrentThreadName("MainThread");
|
||||
version = [[[UIDevice currentDevice] systemVersion] UTF8String];
|
||||
if (2 != sscanf(version.c_str(), "%d", &g_iosVersionMajor)) {
|
||||
// Just set it to 14.0 if the parsing fails for whatever reason.
|
||||
|
||||
Reference in new issue
Block a user