diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index 0cf1971e53..a29525b2f4 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -324,3 +324,25 @@ const TextureShaderInfo *GetTextureShaderInfo(const std::string &name) { const std::vector &GetAllTextureShaderInfo() { return textureShaderInfo; } + +void FixPostShaderOrder(std::vector *names) { + // There's one rule only that we enforce - only one shader can use UsePreviousFrame, + // and it has to be the last one. So we simply remove any we find from the list, + // and then append it to the end if there is one. + std::string prevFrameShader; + for (auto iter = names->begin(); iter != names->end(); ) { + const ShaderInfo *info = GetPostShaderInfo(*iter); + if (info) { + if (info->usePreviousFrame) { + prevFrameShader = *iter; + iter = names->erase(iter++); + continue; + } + } + ++iter; + } + + if (!prevFrameShader.empty()) { + names->push_back(prevFrameShader); + } +} diff --git a/GPU/Common/PostShader.h b/GPU/Common/PostShader.h index 4b4061988c..882290d49f 100644 --- a/GPU/Common/PostShader.h +++ b/GPU/Common/PostShader.h @@ -115,3 +115,8 @@ const std::vector &GetAllPostShaderInfo(); const TextureShaderInfo *GetTextureShaderInfo(const std::string &name); const std::vector &GetAllTextureShaderInfo(); void RemoveUnknownPostShaders(std::vector *names); + +// Call this any time you alter the postshader list. It makes sure +// that "usePrevFrame" shaders are at the end, and that there's only one. +// It'll also enforce any similar future rules. +void FixPostShaderOrder(std::vector *names); diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index f8837e2808..30fcfe7675 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -880,6 +880,7 @@ void PresentationCommon::CalculateRenderResolution(int *width, int *height, int if (!g_Config.vPostShaderNames.empty()) { ReloadAllPostShaderInfo(draw_); RemoveUnknownPostShaders(&g_Config.vPostShaderNames); + FixPostShaderOrder(&g_Config.vPostShaderNames); shaderInfo = GetFullPostShadersChain(g_Config.vPostShaderNames); } diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index 46188760e3..b1612c3c2f 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -152,6 +152,7 @@ void DisplayLayoutScreen::dialogFinished(const Screen *dialog, DialogResult resu UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) { // Remove the virtual "Off" entry. TODO: Get rid of it generally. g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end()); + FixPostShaderOrder(&g_Config.vPostShaderNames); NativeMessageReceived("gpu_configChanged", ""); NativeMessageReceived("gpu_renderResized", ""); // To deal with shaders that can change render resolution like upscaling. @@ -370,7 +371,9 @@ void DisplayLayoutScreen::CreateViews() { moreButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn { PopupContextMenuScreen *contextMenu = new UI::PopupContextMenuScreen(postShaderContextMenu, ARRAY_SIZE(postShaderContextMenu), di.get(), moreButton); screenManager()->push(contextMenu); - contextMenu->SetEnabled(0, i > 0); + const ShaderInfo *info = GetPostShaderInfo(g_Config.vPostShaderNames[i]); + bool usesLastFrame = info ? info->usePreviousFrame : false; + contextMenu->SetEnabled(0, i > 0 && !usesLastFrame); contextMenu->SetEnabled(1, i < g_Config.vPostShaderNames.size() - 1); contextMenu->OnChoice.Add([=](EventParams &e) -> UI::EventReturn { switch (e.a) { @@ -386,6 +389,7 @@ void DisplayLayoutScreen::CreateViews() { default: return UI::EVENT_DONE; } + FixPostShaderOrder(&g_Config.vPostShaderNames); NativeMessageReceived("gpu_configChanged", ""); RecreateViews(); return UI::EVENT_DONE;