From 48859da6e3f80c5eac04f9c1cd9b367b68a84baa Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 1 Nov 2010 19:13:50 +0000 Subject: [PATCH] DX9/DX11: Fix and simplify ClearScreen. At least fixes a small glitch in Super Mario Sunshine with DX11, might fix several other things as well in both plugins though (so test this, please!) Explanation of this commit: We only have to care about four BP registers in ClearScreen, the remaining API state should be reset. The colorEnable and alphaEnable parameters are obsolete, for some reason directly using them caused the SMS glitch with DX11 (because of that bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 check in BPFunctions.cpp, is this one actually correct?) The comment in BPFunctions.cpp was at least misleading (if not even wrong), so I removed it. For what it's worth, someone needs to port this to the OpenGL and Software plugins (unless they're doing this properly already) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6327 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_VideoDX11/Src/BPFunctions.cpp | 3 -- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 54 ++++++++----------- .../Plugin_VideoDX9/Src/BPFunctions.cpp | 3 -- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 27 ++++------ .../Plugin_VideoOGL/Src/BPFunctions.cpp | 3 -- 5 files changed, 33 insertions(+), 57 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/BPFunctions.cpp b/Source/Plugins/Plugin_VideoDX11/Src/BPFunctions.cpp index 2fa0a862be..f7428935f7 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/BPFunctions.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/BPFunctions.cpp @@ -86,9 +86,6 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) { - // it seems that the GC is able to alpha blend on color-fill - // we cant do that so if alpha is != 255 we skip it - bool colorEnable = bpmem.blendmode.colorupdate; bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate); bool zEnable = bpmem.zmode.updateenable; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 97055dedf4..14092c80ad 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -77,8 +77,7 @@ static char s_sScreenshotName[1024]; ID3D11Buffer* access_efb_cbuf = NULL; ID3D11BlendState* clearblendstates[4] = {NULL}; -ID3D11DepthStencilState* cleardepthstates[2] = {NULL}; -ID3D11RasterizerState* clearraststate = NULL; +ID3D11DepthStencilState* cleardepthstates[3] = {NULL}; ID3D11BlendState* resetblendstate = NULL; ID3D11DepthStencilState* resetdepthstate = NULL; ID3D11RasterizerState* resetraststate = NULL; @@ -257,14 +256,12 @@ void SetupDeviceObjects() ddesc.DepthEnable = TRUE; hr = D3D::device->CreateDepthStencilState(&ddesc, &cleardepthstates[1]); CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen"); + ddesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + hr = D3D::device->CreateDepthStencilState(&ddesc, &cleardepthstates[2]); + CHECK(hr==S_OK, "Create depth state for Renderer::ClearScreen"); D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[0], "depth state for Renderer::ClearScreen (depth buffer disabled)"); - D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[1], "depth state for Renderer::ClearScreen (depth buffer enabled)"); - - // TODO: once multisampling gets implemented, this might need to be changed - D3D11_RASTERIZER_DESC rdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0.f, false, true, false, false); - hr = D3D::device->CreateRasterizerState(&rdesc, &clearraststate); - CHECK(hr==S_OK, "Create rasterizer state for Renderer::ClearScreen"); - D3D::SetDebugObjectName((ID3D11DeviceChild*)clearraststate, "rasterizer state for Renderer::ClearScreen"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[1], "depth state for Renderer::ClearScreen (depth buffer enabled, writing enabled)"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)cleardepthstates[2], "depth state for Renderer::ClearScreen (depth buffer enabled, writing disabled)"); D3D11_BLEND_DESC blenddesc; blenddesc.AlphaToCoverageEnable = FALSE; @@ -309,7 +306,7 @@ void SetupDeviceObjects() // this might need to be changed once multisampling support gets added D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0.f, false, false, false, false); hr = D3D::device->CreateRasterizerState(&rastdesc, &resetraststate); - CHECK(hr==S_OK, "Create rasterizer state for Renderer::ClearScreen"); + CHECK(hr==S_OK, "Create rasterizer state for Renderer::ResetAPIState"); D3D::SetDebugObjectName((ID3D11DeviceChild*)resetraststate, "rasterizer state for Renderer::ResetAPIState"); } @@ -324,7 +321,7 @@ void TeardownDeviceObjects() SAFE_RELEASE(clearblendstates[3]); SAFE_RELEASE(cleardepthstates[0]); SAFE_RELEASE(cleardepthstates[1]); - SAFE_RELEASE(clearraststate); + SAFE_RELEASE(cleardepthstates[2]); SAFE_RELEASE(resetblendstate); SAFE_RELEASE(resetdepthstate); SAFE_RELEASE(resetraststate); @@ -833,35 +830,30 @@ void UpdateViewport() D3D::context->RSSetViewports(1, &vp); } -// Tino: color is passed in bgra mode so need to convert it to rgba void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) { ResetAPIState(); - // Update the view port for clearing the picture - TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); - D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)targetRc.left, (float)targetRc.top, (float)targetRc.GetWidth(), (float)targetRc.GetHeight(), - 0.f, - 1.f); - D3D::context->RSSetViewports(1, &vp); - - // Always set the scissor in case it was set by the game and has not been reset - D3D11_RECT sirc = CD3D11_RECT(targetRc.left, targetRc.top, targetRc.right, targetRc.bottom); - D3D::context->RSSetScissorRects(1, &sirc); - u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000); - - D3D::stateman->PushDepthState(cleardepthstates[zEnable]); - D3D::stateman->PushRasterizerState(clearraststate); - if (colorEnable && alphaEnable) D3D::stateman->PushBlendState(clearblendstates[0]); - else if (colorEnable) D3D::stateman->PushBlendState(clearblendstates[1]); - else if (alphaEnable) D3D::stateman->PushBlendState(clearblendstates[2]); + if (bpmem.blendmode.colorupdate && bpmem.blendmode.alphaupdate) D3D::stateman->PushBlendState(clearblendstates[0]); + else if (bpmem.blendmode.colorupdate) D3D::stateman->PushBlendState(clearblendstates[1]); + else if (bpmem.blendmode.alphaupdate) D3D::stateman->PushBlendState(clearblendstates[2]); else D3D::stateman->PushBlendState(clearblendstates[3]); + if (!bpmem.zmode.testenable) D3D::stateman->PushDepthState(cleardepthstates[0]); + else if (bpmem.zmode.updateenable) D3D::stateman->PushDepthState(cleardepthstates[1]); + else /*if (!bpmem.zmode.updateenable)*/ D3D::stateman->PushDepthState(cleardepthstates[2]); + + // Update the view port for clearing the picture + TargetRectangle targetRc = Renderer::ConvertEFBRectangle(rc); + D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)targetRc.left, (float)targetRc.top, (float)targetRc.GetWidth(), (float)targetRc.GetHeight(), 0.f, 1.f); + D3D::context->RSSetViewports(1, &vp); + + // Color is passed in bgra mode so we need to convert it to rgba + u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000); D3D::drawClearQuad(rgbaColor, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader(), VertexShaderCache::GetClearInputLayout()); - D3D::stateman->PopBlendState(); - D3D::stateman->PopRasterizerState(); D3D::stateman->PopDepthState(); + D3D::stateman->PopBlendState(); RestoreAPIState(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp index c9522efe4e..178c0e4e63 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/BPFunctions.cpp @@ -91,9 +91,6 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) { - // it seems that the GC is able to alpha blend on color-fill - // we cant do that so if alpha is != 255 we skip it - bool colorEnable = bpmem.blendmode.colorupdate; bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate); bool zEnable = bpmem.zmode.updateenable; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 96795e81fe..91052cecf1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -990,7 +990,15 @@ void UpdateViewport() void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) { - // Update the view port for clearing the picture + // Reset rendering pipeline while keeping color masks and depth buffer settings + ResetAPIState(); + SetDepthMode(); + SetColorMask(); + + if (zEnable) // other depth functions don't make sense here + D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + + // Update the view port for clearing the whole EFB texture TargetRectangle targetRc = ConvertEFBRectangle(rc); D3DVIEWPORT9 vp; vp.X = targetRc.left; @@ -1000,23 +1008,8 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE vp.MinZ = 0.0; vp.MaxZ = 1.0; D3D::dev->SetViewport(&vp); - - // Always set the scissor in case it was set by the game and has not been reset - RECT sicr; - sicr.left = targetRc.left; - sicr.top = targetRc.top; - sicr.right = targetRc.right; - sicr.bottom = targetRc.bottom; - D3D::dev->SetScissorRect(&sicr); - D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false); - if (zEnable) - D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); D3D::drawClearQuad(color, (z & 0xFFFFFF) / float(0xFFFFFF), PixelShaderCache::GetClearProgram(), VertexShaderCache::GetClearVertexShader()); - if (zEnable) - D3D::RefreshRenderState(D3DRS_ZFUNC); - D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE); - UpdateViewport(); - SetScissorRect(); + RestoreAPIState(); } void Renderer::SetBlendMode(bool forceUpdate) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/BPFunctions.cpp b/Source/Plugins/Plugin_VideoOGL/Src/BPFunctions.cpp index 723d3d0b30..690e2ecdfd 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/BPFunctions.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/BPFunctions.cpp @@ -89,9 +89,6 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) { - // it seems that the GC is able to alpha blend on color-fill - // we cant do that so if alpha is != 255 we skip it - bool colorEnable = bpmem.blendmode.colorupdate; bool alphaEnable = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 && bpmem.blendmode.alphaupdate); bool zEnable = bpmem.zmode.updateenable;