Change destination alpha handling. The blending method introduced in rev 1921 was not the correct way to do it. This way was suggested by hrydgard in October and I should have listened. A simple pixel shader as hrydgard suggested cannot be used because the alpha is not set if the pixel is discarded due to failing depth (after z texture) or alpha (result of tev stages) tests. There is a bit of a performance hit so there should be an option to disable the second render pass which sets the alpha because it is probably not needed most of the time.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2662 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
b1b2868c8b
commit
90254bd924
|
@ -26,7 +26,7 @@
|
|||
|
||||
// Mash together all the inputs that contribute to the code of a generated pixel shader into
|
||||
// a unique identifier, basically containing all the bits. Yup, it's a lot ....
|
||||
void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 zbufrender, u32 zBufRenderToCol0)
|
||||
void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 zbufrender, u32 zBufRenderToCol0, u32 dstAlphaEnable)
|
||||
{
|
||||
u32 projtexcoords = 0;
|
||||
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++) {
|
||||
|
@ -39,7 +39,7 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 zbufrender, u3
|
|||
uid.values[0] = (u32)bpmem.genMode.numtevstages |
|
||||
((u32)bpmem.genMode.numindstages << 4) |
|
||||
((u32)bpmem.genMode.numtexgens << 7) |
|
||||
((u32)bpmem.dstalpha.enable << 11) |
|
||||
((u32)dstAlphaEnable << 11) |
|
||||
((u32)((bpmem.alphaFunc.hex >> 16) & 0xff) << 12) |
|
||||
(projtexcoords << 20) |
|
||||
((u32)bpmem.ztex2.op << 28) |
|
||||
|
@ -369,7 +369,7 @@ static void BuildSwapModeTable()
|
|||
}
|
||||
}
|
||||
|
||||
const char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool bRenderZToCol0, bool HLSL)
|
||||
const char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool bRenderZToCol0, bool dstAlphaEnable, bool HLSL)
|
||||
{
|
||||
text[sizeof(text) - 1] = 0x7C; // canary
|
||||
DVSTARTPROFILE();
|
||||
|
@ -535,17 +535,12 @@ const char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool
|
|||
}
|
||||
else {
|
||||
if (!bRenderZToCol0) {
|
||||
/* donkopunchstania: NEEDS FIX - dstalpha does not change how fragments are blended with the EFB
|
||||
once the blending is done, the dstalpha is written to the EFB in place of the
|
||||
fragment alpha if dstalpha is enabled. this only matters if the EFB supports alpha.
|
||||
Commenting this out fixed Metroids but causes glitches in Super Mario Sunshine.
|
||||
|
||||
if (bpmem.dstalpha.enable)
|
||||
if (dstAlphaEnable) {
|
||||
WRITE(p, " ocol0 = float4(prev.rgb,"I_ALPHA"[0].w);\n");
|
||||
else
|
||||
*/
|
||||
WriteFog(p, bOutputZ);
|
||||
WRITE(p, " ocol0 = prev;\n");
|
||||
} else {
|
||||
WriteFog(p, bOutputZ);
|
||||
WRITE(p, " ocol0 = prev;\n");
|
||||
}
|
||||
} else {
|
||||
WRITE(p, " ocol0 = prev;\n");
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
const char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool bRenderZToCol0, bool HLSL = false);
|
||||
void GetPixelShaderId(PIXELSHADERUID &, u32 s_texturemask, u32 zbufrender, u32 zBufRenderToCol0);
|
||||
const char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool bRenderZToCol0, bool dstAlphaEnable, bool HLSL = false);
|
||||
void GetPixelShaderId(PIXELSHADERUID &, u32 s_texturemask, u32 zbufrender, u32 zBufRenderToCol0, u32 dstAlphaEnable);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,7 +67,7 @@ void PixelShaderCache::SetShader()
|
|||
DVSTARTPROFILE();
|
||||
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), false, false);
|
||||
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), false, false, false);
|
||||
|
||||
PSCache::iterator iter;
|
||||
iter = PixelShaders.find(uid);
|
||||
|
@ -85,7 +85,7 @@ void PixelShaderCache::SetShader()
|
|||
}
|
||||
|
||||
bool HLSL = false;
|
||||
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), false, false, HLSL);
|
||||
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), false, false, false, HLSL);
|
||||
LPDIRECT3DPIXELSHADER9 shader = HLSL ? D3D::CompilePixelShader(code, (int)strlen(code), false) : CompileCgShader(code);
|
||||
if (shader)
|
||||
{
|
||||
|
|
|
@ -153,7 +153,7 @@ void BPWritten(int addr, int changes, int newval)
|
|||
PRIM_LOG("constalpha: alp=%d, en=%d\n", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
|
||||
SETSTAT(stats.dstAlphaEnable, bpmem.dstalpha.enable);
|
||||
SETSTAT_UINT(stats.dstAlpha, bpmem.dstalpha.alpha);
|
||||
Renderer::SetBlendMode(false);
|
||||
PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -105,13 +105,14 @@ GLuint PixelShaderCache::GetColorMatrixProgram()
|
|||
}
|
||||
|
||||
|
||||
FRAGMENTSHADER* PixelShaderCache::GetShader()
|
||||
FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
PIXELSHADERUID uid;
|
||||
u32 zbufrender = (Renderer::UseFakeZTarget() && bpmem.zmode.updateenable) ? 1 : 0;
|
||||
u32 zBufRenderToCol0 = Renderer::GetRenderMode() != Renderer::RM_Normal;
|
||||
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), zbufrender, zBufRenderToCol0);
|
||||
u32 dstAlpha = dstAlphaEnable ? 1 : 0;
|
||||
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), zbufrender, zBufRenderToCol0, dstAlpha);
|
||||
|
||||
PSCache::iterator iter = pshaders.find(uid);
|
||||
|
||||
|
@ -128,7 +129,8 @@ FRAGMENTSHADER* PixelShaderCache::GetShader()
|
|||
PSCacheEntry& newentry = pshaders[uid];
|
||||
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(),
|
||||
Renderer::UseFakeZTarget(),
|
||||
Renderer::GetRenderMode() != Renderer::RM_Normal);
|
||||
Renderer::GetRenderMode() != Renderer::RM_Normal,
|
||||
dstAlphaEnable);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_Config.iLog & CONF_SAVESHADERS && code) {
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
static void ProgressiveCleanup();
|
||||
static void Shutdown();
|
||||
|
||||
static FRAGMENTSHADER* GetShader();
|
||||
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);
|
||||
static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static GLuint GetColorMatrixProgram();
|
||||
|
|
|
@ -111,7 +111,6 @@ static bool s_bATIDrawBuffers = false;
|
|||
static bool s_bHaveStencilBuffer = false;
|
||||
static bool s_bHaveFramebufferBlit = false;
|
||||
static bool s_bHaveCoverageMSAA = false;
|
||||
static bool g_bBlendSeparate = false;
|
||||
static u32 s_blendMode;
|
||||
static bool s_bNativeResolution = false;
|
||||
|
||||
|
@ -206,10 +205,6 @@ bool Renderer::Init()
|
|||
INFO_LOG(VIDEO, ptoken); // write to the log file
|
||||
INFO_LOG(VIDEO, "\n");
|
||||
|
||||
if (strstr(ptoken, "GL_EXT_blend_func_separate") != NULL &&
|
||||
strstr(ptoken, "GL_EXT_blend_equation_separate") != NULL)
|
||||
g_bBlendSeparate = true;
|
||||
|
||||
// Checks if it ONLY has the ATI_draw_buffers extension, some have both
|
||||
if (GLEW_ATI_draw_buffers && !GLEW_ARB_draw_buffers)
|
||||
s_bATIDrawBuffers = true;
|
||||
|
@ -683,58 +678,35 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
|||
{
|
||||
// blend mode bit mask
|
||||
// 0 - blend enable
|
||||
// 1 - dst alpha enable
|
||||
// 2 - reverse subtract enable (else add)
|
||||
// 3-5 - srcRGB function
|
||||
// 6-8 - dstRGB function
|
||||
// 9-16 - dstAlpha
|
||||
|
||||
u32 newval = bpmem.blendmode.subtract << 2;
|
||||
|
||||
if (g_bBlendSeparate) {
|
||||
newval |= bpmem.dstalpha.enable ? 3 : 0;
|
||||
newval |= bpmem.dstalpha.alpha << 9;
|
||||
if (bpmem.blendmode.subtract) {
|
||||
newval |= 0x0049; // enable blending src 1 dst 1
|
||||
} else if (bpmem.blendmode.blendenable) {
|
||||
newval |= 1; // enable blending
|
||||
newval |= bpmem.blendmode.srcfactor << 3;
|
||||
newval |= bpmem.blendmode.dstfactor << 6;
|
||||
}
|
||||
|
||||
if (bpmem.blendmode.blendenable) {
|
||||
newval |= 1;
|
||||
if (bpmem.blendmode.subtract) {
|
||||
newval |= 0x0048; // src 1 dst 1
|
||||
} else {
|
||||
newval |= bpmem.blendmode.srcfactor << 3;
|
||||
newval |= bpmem.blendmode.dstfactor << 6;
|
||||
}
|
||||
} else {
|
||||
newval |= 0x0008; // src 1 dst 0
|
||||
}
|
||||
|
||||
|
||||
u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode;
|
||||
|
||||
if (changes & 1) {
|
||||
// blend enable change
|
||||
(newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
bool dstAlphaEnable = g_bBlendSeparate && newval & 2;
|
||||
|
||||
if (changes & 6) {
|
||||
// dst alpha enable or subtract enable change
|
||||
if (dstAlphaEnable)
|
||||
glBlendEquationSeparate(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD, GL_FUNC_ADD);
|
||||
else
|
||||
glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD);
|
||||
if (changes & 4) {
|
||||
// subtract enable change
|
||||
glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD);
|
||||
}
|
||||
|
||||
if (changes & 0x1FA) {
|
||||
// dst alpha enable or blend RGB change
|
||||
if (dstAlphaEnable)
|
||||
glBlendFuncSeparate(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7], GL_CONSTANT_ALPHA, GL_ZERO);
|
||||
else
|
||||
glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]);
|
||||
}
|
||||
|
||||
if (dstAlphaEnable && changes & 0x1FE00) {
|
||||
// dst alpha color change
|
||||
glBlendColor(0, 0, 0, (float)bpmem.dstalpha.alpha / 255.0f);
|
||||
if (changes & 0x1F8) {
|
||||
// blend RGB change
|
||||
glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]);
|
||||
}
|
||||
|
||||
s_blendMode = newval;
|
||||
|
|
|
@ -238,7 +238,7 @@ void Flush()
|
|||
PixelShaderManager::SetTexturesUsed(nonpow2tex);
|
||||
}
|
||||
|
||||
FRAGMENTSHADER* ps = PixelShaderCache::GetShader();
|
||||
FRAGMENTSHADER* ps = PixelShaderCache::GetShader(false);
|
||||
VERTEXSHADER* vs = VertexShaderCache::GetShader(g_nativeVertexFmt->m_components);
|
||||
|
||||
bool bRestoreBuffers = false;
|
||||
|
@ -284,6 +284,31 @@ void Flush()
|
|||
groupStart += s_vertexGroups[i].second;
|
||||
}
|
||||
|
||||
// run through vertex groups again to set alpha
|
||||
if (bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate) {
|
||||
ps = PixelShaderCache::GetShader(true);
|
||||
|
||||
if (ps) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ps->glprogid);
|
||||
|
||||
// only update alpha
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
|
||||
groupStart = 0;
|
||||
for (unsigned i = 0; i < s_vertexGroups.size(); i++)
|
||||
{
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
glMultiDrawArrays(s_vertexGroups[i].first,
|
||||
&s_vertexFirstOffset[groupStart],
|
||||
&s_vertexGroupSize[groupStart],
|
||||
s_vertexGroups[i].second);
|
||||
groupStart += s_vertexGroups[i].second;
|
||||
}
|
||||
|
||||
// restore color mask
|
||||
if (!bRestoreBuffers)
|
||||
Renderer::SetColorMask();
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_Config.iLog & CONF_SAVESHADERS) {
|
||||
// save the shaders
|
||||
|
|
Loading…
Reference in New Issue