Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postprocessing: User chain support #12924

Merged
merged 2 commits into from
Sep 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion Core/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,8 @@ 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),
ConfigSetting("ShaderChainRequires60FPS", &g_Config.bShaderChainRequires60FPS, false, true, true),

ReportedConfigSetting("MemBlockTransferGPU", &g_Config.bBlockTransferGPU, true, true, true),
ReportedConfigSetting("DisableSlowFramebufEffects", &g_Config.bDisableSlowFramebufEffects, false, true, true),
Expand Down Expand Up @@ -1254,6 +1254,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;
Expand Down Expand Up @@ -1385,6 +1393,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");
Expand Down Expand Up @@ -1643,6 +1658,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);

Expand All @@ -1667,6 +1690,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);
Expand Down Expand Up @@ -1697,6 +1728,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();
}
}
Expand Down
6 changes: 4 additions & 2 deletions Core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,11 @@ struct Config {
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;
bool bShaderChainRequires60FPS;
std::string sTextureShaderName;
bool bGfxDebugOutput;
bool bGfxDebugSplitSubmit;
int iInflightFrames;
Expand Down
4 changes: 2 additions & 2 deletions Core/CwCheat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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;
Expand Down
7 changes: 1 addition & 6 deletions Core/HLE/sceDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 || g_Config.bShaderChainRequires60FPS;
}

const bool fbDirty = gpu->FramebufferDirty();
Expand Down
19 changes: 19 additions & 0 deletions GPU/Common/PostShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions GPU/Common/PostShader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 4 additions & 4 deletions GPU/Common/PresentationCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
74 changes: 50 additions & 24 deletions UI/GameSettingsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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")));

std::vector<std::string> alreadyAddedShader;
for (int i = 0; i < g_Config.vPostShaderNames.size() && i < ARRAY_SIZE(shaderNames_); ++i) {
// Vector element pointer get invalidated on resize, cache name to have always a valid reference in the rendering thread
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.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()));
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) {
Expand Down Expand Up @@ -1226,6 +1255,11 @@ void GameSettingsScreen::update() {
RecreateViews();
lastVertical_ = vertical;
}
if (g_ShaderNameListChanged) {
g_ShaderNameListChanged = false;
g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames));
RecreateViews();
}
}

void GameSettingsScreen::onFinish(DialogResult result) {
Expand Down Expand Up @@ -1489,19 +1523,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;
}

Expand Down
2 changes: 1 addition & 1 deletion UI/GameSettingsScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ class GameSettingsScreen : public UIDialogScreenWithGameBackground {
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);
Expand Down Expand Up @@ -132,6 +131,7 @@ class GameSettingsScreen : public UIDialogScreenWithGameBackground {
int prevInflightFrames_;
bool enableReports_;
bool tessHWEnable_;
std::string shaderNames_[256];

//edit the game-specific settings and restore the global settings after exiting
bool editThenRestore_;
Expand Down
6 changes: 3 additions & 3 deletions UI/MiscScreens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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()));
}
Expand All @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion UI/MiscScreens.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,13 @@ class NewLanguageScreen : public ListPopupScreen {

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 {
Expand Down
1 change: 1 addition & 0 deletions UI/NativeApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading