Skip to content

Commit

Permalink
Merge pull request #533 from PCSX2/gsdx-impossible-blend
Browse files Browse the repository at this point in the history
Gsdx impossible blend support on openGL
  • Loading branch information
gregory38 committed May 9, 2015
2 parents 9023f5f + 390811f commit b89f0cf
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 37 deletions.
15 changes: 14 additions & 1 deletion plugins/GSdx/GLLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,12 +493,25 @@ namespace GLLoader {
if (!found_GL_ARB_direct_state_access) {
Emulate_DSA::Init();
}

if (gl_BindTextureUnit == NULL) {
fprintf(stderr, "FATAL ERROR !!!! Failed to setup DSA function pointer!!!\n");
status = false;
}

if (!found_GL_ARB_texture_barrier) {
if (theApp.GetConfig("accurate_blend", 0)) {
fprintf(stderr, "Error GL_ARB_texture_barrier is not supported by your driver so you can't enable accurate_blend! Sorry.\n");
theApp.SetConfig("accurate_blend", 0);
}
}
if (!found_GL_ARB_shader_image_load_store) {
if (theApp.GetConfig("accurate_date", 0)) {
fprintf(stderr, "Error GL_ARB_shader_image_load_store is not supported by your driver so you can't enable accurate_date! Sorry.\n");
theApp.SetConfig("accurate_date", 0);
}
}


fprintf(stderr, "\n");

return status;
Expand Down
19 changes: 10 additions & 9 deletions plugins/GSdx/GSDeviceOGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ GLuint GSDeviceOGL::CompilePS(PSSelector sel)
+ format("#define PS_DATE %d\n", sel.date)
+ format("#define PS_TCOFFSETHACK %d\n", sel.tcoffsethack)
//+ format("#define PS_POINT_SAMPLER %d\n", sel.point_sampler)
+ format("#define PS_BLEND %d\n", sel.blend)
+ format("#define PS_IIP %d\n", sel.iip)
;

Expand Down Expand Up @@ -1264,32 +1265,32 @@ const GSDeviceOGL::D3D9Blend GSDeviceOGL::m_blendMapD3D9[3*3*3*3] =
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 0020: (Cs - Cs)*F + Cs ==> Cs
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 0021: (Cs - Cs)*F + Cd ==> Cd
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ZERO}, // 0022: (Cs - Cs)*F + 0 ==> 0
{1, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
{4, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As
{0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA}, // 0101: (Cs - Cd)*As + Cd ==> Cs*As + Cd*(1 - As)
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // 0102: (Cs - Cd)*As + 0 ==> Cs*As - Cd*As
{1, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
{5, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_INVDESTALPHA}, // 0111: (Cs - Cd)*Ad + Cd ==> Cs*Ad + Cd*(1 - Ad)
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // 0112: (Cs - Cd)*Ad + 0 ==> Cs*Ad - Cd*Ad
{1, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
{6, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F
{0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_INVBLENDFACTOR}, // 0121: (Cs - Cd)*F + Cd ==> Cs*F + Cd*(1 - F)
{0, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, // 0122: (Cs - Cd)*F + 0 ==> Cs*F - Cd*F
{1, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, //*0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
{7, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, //*0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)
{0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ONE}, // 0201: (Cs - 0)*As + Cd ==> Cs*As + Cd
{0, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, // 0202: (Cs - 0)*As + 0 ==> Cs*As
{1, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, //*0210: (Cs - 0)*Ad + Cs ==> Cs*(Ad + 1)
{8, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, //*0210: (Cs - 0)*Ad + Cs ==> Cs*(Ad + 1)
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ONE}, // 0211: (Cs - 0)*Ad + Cd ==> Cs*Ad + Cd
{0, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, // 0212: (Cs - 0)*Ad + 0 ==> Cs*Ad
{1, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, //*0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
{9, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, //*0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)
{0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ONE}, // 0221: (Cs - 0)*F + Cd ==> Cs*F + Cd
{0, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, // 0222: (Cs - 0)*F + 0 ==> Cs*F
{0, D3DBLENDOP_ADD, D3DBLEND_INVSRCALPHA, D3DBLEND_SRCALPHA}, // 1000: (Cd - Cs)*As + Cs ==> Cd*As + Cs*(1 - As)
{1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
{10,D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, // 1002: (Cd - Cs)*As + 0 ==> Cd*As - Cs*As
{0, D3DBLENDOP_ADD, D3DBLEND_INVDESTALPHA, D3DBLEND_DESTALPHA}, // 1010: (Cd - Cs)*Ad + Cs ==> Cd*Ad + Cs*(1 - Ad)
{1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
{11,D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, // 1012: (Cd - Cs)*Ad + 0 ==> Cd*Ad - Cs*Ad
{0, D3DBLENDOP_ADD, D3DBLEND_INVBLENDFACTOR, D3DBLEND_BLENDFACTOR}, // 1020: (Cd - Cs)*F + Cs ==> Cd*F + Cs*(1 - F)
{1, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},//*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
{12,D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},//*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F
{0, D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},// 1022: (Cd - Cs)*F + 0 ==> Cd*F - Cs*F
{0, D3DBLENDOP_ADD, D3DBLEND_ONE, D3DBLEND_ZERO}, // 1100: (Cd - Cd)*As + Cs ==> Cs
{0, D3DBLENDOP_ADD, D3DBLEND_ZERO, D3DBLEND_ONE}, // 1101: (Cd - Cd)*As + Cd ==> Cd
Expand Down
15 changes: 10 additions & 5 deletions plugins/GSdx/GSDeviceOGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class GSBlendStateOGL {

void SetBogus(char bogus) { m_bogus = bogus; }

int GetBogus() { return m_bogus; }

void RevertOp()
{
if(m_equation_RGB == GL_FUNC_ADD)
Expand Down Expand Up @@ -92,7 +94,7 @@ class GSBlendStateOGL {
#ifdef ENABLE_OGL_DEBUG
if (m_bogus) {
GL_INS("!!! Bogus blending effect !!!");
fprintf(stderr, "Bogus blending effect used : %s\n", (m_bogus == 1) ? "impossible effect" : "clear effect");
fprintf(stderr, "Bogus blending effect used : %s (%d)\n", (m_bogus > 2) ? "impossible effect" : "clear effect", m_bogus);
}
#endif
if (m_enable) {
Expand Down Expand Up @@ -254,6 +256,7 @@ class GSDeviceOGL : public GSDevice
GSVector4 WH;
GSVector4 MinF_TA;
GSVector4i MskFix;
GSVector4 AlphaCoeff;

GSVector4 HalfTexel;
GSVector4 MinMax;
Expand All @@ -267,6 +270,7 @@ class GSDeviceOGL : public GSDevice
MinMax = GSVector4::zero();
MinF_TA = GSVector4::zero();
MskFix = GSVector4i::zero();
AlphaCoeff = GSVector4::zero();
}

__forceinline bool Update(const PSConstantBuffer* cb)
Expand All @@ -276,13 +280,14 @@ class GSDeviceOGL : public GSDevice

// if WH matches both HalfTexel and TC_OffsetHack do too
// MinMax depends on WH and MskFix so no need to check it too
if(!((a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3])).alltrue())
if(!((a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]) & (a[3] == b[3]) & (a[4] == b[4])).alltrue())
{
// Note previous check uses SSE already, a plain copy will be faster than any memcpy
a[0] = b[0];
a[1] = b[1];
a[2] = b[2];
a[3] = b[3];
a[4] = b[4];

return true;
}
Expand Down Expand Up @@ -318,14 +323,14 @@ class GSDeviceOGL : public GSDevice
uint32 wmt:2;
uint32 ltf:1;

uint32 _free:4;
uint32 blend:4;
};

uint32 key;
};

// FIXME is the & useful ?
operator uint32() {return key & 0x0fffffff;}
operator uint32() {return key & 0xffffffff;}

PSSelector() : key(0) {}
};
Expand Down Expand Up @@ -623,7 +628,7 @@ class GSDeviceOGL : public GSDevice
void SetupPS(PSSelector sel);
void SetupCB(const VSConstantBuffer* vs_cb, const PSConstantBuffer* ps_cb);
void SetupSampler(PSSamplerSelector ssel);
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
int SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
GLuint GetSamplerID(PSSamplerSelector ssel);
GLuint GetPaletteSamplerID();

Expand Down
50 changes: 44 additions & 6 deletions plugins/GSdx/GSRendererOGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,26 @@ bool GSRendererOGL::PrimitiveOverlap()
return false;
}

void GSRendererOGL::SendDraw(bool require_barrier)
{
GSDeviceOGL* dev = (GSDeviceOGL*)m_dev;

if (!require_barrier || !PrimitiveOverlap()) {
dev->DrawIndexedPrimitive();
} else {
ASSERT(m_vt.m_primclass != GS_POINT_CLASS);
ASSERT(m_vt.m_primclass != GS_LINE_CLASS);
ASSERT(GLLoader::found_geometry_shader);

size_t nb_vertex = (m_vt.m_primclass == GS_TRIANGLE_CLASS) ? 3 : 2;

for (size_t p = 0; p < m_index.tail; p += nb_vertex) {
gl_TextureBarrier();
dev->DrawIndexedPrimitive(p, nb_vertex);
}
}
}

void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex)
{
#ifdef ENABLE_OGL_DEBUG
Expand All @@ -203,6 +223,8 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
bool DATE_GL42 = false;
bool DATE_GL45 = false;

bool require_barrier = false; // For blend (and maybe in date in the future)

ASSERT(m_dev != NULL);

GSDeviceOGL* dev = (GSDeviceOGL*)m_dev;
Expand Down Expand Up @@ -543,11 +565,25 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
GL_POP();

dev->OMSetColorMaskState(om_csel);
dev->SetupOM(om_dssel, om_bsel, afix);
// Handle blending with care
int bogus_blend = dev->SetupOM(om_dssel, om_bsel, afix);
if (m_accurate_blend && bogus_blend > 2) {
ps_sel.blend = bogus_blend - 3;
dev->SetupPS(ps_sel);
dev->PSSetShaderResource(3, rt);

if (bogus_blend == 6 || bogus_blend == 9 || bogus_blend == 12) {
ps_cb.AlphaCoeff = GSVector4((float)(int)afix / 0x80);
}

require_barrier = ((bogus_blend != 7) && (bogus_blend != 9));
}

dev->SetupCB(&vs_cb, &ps_cb);

if (DATE_GL42) {
GL_PUSH("Date GL42");
ASSERT(bogus_blend <= 2);
// It could be good idea to use stencil in the same time.
// Early stencil test will reduce the number of atomic-load operation

Expand All @@ -562,7 +598,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
// Don't write anything on the color buffer
dev->OMSetWriteBuffer(GL_NONE);
// Compute primitiveID max that pass the date test
dev->DrawIndexedPrimitive();
SendDraw(false);

// Ask PS to discard shader above the primitiveID max
dev->OMSetWriteBuffer();
Expand All @@ -581,10 +617,11 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour

if(context->TEST.DoFirstPass())
{
dev->DrawIndexedPrimitive();
SendDraw(require_barrier);

if (env.COLCLAMP.CLAMP == 0 && !tex && PRIM->PRIM != GS_POINTLIST)
{
ASSERT(bogus_blend <= 2);
GL_PUSH("COLCLIP");
GSDeviceOGL::OMBlendSelector om_bselneg(om_bsel);
GSDeviceOGL::PSSelector ps_selneg(ps_sel);
Expand All @@ -595,7 +632,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
dev->SetupOM(om_dssel, om_bselneg, afix);
dev->SetupPS(ps_selneg);

dev->DrawIndexedPrimitive();
SendDraw(false);
dev->SetupOM(om_dssel, om_bsel, afix);
GL_POP();
}
Expand Down Expand Up @@ -640,10 +677,11 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
dev->OMSetColorMaskState(om_csel);
dev->SetupOM(om_dssel, om_bsel, afix);

dev->DrawIndexedPrimitive();
SendDraw(require_barrier);

if (env.COLCLAMP.CLAMP == 0 && !tex && PRIM->PRIM != GS_POINTLIST)
{
ASSERT(bogus_blend <= 2);
GL_PUSH("COLCLIP");
GSDeviceOGL::OMBlendSelector om_bselneg(om_bsel);
GSDeviceOGL::PSSelector ps_selneg(ps_sel);
Expand All @@ -654,7 +692,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
dev->SetupOM(om_dssel, om_bselneg, afix);
dev->SetupPS(ps_selneg);

dev->DrawIndexedPrimitive();
SendDraw(false);
GL_POP();
}
}
Expand Down
2 changes: 2 additions & 0 deletions plugins/GSdx/GSRendererOGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ class GSRendererOGL : public GSRendererHW
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);

bool PrimitiveOverlap();

void SendDraw(bool require_barrier);
};
23 changes: 13 additions & 10 deletions plugins/GSdx/GSTextureFXOGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,24 @@ GSBlendStateOGL* GSDeviceOGL::CreateBlend(OMBlendSelector bsel, uint8 afix)
{
int i = ((bsel.a * 3 + bsel.b) * 3 + bsel.c) * 3 + bsel.d;

bs->EnableBlend();
bs->SetRGB(m_blendMapD3D9[i].op, m_blendMapD3D9[i].src, m_blendMapD3D9[i].dst);
bs->SetBogus(m_blendMapD3D9[i].bogus);

if(m_blendMapD3D9[i].bogus == 1)
{
if (bsel.a == 0)
bs->SetRGB(m_blendMapD3D9[i].op, GL_ONE, m_blendMapD3D9[i].dst);
else
bs->SetRGB(m_blendMapD3D9[i].op, m_blendMapD3D9[i].src, GL_ONE);
if (m_blendMapD3D9[i].bogus > 2) {
if (!theApp.GetConfig("accurate_blend", 0)) {
bs->EnableBlend();
if (bsel.a == 0)
bs->SetRGB(m_blendMapD3D9[i].op, GL_ONE, m_blendMapD3D9[i].dst);
else
bs->SetRGB(m_blendMapD3D9[i].op, m_blendMapD3D9[i].src, GL_ONE);
}

const string afixstr = format("%d >> 7", afix);
const char *col[3] = {"Cs", "Cd", "0"};
const char *alpha[3] = {"As", "Ad", afixstr.c_str()};

// FIXME, need to investigate OGL capabilities. Maybe for OGL5 ;)
fprintf(stderr, "Impossible blend for D3D: (%s - %s) * %s + %s\n", col[bsel.a], col[bsel.b], alpha[bsel.c], col[bsel.d]);
} else {
bs->EnableBlend();
}

// Not very good but I don't wanna write another 81 row table
Expand Down Expand Up @@ -230,7 +231,7 @@ GLuint GSDeviceOGL::GetPaletteSamplerID()
return m_palette_ss;
}

void GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
int GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
{
GSDepthStencilOGL* dss = m_om_dss[dssel];

Expand All @@ -254,4 +255,6 @@ void GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, ui
// Dynamic
// *************************************************************
OMSetBlendState(bs, (float)(int)afix / 0x80);

return bs->GetBogus();
}
15 changes: 9 additions & 6 deletions plugins/GSdx/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@

//#define DISABLE_DATE

// Allow to dump texture as PNG (require libpng++). It reduces the size of the dump
// and alpha is well supported (on linux)
//#define ENABLE_OGL_PNG
// The next two define allows to dump texture without alpha or only the alpha channel.
//#define ENABLE_OGL_PNG_OPAQUE
//#define ENABLE_OGL_PNG_ALPHA

#if defined(_DEBUG) || defined(_DEVEL)
#define ENABLE_OGL_DEBUG // Create a debug context and check opengl command status. Allow also to dump various textures/states.
Expand All @@ -54,3 +48,12 @@
#ifdef _WINDOWS
//#define ENABLE_OPENCL
#endif

#if defined(ENABLE_OGL_DEBUG) && defined(__linux__)
// Allow to dump texture as PNG (require libpng++). It reduces the size of the dump
// and alpha is well supported (on linux)
#define ENABLE_OGL_PNG
// The next two define allows to dump texture without alpha or only the alpha channel.
#define ENABLE_OGL_PNG_OPAQUE
#define ENABLE_OGL_PNG_ALPHA
#endif
Loading

0 comments on commit b89f0cf

Please sign in to comment.