From 380e420cdde46dcc016ece0613645f728a9ff71c Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 8 May 2015 19:30:48 +0200 Subject: [PATCH 1/9] gsdx-ogl: add a blend parameter to shader --- plugins/GSdx/GSDeviceOGL.cpp | 1 + plugins/GSdx/GSDeviceOGL.h | 8 +++++--- plugins/GSdx/GSRendererOGL.cpp | 2 +- plugins/GSdx/GSTextureFXOGL.cpp | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 7cc1911fa3ed0..0e40243c6e3bd 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -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) ; diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 1c5e480265772..c89c96e7afa0f 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -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) @@ -318,14 +320,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) {} }; @@ -623,7 +625,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(); diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 0bdedb058b8e2..24d558c25a1fb 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -543,7 +543,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour GL_POP(); dev->OMSetColorMaskState(om_csel); - dev->SetupOM(om_dssel, om_bsel, afix); + int bogus_blend = dev->SetupOM(om_dssel, om_bsel, afix); dev->SetupCB(&vs_cb, &ps_cb); if (DATE_GL42) { diff --git a/plugins/GSdx/GSTextureFXOGL.cpp b/plugins/GSdx/GSTextureFXOGL.cpp index fdc80e65b5b9c..b156c992793ef 100644 --- a/plugins/GSdx/GSTextureFXOGL.cpp +++ b/plugins/GSdx/GSTextureFXOGL.cpp @@ -230,7 +230,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]; @@ -254,4 +254,6 @@ void GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, ui // Dynamic // ************************************************************* OMSetBlendState(bs, (float)(int)afix / 0x80); + + return bs->GetBogus(); } From bc5de8df6bb04219d9879cf94d801557c6ffc8ef Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 8 May 2015 19:31:49 +0200 Subject: [PATCH 2/9] gsdx-ogl: disable FF blend when blend is done in shader --- plugins/GSdx/GSTextureFXOGL.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/GSdx/GSTextureFXOGL.cpp b/plugins/GSdx/GSTextureFXOGL.cpp index b156c992793ef..b83df69c7870d 100644 --- a/plugins/GSdx/GSTextureFXOGL.cpp +++ b/plugins/GSdx/GSTextureFXOGL.cpp @@ -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 From 625d65d4b4ca65fa58bafaa4eec16c0bbe8bfbea Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 8 May 2015 19:32:30 +0200 Subject: [PATCH 3/9] gsdx-ogl: encode the bogus id as shader parameter --- plugins/GSdx/GSDeviceOGL.cpp | 18 +++++++++--------- plugins/GSdx/GSDeviceOGL.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 0e40243c6e3bd..3e4fd2e7be207 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -1265,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 diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index c89c96e7afa0f..3f1444636673b 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -94,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) { From 1e8aea033cdcb139027094cbe129df9709147643 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sat, 9 May 2015 15:01:39 +0200 Subject: [PATCH 4/9] gsdx-ogl: add a wrapper to control the drawing of primitives No barrier => draw all primitives Barrier but without overlap => draw all primitives Barrier with overlap => draw primitive by primitve It will ease the implementation of accurate blending and why not date too --- plugins/GSdx/GSRendererOGL.cpp | 32 +++++++++++++++++++++++++++----- plugins/GSdx/GSRendererOGL.h | 2 ++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 24d558c25a1fb..4c3ad17530a79 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -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 @@ -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; @@ -562,7 +584,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(); @@ -581,7 +603,7 @@ 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) { @@ -595,7 +617,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(); } @@ -640,7 +662,7 @@ 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) { @@ -654,7 +676,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(); } } diff --git a/plugins/GSdx/GSRendererOGL.h b/plugins/GSdx/GSRendererOGL.h index 3911a33538c88..bc3e05d75c13d 100644 --- a/plugins/GSdx/GSRendererOGL.h +++ b/plugins/GSdx/GSRendererOGL.h @@ -56,4 +56,6 @@ class GSRendererOGL : public GSRendererHW void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex); bool PrimitiveOverlap(); + + void SendDraw(bool require_barrier); }; From 472608b8797a71bb06bb847d7d8e96f8e8a6fea9 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sat, 9 May 2015 15:02:13 +0200 Subject: [PATCH 5/9] gsdx-ogl: add accurate blending implementation --- plugins/GSdx/GSRendererOGL.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 4c3ad17530a79..f8f0c3f2254c1 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -565,11 +565,21 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour GL_POP(); dev->OMSetColorMaskState(om_csel); + // 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); + + 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 @@ -607,6 +617,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour 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); @@ -666,6 +677,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour 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); From f029e4763fcb7379eddad0e23f8f24c6bd2390ae Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 8 May 2015 20:23:38 +0200 Subject: [PATCH 6/9] gsdx-ogl: add the alpha value in a constant buffer --- plugins/GSdx/GSDeviceOGL.h | 5 ++++- plugins/GSdx/GSRendererOGL.cpp | 4 ++++ plugins/GSdx/res/glsl/tfx_fs.glsl | 1 + plugins/GSdx/res/glsl_source.h | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 3f1444636673b..3928426af04bc 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -256,6 +256,7 @@ class GSDeviceOGL : public GSDevice GSVector4 WH; GSVector4 MinF_TA; GSVector4i MskFix; + GSVector4 AlphaCoeff; GSVector4 HalfTexel; GSVector4 MinMax; @@ -269,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) @@ -278,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; } diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index f8f0c3f2254c1..9167027a8f410 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -572,6 +572,10 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour 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)); } diff --git a/plugins/GSdx/res/glsl/tfx_fs.glsl b/plugins/GSdx/res/glsl/tfx_fs.glsl index ff4e97c80f322..64770f6742d27 100644 --- a/plugins/GSdx/res/glsl/tfx_fs.glsl +++ b/plugins/GSdx/res/glsl/tfx_fs.glsl @@ -65,6 +65,7 @@ layout(std140, binding = 21) uniform cb21 vec2 MinF; vec2 TA; uvec4 MskFix; + vec4 Af; vec4 HalfTexel; vec4 MinMax; vec4 TC_OffsetHack; diff --git a/plugins/GSdx/res/glsl_source.h b/plugins/GSdx/res/glsl_source.h index 9011cde5372a0..e7125df834def 100644 --- a/plugins/GSdx/res/glsl_source.h +++ b/plugins/GSdx/res/glsl_source.h @@ -779,6 +779,7 @@ static const char* tfx_fs_all_glsl = " vec2 MinF;\n" " vec2 TA;\n" " uvec4 MskFix;\n" + " vec4 Af;\n" " vec4 HalfTexel;\n" " vec4 MinMax;\n" " vec4 TC_OffsetHack;\n" From 7fac25edb093774b274134fff711b9cb0384f10f Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 8 May 2015 20:27:13 +0200 Subject: [PATCH 7/9] glsl: add shader implementation of impossible blend Issue: I don't know if destination alpha value must be multiplied by 2.0f --- plugins/GSdx/res/glsl/tfx_fs.glsl | 41 +++++++++++++++++++++++++++++++ plugins/GSdx/res/glsl_source.h | 41 +++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/plugins/GSdx/res/glsl/tfx_fs.glsl b/plugins/GSdx/res/glsl/tfx_fs.glsl index 64770f6742d27..5f018dc8c37bc 100644 --- a/plugins/GSdx/res/glsl/tfx_fs.glsl +++ b/plugins/GSdx/res/glsl/tfx_fs.glsl @@ -375,6 +375,43 @@ vec4 ps_color() return c; } +void ps_blend(inout vec4 c, in float As) +{ + vec4 rt = texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); + // FIXME Ad or Ad * 2? + float Ad = rt.a; + +#if PS_BLEND == 1 + // {4, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As + c.rgb = c.rgb * (As + 1.0f) - rt.rgb * As; +#elif PS_BLEND == 2 + // {5, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad + c.rgb = c.rgb * (Ad + 1.0f) - rt.rgb * Ad; +#elif PS_BLEND == 3 + // {6, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F + c.rgb = c.rgb * (Af.x + 1.0f) - rt.rgb * Af.x; +#elif PS_BLEND == 4 + // {7, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, //*0200: (Cs - 0)*As + Cs ==> Cs*(As + 1) + c.rgb = c.rgb * (As + 1.0f); // FIXME Not bogus +#elif PS_BLEND == 5 + // {8, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, //*0210: (Cs - 0)*Ad + Cs ==> Cs*(Ad + 1) + c.rgb = c.rgb * (Ad + 1.0f); +#elif PS_BLEND == 6 + // {9, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, //*0220: (Cs - 0)*F + Cs ==> Cs*(F + 1) + besoin du fix + c.rgb = c.rgb * (Af.x + 1.0f); // FIXME Not bogus +#elif PS_BLEND == 7 + // {10,D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As + c.rgb = rt.rgb * (As + 1.0f) - c.rgb * As; +#elif PS_BLEND == 8 + // {11,D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad + c.rgb = rt.rgb * (Ad + 1.0f) - c.rgb * Ad; +#elif PS_BLEND == 9 + // {12,D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},//*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F + c.rgb = rt.rgb * (Af.x + 1.0f) - c.rgb * Af.x; +#endif +} + void ps_main() { #if (PS_DATE & 3) == 1 && !defined(DISABLE_GL42_image) @@ -446,6 +483,10 @@ void ps_main() } #endif +#if PS_BLEND > 0 + ps_blend(c, alpha); +#endif + SV_Target0 = c; SV_Target1 = vec4(alpha, alpha, alpha, alpha); } diff --git a/plugins/GSdx/res/glsl_source.h b/plugins/GSdx/res/glsl_source.h index e7125df834def..4f86ec22123cd 100644 --- a/plugins/GSdx/res/glsl_source.h +++ b/plugins/GSdx/res/glsl_source.h @@ -1089,6 +1089,43 @@ static const char* tfx_fs_all_glsl = " return c;\n" "}\n" "\n" + "void ps_blend(inout vec4 c, in float As)\n" + "{\n" + " vec4 rt = texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0);\n" + " // FIXME Ad or Ad * 2?\n" + " float Ad = rt.a;\n" + "\n" + "#if PS_BLEND == 1\n" + " // {4, D3DBLENDOP_SUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*0100: (Cs - Cd)*As + Cs ==> Cs*(As + 1) - Cd*As\n" + " c.rgb = c.rgb * (As + 1.0f) - rt.rgb * As;\n" + "#elif PS_BLEND == 2\n" + " // {5, D3DBLENDOP_SUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*0110: (Cs - Cd)*Ad + Cs ==> Cs*(Ad + 1) - Cd*Ad\n" + " c.rgb = c.rgb * (Ad + 1.0f) - rt.rgb * Ad;\n" + "#elif PS_BLEND == 3\n" + " // {6, D3DBLENDOP_SUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR}, //*0120: (Cs - Cd)*F + Cs ==> Cs*(F + 1) - Cd*F\n" + " c.rgb = c.rgb * (Af.x + 1.0f) - rt.rgb * Af.x;\n" + "#elif PS_BLEND == 4\n" + " // {7, D3DBLENDOP_ADD, D3DBLEND_SRCALPHA, D3DBLEND_ZERO}, //*0200: (Cs - 0)*As + Cs ==> Cs*(As + 1)\n" + " c.rgb = c.rgb * (As + 1.0f); // FIXME Not bogus\n" + "#elif PS_BLEND == 5\n" + " // {8, D3DBLENDOP_ADD, D3DBLEND_DESTALPHA, D3DBLEND_ZERO}, //*0210: (Cs - 0)*Ad + Cs ==> Cs*(Ad + 1)\n" + " c.rgb = c.rgb * (Ad + 1.0f);\n" + "#elif PS_BLEND == 6\n" + " // {9, D3DBLENDOP_ADD, D3DBLEND_BLENDFACTOR, D3DBLEND_ZERO}, //*0220: (Cs - 0)*F + Cs ==> Cs*(F + 1)\n" + " besoin du fix\n" + " c.rgb = c.rgb * (Af.x + 1.0f); // FIXME Not bogus\n" + "#elif PS_BLEND == 7\n" + " // {10,D3DBLENDOP_REVSUBTRACT, D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA}, //*1001: (Cd - Cs)*As + Cd ==> Cd*(As + 1) - Cs*As\n" + " c.rgb = rt.rgb * (As + 1.0f) - c.rgb * As;\n" + "#elif PS_BLEND == 8\n" + " // {11,D3DBLENDOP_REVSUBTRACT, D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA}, //*1011: (Cd - Cs)*Ad + Cd ==> Cd*(Ad + 1) - Cs*Ad\n" + " c.rgb = rt.rgb * (Ad + 1.0f) - c.rgb * Ad;\n" + "#elif PS_BLEND == 9\n" + " // {12,D3DBLENDOP_REVSUBTRACT, D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR},//*1021: (Cd - Cs)*F + Cd ==> Cd*(F + 1) - Cs*F\n" + " c.rgb = rt.rgb * (Af.x + 1.0f) - c.rgb * Af.x;\n" + "#endif\n" + "}\n" + "\n" "void ps_main()\n" "{\n" "#if (PS_DATE & 3) == 1 && !defined(DISABLE_GL42_image)\n" @@ -1160,6 +1197,10 @@ static const char* tfx_fs_all_glsl = " }\n" "#endif\n" "\n" + "#if PS_BLEND > 0\n" + " ps_blend(c, alpha);\n" + "#endif\n" + "\n" " SV_Target0 = c;\n" " SV_Target1 = vec4(alpha, alpha, alpha, alpha);\n" "}\n" From 3c7a3a3d836561ac1e0c6db30edbe4568d203d3c Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sat, 9 May 2015 18:33:28 +0200 Subject: [PATCH 8/9] gsdx-ogl: disable accurate option if driver doesn't support it --- plugins/GSdx/GLLoader.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GLLoader.cpp b/plugins/GSdx/GLLoader.cpp index b7ef05887910c..1ceacae5142ea 100644 --- a/plugins/GSdx/GLLoader.cpp +++ b/plugins/GSdx/GLLoader.cpp @@ -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; From 390811f414cdfaae292b628fb970e6076e0beb49 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sat, 9 May 2015 18:33:55 +0200 Subject: [PATCH 9/9] gsdx-debug: Dump in PNG on linux & dbg/dev build Keep BMP for standard user of release build --- plugins/GSdx/config.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/GSdx/config.h b/plugins/GSdx/config.h index b24395598fccf..26efc05486866 100644 --- a/plugins/GSdx/config.h +++ b/plugins/GSdx/config.h @@ -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. @@ -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