Skip to content

Commit

Permalink
Merge pull request hrydgard#9619 from unknownbrackets/native-restart
Browse files Browse the repository at this point in the history
Windows: Avoid restarting completely on GPU change
  • Loading branch information
hrydgard authored Apr 16, 2017
2 parents 627c280 + 1912a94 commit 1a9e93d
Show file tree
Hide file tree
Showing 17 changed files with 100 additions and 43 deletions.
5 changes: 4 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
root = true

[*]
charset = utf-8
# Temporarily disabled because MSVC2017 misinterprets as utf-8-bom.
# TODO: Reinstate once fixed build is released:
# https://developercommunity.visualstudio.com/content/problem/22922/editorconfig-support-interprets-charset-utf-8-as-u.html
#charset = utf-8
indent_style = tab
insert_final_newline = true
# Would be nice, but don't want to change files unnecessarily.
Expand Down
33 changes: 24 additions & 9 deletions Common/Vulkan/VulkanContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ void VulkanBeginCommandBuffer(VkCommandBuffer cmd) {
assert(res == VK_SUCCESS);
}

void VulkanContext::InitObjects(bool depthPresent) {
bool VulkanContext::InitObjects(bool depthPresent) {
InitQueue();
InitCommandPool();

Expand All @@ -364,13 +364,17 @@ void VulkanContext::InitObjects(bool depthPresent) {
frame_[1].fence = CreateFence(true);

VkCommandBuffer cmd = GetInitCommandBuffer();
InitSwapchain(cmd);
if (!InitSwapchain(cmd)) {
return false;
}
InitDepthStencilBuffer(cmd);

InitSurfaceRenderPass(depthPresent, true);
InitFramebuffers(depthPresent);

// The init command buffer will be executed as part of the first frame.

return true;
}

void VulkanContext::DestroyObjects() {
Expand Down Expand Up @@ -948,7 +952,7 @@ void VulkanContext::InitQueue() {
assert(res == VK_SUCCESS);
}

void VulkanContext::InitSwapchain(VkCommandBuffer cmd) {
bool VulkanContext::InitSwapchain(VkCommandBuffer cmd) {
VkResult U_ASSERT_ONLY res;
VkSurfaceCapabilitiesKHR surfCapabilities;

Expand Down Expand Up @@ -1051,6 +1055,9 @@ void VulkanContext::InitSwapchain(VkCommandBuffer cmd) {

res = vkCreateSwapchainKHR(device_, &swap_chain_info, NULL, &swap_chain_);
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS) {
return false;
}

res = vkGetSwapchainImagesKHR(device_, swap_chain_,
&swapchainImageCount, NULL);
Expand Down Expand Up @@ -1097,6 +1104,8 @@ void VulkanContext::InitSwapchain(VkCommandBuffer cmd) {
free(swapchainImages);

current_buffer = 0;

return true;
}

void VulkanContext::InitSurfaceRenderPass(bool include_depth, bool clear) {
Expand Down Expand Up @@ -1206,14 +1215,18 @@ void VulkanContext::WaitAndResetFence(VkFence fence) {
}

void VulkanContext::DestroyCommandPool() {
vkDestroyCommandPool(device_, cmd_pool_, NULL);
if (cmd_pool_ != VK_NULL_HANDLE)
vkDestroyCommandPool(device_, cmd_pool_, NULL);
cmd_pool_ = VK_NULL_HANDLE;
}

void VulkanContext::DestroyDepthStencilBuffer() {
vkDestroyImageView(device_, depth.view, NULL);
vkDestroyImage(device_, depth.image, NULL);
vkFreeMemory(device_, depth.mem, NULL);
if (depth.view != VK_NULL_HANDLE)
vkDestroyImageView(device_, depth.view, NULL);
if (depth.image != VK_NULL_HANDLE)
vkDestroyImage(device_, depth.image, NULL);
if (depth.mem != VK_NULL_HANDLE)
vkFreeMemory(device_, depth.mem, NULL);

depth.view = VK_NULL_HANDLE;
depth.image = VK_NULL_HANDLE;
Expand All @@ -1224,7 +1237,8 @@ void VulkanContext::DestroySwapChain() {
for (uint32_t i = 0; i < swapchainImageCount; i++) {
vkDestroyImageView(device_, swapChainBuffers[i].view, NULL);
}
vkDestroySwapchainKHR(device_, swap_chain_, NULL);
if (swap_chain_ != VK_NULL_HANDLE)
vkDestroySwapchainKHR(device_, swap_chain_, NULL);
swap_chain_ = VK_NULL_HANDLE;
swapChainBuffers.clear();
vkDestroySemaphore(device_, acquireSemaphore, NULL);
Expand All @@ -1238,7 +1252,8 @@ void VulkanContext::DestroyFramebuffers() {
}

void VulkanContext::DestroySurfaceRenderPass() {
vkDestroyRenderPass(device_, surface_render_pass_, NULL);
if (surface_render_pass_ != VK_NULL_HANDLE)
vkDestroyRenderPass(device_, surface_render_pass_, NULL);
surface_render_pass_ = VK_NULL_HANDLE;
}

Expand Down
16 changes: 8 additions & 8 deletions Common/Vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ class VulkanContext {
void ReinitSurfaceAndroid(int width, int height);
#endif
void InitQueue();
void InitObjects(bool depthPresent);
void InitSwapchain(VkCommandBuffer cmd);
bool InitObjects(bool depthPresent);
bool InitSwapchain(VkCommandBuffer cmd);
void InitSurfaceRenderPass(bool include_depth, bool clear);
void InitFramebuffers(bool include_depth);
void InitDepthStencilBuffer(VkCommandBuffer cmd);
Expand Down Expand Up @@ -365,14 +365,14 @@ class VulkanContext {

struct {
VkFormat format;
VkImage image;
VkDeviceMemory mem;
VkImageView view;
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory mem = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
} depth;

VkRenderPass surface_render_pass_;
uint32_t current_buffer;
uint32_t queue_count;
VkRenderPass surface_render_pass_ = VK_NULL_HANDLE;
uint32_t current_buffer = 0;
uint32_t queue_count = 0;

VkPhysicalDeviceFeatures featuresAvailable_;
VkPhysicalDeviceFeatures featuresEnabled_;
Expand Down
6 changes: 2 additions & 4 deletions Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,6 @@ static ConfigSetting graphicsSettings[] = {
ReportedConfigSetting("AutoFrameSkip", &g_Config.bAutoFrameSkip, false, true, true),
ConfigSetting("FrameRate", &g_Config.iFpsLimit, 0, true, true),
ConfigSetting("FrameSkipUnthrottle", &g_Config.bFrameSkipUnthrottle, &DefaultFrameskipUnthrottle, true, false),
#if defined(USING_WIN_UI)
ConfigSetting("RestartRequired", &g_Config.bRestartRequired, false, false),
#endif
ReportedConfigSetting("ForceMaxEmulatedFPS", &g_Config.iForceMaxEmulatedFPS, 60, true, true),

// TODO: Hm, on fast mobile GPUs we should definitely default to at least 4 (setting = 2)...
Expand Down Expand Up @@ -1094,7 +1091,8 @@ void Config::Save() {
control->Delete("DPadRadius");

IniFile::Section *log = iniFile.GetOrCreateSection(logSectionName);
LogManager::GetInstance()->SaveConfig(log);
if (LogManager::GetInstance())
LogManager::GetInstance()->SaveConfig(log);

if (!iniFile.Save(iniFilename_.c_str())) {
ERROR_LOG(LOADER, "Error saving config - can't write ini %s", iniFilename_.c_str());
Expand Down
2 changes: 0 additions & 2 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ struct Config {
bool bTopMost;
std::string sFont;
bool bIgnoreWindowsKey;

bool bRestartRequired;
#endif

bool bPauseWhenMinimized;
Expand Down
4 changes: 4 additions & 0 deletions Core/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ static volatile CPUThreadState cpuThreadState = CPU_THREAD_NOT_RUNNING;

static GPUBackend gpuBackend;

void ResetUIState() {
globalUIState = UISTATE_MENU;
}

void UpdateUIState(GlobalUIState newState) {
// Never leave the EXIT state.
if (globalUIState != newState && globalUIState != UISTATE_EXIT) {
Expand Down
1 change: 1 addition & 0 deletions Core/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum PSPDirectories {
class GraphicsContext;
enum class GPUBackend;

void ResetUIState();
void UpdateUIState(GlobalUIState newState);
GlobalUIState GetUIState();

Expand Down
3 changes: 1 addition & 2 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1057,8 +1057,7 @@ void GameSettingsScreen::CallbackRenderingBackend(bool yes) {
// If the user ends up deciding not to restart, set the config back to the current backend
// so it doesn't get switched by accident.
if (yes) {
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
System_SendMessage("graphics_restart", "");
} else {
g_Config.iGPUBackend = (int)GetGPUBackend();
}
Expand Down
21 changes: 19 additions & 2 deletions UI/NativeApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ bool targetIsJailbroken;
bool g_TakeScreenshot;
static bool isOuya;
static bool resized = false;
static bool restarting = false;

struct PendingMessage {
std::string msg;
Expand Down Expand Up @@ -361,8 +362,10 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
g_Config.appCacheDirectory = cache_dir;
}

if (!LogManager::GetInstance())
LogManager::Init();

#ifndef _WIN32
LogManager::Init();
logger = new AndroidLogger();

g_Config.AddSearchPath(user_data_path);
Expand Down Expand Up @@ -532,6 +535,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost_manager_init();
}

// Must be done restarting by now.
restarting = false;
}

static UI::Style MakeStyle(uint32_t fg, uint32_t bg) {
Expand Down Expand Up @@ -1051,6 +1057,14 @@ void NativeResized() {
resized = true;
}

void NativeSetRestarting() {
restarting = true;
}

bool NativeIsRestarting() {
return restarting;
}

void NativeShutdown() {
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost_manager_shutdown();
Expand All @@ -1065,7 +1079,10 @@ void NativeShutdown() {
#endif
host = 0;
g_Config.Save();
LogManager::Shutdown();

// Avoid shutting this down when restaring core.
if (!restarting)
LogManager::Shutdown();

#ifdef ANDROID_NDK_PROFILER
moncleanup();
Expand Down
9 changes: 9 additions & 0 deletions Windows/EmuThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ unsigned int WINAPI TheThread(void *)
args.push_back(string.c_str());
}

bool performingRestart = NativeIsRestarting();
NativeInit(static_cast<int>(args.size()), &args[0], "1234", "1234", nullptr);

Host *nativeHost = host;
Expand All @@ -123,6 +124,14 @@ unsigned int WINAPI TheThread(void *)

std::string error_string;
if (!host->InitGraphics(&error_string, &graphicsContext)) {
// Before anything: are we restarting right now?
if (performingRestart) {
// Okay, switching graphics didn't work out. Probably a driver bug - fallback to restart.
// This happens on NVIDIA when switching OpenGL -> Vulkan.
g_Config.Save();
W32Util::ExitAndRestart();
}

I18NCategory *err = GetI18NCategory("Error");
Reporting::ReportMessage("Graphics init error: %s", error_string.c_str());

Expand Down
5 changes: 4 additions & 1 deletion Windows/GPU/WindowsVulkanContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,10 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions);
}
g_Vulkan->InitSurfaceWin32(hInst, hWnd);
g_Vulkan->InitObjects(true);
if (!g_Vulkan->InitObjects(true)) {
Shutdown();
return false;
}

draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);

Expand Down
8 changes: 8 additions & 0 deletions Windows/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,14 @@ namespace MainWindow
BrowseBackgroundDone();
break;

case WM_USER_RESTART_EMUTHREAD:
NativeSetRestarting();
EmuThread_Stop();
coreState = CORE_POWERUP;
ResetUIState();
EmuThread_Start();
break;

case WM_MENUSELECT:
// Called when a menu is opened. Also when an item is selected, but meh.
UpdateMenus(true);
Expand Down
1 change: 1 addition & 0 deletions Windows/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace MainWindow
WM_USER_WINDOW_TITLE_CHANGED = WM_USER + 103,
WM_USER_BROWSE_BOOT_DONE = WM_USER + 104,
WM_USER_TOGGLE_FULLSCREEN = WM_USER + 105,
WM_USER_RESTART_EMUTHREAD = WM_USER + 106,
};

enum {
Expand Down
12 changes: 4 additions & 8 deletions Windows/MainWindowMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,26 +770,22 @@ namespace MainWindow {

case ID_OPTIONS_DIRECT3D9:
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9;
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0);
break;

case ID_OPTIONS_DIRECT3D11:
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D11;
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0);
break;

case ID_OPTIONS_OPENGL:
g_Config.iGPUBackend = GPU_BACKEND_OPENGL;
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0);
break;

case ID_OPTIONS_VULKAN:
g_Config.iGPUBackend = GPU_BACKEND_VULKAN;
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0);
break;

case ID_OPTIONS_NONBUFFEREDRENDERING: setRenderingMode(FB_NON_BUFFERED_MODE); break;
Expand Down
1 change: 0 additions & 1 deletion Windows/WindowsHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ void WindowsHost::ShutdownGraphics() {
gfx_->Shutdown();
delete gfx_;
gfx_ = nullptr;
PostMessage(mainWindow_, WM_CLOSE, 0, 0);
}

void WindowsHost::SetWindowTitle(const char *message) {
Expand Down
10 changes: 5 additions & 5 deletions Windows/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,11 @@ int System_GetPropertyInt(SystemProperty prop) {

void System_SendMessage(const char *command, const char *parameter) {
if (!strcmp(command, "finish")) {
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
if (!NativeIsRestarting()) {
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
}
} else if (!strcmp(command, "graphics_restart")) {
PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0);
} else if (!strcmp(command, "setclipboardtext")) {
if (OpenClipboard(MainWindow::GetDisplayHWND())) {
std::wstring data = ConvertUTF8ToWString(parameter);
Expand Down Expand Up @@ -568,10 +572,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin

LogManager::Shutdown();

if (g_Config.bRestartRequired) {
W32Util::ExitAndRestart();
}

net::Shutdown();
CoUninitialize();

Expand Down
6 changes: 6 additions & 0 deletions ext/native/base/NativeApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ void NativeDeviceRestore();
// and only write dp_xres and dp_yres.
void NativeResized();

// Set a flag to indicate a restart. Reset after NativeInit().
void NativeSetRestarting();

// Retrieve current restarting flag.
bool NativeIsRestarting();

// Called ~sixty times a second, delivers the current input state.
// Main thread.
void NativeUpdate();
Expand Down

0 comments on commit 1a9e93d

Please sign in to comment.