Skip to content
Permalink
Browse files

Add generic "PostShader" functionality, replacing FXAA (it's one of t…

…hem).

Replaces #4018, sorry DanyalZia :)
  • Loading branch information...
hrydgard committed Oct 12, 2013
1 parent 1375b72 commit e0b19decca7ca168ee0517c577c7e6ebc72b83a9
@@ -1001,6 +1001,8 @@ add_library(GPU OBJECT
GPU/Common/IndexGenerator.h
GPU/Common/TextureDecoder.cpp
GPU/Common/TextureDecoder.h
GPU/Common/PostShader.cpp
GPU/Common/PostShader.h
GPU/Common/SplineCommon.h
GPU/GLES/GLES_GPU.cpp
GPU/GLES/GLES_GPU.h
@@ -179,7 +179,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename)
graphics->Get("DisableStencilTest", &bDisableStencilTest, false);
graphics->Get("AlwaysDepthWrite", &bAlwaysDepthWrite, false);
graphics->Get("LowQualitySplineBezier", &bLowQualitySplineBezier, false);
graphics->Get("FXAA", &bFXAA, false);
graphics->Get("PostShader", &sPostShaderName, "Off");

IniFile::Section *sound = iniFile.GetOrCreateSection("Sound");
sound->Get("Enable", &bEnableSound, true);
@@ -349,7 +349,7 @@ void Config::Save() {
graphics->Set("DisableStencilTest", bDisableStencilTest);
graphics->Set("AlwaysDepthWrite", bAlwaysDepthWrite);
graphics->Set("LowQualitySplineBezier", bLowQualitySplineBezier);
graphics->Set("FXAA", bFXAA);
graphics->Set("PostShader", sPostShaderName);

IniFile::Section *sound = iniFile.GetOrCreateSection("Sound");
sound->Set("Enable", bEnableSound);
@@ -94,7 +94,7 @@ struct Config {
bool bDisableStencilTest;
bool bAlwaysDepthWrite;
bool bLowQualitySplineBezier;
bool bFXAA;
std::string sPostShaderName; // Off for off.

// Sound
bool bEnableSound;
@@ -0,0 +1,109 @@
// Copyright (c) 2013- PPSSPP Project.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.


// Postprocessing shader manager

#include <string>
#include <vector>

#include "base/logging.h"
#include "file/ini_file.h"
#include "file/file_util.h"
#include "file/vfs.h"

#include "GPU/Common/PostShader.h"

static std::vector<ShaderInfo> shaderInfo;

// Scans the directories for shader ini files and collects info about all the shaders found.
// Additionally, scan the VFS assets. (TODO)

void LoadPostShaderInfo(std::vector<std::string> directories) {
shaderInfo.clear();
ShaderInfo off;
off.name = "Off";
off.section = "Off";
shaderInfo.push_back(off);

for (size_t d = 0; d < directories.size(); d++) {
std::vector<FileInfo> fileInfo;
getFilesInDir(directories[d].c_str(), &fileInfo, "ini:");
if (fileInfo.size() == 0) {
// TODO: Really gotta fix the filter, now it's gonna open shaders as ini files..
VFSGetFileListing(directories[d].c_str(), &fileInfo, "ini:");
}

for (size_t f = 0; f < fileInfo.size(); f++) {
IniFile ini;
bool success = false;
std::string name = fileInfo[f].fullName;
std::string path = directories[d];
// Hack around Android VFS path bug. really need to redesign this.
if (name.substr(0, 7) == "assets/")
name = name.substr(7);
if (path.substr(0, 7) == "assets/")
path = path.substr(7);
if (!ini.LoadFromVFS(name)) {
// vsh load. meh.
} else {
success = true;
}
if (!success)
continue;

// Alright, let's loop through the sections and see if any is a shader.
// Ignore the first section (which only consists of the comments before the first real one).
for (size_t i = 1; i < ini.Sections().size(); i++) {
IniFile::Section &section = ini.Sections()[i];

This comment has been minimized.

Copy link
@thedax

thedax Oct 12, 2013

Collaborator

This seems to break Windows compilation, at least for me, in 2010 mode:

Error   9   error C2440: 'initializing' : cannot convert from 'const IniFile::Section' to 'IniFile::Section &'  \GPU\Common\PostShader.cpp  71  1   GPU

Edit: 2013 doesn't like it either.

This comment has been minimized.

Copy link
@hrydgard

hrydgard Oct 12, 2013

Author Owner

Hm, did you update native?

This comment has been minimized.

Copy link
@thedax

thedax Oct 12, 2013

Collaborator

That fixed it. Sorry for the false alarm.

if (section.Exists("Fragment") && section.Exists("Vertex")) {
// Valid shader!
ShaderInfo info;
std::string temp;
info.section = section.name();
section.Get("Name", &info.name, section.name().c_str());
section.Get("Fragment", &temp, "");
info.fragmentShaderFile = path + "/" + temp;
section.Get("Vertex", &temp, "");
info.vertexShaderFile = path + "/" + temp;
shaderInfo.push_back(info);
}
}
}
}
}

// Scans the directories for shader ini files and collects info about all the shaders found.
void LoadAllPostShaderInfo() {
std::vector<std::string> directories;
directories.push_back("assets/shaders");
LoadPostShaderInfo(directories);
}

const ShaderInfo *GetPostShaderInfo(std::string name) {
LoadAllPostShaderInfo();
for (size_t i = 0; i < shaderInfo.size(); i++) {
if (shaderInfo[i].section == name)
return &shaderInfo[i];
}
return 0;
}

const std::vector<ShaderInfo> &GetAllPostShaderInfo() {
LoadAllPostShaderInfo();
return shaderInfo;
}
@@ -0,0 +1,41 @@
// Copyright (c) 2013- PPSSPP Project.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.


// Postprocessing shader manager
// For FXAA, "Natural", bloom, B&W, cross processing and whatnot.

#include <string>
#include <vector>

#include "file/ini_file.h"

struct ShaderInfo {
std::string iniFile; // which ini file was this definition in? So we can write settings back later
std::string section; // ini file section. This is saved.
std::string name; // Fancy display name. TODO: Not using yet.

std::string fragmentShaderFile;
std::string vertexShaderFile;

// TODO: Add support for all kinds of fun options like mapping the depth buffer,
// SRGB texture reads, multiple shaders chained, etc.
};

const ShaderInfo *GetPostShaderInfo(std::string name);

const std::vector<ShaderInfo> &GetAllPostShaderInfo();
@@ -29,6 +29,7 @@
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"

#include "GPU/Common/PostShader.h"
#include "GPU/GLES/Framebuffer.h"
#include "GPU/GLES/TextureCache.h"
#include "GPU/GLES/ShaderManager.h"
@@ -172,23 +173,31 @@ void FramebufferManager::CompileDraw2DProgram() {
glUniform1i(draw2dprogram_->sampler0, 0);

SetNumExtraFBOs(0);
if (g_Config.bFXAA) {
useFXAA_ = true;
fxaaProgram_ = glsl_create("shaders/fxaa.vsh", "shaders/fxaa.fsh");
if (!fxaaProgram_) {
ERROR_LOG(G3D, "Failed to build FXAA program");
useFXAA_ = false;

const ShaderInfo *shaderInfo = 0;
if (g_Config.sPostShaderName != "Off") {
shaderInfo = GetPostShaderInfo(g_Config.sPostShaderName);
}

if (shaderInfo) {
postShaderProgram_ = glsl_create(shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str());
if (!postShaderProgram_) {
ERROR_LOG(G3D, "Failed to build post-processing program");
usePostShader_ = false;
} else {
glsl_bind(fxaaProgram_);
glUniform1i(fxaaProgram_->sampler0, 0);
glsl_bind(postShaderProgram_);
glUniform1i(postShaderProgram_->sampler0, 0);
SetNumExtraFBOs(1);
float u_delta = 1.0f / PSP_CoreParameter().renderWidth;
float v_delta = 1.0f / PSP_CoreParameter().renderHeight;
glUniform2f(glsl_uniform_loc(fxaaProgram_, "u_texcoordDelta"), u_delta, v_delta);
int deltaLoc = glsl_uniform_loc(postShaderProgram_, "u_texcoordDelta");
if (deltaLoc != -1)
glUniform2f(deltaLoc, u_delta, v_delta);
usePostShader_ = true;
}
} else {
fxaaProgram_ = 0;
useFXAA_ = false;
postShaderProgram_ = 0;
usePostShader_ = false;
}

glsl_unbind();
@@ -200,9 +209,9 @@ void FramebufferManager::DestroyDraw2DProgram() {
glsl_destroy(draw2dprogram_);
draw2dprogram_ = 0;
}
if (fxaaProgram_) {
glsl_destroy(fxaaProgram_);
fxaaProgram_ = 0;
if (postShaderProgram_) {
glsl_destroy(postShaderProgram_);
postShaderProgram_ = 0;
}
}

@@ -219,10 +228,10 @@ FramebufferManager::FramebufferManager() :
drawPixelsTexFormat_(GE_FORMAT_INVALID),
convBuf(0),
draw2dprogram_(0),
fxaaProgram_(0),
postShaderProgram_(0),
textureCache_(0),
shaderManager_(0),
useFXAA_(false)
usePostShader_(false)
#ifndef USING_GLES2
,
pixelBufObj_(0),
@@ -812,15 +821,15 @@ void FramebufferManager::CopyDisplayToOutput() {
// TODO ES3: Use glInvalidateFramebuffer to discard depth/stencil data at the end of frame.
// and to discard extraFBOs_ after using them.

if (useFXAA_ && extraFBOs_.size() == 1) {
if (usePostShader_ && extraFBOs_.size() == 1) {
glBindTexture(GL_TEXTURE_2D, colorTexture);

// An additional pass, FXAA to the extra FBO.
fbo_bind_as_render_target(extraFBOs_[0]);
int fbo_w, fbo_h;
fbo_get_dimensions(extraFBOs_[0], &fbo_w, &fbo_h);
glstate.viewport.set(0, 0, fbo_w, fbo_h);
DrawActiveTexture(0, 0, fbo_w, fbo_h, fbo_w, fbo_h, true, 1.0f, 1.0f, fxaaProgram_);
DrawActiveTexture(0, 0, fbo_w, fbo_h, fbo_w, fbo_h, true, 1.0f, 1.0f, postShaderProgram_);

fbo_unbind();

@@ -216,11 +216,11 @@ class FramebufferManager {

u8 *convBuf;
GLSLProgram *draw2dprogram_;
GLSLProgram *fxaaProgram_;
GLSLProgram *postShaderProgram_;

TextureCache *textureCache_;
ShaderManager *shaderManager_;
bool useFXAA_;
bool usePostShader_;

// Used by antialiasing
std::vector<FBO *> extraFBOs_;
@@ -157,6 +157,7 @@
<ClInclude Include="..\ext\xbrz\xbrz.h" />
<ClInclude Include="Common\GPUDebugInterface.h" />
<ClInclude Include="Common\IndexGenerator.h" />
<ClInclude Include="Common\PostShader.h" />
<ClInclude Include="Common\SplineCommon.h" />
<ClInclude Include="Common\VertexDecoderCommon.h" />
<ClInclude Include="Directx9\GPU_DX9.h" />
@@ -200,6 +201,7 @@
<ItemGroup>
<ClCompile Include="..\ext\xbrz\xbrz.cpp" />
<ClCompile Include="Common\IndexGenerator.cpp" />
<ClCompile Include="Common\PostShader.cpp" />
<ClCompile Include="Common\VertexDecoderCommon.cpp" />
<ClCompile Include="Directx9\GPU_DX9.cpp" />
<ClCompile Include="Directx9\helper\dx_state.cpp" />
@@ -147,6 +147,7 @@
<ClInclude Include="Common\SplineCommon.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\PostShader.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math3D.cpp">
@@ -266,6 +267,7 @@
<ClCompile Include="Common\TextureDecoder.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="Common\PostShader.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
@@ -138,9 +138,12 @@ void GameSettingsScreen::CreateViews() {
graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gs->T("VSync")));
graphicsSettings->Add(new CheckBox(&g_Config.bFullScreen, gs->T("FullScreen")));
#endif
graphicsSettings->Add(new ItemHeader(gs->T("Antialiasing")));

graphicsSettings->Add(new ItemHeader(gs->T("Antialiasing and postprocessing")));
graphicsSettings->Add(new Choice(gs->T("Postprocessing shader")))->OnClick.Handle(this, &GameSettingsScreen::OnPostProcShader);

// In case we're going to add few other antialiasing option like MSAA in the future.
graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gs->T("FXAA")));
// graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gs->T("FXAA")));
graphicsSettings->Add(new ItemHeader(gs->T("Overlay Information")));
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iShowFPSCounter, gs->T("Show FPS Counter"), fpsChoices, 0, ARRAY_SIZE(fpsChoices), gs, screenManager()));
graphicsSettings->Add(new CheckBox(&g_Config.bShowDebugStats, gs->T("Show Debug Statistics")));
@@ -443,6 +446,20 @@ UI::EventReturn GameSettingsScreen::OnLanguageChange(UI::EventParams &e) {
return UI::EVENT_DONE;
}

UI::EventReturn GameSettingsScreen::OnPostProcShader(UI::EventParams &e) {
I18NCategory *g = GetI18NCategory("Graphics");
auto procScreen = new PostProcScreen(g->T("Postprocessing Shader"));
procScreen->OnChoice.Handle(this, &GameSettingsScreen::OnPostProcShaderChange);
screenManager()->push(procScreen);
return UI::EVENT_DONE;
}

UI::EventReturn GameSettingsScreen::OnPostProcShaderChange(UI::EventParams &e) {
if (gpu) {
gpu->Resized();
}
return UI::EVENT_DONE;
}
UI::EventReturn GameSettingsScreen::OnDeveloperTools(UI::EventParams &e) {
screenManager()->push(new DeveloperToolsScreen());
return UI::EVENT_DONE;
@@ -56,6 +56,8 @@ class GameSettingsScreen : public UIDialogScreenWithBackground {
// Global settings handlers
UI::EventReturn OnLanguage(UI::EventParams &e);
UI::EventReturn OnLanguageChange(UI::EventParams &e);
UI::EventReturn OnPostProcShader(UI::EventParams &e);
UI::EventReturn OnPostProcShaderChange(UI::EventParams &e);
UI::EventReturn OnFactoryReset(UI::EventParams &e);
UI::EventReturn OnDeveloperTools(UI::EventParams &e);
UI::EventReturn OnChangeNickname(UI::EventParams &e);

0 comments on commit e0b19de

Please sign in to comment.
You can’t perform that action at this time.