Merge pull request #1440 from Sonicadvance1/attributeless-workaround
Implements PP shader system using attribute workaround.
This commit is contained in:
commit
3e82cb4628
|
@ -11,12 +11,22 @@
|
||||||
#include "VideoBackends/OGL/PostProcessing.h"
|
#include "VideoBackends/OGL/PostProcessing.h"
|
||||||
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/DriverDetails.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
namespace OGL
|
namespace OGL
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static char s_vertex_workaround_shader[] =
|
||||||
|
"in vec4 rawpos;\n"
|
||||||
|
"out vec2 uv0;\n"
|
||||||
|
"uniform vec4 src_rect;\n"
|
||||||
|
"void main(void) {\n"
|
||||||
|
" gl_Position = vec4(rawpos.xy, 0.0, 1.0);\n"
|
||||||
|
" uv0 = rawpos.zw * src_rect.zw + src_rect.xy;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
static char s_vertex_shader[] =
|
static char s_vertex_shader[] =
|
||||||
"out vec2 uv0;\n"
|
"out vec2 uv0;\n"
|
||||||
"uniform vec4 src_rect;\n"
|
"uniform vec4 src_rect;\n"
|
||||||
|
@ -29,12 +39,26 @@ static char s_vertex_shader[] =
|
||||||
OpenGLPostProcessing::OpenGLPostProcessing()
|
OpenGLPostProcessing::OpenGLPostProcessing()
|
||||||
{
|
{
|
||||||
CreateHeader();
|
CreateHeader();
|
||||||
|
|
||||||
|
m_attribute_workaround = DriverDetails::HasBug(DriverDetails::BUG_BROKENATTRIBUTELESS);
|
||||||
|
if (m_attribute_workaround)
|
||||||
|
{
|
||||||
|
glGenBuffers(1, &m_attribute_vbo);
|
||||||
|
glGenVertexArrays(1, &m_attribute_vao);
|
||||||
|
}
|
||||||
|
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLPostProcessing::~OpenGLPostProcessing()
|
OpenGLPostProcessing::~OpenGLPostProcessing()
|
||||||
{
|
{
|
||||||
m_shader.Destroy();
|
m_shader.Destroy();
|
||||||
|
|
||||||
|
if (m_attribute_workaround)
|
||||||
|
{
|
||||||
|
glDeleteBuffers(1, &m_attribute_vbo);
|
||||||
|
glDeleteVertexArrays(1, &m_attribute_vao);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle dst,
|
void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle dst,
|
||||||
|
@ -46,6 +70,9 @@ void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle
|
||||||
|
|
||||||
glViewport(dst.left, dst.bottom, dst.GetWidth(), dst.GetHeight());
|
glViewport(dst.left, dst.bottom, dst.GetWidth(), dst.GetHeight());
|
||||||
|
|
||||||
|
if (m_attribute_workaround)
|
||||||
|
glBindVertexArray(m_attribute_vao);
|
||||||
|
|
||||||
m_shader.Bind();
|
m_shader.Bind();
|
||||||
|
|
||||||
glUniform4f(m_uniform_resolution, (float)src_width, (float)src_height, 1.0f / (float)src_width, 1.0f / (float)src_height);
|
glUniform4f(m_uniform_resolution, (float)src_width, (float)src_height, 1.0f / (float)src_width, 1.0f / (float)src_height);
|
||||||
|
@ -150,13 +177,18 @@ void OpenGLPostProcessing::ApplyShader()
|
||||||
|
|
||||||
code = LoadShaderOptions(code);
|
code = LoadShaderOptions(code);
|
||||||
|
|
||||||
|
const char* vertex_shader = s_vertex_shader;
|
||||||
|
|
||||||
|
if (m_attribute_workaround)
|
||||||
|
vertex_shader = s_vertex_workaround_shader;
|
||||||
|
|
||||||
// and compile it
|
// and compile it
|
||||||
if (!ProgramShaderCache::CompileShader(m_shader, s_vertex_shader, code.c_str()))
|
if (!ProgramShaderCache::CompileShader(m_shader, vertex_shader, code.c_str()))
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str());
|
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str());
|
||||||
|
|
||||||
code = LoadShaderOptions(default_shader);
|
code = LoadShaderOptions(default_shader);
|
||||||
ProgramShaderCache::CompileShader(m_shader, s_vertex_shader, code.c_str());
|
ProgramShaderCache::CompileShader(m_shader, vertex_shader, code.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// read uniform locations
|
// read uniform locations
|
||||||
|
@ -164,6 +196,23 @@ void OpenGLPostProcessing::ApplyShader()
|
||||||
m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time");
|
m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time");
|
||||||
m_uniform_src_rect = glGetUniformLocation(m_shader.glprogid, "src_rect");
|
m_uniform_src_rect = glGetUniformLocation(m_shader.glprogid, "src_rect");
|
||||||
|
|
||||||
|
if (m_attribute_workaround)
|
||||||
|
{
|
||||||
|
GLfloat vertices[] = {
|
||||||
|
-1.f, -1.f, 0.f, 0.f,
|
||||||
|
1.f, -1.f, 1.f, 0.f,
|
||||||
|
-1.f, 1.f, 0.f, 1.f,
|
||||||
|
1.f, 1.f, 1.f, 1.f,
|
||||||
|
};
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_attribute_vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindVertexArray(m_attribute_vao);
|
||||||
|
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
|
||||||
|
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 4, GL_FLOAT, 0, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& it : m_config.GetOptions())
|
for (const auto& it : m_config.GetOptions())
|
||||||
{
|
{
|
||||||
std::string glsl_name = "option_" + it.first;
|
std::string glsl_name = "option_" + it.first;
|
||||||
|
|
|
@ -34,6 +34,11 @@ private:
|
||||||
GLuint m_uniform_time;
|
GLuint m_uniform_time;
|
||||||
std::string m_glsl_header;
|
std::string m_glsl_header;
|
||||||
|
|
||||||
|
// These are only used when working around Qualcomm's broken attributeless rendering
|
||||||
|
GLuint m_attribute_vao;
|
||||||
|
GLuint m_attribute_vbo;
|
||||||
|
bool m_attribute_workaround = false;
|
||||||
|
|
||||||
std::unordered_map<std::string, GLuint> m_uniform_bindings;
|
std::unordered_map<std::string, GLuint> m_uniform_bindings;
|
||||||
|
|
||||||
void CreateHeader();
|
void CreateHeader();
|
||||||
|
|
|
@ -1395,15 +1395,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
|
||||||
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
|
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
|
||||||
TargetRectangle flipped_trc = GetTargetRectangle();
|
TargetRectangle flipped_trc = GetTargetRectangle();
|
||||||
|
|
||||||
if (DriverDetails::HasBug(DriverDetails::BUG_ROTATEDFRAMEBUFFER))
|
// Flip top and bottom for some reason; TODO: Fix the code to suck less?
|
||||||
{
|
std::swap(flipped_trc.top, flipped_trc.bottom);
|
||||||
std::swap(flipped_trc.left, flipped_trc.right);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Flip top and bottom for some reason; TODO: Fix the code to suck less?
|
|
||||||
std::swap(flipped_trc.top, flipped_trc.bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the framebuffer to screen.
|
// Copy the framebuffer to screen.
|
||||||
const XFBSource* xfbSource = nullptr;
|
const XFBSource* xfbSource = nullptr;
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace DriverDetails
|
||||||
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENSWAP, -1.0, 46.0, true},
|
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENSWAP, -1.0, 46.0, true},
|
||||||
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true},
|
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true},
|
||||||
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENTEXTURESIZE, -1.0, 65.0, true},
|
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENTEXTURESIZE, -1.0, 65.0, true},
|
||||||
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_ROTATEDFRAMEBUFFER, 53.0, 65.0, true},
|
{OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENATTRIBUTELESS, -1.0, 94.0, true},
|
||||||
{OS_ALL, VENDOR_ARM, DRIVER_ARM_MIDGARD, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true},
|
{OS_ALL, VENDOR_ARM, DRIVER_ARM_MIDGARD, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true},
|
||||||
{OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, -1, BUG_BROKENUBO, 900, 916, true},
|
{OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, -1, BUG_BROKENUBO, 900, 916, true},
|
||||||
{OS_ALL, VENDOR_MESA, DRIVER_R600, -1, BUG_BROKENUBO, 900, 913, true},
|
{OS_ALL, VENDOR_MESA, DRIVER_R600, -1, BUG_BROKENUBO, 900, 913, true},
|
||||||
|
|
|
@ -162,15 +162,6 @@ namespace DriverDetails
|
||||||
// TODO: some windows AMD driver/gpu combination seems also affected
|
// TODO: some windows AMD driver/gpu combination seems also affected
|
||||||
// but as they all support pinned memory, it doesn't matter
|
// but as they all support pinned memory, it doesn't matter
|
||||||
BUG_BROKENUNSYNCMAPPING,
|
BUG_BROKENUNSYNCMAPPING,
|
||||||
// Bug: Adreno now rotates the framebuffer on blit a full 180 degrees
|
|
||||||
// Affected devices: Adreno
|
|
||||||
// Started Version: v53 (dev drivers)
|
|
||||||
// Ended Version: v66 (07-14-2014 dev drivers)
|
|
||||||
// Qualcomm is a super pro company that has recently updated their development drivers
|
|
||||||
// These drivers are available to the Nexus 5 and report as v53
|
|
||||||
// Qualcomm in their infinite wisdom thought it was a good idea to rotate the framebuffer 180 degrees on glBlit
|
|
||||||
// This bug allows us to work around that rotation by rotating it the right way around again.
|
|
||||||
BUG_ROTATEDFRAMEBUFFER,
|
|
||||||
// Bug: Intel's Window driver broke buffer_storage with GL_ELEMENT_ARRAY_BUFFER
|
// Bug: Intel's Window driver broke buffer_storage with GL_ELEMENT_ARRAY_BUFFER
|
||||||
// Affected devices: Intel (Windows)
|
// Affected devices: Intel (Windows)
|
||||||
// Started Version: 15.36.3.64.3907 (10.18.10.3907)
|
// Started Version: 15.36.3.64.3907 (10.18.10.3907)
|
||||||
|
@ -179,6 +170,14 @@ namespace DriverDetails
|
||||||
// It works for all the buffer types we use except GL_ELEMENT_ARRAY_BUFFER.
|
// It works for all the buffer types we use except GL_ELEMENT_ARRAY_BUFFER.
|
||||||
// Causes complete blackscreen issues.
|
// Causes complete blackscreen issues.
|
||||||
BUG_INTELBROKENBUFFERSTORAGE,
|
BUG_INTELBROKENBUFFERSTORAGE,
|
||||||
|
// Bug: Qualcomm has broken attributeless rendering
|
||||||
|
// Affected devices: Adreno
|
||||||
|
// Started Version: -1
|
||||||
|
// Ended Version: v66 (07-09-2014 dev version), v95 shipping
|
||||||
|
// Qualcomm has had attributeless rendering broken forever
|
||||||
|
// This was fixed in a v66 development version, the first shipping driver version with the release was v95.
|
||||||
|
// To be safe, make v95 the minimum version to work around this issue
|
||||||
|
BUG_BROKENATTRIBUTELESS,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initializes our internal vendor, device family, and driver version
|
// Initializes our internal vendor, device family, and driver version
|
||||||
|
|
Loading…
Reference in New Issue