diff --git a/GPU/Vulkan/StateMappingVulkan.h b/GPU/Vulkan/StateMappingVulkan.h index 4d7ffbbbda..52dde77ec4 100644 --- a/GPU/Vulkan/StateMappingVulkan.h +++ b/GPU/Vulkan/StateMappingVulkan.h @@ -34,7 +34,6 @@ struct VulkanPipelineRasterStateKey { unsigned int destColor : 5; // VkBlendFactor unsigned int srcAlpha : 5; // VkBlendFactor unsigned int destAlpha : 5; // VkBlendFactor - // bool useBlendConstant : 1; // sacrifice a bit to cheaply check if we need to update the blend color unsigned int blendOpColor : 3; // VkBlendOp unsigned int blendOpAlpha : 3; // VkBlendOp unsigned int logicOpEnable : 1; @@ -53,7 +52,7 @@ struct VulkanPipelineRasterStateKey { unsigned int stencilDepthFailOp : 4; // VkStencilOp // We'll use dynamic state for writemask, reference and comparemask to start with, - // and viewport/scissor. + // and viewport/scissor. More dynamic state requires extensions. // Rasterizer unsigned int cullMode : 2; // VkCullModeFlagBits diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index a2ef1a141b..70eba83e4c 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -341,9 +341,12 @@ void GamePauseScreen::update() { firstFrame_ = false; - if (finishNextFrame_) { - TriggerFinish(finishNextFrameResult_); - finishNextFrame_ = false; + { + std::lock_guard lock(finishNextFrameMutex_); + if (finishNextFrame_) { + TriggerFinish(finishNextFrameResult_); + finishNextFrame_ = false; + } } const bool networkConnected = IsNetworkConnected(); @@ -385,6 +388,7 @@ GamePauseScreen::~GamePauseScreen() { void GamePauseScreen::OnVKey(VirtKey virtualKeyCode, bool down) { // Simple de-bounce using createdTime_, just to be safe. if (down && virtualKeyCode == VIRTKEY_PAUSE && time_now_d() > createdTime_ + 0.1) { + std::lock_guard lock(finishNextFrameMutex_); finishNextFrame_ = true; finishNextFrameResult_ = DR_BACK; } @@ -405,6 +409,7 @@ void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems, int slotNum = v->GetSlot(); auto doLoad = [this, slotNum]() { SaveState::LoadSlot(saveStatePrefix_, slotNum, &ShowMessageAfterSaveStateAction); + std::lock_guard lock(finishNextFrameMutex_); finishNextFrame_ = true; finishNextFrameResult_ = DR_CANCEL; }; @@ -777,12 +782,14 @@ void GamePauseScreen::ShowContextMenu(UI::View *menuButton, bool portrait) { screenManager()->push(new UI::MessagePopupScreen(di->T("Reset"), confirmMessage, di->T("Reset"), di->T("Cancel"), [this](bool result) { if (result) { System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); - finishNextFrameResult_ = DR_BACK; // resume + std::lock_guard lock(finishNextFrameMutex_); finishNextFrame_ = true; + finishNextFrameResult_ = DR_BACK; // resume } })); } else { System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); + std::lock_guard lock(finishNextFrameMutex_); finishNextFrameResult_ = DR_BACK; // resume finishNextFrame_ = true; } @@ -819,6 +826,7 @@ void GamePauseScreen::dialogFinished(const Screen *dialog, DialogResult dr) { std::string tag = dialog->tag(); if (tag == "ScreenshotView") { if (dr == DR_OK) { + std::lock_guard lock(finishNextFrameMutex_); finishNextFrame_ = true; } else if (dr != DR_CANCEL && dr != DR_BACK) { // Just go back to the pause menu, but refresh the savestate thumbnails in case something changed. @@ -894,6 +902,7 @@ void GamePauseScreen::OnExit(UI::EventParams &e) { if (g_Config.bPauseMenuExitsEmulator) { System_ExitApp(); } else { + std::lock_guard lock(finishNextFrameMutex_); finishNextFrameResult_ = DR_OK; // exit game finishNextFrame_ = true; } diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index 5e8452f330..7852b5ed01 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -67,6 +67,7 @@ private: void AddExtraOptions(UI::ViewGroup *parent); // hack + std::mutex finishNextFrameMutex_; bool finishNextFrame_ = false; DialogResult finishNextFrameResult_ = DR_CANCEL;