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
This commit is contained in:
gregory.hainaut 2012-05-11 19:39:32 +00:00
parent 5dc57ace33
commit a7dbaed3b1
3 changed files with 58 additions and 24 deletions

View File

@ -29,9 +29,6 @@
//#define PRINT_FRAME_NUMBER //#define PRINT_FRAME_NUMBER
//#define ONLY_LINES //#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_draw_count = 0;
static uint32 g_frame_count = 1; 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) 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 entry_main = format("#define %s main\n", entry.c_str());
std::string header = version + shader_type + entry_main + macro_sel; 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 // 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.copy(header_str, header.size(), 0);
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(source_str);
free(header_str); free(header_str);
free(sources_array); 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_BLENDFACTOR GL_CONSTANT_COLOR
#define D3DBLEND_INVBLENDFACTOR GL_ONE_MINUS_CONSTANT_COLOR #define D3DBLEND_INVBLENDFACTOR GL_ONE_MINUS_CONSTANT_COLOR
#ifdef DISABLE_DUAL_BLEND #define D3DBLEND_SRCALPHA GL_SRC1_ALPHA
#define D3DBLEND_SRCALPHA GL_SRC_ALPHA #define D3DBLEND_INVSRCALPHA GL_ONE_MINUS_SRC1_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
const GSDeviceOGL::D3D9Blend GSDeviceOGL::m_blendMapD3D9[3*3*3*3] = const GSDeviceOGL::D3D9Blend GSDeviceOGL::m_blendMapD3D9[3*3*3*3] =
{ {

View File

@ -919,4 +919,6 @@ class GSDeviceOGL : public GSDevice
void SetupGS(GSSelector sel); void SetupGS(GSSelector sel);
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel); void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix); void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
GLuint glCreateShaderProgramv_AMD_BUG_WORKAROUND(GLenum type, GLsizei count, const char ** strings);
}; };

View File

@ -261,12 +261,8 @@ void gs_main()
layout(location = 0) in vertex PSin; layout(location = 0) in vertex PSin;
// Same buffer but 2 colors for dual source blending // Same buffer but 2 colors for dual source blending
#ifndef DISABLE_DUAL_BLEND layout(location = 0, index = 0) out vec4 SV_Target0;
layout(location = 0, index = 1) out vec4 SV_Target0; layout(location = 0, index = 1) out vec4 SV_Target1;
layout(location = 0, index = 0) out vec4 SV_Target1;
#else
layout(location = 0) out vec4 SV_Target1;
#endif
layout(binding = 0) uniform sampler2D TextureSampler; layout(binding = 0) uniform sampler2D TextureSampler;
layout(binding = 1) uniform sampler2D PaletteSampler; layout(binding = 1) uniform sampler2D PaletteSampler;
@ -650,9 +646,7 @@ void ps_main()
if(c.a < 0.5) c.a += 0.5; if(c.a < 0.5) c.a += 0.5;
} }
SV_Target1 = c; SV_Target0 = c;
#ifndef DISABLE_DUAL_BLEND SV_Target1 = vec4(alpha, alpha, alpha, alpha);
SV_Target0 = vec4(alpha, alpha, alpha, alpha);
#endif
} }
#endif #endif