User chain support

This commit is contained in:
iota97 2020-05-18 11:17:45 +02:00
parent a81991f114
commit 0c885db052
13 changed files with 134 additions and 48 deletions

View file

@ -805,7 +805,6 @@ static ConfigSetting graphicsSettings[] = {
// Not really a graphics setting...
ReportedConfigSetting("SplineBezierQuality", &g_Config.iSplineBezierQuality, 2, true, true),
ReportedConfigSetting("HardwareTessellation", &g_Config.bHardwareTessellation, false, true, true),
ReportedConfigSetting("PostShader", &g_Config.sPostShaderName, "Off", true, true),
ConfigSetting("TextureShader", &g_Config.sTextureShaderName, "Off", true, true),
ReportedConfigSetting("MemBlockTransferGPU", &g_Config.bBlockTransferGPU, true, true, true),
@ -1254,6 +1253,14 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
mPostShaderSetting[it.first] = std::stof(it.second);
}
auto postShaderChain = iniFile.GetOrCreateSection("PostShaderList")->ToMap();
vPostShaderNames.clear();
for (auto it : postShaderChain) {
vPostShaderNames.push_back(it.second);
}
if (vPostShaderNames.empty())
vPostShaderNames.push_back("Off");
// This caps the exponent 4 (so 16x.)
if (iAnisotropyLevel > 4) {
iAnisotropyLevel = 4;
@ -1385,6 +1392,13 @@ void Config::Save(const char *saveReason) {
for (auto it = mPostShaderSetting.begin(), end = mPostShaderSetting.end(); it != end; ++it) {
postShaderSetting->Set(it->first.c_str(), it->second);
}
Section *postShaderChain = iniFile.GetOrCreateSection("PostShaderList");
postShaderChain->Clear();
for (size_t i = 0; i < vPostShaderNames.size(); ++i) {
char keyName[64];
snprintf(keyName, sizeof(keyName), "PostShader%d", (int)i+1);
postShaderChain->Set(keyName, vPostShaderNames[i]);
}
}
Section *control = iniFile.GetOrCreateSection("Control");
@ -1643,6 +1657,14 @@ bool Config::saveGameConfig(const std::string &pGameId, const std::string &title
postShaderSetting->Set(it->first.c_str(), it->second);
}
Section *postShaderChain = iniFile.GetOrCreateSection("PostShaderList");
postShaderChain->Clear();
for (size_t i = 0; i < vPostShaderNames.size(); ++i) {
char keyName[64];
snprintf(keyName, sizeof(keyName), "PostShader%d", (int)i+1);
postShaderChain->Set(keyName, vPostShaderNames[i]);
}
KeyMap::SaveToIni(iniFile);
iniFile.Save(fullIniFilePath);
@ -1667,6 +1689,14 @@ bool Config::loadGameConfig(const std::string &pGameId, const std::string &title
mPostShaderSetting[it.first] = std::stof(it.second);
}
auto postShaderChain = iniFile.GetOrCreateSection("PostShaderList")->ToMap();
vPostShaderNames.clear();
for (auto it : postShaderChain) {
vPostShaderNames.push_back(it.second);
}
if (vPostShaderNames.empty())
vPostShaderNames.push_back("Off");
IterateSettings(iniFile, [](Section *section, ConfigSetting *setting) {
if (setting->perGame_) {
setting->Get(section);
@ -1697,6 +1727,14 @@ void Config::unloadGameConfig() {
mPostShaderSetting[it.first] = std::stof(it.second);
}
auto postShaderChain = iniFile.GetOrCreateSection("PostShaderList")->ToMap();
vPostShaderNames.clear();
for (auto it : postShaderChain) {
vPostShaderNames.push_back(it.second);
}
if (vPostShaderNames.empty())
vPostShaderNames.push_back("Off");
LoadStandardControllerIni();
}
}

View file

@ -212,9 +212,10 @@ public:
bool bFragmentTestCache;
int iSplineBezierQuality; // 0 = low , 1 = Intermediate , 2 = High
bool bHardwareTessellation;
std::string sPostShaderName; // Off for off.
std::string sTextureShaderName;
std::vector<std::string> vPostShaderNames; // Off for chain end (only Off for no shader)
std::map<std::string, float> mPostShaderSetting;
std::string sTextureShaderName;
bool bGfxDebugOutput;
bool bGfxDebugSplitSubmit;
int iInflightFrames;

View file

@ -950,7 +950,7 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat,
case CheatOp::PostShader:
{
auto shaderChain = GetPostShaderChain(g_Config.sPostShaderName);
auto shaderChain = GetFullPostShadersChain(g_Config.vPostShaderNames);
if (op.PostShaderUniform.shader < shaderChain.size()) {
std::string shaderName = shaderChain[op.PostShaderUniform.shader]->section;
if (shaderName != "Off")
@ -961,7 +961,7 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat,
case CheatOp::PostShaderFromMemory:
{
auto shaderChain = GetPostShaderChain(g_Config.sPostShaderName);
auto shaderChain = GetFullPostShadersChain(g_Config.vPostShaderNames);
if (Memory::IsValidAddress(op.addr) && op.PostShaderUniform.shader < shaderChain.size()) {
union {
float f;

View file

@ -751,7 +751,6 @@ void __DisplayFlip(int cyclesLate) {
// But, let's flip at least once every 10 vblanks, to update fps, etc.
const bool noRecentFlip = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE && numVBlanksSinceFlip >= 10;
// Also let's always flip for animated shaders.
const ShaderInfo *shaderInfo = g_Config.sPostShaderName == "Off" ? nullptr : GetPostShaderInfo(g_Config.sPostShaderName);
bool postEffectRequiresFlip = false;
bool duplicateFrames = g_Config.bRenderDuplicateFrames && g_Config.iFrameSkip == 0;
@ -764,11 +763,7 @@ void __DisplayFlip(int cyclesLate) {
// postEffectRequiresFlip is not compatible with frameskip unthrottling, see #12325.
if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE && !(unthrottleNeedsSkip && !FrameTimingThrottled())) {
if (shaderInfo) {
postEffectRequiresFlip = (shaderInfo->requires60fps || duplicateFrames);
} else {
postEffectRequiresFlip = duplicateFrames;
}
postEffectRequiresFlip = duplicateFrames || PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames));
}
const bool fbDirty = gpu->FramebufferDirty();

View file

@ -213,6 +213,25 @@ std::vector<const ShaderInfo *> GetPostShaderChain(const std::string &name) {
return backwards;
}
std::vector<const ShaderInfo *> GetFullPostShadersChain(const std::vector<std::string> &names) {
std::vector<const ShaderInfo *> fullChain;
for (auto shaderName : names) {
if (shaderName == "Off")
break;
auto shaderChain = GetPostShaderChain(shaderName);
fullChain.insert(fullChain.end(), shaderChain.begin(), shaderChain.end());
}
return fullChain;
}
bool PostShaderChainRequires60FPS(const std::vector<const ShaderInfo *> &chain) {
for (auto shaderInfo : chain) {
if (shaderInfo->requires60fps)
return true;
}
return false;
}
const std::vector<ShaderInfo> &GetAllPostShaderInfo() {
return shaderInfo;
}

View file

@ -83,6 +83,8 @@ void ReloadAllPostShaderInfo();
const ShaderInfo *GetPostShaderInfo(const std::string &name);
std::vector<const ShaderInfo *> GetPostShaderChain(const std::string &name);
std::vector<const ShaderInfo *> GetFullPostShadersChain(const std::vector<std::string> &names);
bool PostShaderChainRequires60FPS(const std::vector<const ShaderInfo *> &chain);
const std::vector<ShaderInfo> &GetAllPostShaderInfo();
const TextureShaderInfo *GetTextureShaderInfo(const std::string &name);

View file

@ -210,9 +210,9 @@ static std::string ReadShaderSrc(const std::string &filename) {
// Note: called on resize and settings changes.
bool PresentationCommon::UpdatePostShader() {
std::vector<const ShaderInfo *> shaderInfo;
if (g_Config.sPostShaderName != "Off") {
if (g_Config.vPostShaderNames[0] != "Off") {
ReloadAllPostShaderInfo();
shaderInfo = GetPostShaderChain(g_Config.sPostShaderName);
shaderInfo = GetFullPostShadersChain(g_Config.vPostShaderNames);
}
DestroyPostShader();
@ -754,9 +754,9 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa) {
// Check if postprocessing shader is doing upscaling as it requires native resolution
std::vector<const ShaderInfo *> shaderInfo;
if (g_Config.sPostShaderName != "Off") {
if (g_Config.vPostShaderNames[0] != "Off") {
ReloadAllPostShaderInfo();
shaderInfo = GetPostShaderChain(g_Config.sPostShaderName);
shaderInfo = GetFullPostShadersChain(g_Config.vPostShaderNames);
}
bool firstIsUpscalingFilter = shaderInfo.empty() ? false : shaderInfo.front()->isUpscalingFilter;

View file

@ -74,6 +74,8 @@
#include "Windows/W32Util/ShellUtil.h"
#endif
extern bool g_ShaderNameListChanged;
GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore)
: UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) {
lastVertical_ = UseVerticalLayout();
@ -305,24 +307,51 @@ void GameSettingsScreen::CreateViews() {
altSpeed2->SetZeroLabel(gr->T("Unlimited"));
altSpeed2->SetNegativeDisable(gr->T("Disabled"));
graphicsSettings->Add(new ItemHeader(gr->T("Features")));
postProcChoice_ = graphicsSettings->Add(new ChoiceWithValueDisplay(&g_Config.sPostShaderName, gr->T("Postprocessing Shader"), &PostShaderTranslateName));
postProcChoice_->OnClick.Handle(this, &GameSettingsScreen::OnPostProcShader);
postProcChoice_->SetEnabledFunc([] {
return g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
});
graphicsSettings->Add(new ItemHeader(gr->T("Postprocessing effect")));
auto shaderChain = GetPostShaderChain(g_Config.sPostShaderName);
for (auto shaderInfo : shaderChain) {
for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) {
auto &setting = shaderInfo->settings[i];
if (!setting.name.empty()) {
auto &value = g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderInfo->section.c_str(), i + 1)];
graphicsSettings->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, ps->T(setting.name), setting.step, screenManager()));
std::vector<std::string> alreadyAddedShader;
for (int i = 0; i < g_Config.vPostShaderNames.size() && i < ARRAY_SIZE(shaderNames_); ++i) {
// Vector pointer get invalidated on resize, cache name to have always a valid reference for drawing
shaderNames_[i] = g_Config.vPostShaderNames[i];
postProcChoice_ = graphicsSettings->Add(new ChoiceWithValueDisplay(&shaderNames_[i], StringFromFormat("%s #%d", gr->T("Postprocessing Shader"), i + 1), &PostShaderTranslateName));
postProcChoice_->OnClick.Add([=](EventParams &e) {
auto gr = GetI18NCategory("Graphics");
auto procScreen = new PostProcScreen(gr->T("Postprocessing Shader"), i);
procScreen->OnChoice.Handle(this, &GameSettingsScreen::OnPostProcShaderChange);
if (e.v)
procScreen->SetPopupOrigin(e.v);
screenManager()->push(procScreen);
return UI::EVENT_DONE;
});
postProcChoice_->SetEnabledFunc([] {
return g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
});
auto shaderChain = GetPostShaderChain(g_Config.vPostShaderNames[i]);
for (auto shaderInfo : shaderChain) {
// Disable duplicated shader slider
bool duplicated = std::find(alreadyAddedShader.begin(), alreadyAddedShader.end(), shaderInfo->section) != alreadyAddedShader.end();
alreadyAddedShader.push_back(shaderInfo->section);
for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) {
auto &setting = shaderInfo->settings[i];
if (!setting.name.empty()) {
auto &value = g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderInfo->section.c_str(), i + 1)];
if (duplicated) {
auto sliderName = StringFromFormat("%s %s", ps->T(setting.name), ps->T("(duplicated setting, previous slider will be used)"));
PopupSliderChoiceFloat *settingValue = graphicsSettings->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, sliderName, setting.step, screenManager()));
settingValue->SetEnabled(false);
} else {
PopupSliderChoiceFloat *settingValue = graphicsSettings->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, ps->T(setting.name), setting.step, screenManager()));
settingValue->SetEnabledFunc([] {
return g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
});
}
}
}
}
}
graphicsSettings->Add(new ItemHeader(gr->T("Screen layout")));
#if !defined(MOBILE_DEVICE)
graphicsSettings->Add(new CheckBox(&g_Config.bFullScreen, gr->T("FullScreen", "Full Screen")))->OnClick.Handle(this, &GameSettingsScreen::OnFullscreenChange);
if (System_GetPropertyInt(SYSPROP_DISPLAY_COUNT) > 1) {
@ -1226,6 +1255,10 @@ void GameSettingsScreen::update() {
RecreateViews();
lastVertical_ = vertical;
}
if (g_ShaderNameListChanged) {
g_ShaderNameListChanged = false;
RecreateViews();
}
}
void GameSettingsScreen::onFinish(DialogResult result) {
@ -1489,19 +1522,11 @@ UI::EventReturn GameSettingsScreen::OnLanguageChange(UI::EventParams &e) {
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnPostProcShader(UI::EventParams &e) {
auto gr = GetI18NCategory("Graphics");
auto procScreen = new PostProcScreen(gr->T("Postprocessing Shader"));
procScreen->OnChoice.Handle(this, &GameSettingsScreen::OnPostProcShaderChange);
if (e.v)
procScreen->SetPopupOrigin(e.v);
screenManager()->push(procScreen);
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnPostProcShaderChange(UI::EventParams &e) {
g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end());
g_Config.vPostShaderNames.push_back("Off");
g_ShaderNameListChanged = true;
NativeMessageReceived("gpu_resized", "");
RecreateViews(); // Update setting name
return UI::EVENT_DONE;
}

View file

@ -80,7 +80,6 @@ private:
UI::EventReturn OnLanguage(UI::EventParams &e);
UI::EventReturn OnLanguageChange(UI::EventParams &e);
UI::EventReturn OnAutoFrameskip(UI::EventParams &e);
UI::EventReturn OnPostProcShader(UI::EventParams &e);
UI::EventReturn OnPostProcShaderChange(UI::EventParams &e);
UI::EventReturn OnTextureShader(UI::EventParams &e);
UI::EventReturn OnTextureShaderChange(UI::EventParams &e);
@ -132,6 +131,7 @@ private:
int prevInflightFrames_;
bool enableReports_;
bool tessHWEnable_;
std::string shaderNames_[256];
//edit the game-specific settings and restore the global settings after exiting
bool editThenRestore_;

View file

@ -301,7 +301,7 @@ void PromptScreen::TriggerFinish(DialogResult result) {
UIDialogScreenWithBackground::TriggerFinish(result);
}
PostProcScreen::PostProcScreen(const std::string &title) : ListPopupScreen(title) {
PostProcScreen::PostProcScreen(const std::string &title, int id) : ListPopupScreen(title), id_(id) {
auto ps = GetI18NCategory("PostShaders");
ReloadAllPostShaderInfo();
shaders_ = GetAllPostShaderInfo();
@ -310,7 +310,7 @@ PostProcScreen::PostProcScreen(const std::string &title) : ListPopupScreen(title
for (int i = 0; i < (int)shaders_.size(); i++) {
if (!shaders_[i].visible)
continue;
if (shaders_[i].section == g_Config.sPostShaderName)
if (shaders_[i].section == g_Config.vPostShaderNames[id_])
selected = i;
items.push_back(ps->T(shaders_[i].section.c_str(), shaders_[i].name.c_str()));
}
@ -320,7 +320,7 @@ PostProcScreen::PostProcScreen(const std::string &title) : ListPopupScreen(title
void PostProcScreen::OnCompleted(DialogResult result) {
if (result != DR_OK)
return;
g_Config.sPostShaderName = shaders_[listView_->GetSelected()].section;
g_Config.vPostShaderNames[id_] = shaders_[listView_->GetSelected()].section;
}
TextureShaderScreen::TextureShaderScreen(const std::string &title) : ListPopupScreen(title) {

View file

@ -105,12 +105,13 @@ private:
class PostProcScreen : public ListPopupScreen {
public:
PostProcScreen(const std::string &title);
PostProcScreen(const std::string &title, int id);
private:
void OnCompleted(DialogResult result) override;
bool ShowButtons() const override { return true; }
std::vector<ShaderInfo> shaders_;
int id_;
};
class TextureShaderScreen : public ListPopupScreen {

View file

@ -148,6 +148,7 @@ std::string config_filename;
// Really need to clean this mess of globals up... but instead I add more :P
bool g_TakeScreenshot;
bool g_ShaderNameListChanged = false;
static bool isOuya;
static bool resized = false;
static bool restarting = false;

View file

@ -47,6 +47,7 @@
#include "Core/Core.h"
extern bool g_TakeScreenshot;
extern bool g_ShaderNameListChanged;
namespace MainWindow {
extern HINSTANCE hInst;
@ -154,7 +155,7 @@ namespace MainWindow {
int item = ID_SHADERS_BASE + 1;
for (size_t i = 0; i < availableShaders.size(); i++)
CheckMenuItem(menu, item++, ((g_Config.sPostShaderName == availableShaders[i]) ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, item++, ((g_Config.vPostShaderNames[0] == availableShaders[i] && (g_Config.vPostShaderNames[0] == "Off" || g_Config.vPostShaderNames[1] == "Off")) ? MF_CHECKED : MF_UNCHECKED));
}
bool CreateShadersSubmenu(HMENU menu) {
@ -188,7 +189,7 @@ namespace MainWindow {
continue;
int checkedStatus = MF_UNCHECKED;
availableShaders.push_back(i->section);
if (g_Config.sPostShaderName == i->section) {
if (g_Config.vPostShaderNames[0] == i->section && (g_Config.vPostShaderNames[0] == "Off" || g_Config.vPostShaderNames[1] == "Off")) {
checkedStatus = MF_CHECKED;
}
@ -1064,8 +1065,11 @@ namespace MainWindow {
// ID_SHADERS_BASE and an additional 1 off it.
u32 index = (wParam - ID_SHADERS_BASE - 1);
if (index < availableShaders.size()) {
g_Config.sPostShaderName = availableShaders[index];
g_Config.vPostShaderNames.clear();
if (availableShaders[index] != "Off")
g_Config.vPostShaderNames.push_back(availableShaders[index]);
g_Config.vPostShaderNames.push_back("Off");
g_ShaderNameListChanged = true;
NativeMessageReceived("gpu_resized", "");
break;
}