After a simple pass-through compute shader pass, the resolution is reduced

I implemented a simple pass-through compute shader, and used it to add a new pass. Everything is fine except the resolution. It looks like the resolution is reduced.


code of render func in .cpp

FScreenPassTexture FExtraPostProcessExtension::PostProcessPassAfterTonemap_RenderThread(FRDGBuilder& GraphBuilder, const FSceneView& View, const FPostProcessMaterialInputs& InOutInputs)
{
	const FScreenPassTexture SceneColor = InOutInputs.Textures[(uint32)EPostProcessMaterialInput::SceneColor];
	const FViewInfo& ViewInfo = static_cast<const FViewInfo&>(View);

  //Desc
	FRDGTextureDesc TextureDesc = SceneColor.Texture->Desc;
	TextureDesc.Flags = ETextureCreateFlags::UAV;

	//output
	FScreenPassRenderTarget Output(GraphBuilder.CreateTexture(TextureDesc, TEXT("CSTexture")), ERenderTargetLoadAction::ELoad);

	//
	FRDGTextureRef TempTexture = SceneColor.Texture;

	//UAV
	FRDGTextureUAVRef OutTexture = GraphBuilder.CreateUAV(Output.Texture);

  //Params
  FMyCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FMyCS::FParameters>();
  PassParameters->InTexture = TempTexture;
  PassParameters->Sampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
  PassParameters->RWOutputTexture = OutTexture;
  //
  TShaderMapRef<FMyCS> ComputeShader(ViewInfo.ShaderMap);

  //Add pass
  FComputeShaderUtils::AddPass(GraphBuilder,
    RDG_EVENT_NAME("TestCS %dx%d (CS)", OutTexture->Desc.Texture->Desc.Extent.X, OutTexture->Desc.Texture->Desc.Extent.Y),
    ComputeShader,
    PassParameters,
    FComputeShaderUtils::GetGroupCount(SceneColor.ViewRect.Size(), FIntPoint(32, 32)));

	if (Output.IsValid())
	{
		return MoveTemp(Output);
	}
	else
	{
		return SceneColor;
	}
}

code in .usf

#include "/Engine/Public/Platform.ush"

//for Texture2DSample
#include "/Engine/Private/Common.ush"

// COMPUTE SHADER
#if COMPUTESHADER
Texture2D InTexture;
SamplerState Sampler;
RWTexture2D<float4> RWOutputTexture;
 
[numthreads(NUMTHREADS_X, NUMTHREADS_Y, 1)]
void MainCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
  float sizeX, sizeY;
  RWOutputTexture.GetDimensions(sizeX, sizeY);
  float2 TexSize = float2(sizeX, sizeY);
  float2 InvSize = (1 / TexSize.xy);
  uint2 PixelPos = DispatchThreadId.xy;

  float2 UV = PixelPos * InvSize;

  float4 OutColor = Texture2DSample(InTexture, Sampler, UV);

  RWOutputTexture[PixelPos] = OutColor;
}
#endif

Any help would be greatly appreciated!

I solved the problem myself

I made a few changes in .usf file.
I changed the way for calculating UV and pass a new struct param (ScreenPassTextureViewportParameters) from .cpp.

//for IsComputeUVOutOfBounds(UV)
#include "/Engine/Private/PostProcessCommon.ush"
//for SCREEN_PASS_TEXTURE_VIEWPORT
#include "/Engine/Private/ScreenPass.ush"

...
//you should pass 'Input' from .cpp
SCREEN_PASS_TEXTURE_VIEWPORT(Input)

void MainCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
	...
	//compute UV
	float2 UV = ((float2)DispatchThreadId + (float2)Input_ViewportMin + 0.5f) * Input_ExtentInverse;

	if (IsComputeUVOutOfBounds(UV))
	{
		return;
	}

	float4 OutColor = Texture2DSample(InTexture, Sampler, UV);
	...
}

Although I still don’t know what’s going on. ​Any ideas are welcome.
Have fun!

I’d speculate it has something to do with resolution scaling / screen percentage. If this is the case, the original shader may work when screen percentage is set to 100%. It’s often ~70% by default.
But if it works idk that I’d bother diving much deeper.

1 Like