From dcc51e0ef8fece409f093ea4d9124903562aedcd Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 12 Jul 2010 15:10:27 +0000 Subject: [PATCH] DX9/DX11, improvement to r5870: Instead of skipping SetViewport(), fix the viewport to match the old EFB dimensions. Should reduce or even fix most graphical glitches caused by huge viewports in HD resolutions. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5873 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 28 +++++++++++++----- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 29 ++++++++++++------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 1ab07b4130..d5a81ee5ec 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -740,25 +740,39 @@ void UpdateViewport() Y = 0; sizeChanged=true; } + + float newx = (float)X; + float newy = (float)Y; + float newwidth = (float)Width; + float newheight = (float)Height; if (sizeChanged) { // Make sure that the requested size is actually supported by the GFX driver if (s_Fulltarget_width > (int)D3D::GetMaxTextureSize() || s_Fulltarget_height > (int)D3D::GetMaxTextureSize()) { - // Skip EFB recreation and viewport setting. Most likely cause glitches in this case, but prevents crashes at least + // Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D11. Requested EFB size is %dx%d\n", s_Fulltarget_width, s_Fulltarget_height); + + // Fix the viewport to fit to the old EFB size, TODO: Check this for off-by-one errors + newx *= (float)old_fulltarget_w / (float)s_Fulltarget_width; + newy *= (float)old_fulltarget_h / (float)s_Fulltarget_height; + newwidth *= (float)old_fulltarget_w / (float)s_Fulltarget_width; + newheight *= (float)old_fulltarget_h / (float)s_Fulltarget_height; + s_Fulltarget_width = old_fulltarget_w; s_Fulltarget_height = old_fulltarget_h; - return; } - D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); - FBManager.Destroy(); - FBManager.Create(); - D3D::context->OMSetRenderTargets(1, &FBManager.GetEFBColorTexture()->GetRTV(), FBManager.GetEFBDepthTexture()->GetDSV()); + else + { + D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), NULL); + FBManager.Destroy(); + FBManager.Create(); + D3D::context->OMSetRenderTargets(1, &FBManager.GetEFBColorTexture()->GetRTV(), FBManager.GetEFBDepthTexture()->GetDSV()); + } } // some games set invalids values MinDepth and MaxDepth so fix them to the max an min allowed and let the shaders do this work - D3D11_VIEWPORT vp = CD3D11_VIEWPORT((float)X, (float)Y, (float)Width, (float)Height, + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(newx, newy, newwidth, newheight, 0.f, // (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f; 1.f); // xfregs.rawViewport[5] / 16777216.0f; D3D::context->RSSetViewports(1, &vp); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 65fd01aa52..8854692e55 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -884,18 +884,27 @@ void UpdateViewport() // Make sure that the requested size is actually supported by the GFX driver if (s_Fulltarget_width > caps.MaxTextureWidth || s_Fulltarget_height > caps.MaxTextureHeight) { - // Skip EFB recreation and viewport setting. Most likely cause glitches in this case, but prevents crashes at least - ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d\n", s_Fulltarget_width, s_Fulltarget_height); + // Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least + ERROR_LOG(VIDEO, "Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d, keeping the %dx%d EFB now\n", s_Fulltarget_width, s_Fulltarget_height, old_fulltarget_w, old_fulltarget_h); + + // Fix the viewport to fit to the old EFB size, TODO: Check this for off-by-one errors + X *= old_fulltarget_w / s_Fulltarget_width; + Y *= old_fulltarget_h / s_Fulltarget_height; + Width *= old_fulltarget_w / s_Fulltarget_width; + Height *= old_fulltarget_h / s_Fulltarget_height; + s_Fulltarget_width = old_fulltarget_w; s_Fulltarget_height = old_fulltarget_h; - return; } - D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); - D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); - FBManager.Destroy(); - FBManager.Create(); - D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface()); - D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface()); + else + { + D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); + D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); + FBManager.Destroy(); + FBManager.Create(); + D3D::dev->SetRenderTarget(0, FBManager.GetEFBColorRTSurface()); + D3D::dev->SetDepthStencilSurface(FBManager.GetEFBDepthRTSurface()); + } } vp.X = X; vp.Y = Y; @@ -904,7 +913,7 @@ void UpdateViewport() // Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work vp.MinZ = 0.0f; // (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f; - vp.MaxZ =1.0f; // xfregs.rawViewport[5] / 16777216.0f; + vp.MaxZ = 1.0f; // xfregs.rawViewport[5] / 16777216.0f; D3D::dev->SetViewport(&vp); }