void FDeferredShadingSceneRenderer::PropagateLPVs() { for(int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { FViewInfo& View = Views[ViewIndex]; FSceneViewState* ViewState = (FSceneViewState*)Views[ViewIndex].State; if(ViewState) { FLightPropagationVolume* LightPropagationVolume = ViewState->GetLightPropagationVolume(); if(LightPropagationVolume) { SCOPED_DRAW_EVENT(UpdateLPVs, DEC_SCENE_ITEMS); SCOPE_CYCLE_COUNTER(STAT_UpdateLPVs); LightPropagationVolume->Propagate(); } } } }
void FRCPassPostProcessLpvIndirect::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(PostProcessLpvIndirect, DEC_SCENE_ITEMS); const FPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; // todo: view size should scale with input texture size so we can do SSAO in half resolution as well FIntRect DestRect = View.ViewRect; FIntPoint DestSize = DestRect.Size(); uint32 NumReflectionCaptures = ViewFamily.Scene->GetRenderScene()->ReflectionSceneData.RegisteredReflectionCaptures.Num(); const FSceneRenderTargetItem& DestColorRenderTarget = GSceneRenderTargets.SceneColor->GetRenderTargetItem(); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[] = { DestColorRenderTarget.TargetableTexture, }; // Set the view family's render target/viewport. RHISetRenderTargets(1, RenderTargets, GSceneRenderTargets.GetSceneDepthSurface(), 0, NULL); Context.SetViewportAndCallRHI(View.ViewRect); // set the state if ( ViewFamily.EngineShowFlags.LpvLightingOnly ) { RHISetBlendState( TStaticBlendState<>::GetRHI() ); } else { // additive blending RHISetBlendState(TStaticBlendState<CW_RGB,BO_Add,BF_One,BF_One>::GetRHI()); } RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(GetGlobalShaderMap()); FSceneViewState* ViewState = (FSceneViewState*)View.State; FLightPropagationVolume* Lpv = NULL; bool bUseLpv = false; if ( ViewState ) { Lpv = ViewState->GetLightPropagationVolume(); bUseLpv = Lpv && PostprocessSettings.LPVIntensity > 0.0f; } if ( !bUseLpv ) { return; } TShaderMapRef<FPostProcessLpvIndirectPS> PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleUse ); #if LPV_VOLUME_TEXTURE FTextureRHIParamRef LpvBufferSrvs[7]; for ( int i = 0; i < 7; i++ ) { LpvBufferSrvs[i] = Lpv->GetLpvBufferSrv(i); } PixelShader->SetParameters(LpvBufferSrvs, LpvReadUniformBuffer, Context ); #else FShaderResourceViewRHIParamRef LpvBufferSrv = Lpv->GetLpvBufferSrv(); PixelShader->SetParameters(LpvBufferSrv, LpvReadUniformBuffer, Context ); #endif // Draw a quad mapping scene color to the view's render target DrawRectangle( 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), GSceneRenderTargets.SceneColor->GetDesc().Extent); RHICopyToResolveTarget(DestColorRenderTarget.TargetableTexture, DestColorRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessLpvIndirect::Process(FRenderingCompositePassContext& Context) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); { FRenderingCompositeOutput* OutputOfMyInput = GetInput(ePId_Input0)->GetOutput(); PassOutputs[0].PooledRenderTarget = OutputOfMyInput->PooledRenderTarget; OutputOfMyInput->RenderTargetDesc.DebugName = PassOutputs[0].RenderTargetDesc.DebugName; PassOutputs[0].RenderTargetDesc = OutputOfMyInput->RenderTargetDesc; check(PassOutputs[0].RenderTargetDesc.Extent.X); check(PassOutputs[0].RenderTargetDesc.Extent.Y); } const FFinalPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FSceneView& View = Context.View; FSceneViewState* ViewState = (FSceneViewState*)View.State; if(!ViewState) { return; } // This check should be inclusive to stereo views const bool bIncludeStereoViews = true; FLightPropagationVolume* Lpv = ViewState->GetLightPropagationVolume(Context.GetFeatureLevel(), bIncludeStereoViews); const FLightPropagationVolumeSettings& LPVSettings = PostprocessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>(); if(!Lpv || LPVSettings.LPVIntensity == 0.0f) { return; } const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; // todo: view size should scale with input texture size so we can do SSAO in half resolution as well FIntRect DestRect = View.ViewRect; FIntPoint DestSize = DestRect.Size(); const bool bMixing = CVarLPVMixing.GetValueOnRenderThread() != 0; // Apply specular separately if we're mixing reflection environment with indirect lighting const bool bApplySeparateSpecularRT = View.Family->EngineShowFlags.ReflectionEnvironment && bMixing; const FSceneRenderTargetItem& DestColorRenderTarget = SceneContext.GetSceneColor()->GetRenderTargetItem(); const FSceneRenderTargetItem& DestSpecularRenderTarget = SceneContext.LightAccumulation->GetRenderTargetItem(); const FSceneRenderTargetItem& DestDirectionalOcclusionRenderTarget = SceneContext.DirectionalOcclusion->GetRenderTargetItem(); // Make sure the LPV Update has completed Lpv->InsertGPUWaitForAsyncUpdate(Context.RHICmdList); if ( LPVSettings.LPVDirectionalOcclusionIntensity > 0.0001f ) { DoDirectionalOcclusionPass(Context); } FTextureRHIParamRef RenderTargets[2]; RenderTargets[0] = DestColorRenderTarget.TargetableTexture; RenderTargets[1] = DestSpecularRenderTarget.TargetableTexture; // Set the view family's render target/viewport. // If specular not applied: set only color target uint32 NumRenderTargets = 1; if ( bApplySeparateSpecularRT ) { NumRenderTargets = 2; } SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, 0, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilNop); Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<CW_RGB,BO_Add,BF_One,BF_One,BO_Add,BF_One,BF_One>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); TShaderMapRef< TPostProcessLpvIndirectPS<false> > PixelShaderNoSpecular(Context.GetShaderMap()); TShaderMapRef< TPostProcessLpvIndirectPS<true> > PixelShaderWithSpecular(Context.GetShaderMap()); FPostProcessLpvIndirectPS* PixelShader = NULL; int BoundShaderIndex = -1; if ( bApplySeparateSpecularRT ) { PixelShader = (FPostProcessLpvIndirectPS*)*PixelShaderWithSpecular; BoundShaderIndex = 0; } else { PixelShader = (FPostProcessLpvIndirectPS*)*PixelShaderNoSpecular; BoundShaderIndex = 1; } static FGlobalBoundShaderState BoundShaderState[2]; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState[BoundShaderIndex], GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, PixelShader); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleDraw ); FTextureRHIParamRef LpvBufferSrvs[7]; for ( int i = 0; i < 7; i++ ) { LpvBufferSrvs[i] = Lpv->GetLpvBufferSrv(i); } PixelShader->SetParameters( LpvBufferSrvs, Lpv->GetAOVolumeTextureSRV(), LpvReadUniformBuffer, Context ); { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessLpvIndirect ); DrawPostProcessPass( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), SceneContext.GetBufferSizeXY(), *VertexShader, View.StereoPass, Context.HasHmdMesh()); Context.RHICmdList.CopyToResolveTarget(DestColorRenderTarget.TargetableTexture, DestColorRenderTarget.ShaderResourceTexture, false, FResolveParams()); if(bApplySeparateSpecularRT) { Context.RHICmdList.CopyToResolveTarget(DestSpecularRenderTarget.TargetableTexture, DestSpecularRenderTarget.ShaderResourceTexture, false, FResolveParams()); } } if ( LPVSettings.LPVDirectionalOcclusionIntensity > 0.0001f ) { GRenderTargetPool.VisualizeTexture.SetCheckPoint(Context.RHICmdList, SceneContext.DirectionalOcclusion); } }
void FRCPassPostProcessLpvIndirect::DoDirectionalOcclusionPass(FRenderingCompositePassContext& Context) const { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessLpvDirectionalOcclusion ); const FSceneRenderTargetItem& DestDirectionalOcclusionRenderTarget = SceneContext.DirectionalOcclusion->GetRenderTargetItem(); const FViewInfo& View = Context.View; FSceneViewState* ViewState = (FSceneViewState*)View.State; if(!ViewState) { return; } const FFinalPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FLightPropagationVolumeSettings& LPVSettings = PostprocessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>(); FLightPropagationVolume* Lpv = ViewState->GetLightPropagationVolume(Context.GetFeatureLevel()); if(!Lpv || LPVSettings.LPVIntensity == 0.0f) { return; } FTextureRHIParamRef RenderTarget = DestDirectionalOcclusionRenderTarget.TargetableTexture; SetRenderTargets(Context.RHICmdList, 1, &RenderTarget, NULL, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilNop); Context.SetViewportAndCallRHI(View.ViewRect); Context.RHICmdList.SetBlendState( TStaticBlendState<>::GetRHI() ); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(View.ShaderMap); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; TShaderMapRef< FPostProcessLpvDirectionalOcclusionPS > PixelShader(View.ShaderMap); static FGlobalBoundShaderState BoundShaderState; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleDraw ); PixelShader->SetParameters( Lpv->GetAOVolumeTextureSRV(), LpvReadUniformBuffer, Context ); DrawPostProcessPass( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), SceneContext.GetBufferSizeXY(), *VertexShader, View.StereoPass, Context.HasHmdMesh()); }
void FDeferredShadingSceneRenderer::BeginOcclusionTests(FRHICommandListImmediate& RHICmdList, bool bRenderQueries) { SCOPE_CYCLE_COUNTER(STAT_BeginOcclusionTestsTime); int32 NumBufferedFrames = FOcclusionQueryHelpers::GetNumBufferedFrames(); FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const bool bUseDownsampledDepth = SceneContext.UseDownsizedOcclusionQueries() && IsValidRef(SceneContext.SmallDepthZ) && IsValidRef(SceneContext.GetSmallDepthSurface()); if (bUseDownsampledDepth) { SetRenderTarget(RHICmdList, NULL, SceneContext.GetSmallDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } else { SetRenderTarget(RHICmdList, NULL, SceneContext.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } if (bRenderQueries) { RHICmdList.BeginOcclusionQueryBatch(); // Perform occlusion queries for each view for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++) { SCOPED_DRAW_EVENT(RHICmdList, BeginOcclusionTests); FViewInfo& View = Views[ViewIndex]; if (bUseDownsampledDepth) { const uint32 DownsampledX = FMath::TruncToInt(View.ViewRect.Min.X / SceneContext.GetSmallColorDepthDownsampleFactor()); const uint32 DownsampledY = FMath::TruncToInt(View.ViewRect.Min.Y / SceneContext.GetSmallColorDepthDownsampleFactor()); const uint32 DownsampledSizeX = FMath::TruncToInt(View.ViewRect.Width() / SceneContext.GetSmallColorDepthDownsampleFactor()); const uint32 DownsampledSizeY = FMath::TruncToInt(View.ViewRect.Height() / SceneContext.GetSmallColorDepthDownsampleFactor()); // Setup the viewport for rendering to the downsampled depth buffer RHICmdList.SetViewport(DownsampledX, DownsampledY, 0.0f, DownsampledX + DownsampledSizeX, DownsampledY + DownsampledSizeY, 1.0f); } else { RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f); } FSceneViewState* ViewState = (FSceneViewState*)View.State; if (ViewState && !View.bDisableQuerySubmissions) { // Depth tests, no depth writes, no color writes, opaque, solid rasterization wo/ backface culling. RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI()); // We only need to render the front-faces of the culling geometry (this halves the amount of pixels we touch) RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI()); RHICmdList.SetBlendState(TStaticBlendState<CW_NONE>::GetRHI()); // Lookup the vertex shader. TShaderMapRef<FOcclusionQueryVS> VertexShader(View.ShaderMap); SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), OcclusionTestBoundShaderState, GetVertexDeclarationFVector3(), *VertexShader, NULL); VertexShader->SetParameters(RHICmdList, View); // Issue this frame's occlusion queries (occlusion queries from last frame may still be in flight) const uint32 QueryIndex = FOcclusionQueryHelpers::GetQueryIssueIndex(ViewState->PendingPrevFrameNumber, NumBufferedFrames); FSceneViewState::ShadowKeyOcclusionQueryMap& ShadowOcclusionQueryMap = ViewState->ShadowOcclusionQueryMaps[QueryIndex]; // Clear primitives which haven't been visible recently out of the occlusion history, and reset old pending occlusion queries. ViewState->TrimOcclusionHistory(RHICmdList, ViewFamily.CurrentRealTime, ViewFamily.CurrentRealTime - GEngine->PrimitiveProbablyVisibleTime, ViewFamily.CurrentRealTime, ViewState->OcclusionFrameCounter); // Give back all these occlusion queries to the pool. for (TMap<FSceneViewState::FProjectedShadowKey, FRenderQueryRHIRef>::TIterator QueryIt(ShadowOcclusionQueryMap); QueryIt; ++QueryIt) { //FRenderQueryRHIParamRef Query = QueryIt.Value(); //check( Query.GetRefCount() == 1 ); ViewState->OcclusionQueryPool.ReleaseQuery(QueryIt.Value()); } ShadowOcclusionQueryMap.Reset(); { SCOPED_DRAW_EVENT(RHICmdList, ShadowFrustumQueries); for (TSparseArray<FLightSceneInfoCompact>::TConstIterator LightIt(Scene->Lights); LightIt; ++LightIt) { const FVisibleLightInfo& VisibleLightInfo = VisibleLightInfos[LightIt.GetIndex()]; for (int32 ShadowIndex = 0; ShadowIndex < VisibleLightInfo.AllProjectedShadows.Num(); ShadowIndex++) { const FProjectedShadowInfo& ProjectedShadowInfo = *VisibleLightInfo.AllProjectedShadows[ShadowIndex]; if (ProjectedShadowInfo.DependentView && ProjectedShadowInfo.DependentView != &View) { continue; } if (ProjectedShadowInfo.CascadeSettings.bOnePassPointLightShadow) { FLightSceneProxy& LightProxy = *(ProjectedShadowInfo.GetLightSceneInfo().Proxy); // Query one pass point light shadows separately because they don't have a shadow frustum, they have a bounding sphere instead. FSphere LightBounds = LightProxy.GetBoundingSphere(); const bool bCameraInsideLightGeometry = ((FVector)View.ViewMatrices.ViewOrigin - LightBounds.Center).SizeSquared() < FMath::Square(LightBounds.W * 1.05f + View.NearClippingDistance * 2.0f); if (!bCameraInsideLightGeometry) { const FRenderQueryRHIRef ShadowOcclusionQuery = ViewState->OcclusionQueryPool.AllocateQuery(); RHICmdList.BeginRenderQuery(ShadowOcclusionQuery); FSceneViewState::FProjectedShadowKey Key(ProjectedShadowInfo); checkSlow(ShadowOcclusionQueryMap.Find(Key) == NULL); ShadowOcclusionQueryMap.Add(Key, ShadowOcclusionQuery); // Draw bounding sphere VertexShader->SetParametersWithBoundingSphere(RHICmdList, View, LightBounds); StencilingGeometry::DrawVectorSphere(RHICmdList); RHICmdList.EndRenderQuery(ShadowOcclusionQuery); } } // Don't query preshadows, since they are culled if their subject is occluded. // Don't query if any subjects are visible because the shadow frustum will be definitely unoccluded else if (!ProjectedShadowInfo.IsWholeSceneDirectionalShadow() && !ProjectedShadowInfo.bPreShadow && !ProjectedShadowInfo.SubjectsVisible(View)) { IssueProjectedShadowOcclusionQuery(RHICmdList, View, ProjectedShadowInfo, *VertexShader, NumBufferedFrames); } } // Issue occlusion queries for all per-object projected shadows that we would have rendered but were occluded last frame. for (int32 ShadowIndex = 0; ShadowIndex < VisibleLightInfo.OccludedPerObjectShadows.Num(); ShadowIndex++) { const FProjectedShadowInfo& ProjectedShadowInfo = *VisibleLightInfo.OccludedPerObjectShadows[ShadowIndex]; IssueProjectedShadowOcclusionQuery(RHICmdList, View, ProjectedShadowInfo, *VertexShader, NumBufferedFrames); } } } // Don't do primitive occlusion if we have a view parent or are frozen. #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (!ViewState->HasViewParent() && !ViewState->bIsFrozen) #endif { VertexShader->SetParameters(RHICmdList, View); { SCOPED_DRAW_EVENT(RHICmdList, IndividualQueries); View.IndividualOcclusionQueries.Flush(RHICmdList); } { SCOPED_DRAW_EVENT(RHICmdList, GroupedQueries); View.GroupedOcclusionQueries.Flush(RHICmdList); } } } } RHICmdList.EndOcclusionQueryBatch(); } if (bUseDownsampledDepth) { // Restore default render target SceneContext.BeginRenderingSceneColor(RHICmdList, ESimpleRenderTargetMode::EUninitializedColorExistingDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } }