From 725b0ce9707dcaa252381f94c026375aa5064350 Mon Sep 17 00:00:00 2001 From: githubawn <115191165+githubawn@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:23:09 +0100 Subject: [PATCH 1/2] Fix Microwave blackout on (Nvidia) forced AA Co-authored-by: stm <14291421+stephanmeesters@users.noreply.github.com> --- .../Include/W3DDevice/GameClient/W3DSmudge.h | 2 - .../W3DDevice/GameClient/W3DShaderManager.cpp | 40 ++++++++--- .../Source/W3DDevice/GameClient/W3DSmudge.cpp | 71 +++++++++---------- 3 files changed, 62 insertions(+), 51 deletions(-) diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DSmudge.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DSmudge.h index 3ebba960043..080dec5759f 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DSmudge.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DSmudge.h @@ -55,9 +55,7 @@ class W3DSmudgeManager : public SmudgeManager ShareBufferClass *m_RGBABuffer; ///< array of particle color and alpha ShareBufferClass *m_sizeBuffer; ///< array of particle sizes -#ifdef USE_COPY_RECTS TextureClass *m_backgroundTexture; -#endif DX8IndexBufferClass *m_indexBuffer; Int m_backBufferWidth; Int m_backBufferHeight; diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DShaderManager.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DShaderManager.cpp index 87fa12f5c29..5e5c802b291 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DShaderManager.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DShaderManager.cpp @@ -173,13 +173,12 @@ Int ScreenDefaultFilter::init() Bool ScreenDefaultFilter::preRender(Bool &skipRender, CustomScenePassModes &scenePassMode) { - //Right now this filter is only used for smudges, so don't bother if none are present. - if (TheSmudgeManager) - { if (((W3DSmudgeManager *)TheSmudgeManager)->getSmudgeCountLastFrame() == 0) - return FALSE; - } - W3DShaderManager::startRenderToTexture(); - return true; + // TheSuperHackers @bugfix Disable RTT redirection for the default filter. + // When MSAA is forced by Nvidia driver profile, the D3D8 API reports MultiSampleType=NONE + // and SetRenderTarget returns S_OK, but the depth buffer is actually multisampled internally. + // Rendering to a non-MSAA texture with this hidden-MSAA depth buffer corrupts depth testing, + // producing a black screen. The smudge system has its own Copy path that works without RTT. + return FALSE; } Bool ScreenDefaultFilter::postRender(FilterModes mode, Coord2D &scrollDelta,Bool &doExtraRender) @@ -2605,8 +2604,18 @@ void W3DShaderManager::init() HRESULT hr=DX8Wrapper::_Get_D3D_Device8()->GetRenderTarget(&m_oldRenderSurface); m_oldRenderSurface->GetDesc(&desc); - - hr=DX8Wrapper::_Get_D3D_Device8()->CreateTexture(desc.Width,desc.Height,1,D3DUSAGE_RENDERTARGET,desc.Format,D3DPOOL_DEFAULT,&m_renderTexture); + + // TheSuperHackers @bugfix Redirecting rendering to a non-multisampled texture + // while using a multisampled depth buffer is an API violation in DX8. + if (desc.MultiSampleType == D3DMULTISAMPLE_NONE) + { + hr=DX8Wrapper::_Get_D3D_Device8()->CreateTexture(desc.Width,desc.Height,1,D3DUSAGE_RENDERTARGET,desc.Format,D3DPOOL_DEFAULT,&m_renderTexture); + } + else + { + // Force failure path to avoid MSAA mismatch + hr = E_FAIL; + } if (hr != S_OK) { @@ -2831,9 +2840,20 @@ void W3DShaderManager::startRenderToTexture() if (m_renderingToTexture || m_newRenderSurface==nullptr || m_oldDepthSurface==nullptr) return; HRESULT hr = DX8Wrapper::_Get_D3D_Device8()->SetRenderTarget(m_newRenderSurface,m_oldDepthSurface); - DEBUG_ASSERTCRASH(hr==S_OK, ("Set target failed unexpectedly.")); + + // TheSuperHackers @bugfix If SetRenderTarget fails (e.g. due to MSAA forced by driver + // profile causing a depth buffer mismatch that D3DSURFACE_DESC doesn't report), permanently + // disable RTT to prevent repeated failures and accidental backbuffer clears. if (hr != S_OK) + { + // Permanently disable RTT + if (m_newRenderSurface) { m_newRenderSurface->Release(); m_newRenderSurface = nullptr; } + if (m_renderTexture) { m_renderTexture->Release(); m_renderTexture = nullptr; } + if (m_oldRenderSurface) { m_oldRenderSurface->Release(); m_oldRenderSurface = nullptr; } + if (m_oldDepthSurface) { m_oldDepthSurface->Release(); m_oldDepthSurface = nullptr; } return; + } + m_renderingToTexture = true; if (TheGlobalData->m_showSoftWaterEdge) { //Soft water edges use frame buffer destination alpha so we must clear it to a known value. diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp index 9fde80ea320..b52cd240c28 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp @@ -66,9 +66,7 @@ void W3DSmudgeManager::reset () void W3DSmudgeManager::ReleaseResources() { -#ifdef USE_COPY_RECTS REF_PTR_RELEASE(m_backgroundTexture); -#endif REF_PTR_RELEASE(m_indexBuffer); } @@ -85,9 +83,12 @@ void W3DSmudgeManager::ReAcquireResources() surface->Get_Description(surface_desc); REF_PTR_RELEASE(surface); - #ifdef USE_COPY_RECTS - m_backgroundTexture = MSGNEW("TextureClass") TextureClass(TheTacticalView->getWidth(),TheTacticalView->getHeight(),surface_desc.Format,MIP_LEVELS_1,TextureClass::POOL_DEFAULT, true); - #endif + // TheSuperHackers @bugfix Use backbuffer dimensions instead of tactical view dimensions. + // With forced MSAA, SurfaceClass::Copy uses CopyRects with NULL rects for whole-surface resolve. + // This requires the destination surface to match the source surface dimensions exactly. + // Using TheTacticalView dimensions caused a size mismatch, forcing a fallback to + // D3DXLoadSurfaceFromSurface which cannot read from MSAA surfaces. + m_backgroundTexture = MSGNEW("TextureClass") TextureClass(surface_desc.Width,surface_desc.Height,surface_desc.Format,MIP_LEVELS_1,TextureClass::POOL_DEFAULT, true); m_backBufferWidth = surface_desc.Width; m_backBufferHeight = surface_desc.Height; @@ -207,15 +208,20 @@ Bool W3DSmudgeManager::testHardwareSupport() { //we have not done the test yet. IDirect3DTexture8 *backTexture=W3DShaderManager::getRenderTexture(); - if (!backTexture) - { //do trivial test first to see if render target exists. + if (!backTexture || !W3DShaderManager::isRenderingToTexture()) + { + // TheSuperHackers @bugfix When RTT is disabled globally (e.g. due to forced MSAA), + // if the Copy path is still available, accept that as hardware support. + if (m_backgroundTexture) + { + m_hardwareSupportStatus = SMUDGE_SUPPORT_YES; + return TRUE; + } + m_hardwareSupportStatus = SMUDGE_SUPPORT_NO; return FALSE; } - if (!W3DShaderManager::isRenderingToTexture()) - return FALSE; //can't do the test unless we're rendering to texture. - VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE); DX8Wrapper::Set_Material(vmat); REF_PTR_RELEASE(vmat); //no need to keep a reference since it's a preset. @@ -306,6 +312,12 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) if (!testHardwareSupport()) return; + SurfaceClass *backBuffer = DX8Wrapper::_Get_DX8_Back_Buffer(); + if (!backBuffer) return; + + SurfaceClass::SurfaceDescription surface_desc; + backBuffer->Get_Description(surface_desc); + CameraClass &camera=rinfo.Camera; Vector3 vsVert; Vector4 ssVert; @@ -327,22 +339,13 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) camera.Get_View_Matrix(&view); camera.Get_Projection_Matrix(&proj); - SurfaceClass::SurfaceDescription surface_desc; -#ifdef USE_COPY_RECTS - SurfaceClass *background=m_backgroundTexture->Get_Surface_Level(); - background->Get_Description(surface_desc); -#else - D3DSURFACE_DESC D3DDesc; + SurfaceClass *background=m_backgroundTexture ? m_backgroundTexture->Get_Surface_Level() : nullptr; - IDirect3DTexture8 *backTexture=W3DShaderManager::getRenderTexture(); - if (!backTexture || !W3DShaderManager::isRenderingToTexture()) - return; //this card doesn't support render targets. - - backTexture->GetLevelDesc(0,&D3DDesc); - - surface_desc.Width = D3DDesc.Width; - surface_desc.Height = D3DDesc.Height; -#endif + if (!background) + { + REF_PTR_RELEASE(backBuffer); + return; + } Real texClampX = (Real)TheTacticalView->getWidth()/(Real)surface_desc.Width; Real texClampY = (Real)TheTacticalView->getHeight()/(Real)surface_desc.Height; @@ -421,23 +424,16 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) if (!count) { -#ifdef USE_COPY_RECTS REF_PTR_RELEASE(background); -#endif + REF_PTR_RELEASE(backBuffer); return; //nothing to render. } -#ifdef USE_COPY_RECTS - SurfaceClass *backBuffer=DX8Wrapper::_Get_DX8_Back_Buffer(); - - backBuffer->Get_Description(surface_desc); - - //Copy the area of backbuffer occupied by smudges into an alternate buffer. - background->Copy(0,0,0,0,surface_desc.Width,surface_desc.Height,backBuffer); + //Copy the area of backbuffer occupied by smudges into an alternate buffer. + background->Copy(0,0,0,0,surface_desc.Width,surface_desc.Height,backBuffer); REF_PTR_RELEASE(background); REF_PTR_RELEASE(backBuffer); -#endif Matrix4x4 identity(true); DX8Wrapper::Set_Transform(D3DTS_WORLD,identity); @@ -447,10 +443,8 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) //DX8Wrapper::Set_Shader(ShaderClass::_PresetOpaqueSpriteShader); DX8Wrapper::Set_Shader(ShaderClass::_PresetAlphaShader); -#ifdef USE_COPY_RECTS + DX8Wrapper::Set_Texture(0,m_backgroundTexture); -#else - DX8Wrapper::Set_DX8_Texture(0,backTexture); //Need these states in case texture is non-power-of-2 DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); @@ -458,7 +452,6 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); DX8Wrapper::Set_DX8_Texture_Stage_State( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE); -#endif VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE); DX8Wrapper::Set_Material(vmat); REF_PTR_RELEASE(vmat); From 6533d5799e7ba19e48474f189ae0b740925224fe Mon Sep 17 00:00:00 2001 From: githubawn <115191165+githubawn@users.noreply.github.com> Date: Sun, 1 Mar 2026 23:53:28 +0100 Subject: [PATCH 2/2] Update Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- .../Source/W3DDevice/GameClient/W3DSmudge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp index b52cd240c28..aa6ea46d4ec 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DSmudge.cpp @@ -429,8 +429,8 @@ void W3DSmudgeManager::render(RenderInfoClass &rinfo) return; //nothing to render. } - //Copy the area of backbuffer occupied by smudges into an alternate buffer. - background->Copy(0,0,0,0,surface_desc.Width,surface_desc.Height,backBuffer); + //Copy the area of backbuffer occupied by smudges into an alternate buffer. + background->Copy(0,0,0,0,surface_desc.Width,surface_desc.Height,backBuffer); REF_PTR_RELEASE(background); REF_PTR_RELEASE(backBuffer);