From a7dbaed3b1d5f17afdcb2e1963b3519386633d11 Mon Sep 17 00:00:00 2001 From: "gregory.hainaut" Date: Fri, 11 May 2012 19:39:32 +0000 Subject: [PATCH] gsdx ogl: find a way to workaround the buggy amd driver to support dual blending git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5203 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSdx/GSDeviceOGL.cpp | 66 ++++++++++++++++++++++++++++-------- plugins/GSdx/GSDeviceOGL.h | 2 ++ plugins/GSdx/res/tfx.glsl | 14 +++----- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index e81596549e..1edc371395 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -29,9 +29,6 @@ //#define PRINT_FRAME_NUMBER //#define ONLY_LINES -// It seems dual blending does not work on AMD !!! -//#define DISABLE_DUAL_BLEND - static uint32 g_draw_count = 0; static uint32 g_frame_count = 1; @@ -1236,6 +1233,40 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto } } +// AMD drivers fail to support correctly the setting of index in fragment shader (layout statement in glsl)... +// So instead to use directly glCreateShaderProgramv, you need to emulate the function and manually set +// the index in the fragment shader. +GLuint GSDeviceOGL::glCreateShaderProgramv_AMD_BUG_WORKAROUND(GLenum type, GLsizei count, const char ** strings) +{ + const GLuint shader = glCreateShader(type); + if (shader) { + glShaderSource(shader, count, strings, NULL); + glCompileShader(shader); + const GLuint program = glCreateProgram(); + if (program) { + GLint compiled = GL_FALSE; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE); + if (compiled) { + glAttachShader(program, shader); + // HACK TO SET CORRECTLY THE INDEX + if (type == GL_FRAGMENT_SHADER) { + glBindFragDataLocationIndexed(program, 0, 0, "SV_Target0"); + glBindFragDataLocationIndexed(program, 0, 1, "SV_Target1"); + } + // END OF HACK + glLinkProgram(program); + glDetachShader(program, shader); + } + /* append-shader-info-log-to-program-info-log */ + } + glDeleteShader(shader); + return program; + } else { + return 0; + } +} + void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const std::string& macro_sel) { // ***************************************************** @@ -1264,9 +1295,6 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st std::string entry_main = format("#define %s main\n", entry.c_str()); std::string header = version + shader_type + entry_main + macro_sel; -#ifdef DISABLE_DUAL_BLEND - header += "#define DISABLE_DUAL_BLEND 1\n"; -#endif // ***************************************************** // Read the source file @@ -1309,7 +1337,22 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st header.copy(header_str, header.size(), 0); header_str[header.size()] = '\0'; - *program = glCreateShaderProgramv(type, 2, sources_array); + // ... See below to test that index is correctly set by driver + //*program = glCreateShaderProgramv(type, 2, sources_array); + *program = glCreateShaderProgramv_AMD_BUG_WORKAROUND(type, 2, sources_array); + + // DEBUG AMD failure... + // GLint index = -1; + + // index = glGetFragDataIndex(*program, "SV_Target0"); + // fprintf(stderr, "Frag0 index %d\n", index); + // assert(index == 0); + + // index = glGetFragDataIndex(*program, "SV_Target1"); + // fprintf(stderr, "Frag1 index %d\n", index); + // assert(index == 1); + // END DEBUG AMD + free(source_str); free(header_str); free(sources_array); @@ -1430,13 +1473,8 @@ void GSDeviceOGL::DebugOutputToFile(unsigned int source, unsigned int type, unsi #define D3DBLEND_BLENDFACTOR GL_CONSTANT_COLOR #define D3DBLEND_INVBLENDFACTOR GL_ONE_MINUS_CONSTANT_COLOR -#ifdef DISABLE_DUAL_BLEND - #define D3DBLEND_SRCALPHA GL_SRC_ALPHA - #define D3DBLEND_INVSRCALPHA GL_ONE_MINUS_SRC_ALPHA -#else - #define D3DBLEND_SRCALPHA GL_SRC1_ALPHA - #define D3DBLEND_INVSRCALPHA GL_ONE_MINUS_SRC1_ALPHA -#endif +#define D3DBLEND_SRCALPHA GL_SRC1_ALPHA +#define D3DBLEND_INVSRCALPHA GL_ONE_MINUS_SRC1_ALPHA const GSDeviceOGL::D3D9Blend GSDeviceOGL::m_blendMapD3D9[3*3*3*3] = { diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 96eebf4b58..a8b1223f4a 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -919,4 +919,6 @@ class GSDeviceOGL : public GSDevice void SetupGS(GSSelector sel); void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel); void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix); + + GLuint glCreateShaderProgramv_AMD_BUG_WORKAROUND(GLenum type, GLsizei count, const char ** strings); }; diff --git a/plugins/GSdx/res/tfx.glsl b/plugins/GSdx/res/tfx.glsl index 92ce5fb75e..6be47a8034 100644 --- a/plugins/GSdx/res/tfx.glsl +++ b/plugins/GSdx/res/tfx.glsl @@ -261,12 +261,8 @@ void gs_main() layout(location = 0) in vertex PSin; // Same buffer but 2 colors for dual source blending -#ifndef DISABLE_DUAL_BLEND -layout(location = 0, index = 1) out vec4 SV_Target0; -layout(location = 0, index = 0) out vec4 SV_Target1; -#else -layout(location = 0) out vec4 SV_Target1; -#endif +layout(location = 0, index = 0) out vec4 SV_Target0; +layout(location = 0, index = 1) out vec4 SV_Target1; layout(binding = 0) uniform sampler2D TextureSampler; layout(binding = 1) uniform sampler2D PaletteSampler; @@ -650,9 +646,7 @@ void ps_main() if(c.a < 0.5) c.a += 0.5; } - SV_Target1 = c; -#ifndef DISABLE_DUAL_BLEND - SV_Target0 = vec4(alpha, alpha, alpha, alpha); -#endif + SV_Target0 = c; + SV_Target1 = vec4(alpha, alpha, alpha, alpha); } #endif