From 9698f76c0c5fb369a1d7b66082c7fa2f66759b3c Mon Sep 17 00:00:00 2001 From: Filipp Pavlov Date: Mon, 31 Aug 2026 09:56:42 +0000 Subject: [PATCH 1/2] Move CAS sharpening back, after tonemapping; disable tonemapping dithering and change tonemapping result texture to FP16 if CAS is required; expose sharpening strength --- trinity/Eve/EveSpaceScene.cpp | 1 + trinity/PostProcess/Tr2PostProcess2.h | 1 + trinity/PostProcess/Tr2PostProcess2_Blue.cpp | 2 + .../PostProcess/Tr2PostProcessRenderer.cpp | 55 +++++++++++-------- trinity/PostProcess/Tr2PostProcessRenderer.h | 2 +- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/trinity/Eve/EveSpaceScene.cpp b/trinity/Eve/EveSpaceScene.cpp index 8e109eb1a..0f7e859d6 100644 --- a/trinity/Eve/EveSpaceScene.cpp +++ b/trinity/Eve/EveSpaceScene.cpp @@ -368,6 +368,7 @@ void EveSpaceScene::UpdatePostProcessAttributes() { m_combinedPostProcess.CreateInstance(); } + m_combinedPostProcess->m_sharpeningStrength = m_sceneDefaultPostProcess->m_sharpeningStrength; std::sort( begin( postProcessAttributes ), diff --git a/trinity/PostProcess/Tr2PostProcess2.h b/trinity/PostProcess/Tr2PostProcess2.h index 06a76932c..e821bcb43 100644 --- a/trinity/PostProcess/Tr2PostProcess2.h +++ b/trinity/PostProcess/Tr2PostProcess2.h @@ -86,6 +86,7 @@ BLUE_CLASS( Tr2PostProcess2 ) : float GetMipLodBias() const; float m_exposureAdjustment = 0; + float m_sharpeningStrength = 0.5f; private: Tr2PPSignalLossEffectPtr m_signalLoss; diff --git a/trinity/PostProcess/Tr2PostProcess2_Blue.cpp b/trinity/PostProcess/Tr2PostProcess2_Blue.cpp index 63b0703f4..4e3aff0bf 100644 --- a/trinity/PostProcess/Tr2PostProcess2_Blue.cpp +++ b/trinity/PostProcess/Tr2PostProcess2_Blue.cpp @@ -28,5 +28,7 @@ const Be::ClassInfo* Tr2PostProcess2::ExposeToBlue() MAP_ATTRIBUTE( "colorCorrection", m_colorCorrection, "Accesses the color correction effect", Be::READWRITE | Be::PERSIST ) MAP_ATTRIBUTE( "genericEffect", m_generic, "Accesses the generic effect", Be::READWRITE | Be::PERSIST ) + MAP_ATTRIBUTE( "sharpeningStrength", m_sharpeningStrength, "CAS sharpening strength: from 0 to 1", Be::READWRITE | Be::PERSIST ) + EXPOSURE_END() } diff --git a/trinity/PostProcess/Tr2PostProcessRenderer.cpp b/trinity/PostProcess/Tr2PostProcessRenderer.cpp index 7be3b3076..f1e9deeb3 100644 --- a/trinity/PostProcess/Tr2PostProcessRenderer.cpp +++ b/trinity/PostProcess/Tr2PostProcessRenderer.cpp @@ -678,19 +678,17 @@ void Tr2PostProcessRenderer::Execute( const auto upscalingInfo = renderContext.GetPrimaryRenderContext().GetUpscalingInfo( upscalingContext ? upscalingContext->GetID() : Tr2UpscalingAL::INVALID_CONTEXT_ID ); auto upscalingEnabled = upscalingInfo.technique != Tr2UpscalingAL::NONE; - bool sharpeningRequired = !upscalingInfo.hasSharpening; + bool sharpeningRequired = postProcess ? !upscalingInfo.hasSharpening && postProcess->m_sharpeningStrength > 0.f : false; - Tr2GpuResourcePool::Texture output; if( upscalingEnabled ) { displaySize = { upscalingInfo.displayWidth, upscalingInfo.displayHeight }; - - output = gpuResourcePool.GetTempTexture( "Final Result", displaySize, destination.GetFormat(), RENDER_TARGET ); - } - else - { - output = gpuResourcePool.GetTempTexture( "Final Result", displaySize, destination.GetFormat(), RENDER_TARGET ); } + Tr2GpuResourcePool::Texture output = gpuResourcePool.GetTempTexture( + "Final Result", + displaySize, + sharpeningRequired ? GetUavCompatibleFormat( destination.GetFormat() ) : destination.GetFormat(), + sharpeningRequired ? RENDER_TARGET | Tr2GpuUsage::UNORDERED_ACCESS : RENDER_TARGET ); // Always copy auto nonMsaaSource = gpuResourcePool.GetTempTexture( "Pre-upscaling Composite", renderSize, sourceBuffer->GetFormat(), RENDER_TARGET ); @@ -787,12 +785,11 @@ void Tr2PostProcessRenderer::Execute( } } - upscaledSource = RenderSharpening( sharpeningRequired, upscaledSource, gpuResourcePool, renderContext ); - TEMP_PARAM( m_tonemappingEffect, "BlitCurrent", bloomTexture ); TEMP_PARAM( m_tonemappingEffect, "BlitOriginal", upscaledSource ); TEMP_PARAM( m_tonemappingEffect, "Exposure", GetExposureBuffer( gpuResourcePool ) ); TEMP_PARAM( m_tonemappingEffect, "Histogram", histogramBuffer ); + m_tonemappingEffect->SetParameter( MEMOIZED_STRING( "DitherStrength" ), sharpeningRequired ? 0.f : 1.f ); Tr2PPFilmGrainEffect* filmGrain = postProcess != nullptr ? postProcess->GetFilmGrainIfAvailable( m_quality ) : nullptr; @@ -801,23 +798,36 @@ void Tr2PostProcessRenderer::Execute( GPU_REGION( renderContext, "Tonemapping" ); if( upscalingContext && !upscalingInfo.temporal ) { - auto tonemappedOutput = gpuResourcePool.GetTempTexture( "Tonemapping Result", renderSize, destination.GetFormat(), RENDER_TARGET ); + auto tonemappedOutput = gpuResourcePool.GetTempTexture( "Tonemapping Result", renderSize, sharpeningRequired ? upscaledSource->GetFormat() : destination.GetFormat(), RENDER_TARGET ); RenderTonemapping( tonemappedOutput, postProcess, renderContext ); - output = RenderUpscaling( tonemappedOutput, depthMap, velocity, opaqueColor, scene->GetReprojectionMatrix(), gpuResourcePool, renderContext, upscalingContext, dynamicExposure ); + auto upscaled = RenderUpscaling( tonemappedOutput, depthMap, velocity, opaqueColor, scene->GetReprojectionMatrix(), gpuResourcePool, renderContext, upscalingContext, dynamicExposure ); depthMap = {}; velocity = {}; opaqueColor = {}; // need to reset the perframedata so we have the correct viewport size etc scene->ApplyUpscalingToPerFrameData( displaySize.width, displaySize.height, renderContext ); + if( sharpeningRequired ) + { + RenderSharpening( postProcess->m_sharpeningStrength, upscaled, output, gpuResourcePool, renderContext ); + } + else + { + output = upscaled; + } + } + else if ( sharpeningRequired ) + { + auto tonemappedOutput = gpuResourcePool.GetTempTexture( "Tonemapping Result", displaySize, upscaledSource->GetFormat(), RENDER_TARGET ); + RenderTonemapping( tonemappedOutput, postProcess, renderContext ); + RenderSharpening( postProcess->m_sharpeningStrength, tonemappedOutput, output, gpuResourcePool, renderContext ); } else { RenderTonemapping( output, postProcess, renderContext ); } - renderContext.m_esm.SetRenderTarget( 0, destination ); if( filmGrain != nullptr ) { @@ -828,6 +838,13 @@ void Tr2PostProcessRenderer::Execute( Tr2Renderer::DrawTexture( renderContext, output ); } } + else if ( sharpeningRequired ) + { + auto tonemappedOutput = gpuResourcePool.GetTempTexture( "Tonemapping Result", displaySize, upscaledSource->GetFormat(), RENDER_TARGET ); + RenderTonemapping( tonemappedOutput, postProcess, renderContext ); + RenderSharpening( postProcess->m_sharpeningStrength, tonemappedOutput, output, gpuResourcePool, renderContext ); + Tr2Renderer::DrawTexture( renderContext, output ); + } else { RenderTonemapping( output, postProcess, renderContext ); @@ -856,27 +873,20 @@ void Tr2PostProcessRenderer::SetupExposureConversion( bool enable, float middleV } } -Tr2GpuResourcePool::Texture Tr2PostProcessRenderer::RenderSharpening( bool enable, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool& gpuResourcePool, Tr2RenderContext& renderContext ) +void Tr2PostProcessRenderer::RenderSharpening( float strength, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool::Texture& output, Tr2GpuResourcePool& gpuResourcePool, Tr2RenderContext& renderContext ) { - if( !enable ) - { - return input; - } GPU_REGION( renderContext, "CAS Sharpening" ); static const uint32_t CAS_THREAD_GROUP_WORK_REGION_DIM = 16; - auto format = GetUavCompatibleFormat( input->GetFormat() ); - auto output = gpuResourcePool.GetTempTexture( "Sharpening Output", input->GetWidth(), input->GetHeight(), format, RENDER_TARGET | Tr2GpuUsage::UNORDERED_ACCESS ); auto renderWidth = output->GetWidth(); auto renderHeight = output->GetHeight(); AF1 outWidth = static_cast( renderWidth ); AF1 outHeight = static_cast( renderHeight ); - float casIntensity = 0.0f; AMDSharpening::CASConstants casConst; - CasSetup( casConst.const0.u, casConst.const1.u, casIntensity, outWidth, outHeight, outWidth, outHeight ); + CasSetup( casConst.const0.u, casConst.const1.u, std::clamp( strength, 0.0f, 1.0f ), outWidth, outHeight, outWidth, outHeight ); m_fidelityFxCasShader->SetParameter( MEMOIZED_STRING( "const0" ), AMDSharpening::AsVector( casConst.const0 ) ); m_fidelityFxCasShader->SetParameter( MEMOIZED_STRING( "const1" ), AMDSharpening::AsVector( casConst.const1 ) ); @@ -886,7 +896,6 @@ Tr2GpuResourcePool::Texture Tr2PostProcessRenderer::RenderSharpening( bool enabl auto dispatchX = ( renderWidth + ( CAS_THREAD_GROUP_WORK_REGION_DIM - 1 ) ) / CAS_THREAD_GROUP_WORK_REGION_DIM; auto dispatchY = ( renderHeight + ( CAS_THREAD_GROUP_WORK_REGION_DIM - 1 ) ) / CAS_THREAD_GROUP_WORK_REGION_DIM; Tr2Renderer::RunComputeShader( m_fidelityFxCasShader, dispatchX, dispatchY, 1, renderContext ); - return output; } // Helper function to blur certain channel of a source render target to a destination render target with a blur type (Big/Small) diff --git a/trinity/PostProcess/Tr2PostProcessRenderer.h b/trinity/PostProcess/Tr2PostProcessRenderer.h index 6c296ade0..317dd4f3e 100644 --- a/trinity/PostProcess/Tr2PostProcessRenderer.h +++ b/trinity/PostProcess/Tr2PostProcessRenderer.h @@ -147,7 +147,7 @@ BLUE_CLASS( Tr2PostProcessRenderer ) : void SetupExposureConversion( bool enable, float middleValue ); // optional sharpening - Tr2GpuResourcePool::Texture RenderSharpening( bool enable, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool& gpuResourcePool, Tr2RenderContext& renderContext ); + void RenderSharpening( float strength, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool::Texture& output, Tr2GpuResourcePool& gpuResourcePool, Tr2RenderContext& renderContext ); // bloom Tr2GpuResourcePool::Texture RenderBloom( Tr2GpuResourcePool::Texture & dest, Tr2GpuResourcePool & gpuResourcePool, Tr2RenderContext & renderContext, Tr2PPBloomEffect * bloom, Tr2PPDynamicExposureEffect * dynamicExposure ); From 5ede752dfefcbe53de6be7bafe8dcd023e4af4b7 Mon Sep 17 00:00:00 2001 From: Filipp Pavlov Date: Mon, 31 Aug 2026 10:59:31 +0000 Subject: [PATCH 2/2] Address PR comments --- trinity/Eve/EveSpaceScene.cpp | 2 +- .../PostProcess/Tr2PostProcessRenderer.cpp | 20 +++++++++---------- trinity/PostProcess/Tr2PostProcessRenderer.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/trinity/Eve/EveSpaceScene.cpp b/trinity/Eve/EveSpaceScene.cpp index 0f7e859d6..4a345b411 100644 --- a/trinity/Eve/EveSpaceScene.cpp +++ b/trinity/Eve/EveSpaceScene.cpp @@ -368,7 +368,7 @@ void EveSpaceScene::UpdatePostProcessAttributes() { m_combinedPostProcess.CreateInstance(); } - m_combinedPostProcess->m_sharpeningStrength = m_sceneDefaultPostProcess->m_sharpeningStrength; + m_combinedPostProcess->m_sharpeningStrength = m_sceneDefaultPostProcess ? m_sceneDefaultPostProcess->m_sharpeningStrength : 0.5f; std::sort( begin( postProcessAttributes ), diff --git a/trinity/PostProcess/Tr2PostProcessRenderer.cpp b/trinity/PostProcess/Tr2PostProcessRenderer.cpp index f1e9deeb3..d11887c2e 100644 --- a/trinity/PostProcess/Tr2PostProcessRenderer.cpp +++ b/trinity/PostProcess/Tr2PostProcessRenderer.cpp @@ -684,10 +684,10 @@ void Tr2PostProcessRenderer::Execute( { displaySize = { upscalingInfo.displayWidth, upscalingInfo.displayHeight }; } - Tr2GpuResourcePool::Texture output = gpuResourcePool.GetTempTexture( - "Final Result", - displaySize, - sharpeningRequired ? GetUavCompatibleFormat( destination.GetFormat() ) : destination.GetFormat(), + Tr2GpuResourcePool::Texture output = gpuResourcePool.GetTempTexture( + "Final Result", + displaySize, + sharpeningRequired ? GetUavCompatibleFormat( destination.GetFormat() ) : destination.GetFormat(), sharpeningRequired ? RENDER_TARGET | Tr2GpuUsage::UNORDERED_ACCESS : RENDER_TARGET ); // Always copy @@ -811,18 +811,18 @@ void Tr2PostProcessRenderer::Execute( scene->ApplyUpscalingToPerFrameData( displaySize.width, displaySize.height, renderContext ); if( sharpeningRequired ) { - RenderSharpening( postProcess->m_sharpeningStrength, upscaled, output, gpuResourcePool, renderContext ); + RenderSharpening( postProcess->m_sharpeningStrength, upscaled, output, renderContext ); } else { output = upscaled; } } - else if ( sharpeningRequired ) + else if( sharpeningRequired ) { auto tonemappedOutput = gpuResourcePool.GetTempTexture( "Tonemapping Result", displaySize, upscaledSource->GetFormat(), RENDER_TARGET ); RenderTonemapping( tonemappedOutput, postProcess, renderContext ); - RenderSharpening( postProcess->m_sharpeningStrength, tonemappedOutput, output, gpuResourcePool, renderContext ); + RenderSharpening( postProcess->m_sharpeningStrength, tonemappedOutput, output, renderContext ); } else { @@ -838,11 +838,11 @@ void Tr2PostProcessRenderer::Execute( Tr2Renderer::DrawTexture( renderContext, output ); } } - else if ( sharpeningRequired ) + else if( sharpeningRequired ) { auto tonemappedOutput = gpuResourcePool.GetTempTexture( "Tonemapping Result", displaySize, upscaledSource->GetFormat(), RENDER_TARGET ); RenderTonemapping( tonemappedOutput, postProcess, renderContext ); - RenderSharpening( postProcess->m_sharpeningStrength, tonemappedOutput, output, gpuResourcePool, renderContext ); + RenderSharpening( postProcess->m_sharpeningStrength, tonemappedOutput, output, renderContext ); Tr2Renderer::DrawTexture( renderContext, output ); } else @@ -873,7 +873,7 @@ void Tr2PostProcessRenderer::SetupExposureConversion( bool enable, float middleV } } -void Tr2PostProcessRenderer::RenderSharpening( float strength, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool::Texture& output, Tr2GpuResourcePool& gpuResourcePool, Tr2RenderContext& renderContext ) +void Tr2PostProcessRenderer::RenderSharpening( float strength, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool::Texture& output, Tr2RenderContext& renderContext ) { GPU_REGION( renderContext, "CAS Sharpening" ); diff --git a/trinity/PostProcess/Tr2PostProcessRenderer.h b/trinity/PostProcess/Tr2PostProcessRenderer.h index 317dd4f3e..cc0014f03 100644 --- a/trinity/PostProcess/Tr2PostProcessRenderer.h +++ b/trinity/PostProcess/Tr2PostProcessRenderer.h @@ -147,7 +147,7 @@ BLUE_CLASS( Tr2PostProcessRenderer ) : void SetupExposureConversion( bool enable, float middleValue ); // optional sharpening - void RenderSharpening( float strength, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool::Texture& output, Tr2GpuResourcePool& gpuResourcePool, Tr2RenderContext& renderContext ); + void RenderSharpening( float strength, Tr2GpuResourcePool::Texture& input, Tr2GpuResourcePool::Texture& output, Tr2RenderContext& renderContext ); // bloom Tr2GpuResourcePool::Texture RenderBloom( Tr2GpuResourcePool::Texture & dest, Tr2GpuResourcePool & gpuResourcePool, Tr2RenderContext & renderContext, Tr2PPBloomEffect * bloom, Tr2PPDynamicExposureEffect * dynamicExposure );