// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. /*============================================================================= DistanceFieldVisualization.cpp =============================================================================*/ #include "DistanceFieldAmbientOcclusion.h" #include "DeferredShadingRenderer.h" #include "PostProcess/PostProcessing.h" #include "PostProcess/SceneFilterRendering.h" #include "DistanceFieldLightingShared.h" #include "ScreenRendering.h" #include "DistanceFieldLightingPost.h" #include "OneColorShader.h" #include "GlobalDistanceField.h" #include "FXSystem.h" #include "PostProcess/PostProcessSubsurface.h" #include "PipelineStateCache.h" template class TVisualizeMeshDistanceFieldCS : public FGlobalShader { DECLARE_SHADER_TYPE(TVisualizeMeshDistanceFieldCS, Global); public: static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldAO(Parameters.Platform) && IsUsingDistanceFields(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { OutEnvironment.SetDefine(TEXT("DOWNSAMPLE_FACTOR"), GAODownsampleFactor); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEX"), GDistanceFieldAOTileSizeX); OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEY"), GDistanceFieldAOTileSizeY); OutEnvironment.SetDefine(TEXT("USE_GLOBAL_DISTANCE_FIELD"), bUseGlobalDistanceField); } /** Default constructor. */ TVisualizeMeshDistanceFieldCS() {} /** Initialization constructor. */ TVisualizeMeshDistanceFieldCS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FGlobalShader(Initializer) { VisualizeMeshDistanceFields.Bind(Initializer.ParameterMap, TEXT("VisualizeMeshDistanceFields")); NumGroups.Bind(Initializer.ParameterMap, TEXT("NumGroups")); ObjectParameters.Bind(Initializer.ParameterMap); SceneTextureParameters.Bind(Initializer); AOParameters.Bind(Initializer.ParameterMap); GlobalDistanceFieldParameters.Bind(Initializer.ParameterMap); } void SetParameters( FRHICommandList& RHICmdList, const FSceneView& View, FSceneRenderTargetItem& VisualizeMeshDistanceFieldsValue, FVector2D NumGroupsValue, const FDistanceFieldAOParameters& Parameters, const FGlobalDistanceFieldInfo& GlobalDistanceFieldInfo) { const FComputeShaderRHIParamRef ShaderRHI = GetComputeShader(); FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View.ViewUniformBuffer); RHICmdList.TransitionResource(EResourceTransitionAccess::ERWBarrier, EResourceTransitionPipeline::EComputeToCompute, VisualizeMeshDistanceFieldsValue.UAV); VisualizeMeshDistanceFields.SetTexture(RHICmdList, ShaderRHI, VisualizeMeshDistanceFieldsValue.ShaderResourceTexture, VisualizeMeshDistanceFieldsValue.UAV); ObjectParameters.Set(RHICmdList, ShaderRHI, GAOCulledObjectBuffers.Buffers); AOParameters.Set(RHICmdList, ShaderRHI, Parameters); SceneTextureParameters.Set(RHICmdList, ShaderRHI, View.FeatureLevel, ESceneTextureSetupMode::All); if (bUseGlobalDistanceField) { GlobalDistanceFieldParameters.Set(RHICmdList, ShaderRHI, GlobalDistanceFieldInfo.ParameterData); } SetShaderValue(RHICmdList, ShaderRHI, NumGroups, NumGroupsValue); } void UnsetParameters(FRHICommandList& RHICmdList, FSceneRenderTargetItem& VisualizeMeshDistanceFieldsValue) { RHICmdList.TransitionResource(EResourceTransitionAccess::EReadable, EResourceTransitionPipeline::EComputeToCompute, VisualizeMeshDistanceFieldsValue.UAV); VisualizeMeshDistanceFields.UnsetUAV(RHICmdList, GetComputeShader()); } // FShader interface. virtual bool Serialize(FArchive& Ar) override { bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar); Ar << VisualizeMeshDistanceFields; Ar << NumGroups; Ar << ObjectParameters; Ar << SceneTextureParameters; Ar << AOParameters; Ar << GlobalDistanceFieldParameters; return bShaderHasOutdatedParameters; } private: FRWShaderParameter VisualizeMeshDistanceFields; FShaderParameter NumGroups; FDistanceFieldCulledObjectBufferParameters ObjectParameters; FSceneTextureShaderParameters SceneTextureParameters; FAOParameters AOParameters; FGlobalDistanceFieldParameters GlobalDistanceFieldParameters; }; IMPLEMENT_SHADER_TYPE(template<>,TVisualizeMeshDistanceFieldCS,TEXT("/Engine/Private/DistanceFieldVisualization.usf"),TEXT("VisualizeMeshDistanceFieldCS"),SF_Compute); IMPLEMENT_SHADER_TYPE(template<>,TVisualizeMeshDistanceFieldCS,TEXT("/Engine/Private/DistanceFieldVisualization.usf"),TEXT("VisualizeMeshDistanceFieldCS"),SF_Compute); class FVisualizeDistanceFieldUpsamplePS : public FGlobalShader { DECLARE_SHADER_TYPE(FVisualizeDistanceFieldUpsamplePS, Global); public: static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters) { return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && DoesPlatformSupportDistanceFieldAO(Parameters.Platform) && IsUsingDistanceFields(Parameters.Platform); } static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment) { OutEnvironment.SetDefine(TEXT("DOWNSAMPLE_FACTOR"), GAODownsampleFactor); } /** Default constructor. */ FVisualizeDistanceFieldUpsamplePS() {} /** Initialization constructor. */ FVisualizeDistanceFieldUpsamplePS(const ShaderMetaType::CompiledShaderInitializerType& Initializer) : FGlobalShader(Initializer) { SceneTextureParameters.Bind(Initializer); VisualizeDistanceFieldTexture.Bind(Initializer.ParameterMap,TEXT("VisualizeDistanceFieldTexture")); VisualizeDistanceFieldSampler.Bind(Initializer.ParameterMap,TEXT("VisualizeDistanceFieldSampler")); } void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, TRefCountPtr& VisualizeDistanceField) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View.ViewUniformBuffer); SceneTextureParameters.Set(RHICmdList, ShaderRHI, View.FeatureLevel, ESceneTextureSetupMode::All); SetTextureParameter(RHICmdList, ShaderRHI, VisualizeDistanceFieldTexture, VisualizeDistanceFieldSampler, TStaticSamplerState::GetRHI(), VisualizeDistanceField->GetRenderTargetItem().ShaderResourceTexture); } // FShader interface. virtual bool Serialize(FArchive& Ar) override { bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar); Ar << SceneTextureParameters; Ar << VisualizeDistanceFieldTexture; Ar << VisualizeDistanceFieldSampler; return bShaderHasOutdatedParameters; } private: FSceneTextureShaderParameters SceneTextureParameters; FShaderResourceParameter VisualizeDistanceFieldTexture; FShaderResourceParameter VisualizeDistanceFieldSampler; }; IMPLEMENT_SHADER_TYPE(,FVisualizeDistanceFieldUpsamplePS,TEXT("/Engine/Private/DistanceFieldVisualization.usf"),TEXT("VisualizeDistanceFieldUpsamplePS"),SF_Pixel); void FDeferredShadingSceneRenderer::RenderMeshDistanceFieldVisualization(FRHICommandListImmediate& RHICmdList, const FDistanceFieldAOParameters& Parameters) { //@todo - support multiple views const FViewInfo& View = Views[0]; if (UseDistanceFieldAO() && FeatureLevel >= ERHIFeatureLevel::SM5 && DoesPlatformSupportDistanceFieldAO(View.GetShaderPlatform()) && Views.Num() == 1) { QUICK_SCOPE_CYCLE_COUNTER(STAT_RenderMeshDistanceFieldVis); SCOPED_DRAW_EVENT(RHICmdList, VisualizeMeshDistanceFields); if (GDistanceFieldVolumeTextureAtlas.VolumeTextureRHI && Scene->DistanceFieldSceneData.NumObjectsInBuffer > 0) { check(!Scene->DistanceFieldSceneData.HasPendingOperations()); QUICK_SCOPE_CYCLE_COUNTER(STAT_AOIssueGPUWork); const bool bUseGlobalDistanceField = UseGlobalDistanceField(Parameters) && View.Family->EngineShowFlags.VisualizeGlobalDistanceField; CullObjectsToView(RHICmdList, Scene, View, Parameters, GAOCulledObjectBuffers); TRefCountPtr VisualizeResultRT; { const FIntPoint BufferSize = GetBufferSizeForAO(); FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(BufferSize, PF_FloatRGBA, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable | TexCreate_UAV, false)); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, VisualizeResultRT, TEXT("VisualizeDistanceField")); } { UnbindRenderTargets(RHICmdList); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { const FViewInfo& ViewInfo = Views[ViewIndex]; uint32 GroupSizeX = FMath::DivideAndRoundUp(ViewInfo.ViewRect.Size().X / GAODownsampleFactor, GDistanceFieldAOTileSizeX); uint32 GroupSizeY = FMath::DivideAndRoundUp(ViewInfo.ViewRect.Size().Y / GAODownsampleFactor, GDistanceFieldAOTileSizeY); SCOPED_DRAW_EVENT(RHICmdList, VisualizeMeshDistanceFieldCS); FSceneRenderTargetItem& VisualizeResultRTI = VisualizeResultRT->GetRenderTargetItem(); if (bUseGlobalDistanceField) { check(View.GlobalDistanceFieldInfo.Clipmaps.Num() > 0); TShaderMapRef > ComputeShader(ViewInfo.ShaderMap); RHICmdList.SetComputeShader(ComputeShader->GetComputeShader()); ComputeShader->SetParameters(RHICmdList, ViewInfo, VisualizeResultRTI, FVector2D(GroupSizeX, GroupSizeY), Parameters, View.GlobalDistanceFieldInfo); DispatchComputeShader(RHICmdList, *ComputeShader, GroupSizeX, GroupSizeY, 1); ComputeShader->UnsetParameters(RHICmdList, VisualizeResultRTI); } else { TShaderMapRef > ComputeShader(ViewInfo.ShaderMap); RHICmdList.SetComputeShader(ComputeShader->GetComputeShader()); ComputeShader->SetParameters(RHICmdList, ViewInfo, VisualizeResultRTI, FVector2D(GroupSizeX, GroupSizeY), Parameters, View.GlobalDistanceFieldInfo); DispatchComputeShader(RHICmdList, *ComputeShader, GroupSizeX, GroupSizeY, 1); ComputeShader->UnsetParameters(RHICmdList, VisualizeResultRTI); } } } if ( IsTransientResourceBufferAliasingEnabled()) { GAOCulledObjectBuffers.Buffers.DiscardTransientResource(); } check(RHICmdList.IsOutsideRenderPass()); { // We must specify StencilWrite or VK will lose the attachment FSceneRenderTargets::Get(RHICmdList).BeginRenderingSceneColor(RHICmdList, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { const FViewInfo& ViewInfo = Views[ViewIndex]; SCOPED_DRAW_EVENT(RHICmdList, UpsampleAO); RHICmdList.SetViewport(ViewInfo.ViewRect.Min.X, ViewInfo.ViewRect.Min.Y, 0.0f, ViewInfo.ViewRect.Max.X, ViewInfo.ViewRect.Max.Y, 1.0f); FGraphicsPipelineStateInitializer GraphicsPSOInit; RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); GraphicsPSOInit.RasterizerState = TStaticRasterizerState::GetRHI(); GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::GetRHI(); GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI(); TShaderMapRef VertexShader( ViewInfo.ShaderMap ); TShaderMapRef PixelShader( ViewInfo.ShaderMap ); GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; GraphicsPSOInit.BoundShaderState.VertexShaderRHI = GETSAFERHISHADER_VERTEX(*VertexShader); GraphicsPSOInit.BoundShaderState.PixelShaderRHI = GETSAFERHISHADER_PIXEL(*PixelShader); GraphicsPSOInit.PrimitiveType = PT_TriangleList; SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit); PixelShader->SetParameters(RHICmdList, ViewInfo, VisualizeResultRT); DrawRectangle( RHICmdList, 0, 0, ViewInfo.ViewRect.Width(), ViewInfo.ViewRect.Height(), ViewInfo.ViewRect.Min.X / GAODownsampleFactor, ViewInfo.ViewRect.Min.Y / GAODownsampleFactor, ViewInfo.ViewRect.Width() / GAODownsampleFactor, ViewInfo.ViewRect.Height() / GAODownsampleFactor, FIntPoint(ViewInfo.ViewRect.Width(), ViewInfo.ViewRect.Height()), GetBufferSizeForAO(), *VertexShader); } FSceneRenderTargets::Get(RHICmdList).FinishRenderingSceneColor(RHICmdList); } } } }