gsdx-ogl: try to enable sw blending for sprite rendering

The idea is that sprites are often use for post-processing effect (ofc except 2D games)

Most of the time post-processing supports SW blending with a small speed penality. SW
blending is more accurate so it is better to use it.
This commit is contained in:
Gregory Hainaut 2015-07-11 13:48:50 +02:00
parent f4e881ad30
commit 8da63cf95a
2 changed files with 37 additions and 12 deletions

View File

@ -153,13 +153,15 @@ void GSRendererOGL::SetupIA()
dev->IASetPrimitiveTopology(t); dev->IASetPrimitiveTopology(t);
} }
bool GSRendererOGL::PrimitiveOverlap() GSRendererOGL::PRIM_OVERLAP GSRendererOGL::PrimitiveOverlap()
{ {
// Either 1 triangle or 1 line or 3 POINTs
// It is bad for the POINTs but low probability that they overlap
if (m_vertex.next < 4) if (m_vertex.next < 4)
return false; return PRIM_OVERLAP_NO;
if (m_vt.m_primclass != GS_SPRITE_CLASS) if (m_vt.m_primclass != GS_SPRITE_CLASS)
return true; return PRIM_OVERLAP_UNKNOW; // maybe, maybe not
// Check intersection of sprite primitive only // Check intersection of sprite primitive only
size_t count = m_vertex.next; size_t count = m_vertex.next;
@ -173,20 +175,20 @@ bool GSRendererOGL::PrimitiveOverlap()
GSVector4i inter = vi.rintersect(vj); GSVector4i inter = vi.rintersect(vj);
if (!inter.rempty()) { if (!inter.rempty()) {
//fprintf(stderr, "Overlap found between %d and %d (draw of %d vertices)\n", i, j, count); //fprintf(stderr, "Overlap found between %d and %d (draw of %d vertices)\n", i, j, count);
return true; return PRIM_OVERLAP_YES;
} }
} }
} }
//fprintf(stderr, "Yes, code can be optimized (draw of %d vertices)\n", count); //fprintf(stderr, "Yes, code can be optimized (draw of %d vertices)\n", count);
return false; return PRIM_OVERLAP_NO;
} }
void GSRendererOGL::SendDraw(bool require_barrier) void GSRendererOGL::SendDraw(bool require_barrier)
{ {
GSDeviceOGL* dev = (GSDeviceOGL*)m_dev; GSDeviceOGL* dev = (GSDeviceOGL*)m_dev;
if (!require_barrier || !PrimitiveOverlap()) { if (!require_barrier || (m_prim_overlap == PRIM_OVERLAP_NO)) {
dev->DrawIndexedPrimitive(); dev->DrawIndexedPrimitive();
} else { } else {
ASSERT(m_vt.m_primclass != GS_POINT_CLASS); ASSERT(m_vt.m_primclass != GS_POINT_CLASS);
@ -226,7 +228,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
bool DATE_GL42 = false; bool DATE_GL42 = false;
bool DATE_GL45 = false; bool DATE_GL45 = false;
bool require_barrier = false; // For blend (and maybe in date in the future) bool require_barrier = false; // For accurate option
ASSERT(m_dev != NULL); ASSERT(m_dev != NULL);
@ -246,6 +248,18 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
GSDeviceOGL::OMColorMaskSelector om_csel; GSDeviceOGL::OMColorMaskSelector om_csel;
GSDeviceOGL::OMDepthStencilSelector om_dssel; GSDeviceOGL::OMDepthStencilSelector om_dssel;
if (GLLoader::found_GL_ARB_texture_barrier && (m_vt.m_primclass == GS_SPRITE_CLASS)) {
// Except 2D games, sprites are often use for special post-processing effect
m_prim_overlap = PrimitiveOverlap();
#ifdef ENABLE_OGL_DEBUG
if ((context->FRAME.Block() == context->TEX0.TBP0) && (m_vertex.next > 2)) {
GL_INS("ERROR: Source and Target are the same!");
}
#endif
} else {
m_prim_overlap = PRIM_OVERLAP_UNKNOW;
}
if (m_texture_shuffle) { if (m_texture_shuffle) {
ps_sel.shuffle = 1; ps_sel.shuffle = 1;
ps_sel.dfmt = 0; ps_sel.dfmt = 0;
@ -450,7 +464,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
} }
if (DATE) { if (DATE) {
if (GLLoader::found_GL_ARB_texture_barrier && !PrimitiveOverlap()) { if (GLLoader::found_GL_ARB_texture_barrier && (m_prim_overlap == PRIM_OVERLAP_NO)) {
DATE_GL45 = true; DATE_GL45 = true;
DATE = false; DATE = false;
} else if (m_accurate_date && om_csel.wa } else if (m_accurate_date && om_csel.wa
@ -755,7 +769,11 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
int blend_sel = ((om_bsel.a * 3 + om_bsel.b) * 3 + om_bsel.c) * 3 + om_bsel.d; int blend_sel = ((om_bsel.a * 3 + om_bsel.b) * 3 + om_bsel.c) * 3 + om_bsel.d;
int bogus_blend = GSDeviceOGL::m_blendMapD3D9[blend_sel].bogus; int bogus_blend = GSDeviceOGL::m_blendMapD3D9[blend_sel].bogus;
bool all_sw = !( (ALPHA.A == ALPHA.B) || (ALPHA.C == 2 && afix <= 1.002f) ) && (m_accurate_blend > 1); bool all_sw = !( (ALPHA.A == ALPHA.B) || (ALPHA.C == 2 && afix <= 1.002f) ) && (m_accurate_blend > 1);
bool sw_blending = (m_accurate_blend && (bogus_blend & A_MAX)) || acc_colclip_wrap || all_sw || ps_sel.fbmask;
bool sw_blending = (m_prim_overlap == PRIM_OVERLAP_NO) // Free case
|| (m_accurate_blend && (bogus_blend & A_MAX)) || all_sw // Impossible blend or all
|| acc_colclip_wrap // accurate colclip
|| ps_sel.fbmask; // accurate fbmask
// GL42 interact very badly with sw blending. GL42 uses the primitiveID to find the primitive // GL42 interact very badly with sw blending. GL42 uses the primitiveID to find the primitive
// that write the bad alpha value. Sw blending will force the draw to run primitive by primitive // that write the bad alpha value. Sw blending will force the draw to run primitive by primitive
// (therefore primitiveID will be constant to 1) // (therefore primitiveID will be constant to 1)
@ -822,7 +840,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
if (DATE_GL42) { if (DATE_GL42) {
GL_PUSH("Date GL42"); GL_PUSH("Date GL42");
ASSERT((bogus_blend & A_MAX) == 0);
// It could be good idea to use stencil in the same time. // It could be good idea to use stencil in the same time.
// Early stencil test will reduce the number of atomic-load operation // Early stencil test will reduce the number of atomic-load operation

View File

@ -29,6 +29,12 @@
class GSRendererOGL : public GSRendererHW class GSRendererOGL : public GSRendererHW
{ {
enum PRIM_OVERLAP {
PRIM_OVERLAP_UNKNOW,
PRIM_OVERLAP_YES,
PRIM_OVERLAP_NO
};
private: private:
GSVector2 m_pixelcenter; GSVector2 m_pixelcenter;
int m_accurate_blend; int m_accurate_blend;
@ -39,6 +45,8 @@ class GSRendererOGL : public GSRendererHW
unsigned int UserHacks_TCOffset; unsigned int UserHacks_TCOffset;
float UserHacks_TCO_x, UserHacks_TCO_y; float UserHacks_TCO_x, UserHacks_TCO_y;
PRIM_OVERLAP m_prim_overlap;
protected: protected:
void EmulateGS(); void EmulateGS();
void SetupIA(); void SetupIA();
@ -51,7 +59,7 @@ class GSRendererOGL : public GSRendererHW
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex); void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
bool PrimitiveOverlap(); PRIM_OVERLAP PrimitiveOverlap();
void SendDraw(bool require_barrier); void SendDraw(bool require_barrier);
}; };