Change OpenGL's post processing to use the new VideoCommon PP object.

Let's OpenGL's PostProcessing namespace be changed to a class inheriting from VideoCommon's PostProcessing class.
This commit is contained in:
Ryan Houdek 2014-07-29 11:57:02 -05:00
parent b8a21b3744
commit cced3b4a18
4 changed files with 148 additions and 71 deletions

View File

@ -4,6 +4,7 @@
#include "Common/CommonPaths.h" #include "Common/CommonPaths.h"
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Common/StringUtil.h"
#include "VideoBackends/OGL/FramebufferManager.h" #include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/GLUtil.h" #include "VideoBackends/OGL/GLUtil.h"
@ -16,20 +17,6 @@
namespace OGL namespace OGL
{ {
namespace PostProcessing
{
static std::string s_currentShader;
static SHADER s_shader;
static bool s_enable;
static u32 s_width;
static u32 s_height;
static GLuint s_fbo;
static GLuint s_texture;
static GLuint s_uniform_resolution;
static char s_vertex_shader[] = static char s_vertex_shader[] =
"out vec2 uv0;\n" "out vec2 uv0;\n"
"void main(void) {\n" "void main(void) {\n"
@ -38,7 +25,7 @@ static char s_vertex_shader[] =
" uv0 = rawpos;\n" " uv0 = rawpos;\n"
"}\n"; "}\n";
void Init() OpenGLPostProcessing::OpenGLPostProcessing()
{ {
m_enable = false; m_enable = false;
m_width = 0; m_width = 0;
@ -51,98 +38,151 @@ void Init()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glBindFramebuffer(GL_FRAMEBUFFER, s_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s_texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
FramebufferManager::SetFramebuffer(0); FramebufferManager::SetFramebuffer(0);
CreateHeader();
} }
void Shutdown() OpenGLPostProcessing::~OpenGLPostProcessing()
{ {
m_shader.Destroy(); m_shader.Destroy();
glDeleteFramebuffers(1, &s_fbo); glDeleteFramebuffers(1, &m_fbo);
glDeleteTextures(1, &s_texture); glDeleteTextures(1, &m_texture);
} }
void ReloadShader() void OpenGLPostProcessing::BindTargetFramebuffer()
{ {
s_currentShader = ""; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_enable ? m_fbo : 0);
} }
void BindTargetFramebuffer () void OpenGLPostProcessing::BlitToScreen()
{ {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_enable ? s_fbo : 0); if (!m_enable) return;
}
void BlitToScreen()
{
if (!s_enable) return;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, s_width, s_height); glViewport(0, 0, m_width, m_height);
s_shader.Bind(); m_shader.Bind();
glUniform4f(m_uniform_resolution, (float)m_width, (float)m_height, 1.0f/(float)m_width, 1.0f/(float)m_height); glUniform4f(m_uniform_resolution, (float)m_width, (float)m_height, 1.0f/(float)m_width, 1.0f/(float)m_height);
glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed()); glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed());
glUniform4f(s_uniform_resolution, (float)s_width, (float)s_height, 1.0f/(float)s_width, 1.0f/(float)s_height); if (m_config.IsDirty())
{
for (auto& it : m_config.GetOptions())
{
if (it.second.m_dirty)
{
switch (it.second.m_type)
{
case PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_BOOL:
glUniform1i(m_uniform_bindings[it.first], it.second.m_bool_value);
break;
case PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER:
switch (it.second.m_integer_values.size())
{
case 1:
glUniform1i(m_uniform_bindings[it.first], it.second.m_integer_values[0]);
break;
case 2:
glUniform2i(m_uniform_bindings[it.first],
it.second.m_integer_values[0],
it.second.m_integer_values[1]);
break;
case 3:
glUniform3i(m_uniform_bindings[it.first],
it.second.m_integer_values[0],
it.second.m_integer_values[1],
it.second.m_integer_values[2]);
break;
case 4:
glUniform4i(m_uniform_bindings[it.first],
it.second.m_integer_values[0],
it.second.m_integer_values[1],
it.second.m_integer_values[2],
it.second.m_integer_values[3]);
break;
}
break;
case PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_FLOAT:
switch (it.second.m_float_values.size())
{
case 1:
glUniform1f(m_uniform_bindings[it.first], it.second.m_float_values[0]);
break;
case 2:
glUniform2f(m_uniform_bindings[it.first],
it.second.m_float_values[0],
it.second.m_float_values[1]);
break;
case 3:
glUniform3f(m_uniform_bindings[it.first],
it.second.m_float_values[0],
it.second.m_float_values[1],
it.second.m_float_values[2]);
break;
case 4:
glUniform4f(m_uniform_bindings[it.first],
it.second.m_float_values[0],
it.second.m_float_values[1],
it.second.m_float_values[2],
it.second.m_float_values[3]);
break;
}
break;
}
it.second.m_dirty = false;
}
}
m_config.SetDirty(false);
}
glActiveTexture(GL_TEXTURE0+9); glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, s_texture); glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo);
glBlitFramebuffer(rc.left, rc.bottom, rc.right, rc.top,
rc.left, rc.bottom, rc.right, rc.top,
GL_COLOR_BUFFER_BIT, GL_NEAREST);*/
} }
void Update ( u32 width, u32 height ) void OpenGLPostProcessing::Update(u32 width, u32 height)
{ {
ApplyShader(); ApplyShader();
if (s_enable && (width != s_width || height != s_height)) { if (m_enable && (width != m_width || height != m_height))
s_width = width; {
s_height = height; m_width = width;
m_height = height;
// alloc texture for framebuffer // alloc texture for framebuffer
glActiveTexture(GL_TEXTURE0+9); glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, s_texture); glBindTexture(GL_TEXTURE_2D, m_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
} }
} }
void ApplyShader() void OpenGLPostProcessing::ApplyShader()
{ {
// shader didn't changed // shader didn't changed
if (s_currentShader == g_ActiveConfig.sPostProcessingShader) return; if (m_config.GetShader() == g_ActiveConfig.sPostProcessingShader) return;
s_currentShader = g_ActiveConfig.sPostProcessingShader;
s_enable = false; m_enable = false;
s_shader.Destroy(); m_shader.Destroy();
m_uniform_bindings.clear();
// shader disabled // shader disabled
if (g_ActiveConfig.sPostProcessingShader == "") return; if (g_ActiveConfig.sPostProcessingShader == "") return;
// so need to compile shader // so need to compile shader
std::string code = m_config.LoadShader();
// loading shader code if (code == "") return;
std::string code;
std::string path = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".glsl"; code = LoadShaderOptions(code);
if (!File::Exists(path))
{
// Fallback to shared user dir
path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + g_ActiveConfig.sPostProcessingShader + ".glsl";
}
if (!File::ReadFileToString(path, code)) {
ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str());
return;
}
// and compile it // and compile it
if (!ProgramShaderCache::CompileShader(s_shader, s_vertex_shader, code.c_str())) { if (!ProgramShaderCache::CompileShader(m_shader, s_vertex_shader, code.c_str())) {
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str()); ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str());
return; return;
} }
@ -150,7 +190,7 @@ void ApplyShader()
m_uniform_resolution = glGetUniformLocation(m_shader.glprogid, "resolution"); m_uniform_resolution = glGetUniformLocation(m_shader.glprogid, "resolution");
m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time"); m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time");
for (const auto& it : m_options) for (const auto& it : m_config.GetOptions())
{ {
std::string glsl_name = "option_" + it.first; std::string glsl_name = "option_" + it.first;
m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str()); m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str());
@ -225,6 +265,38 @@ void OpenGLPostProcessing::CreateHeader()
"#define OptionEnabled(x) (option_#x != 0)\n"; "#define OptionEnabled(x) (option_#x != 0)\n";
} }
} // namespace std::string OpenGLPostProcessing::LoadShaderOptions(const std::string& code)
{
std::string glsl_options = "";
m_uniform_bindings.clear();
for (const auto& it : m_config.GetOptions())
{
if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_BOOL)
{
glsl_options += StringFromFormat("uniform int option_%s;\n", it.first.c_str());
}
else if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER)
{
u32 count = it.second.m_integer_values.size();
if (count == 1)
glsl_options += StringFromFormat("uniform int option_%s;\n", it.first.c_str());
else
glsl_options += StringFromFormat("uniform int%d option_%s;\n", count, it.first.c_str());
}
else if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_FLOAT)
{
u32 count = it.second.m_float_values.size();
if (count == 1)
glsl_options += StringFromFormat("uniform float option_%s;\n", it.first.c_str());
else
glsl_options += StringFromFormat("uniform float%d option_%s;\n", count, it.first.c_str());
}
m_uniform_bindings[it.first] = 0;
}
return m_glsl_header + glsl_options + code;
}
} // namespace OGL } // namespace OGL

View File

@ -8,6 +8,8 @@
#include <unordered_map> #include <unordered_map>
#include "VideoBackends/OGL/GLUtil.h" #include "VideoBackends/OGL/GLUtil.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoCommon.h"
namespace OGL namespace OGL

View File

@ -641,6 +641,9 @@ void Renderer::Shutdown()
delete s_pfont; delete s_pfont;
s_pfont = nullptr; s_pfont = nullptr;
s_ShowEFBCopyRegions.Destroy(); s_ShowEFBCopyRegions.Destroy();
delete m_post_processor;
m_post_processor = nullptr;
} }
void Renderer::Init() void Renderer::Init()
@ -649,6 +652,8 @@ void Renderer::Init()
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height, g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples); s_MSAASamples);
m_post_processor = new OpenGLPostProcessing();
s_pfont = new RasterFont(); s_pfont = new RasterFont();
ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions, ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
@ -1331,7 +1336,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
ResetAPIState(); ResetAPIState();
PostProcessing::Update(s_backbuffer_width, s_backbuffer_height); m_post_processor->Update(s_backbuffer_width, s_backbuffer_height);
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
TargetRectangle flipped_trc = GetTargetRectangle(); TargetRectangle flipped_trc = GetTargetRectangle();
@ -1354,7 +1359,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
if (g_ActiveConfig.bUseXFB) if (g_ActiveConfig.bUseXFB)
{ {
// Render to the real/postprocessing buffer now. // Render to the real/postprocessing buffer now.
PostProcessing::BindTargetFramebuffer(); m_post_processor->BindTargetFramebuffer();
// draw each xfb source // draw each xfb source
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer()); glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
@ -1413,7 +1418,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
FramebufferManager::ResolveAndGetRenderTarget(rc); FramebufferManager::ResolveAndGetRenderTarget(rc);
// Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode) // Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode)
PostProcessing::BindTargetFramebuffer(); m_post_processor->BindTargetFramebuffer();
// always the non-msaa fbo // always the non-msaa fbo
GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer(); GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer();
@ -1424,7 +1429,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
GL_COLOR_BUFFER_BIT, GL_LINEAR); GL_COLOR_BUFFER_BIT, GL_LINEAR);
} }
PostProcessing::BlitToScreen(); m_post_processor->BlitToScreen();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

View File

@ -210,7 +210,6 @@ void VideoBackend::Video_Prepare()
VertexShaderManager::Init(); VertexShaderManager::Init();
PixelShaderManager::Init(); PixelShaderManager::Init();
ProgramShaderCache::Init(); ProgramShaderCache::Init();
PostProcessing::Init();
g_texture_cache = new TextureCache(); g_texture_cache = new TextureCache();
g_sampler_cache = new SamplerCache(); g_sampler_cache = new SamplerCache();
Renderer::Init(); Renderer::Init();
@ -250,7 +249,6 @@ void VideoBackend::Video_Cleanup() {
g_sampler_cache = nullptr; g_sampler_cache = nullptr;
delete g_texture_cache; delete g_texture_cache;
g_texture_cache = nullptr; g_texture_cache = nullptr;
PostProcessing::Shutdown();
ProgramShaderCache::Shutdown(); ProgramShaderCache::Shutdown();
VertexShaderManager::Shutdown(); VertexShaderManager::Shutdown();
PixelShaderManager::Shutdown(); PixelShaderManager::Shutdown();