virtual void ReleaseRHI() override { DEC_DWORD_STAT_BY( STAT_TextureMemory, TextureSize ); DEC_DWORD_STAT_FNAME_BY( LODGroupStatName, TextureSize ); RHIUpdateTextureReference(Owner->TextureReference.TextureReferenceRHI,FTextureRHIParamRef()); TextureCubeRHI.SafeRelease(); FTextureResource::ReleaseRHI(); }
void FMediaTextureResource::ReleaseDynamicRHI() { // release the FTexture RHI resources here as well ReleaseRHI(); RHIUpdateTextureReference(Owner->TextureReference.TextureReferenceRHI, FTextureRHIParamRef()); Texture2DRHI.SafeRelease(); RenderTargetTextureRHI.SafeRelease(); // remove from global list of deferred updates RemoveFromDeferredUpdateList(); }
void FRCPassPostProcessDOFSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, DOFSetup); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } uint32 NumRenderTargets = bNearBlurEnabled ? 2 : 1; const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); const auto FeatureLevel = Context.GetFeatureLevel(); auto ShaderMap = Context.GetShaderMap(); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect / 2; const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem& DestRenderTarget1 = bNearBlurEnabled ? PassOutputs[1].RequestSurface(Context) : FSceneRenderTargetItem(); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[2] = { DestRenderTarget0.TargetableTexture, DestRenderTarget1.TargetableTexture }; SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, FTextureRHIParamRef(), 0, NULL); FLinearColor ClearColors[2] = { FLinearColor(0, 0, 0, 0), FLinearColor(0, 0, 0, 0) }; // is optimized away if possible (RT size=view size, ) Context.RHICmdList.ClearMRT(true, NumRenderTargets, ClearColors, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(ShaderMap); if (bNearBlurEnabled) { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<1> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } else { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<0> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } VertexShader->SetParameters(Context); DrawPostProcessPass( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width() + 1, DestRect.Height() + 1, SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width() + 1, SrcRect.Height() + 1, DestSize, SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams()); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams()); }
void UnbindBuffers(FRHICommandList& RHICmdList) { // TODO: Is this necessary here? FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); #if LPV_VOLUME_TEXTURE for ( int i=0; i<7; i++ ) { if ( LpvBufferSRVParameters[i].IsBound() ) { RHICmdList.SetShaderTexture(ShaderRHI, LpvBufferSRVParameters[i].GetBaseIndex(), FTextureRHIParamRef()); } } #else if ( InLpvBuffer.IsBound() ) RHICmdList.SetShaderResourceViewParameter( ShaderRHI, InLpvBuffer.GetBaseIndex(), FShaderResourceViewRHIParamRef() ); #endif #if LPV_GV_VOLUME_TEXTURE for ( int i=0; i<3; i++ ) { if ( GvBufferSRVParameters[i].IsBound() ) { RHICmdList.SetShaderTexture(ShaderRHI, GvBufferSRVParameters[i].GetBaseIndex(), FTextureRHIParamRef()); } } #else if ( InGvBuffer.IsBound() ) RHICmdList.SetShaderResourceViewParameter( ShaderRHI, InGvBuffer.GetBaseIndex(), FShaderResourceViewRHIParamRef() ); #endif }
/** Called when the resource is released. This is only called by the rendering thread. */ void FTexture2DDynamicResource::ReleaseRHI() { RHIUpdateTextureReference(Owner->TextureReference.TextureReferenceRHI,FTextureRHIParamRef()); FTextureResource::ReleaseRHI(); Texture2DRHI.SafeRelease(); }
checkSlow( RenderTargetResource ); TArray< TSharedPtr<FSlateWindowElementList> >& WindowsToDraw = WindowDrawBuffer.GetWindowElementLists(); // Enqueue a command to unlock the draw buffer after all windows have been drawn ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(SlateBeginDrawingWindowsCommand, FSlateRHIRenderingPolicy&, Policy, *RenderTargetPolicy, { Policy.BeginDrawingWindows(); }); // Set render target and clear. FTexture2DRHIRef RTResource = RenderTargetResource->GetTextureRHI(); FRHIRenderTargetView ColorRTV(RTResource); ColorRTV.LoadAction = ERenderTargetLoadAction::EClear; FRHISetRenderTargetsInfo Info(1, &ColorRTV, FTextureRHIParamRef()); Info.bClearColor = bInClearTarget; InRHICmdList.TransitionResource(EResourceTransitionAccess::EWritable, RTResource); InRHICmdList.SetRenderTargetsAndClear(Info); for ( int32 WindowIndex = 0; WindowIndex < WindowsToDraw.Num(); WindowIndex++ ) { FSlateWindowElementList& WindowElementList = *WindowsToDraw[WindowIndex].Get(); FSlateBatchData& BatchData = WindowElementList.GetBatchData(); FElementBatchMap& RootBatchMap = WindowElementList.GetRootDrawLayer().GetElementBatchMap(); WindowElementList.PreDraw_ParallelThread(); BatchData.CreateRenderBatches(RootBatchMap);
void FRCPassPostProcessMotionBlurSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(MotionBlurSetup, DEC_SCENE_ITEMS); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; // Viewport size not even also causes issue FIntRect DestRect = FIntRect::DivideAndRoundUp(SrcRect, 2); const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem& DestRenderTarget1 = PassOutputs[1].RequestSurface(Context); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[] = { DestRenderTarget0.TargetableTexture, DestRenderTarget1.TargetableTexture }; RHISetRenderTargets( ARRAY_COUNT(RenderTargets), RenderTargets, FTextureRHIParamRef(), 0, NULL ); // is optimized away if possible (RT size=view size, ) FLinearColor ClearColors[2] = {FLinearColor(0,0,0,0), FLinearColor(0,0,0,0)}; RHIClearMRT(true, 2, ClearColors, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); { TShaderMapRef<FPostProcessVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FPostProcessMotionBlurSetupPS > PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); VertexShader->SetParameters(Context); } // Draw a quad mapping scene color to the view's render target DrawRectangle( DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, EDRF_UseTriangleOptimization); RHICopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams()); RHICopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessMaterial::Process(FRenderingCompositePassContext& Context) { FMaterialRenderProxy* Proxy = MaterialInterface->GetRenderProxy(false); check(Proxy); const FMaterial* Material = Proxy->GetMaterial(Context.View.GetFeatureLevel()); check(Material); SCOPED_DRAW_EVENTF(Context.RHICmdList, PostProcessMaterial, TEXT("PostProcessMaterial Material=%s"), *Material->GetFriendlyName()); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); // hacky cast FRenderingCompositePassContext RenderingCompositePassContext(Context.RHICmdList, (FViewInfo&)View); RenderingCompositePassContext.Pass = this; FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; FIntPoint SrcSize = InputDesc->Extent; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIParamRef()); if( ViewFamily.RenderTarget->GetRenderTargetTexture() != DestRenderTarget.TargetableTexture ) { Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, View.ViewRect); } Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); float ScaleX = 1.0f / InputDesc->Extent.X; float ScaleY = 1.0f / InputDesc->Extent.Y; const FMaterialShaderMap* MaterialShaderMap = Material->GetRenderingThreadShaderMap(); FPostProcessMaterialPS* PixelShader = MaterialShaderMap->GetShader<FPostProcessMaterialPS>(); FPostProcessMaterialVS* VertexShader = MaterialShaderMap->GetShader<FPostProcessMaterialVS>(); Context.RHICmdList.SetLocalBoundShaderState(Context.RHICmdList.BuildLocalBoundShaderState(GetVertexDeclarationFVector4(), VertexShader->GetVertexShader(), FHullShaderRHIRef(), FDomainShaderRHIRef(), PixelShader->GetPixelShader(), FGeometryShaderRHIRef())); VertexShader->SetParameters(Context.RHICmdList, Context); PixelShader->SetParameters(Context.RHICmdList, Context, MaterialInterface->GetRenderProxy(false)); DrawRectangle( Context.RHICmdList, 0, 0, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), SrcSize, VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); if(Material->NeedsGBuffer()) { GSceneRenderTargets.AdjustGBufferRefCount(-1); } }
void FRCPassPostProcessSelectionOutlineColor::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSelectionOutlineBuffer); const FPooledRenderTargetDesc* SceneColorInputDesc = GetInputDesc(ePId_Input0); if(!SceneColorInputDesc) { // input is not hooked up correctly return; } const FViewInfo& View = Context.View; FIntRect ViewRect = View.ViewRect; FIntPoint SrcSize = SceneColorInputDesc->Extent; // Get the output render target const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the render target/viewport. SetRenderTarget(Context.RHICmdList, FTextureRHIParamRef(), DestRenderTarget.TargetableTexture); // This is a reversed Z depth surface, so 0.0f is the far plane. Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); Context.SetViewportAndCallRHI(ViewRect); if (View.Family->EngineShowFlags.Selection) { FHitProxyDrawingPolicyFactory::ContextType FactoryContext; //@todo - use memstack TMap<FName, int32> ActorNameToStencilIndex; TMap<const FPrimitiveSceneProxy*, int32> IndividuallySelectedProxies; ActorNameToStencilIndex.Add(NAME_BSP, 1); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetBlendState(TStaticBlendStateWriteMask<CW_NONE, CW_NONE, CW_NONE, CW_NONE>::GetRHI()); for (int32 MeshBatchIndex = 0; MeshBatchIndex < View.DynamicMeshElements.Num(); MeshBatchIndex++) { const FMeshBatchAndRelevance& MeshBatchAndRelevance = View.DynamicMeshElements[MeshBatchIndex]; const FPrimitiveSceneProxy* PrimitiveSceneProxy = MeshBatchAndRelevance.PrimitiveSceneProxy; #if WITH_EDITOR // Selected actors should be subdued if any component is individually selected bool bActorSelectionColorIsSubdued = View.bHasSelectedComponents; #else bool bActorSelectionColorIsSubdued = false; #endif if (PrimitiveSceneProxy->IsSelected() && MeshBatchAndRelevance.Mesh->bUseSelectionOutline) { const int32* AssignedStencilIndexPtr = PrimitiveSceneProxy->IsIndividuallySelected() ? IndividuallySelectedProxies.Find( PrimitiveSceneProxy ) : ActorNameToStencilIndex.Find(PrimitiveSceneProxy->GetOwnerName()); if (!AssignedStencilIndexPtr) { if( PrimitiveSceneProxy->IsIndividuallySelected() ) { // Any component that is individually selected should have a stencil value of < 128 so that it can have a unique color. We offset the value by 2 because 0 means no selection and 1 is for bsp int32 StencilValue = IndividuallySelectedProxies.Num() % 126 + 2; AssignedStencilIndexPtr = &IndividuallySelectedProxies.Add(PrimitiveSceneProxy, StencilValue); } else { // If we are subduing actor color highlight then use the top level bits to indicate that to the shader. int32 StencilValue = bActorSelectionColorIsSubdued ? ActorNameToStencilIndex.Num() % 128 + 128 : ActorNameToStencilIndex.Num() % 126 + 2; AssignedStencilIndexPtr = &ActorNameToStencilIndex.Add(PrimitiveSceneProxy->GetOwnerName(), StencilValue); } } // Note that the stencil value will overflow with enough selected objects Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_DepthNearOrEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), *AssignedStencilIndexPtr); const FMeshBatch& MeshBatch = *MeshBatchAndRelevance.Mesh; FHitProxyDrawingPolicyFactory::DrawDynamicMesh(Context.RHICmdList, View, FactoryContext, MeshBatch, false, true, MeshBatchAndRelevance.PrimitiveSceneProxy, MeshBatch.BatchHitProxyId); } } // to get an outline around the objects if it's partly outside of the screen { FIntRect InnerRect = ViewRect; // 1 as we have an outline that is that thick InnerRect.InflateRect(-1); // We could use Clear with InnerRect but this is just an optimization - on some hardware it might do a full clear (and we cannot disable yet) // RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, InnerRect); // so we to 4 clears - one for each border. // top Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Max.X, InnerRect.Min.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // bottom Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, InnerRect.Max.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // left Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, InnerRect.Min.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // right Context.RHICmdList.SetScissorRect(true, InnerRect.Max.X, ViewRect.Min.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); Context.RHICmdList.SetScissorRect(false, 0, 0, 0, 0); } } // Resolve to the output Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
/** * Transfers a list of curves to a texture on the GPU. All main memory allocated * for curve samples is released. * @param CurveTextureRHI - The * @param CurveTextureTargetRHI - The render target for the curve texture. * @param InPendingCurves - Curves to be stored on the GPU. */ static void InjectCurves( FRHICommandListImmediate& RHICmdList, FTexture2DRHIParamRef CurveTextureRHI, FTexture2DRHIParamRef CurveTextureTargetRHI, TArray<FCurveSamples>& InPendingCurves ) { static bool bFirstCall = true; check( IsInRenderingThread() ); SCOPED_DRAW_EVENT(RHICmdList, InjectParticleCurves); FVertexBufferRHIParamRef ScratchVertexBufferRHI = GParticleScratchVertexBuffer.VertexBufferRHI; SetRenderTarget(RHICmdList, CurveTextureTargetRHI, FTextureRHIParamRef()); RHICmdList.SetScissorRect(false, 0, 0, 0, 0); RHICmdList.SetViewport(0, 0, 0.0f, GParticleCurveTextureSizeX, GParticleCurveTextureSizeY, 1.0f); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI()); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); if (bFirstCall) { RHICmdList.Clear(true, FLinearColor::Blue, false, 0.0f, false, 0, FIntRect()); bFirstCall = false; } int32 PendingCurveCount = InPendingCurves.Num(); for ( int32 CurveIndex = 0; CurveIndex < PendingCurveCount; ++CurveIndex ) { FCurveSamples& Curve = InPendingCurves[CurveIndex]; check( Curve.Samples ); // Copy curve samples in to the scratch vertex buffer. const int32 SampleCount = Curve.TexelAllocation.Size; const int32 SampleByteCount = SampleCount * sizeof(FColor); FColor* RESTRICT DestSamples = (FColor*)RHILockVertexBuffer( ScratchVertexBufferRHI, 0, SampleByteCount, RLM_WriteOnly ); FMemory::Memcpy( DestSamples, Curve.Samples, SampleByteCount ); RHICmdList.UnlockVertexBuffer(ScratchVertexBufferRHI); FMemory::Free( Curve.Samples ); Curve.Samples = NULL; // Compute the offset in to the texture. FVector2D CurveOffset( (float)Curve.TexelAllocation.X / GParticleCurveTextureSizeX, (float)Curve.TexelAllocation.Y / GParticleCurveTextureSizeY ); // Grab shaders. TShaderMapRef<FParticleCurveInjectionVS> VertexShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); TShaderMapRef<FParticleCurveInjectionPS> PixelShader(GetGlobalShaderMap(GMaxRHIFeatureLevel)); // Bound shader state. static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState( RHICmdList, GMaxRHIFeatureLevel, BoundShaderState, GParticleCurveInjectionVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader, 0 ); VertexShader->SetParameters(RHICmdList, CurveOffset ); // Stream 0: New particles. RHICmdList.SetStreamSource( 0, ScratchVertexBufferRHI, /*Stride=*/ sizeof(FColor), /*Offset=*/ 0 ); // Stream 1: TexCoord. RHICmdList.SetStreamSource( 1, GParticleTexCoordVertexBuffer.VertexBufferRHI, /*Stride=*/ sizeof(FVector2D), /*Offset=*/ 0 ); // Inject particles. RHICmdList.DrawIndexedPrimitive( GParticleIndexBuffer.IndexBufferRHI, PT_TriangleList, /*BaseVertexIndex=*/ 0, /*MinIndex=*/ 0, /*NumVertices=*/ 4, /*StartIndex=*/ 0, /*NumPrimitives=*/ 2, /*NumInstances=*/ SampleCount ); } RHICmdList.CopyToResolveTarget(CurveTextureTargetRHI, CurveTextureRHI, /*bKeepOriginalSurface=*/ false, FResolveParams()); }
void FRCPassPostProcessSelectionOutlineColor::Process(FRenderingCompositePassContext& Context) { #if WITH_EDITOR SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSelectionOutlineBuffer); const FPooledRenderTargetDesc* SceneColorInputDesc = GetInputDesc(ePId_Input0); if(!SceneColorInputDesc) { // input is not hooked up correctly return; } const FViewInfo& View = Context.View; FIntRect ViewRect = View.ViewRect; FIntPoint SrcSize = SceneColorInputDesc->Extent; // Get the output render target const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the render target/viewport. SetRenderTarget(Context.RHICmdList, FTextureRHIParamRef(), DestRenderTarget.TargetableTexture); // This is a reversed Z depth surface, so 0.0f is the far plane. Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); Context.SetViewportAndCallRHI(ViewRect); if (View.Family->EngineShowFlags.Selection) { FHitProxyDrawingPolicyFactory::ContextType FactoryContext; Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetBlendState(TStaticBlendStateWriteMask<CW_NONE, CW_NONE, CW_NONE, CW_NONE>::GetRHI()); // Note that the stencil value will overflow with enough selected objects FEditorSelectionDrawingPolicy::ResetStencilValues(); // Run selection pass on static elements FScene* Scene = View.Family->Scene->GetRenderScene(); if(Scene) { Scene->EditorSelectionDrawList.DrawVisible(Context.RHICmdList, View, View.StaticMeshEditorSelectionMap, View.StaticMeshBatchVisibility); } for (int32 MeshBatchIndex = 0; MeshBatchIndex < View.DynamicMeshElements.Num(); MeshBatchIndex++) { const FMeshBatchAndRelevance& MeshBatchAndRelevance = View.DynamicMeshElements[MeshBatchIndex]; const FPrimitiveSceneProxy* PrimitiveSceneProxy = MeshBatchAndRelevance.PrimitiveSceneProxy; // Selected actors should be subdued if any component is individually selected bool bActorSelectionColorIsSubdued = View.bHasSelectedComponents; if (PrimitiveSceneProxy->IsSelected() && MeshBatchAndRelevance.Mesh->bUseSelectionOutline && PrimitiveSceneProxy->WantsSelectionOutline()) { int32 StencilValue = 1; if(PrimitiveSceneProxy->GetOwnerName() != NAME_BSP) { StencilValue = FEditorSelectionDrawingPolicy::GetStencilValue(View, PrimitiveSceneProxy); } // Note that the stencil value will overflow with enough selected objects Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_DepthNearOrEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), StencilValue); const FMeshBatch& MeshBatch = *MeshBatchAndRelevance.Mesh; FHitProxyDrawingPolicyFactory::DrawDynamicMesh(Context.RHICmdList, View, FactoryContext, MeshBatch, false, true, MeshBatchAndRelevance.PrimitiveSceneProxy, MeshBatch.BatchHitProxyId); } } // to get an outline around the objects if it's partly outside of the screen { FIntRect InnerRect = ViewRect; // 1 as we have an outline that is that thick InnerRect.InflateRect(-1); // We could use Clear with InnerRect but this is just an optimization - on some hardware it might do a full clear (and we cannot disable yet) // RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, InnerRect); // so we to 4 clears - one for each border. // top Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Max.X, InnerRect.Min.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // bottom Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, InnerRect.Max.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // left Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, InnerRect.Min.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // right Context.RHICmdList.SetScissorRect(true, InnerRect.Max.X, ViewRect.Min.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); Context.RHICmdList.SetScissorRect(false, 0, 0, 0, 0); } } // Resolve to the output Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); #endif }
void FRCPassPostProcessSelectionOutlineColor::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSelectionOutlineBuffer, DEC_SCENE_ITEMS); const FPooledRenderTargetDesc* SceneColorInputDesc = GetInputDesc(ePId_Input0); if(!SceneColorInputDesc) { // input is not hooked up correctly return; } const FViewInfo& View = Context.View; FIntRect ViewRect = View.ViewRect; FIntPoint SrcSize = SceneColorInputDesc->Extent; // Get the output render target const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the render target/viewport. SetRenderTarget(Context.RHICmdList, FTextureRHIParamRef(), DestRenderTarget.TargetableTexture); // This is a reversed Z depth surface, so 0.0f is the far plane. Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); Context.SetViewportAndCallRHI(ViewRect); if (View.Family->EngineShowFlags.Selection) { const bool bUseGetMeshElements = ShouldUseGetDynamicMeshElements(); if (bUseGetMeshElements) { FHitProxyDrawingPolicyFactory::ContextType FactoryContext; //@todo - use memstack TMap<FName, int32> ActorNameToStencilIndex; ActorNameToStencilIndex.Add(NAME_BSP, 1); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetBlendState(TStaticBlendStateWriteMask<CW_NONE, CW_NONE, CW_NONE, CW_NONE>::GetRHI()); for (int32 MeshBatchIndex = 0; MeshBatchIndex < View.DynamicMeshElements.Num(); MeshBatchIndex++) { const FMeshBatchAndRelevance& MeshBatchAndRelevance = View.DynamicMeshElements[MeshBatchIndex]; const FPrimitiveSceneProxy* PrimitiveSceneProxy = MeshBatchAndRelevance.PrimitiveSceneProxy; if (PrimitiveSceneProxy->IsSelected() && MeshBatchAndRelevance.Mesh->bUseSelectionOutline) { const int32* AssignedStencilIndexPtr = ActorNameToStencilIndex.Find(PrimitiveSceneProxy->GetOwnerName()); if (!AssignedStencilIndexPtr) { AssignedStencilIndexPtr = &ActorNameToStencilIndex.Add(PrimitiveSceneProxy->GetOwnerName(), ActorNameToStencilIndex.Num() + 1); } // This is a reversed Z depth surface, using CF_GreaterEqual. // Note that the stencil value will overflow with enough selected objects Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), *AssignedStencilIndexPtr); const FMeshBatch& MeshBatch = *MeshBatchAndRelevance.Mesh; FHitProxyDrawingPolicyFactory::DrawDynamicMesh(Context.RHICmdList, View, FactoryContext, MeshBatch, false, true, MeshBatchAndRelevance.PrimitiveSceneProxy, MeshBatch.BatchHitProxyId); } } } else if (View.VisibleDynamicPrimitives.Num() > 0) { TDynamicPrimitiveDrawer<FHitProxyDrawingPolicyFactory> Drawer(Context.RHICmdList, &View, FHitProxyDrawingPolicyFactory::ContextType(), true, false, false, true); TMultiMap<FName, const FPrimitiveSceneInfo*> PrimitivesByActor; for (int32 PrimitiveIndex = 0; PrimitiveIndex < View.VisibleDynamicPrimitives.Num();PrimitiveIndex++) { const FPrimitiveSceneInfo* PrimitiveSceneInfo = View.VisibleDynamicPrimitives[PrimitiveIndex]; // Only draw the primitive if relevant if(PrimitiveSceneInfo->Proxy->IsSelected()) { PrimitivesByActor.Add(PrimitiveSceneInfo->Proxy->GetOwnerName(), PrimitiveSceneInfo); } } if (PrimitivesByActor.Num()) { // 0 means no object, 1 means BSP so we start with 2 uint32 StencilValue = 2; Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetBlendState(TStaticBlendStateWriteMask<CW_NONE, CW_NONE, CW_NONE, CW_NONE>::GetRHI()); // Sort by actor TArray<FName> Actors; PrimitivesByActor.GetKeys(Actors); for( TArray<FName>::TConstIterator ActorIt(Actors); ActorIt; ++ActorIt ) { bool bBSP = *ActorIt == NAME_BSP; if (bBSP) { // This is a reversed Z depth surface, using CF_GreaterEqual. Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), 1); } else { // This is a reversed Z depth surface, using CF_GreaterEqual. Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), StencilValue); // we want to use 1..255 for all objects, not correct silhouettes after that is acceptable StencilValue = (StencilValue == 255) ? 2 : (StencilValue + 1); } TArray<const FPrimitiveSceneInfo*> Primitives; PrimitivesByActor.MultiFind(*ActorIt, Primitives); for( TArray<const FPrimitiveSceneInfo*>::TConstIterator PrimIt(Primitives); PrimIt; ++PrimIt ) { const FPrimitiveSceneInfo* PrimitiveSceneInfo = *PrimIt; // Render the object to the stencil/depth buffer Drawer.SetPrimitive(PrimitiveSceneInfo->Proxy); PrimitiveSceneInfo->Proxy->DrawDynamicElements(&Drawer, &View); } } } } // to get an outline around the objects if it's partly outside of the screen { FIntRect InnerRect = ViewRect; // 1 as we have an outline that is that thick InnerRect.InflateRect(-1); // We could use Clear with InnerRect but this is just an optimization - on some hardware it might do a full clear (and we cannot disable yet) // RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, InnerRect); // so we to 4 clears - one for each border. // top Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Max.X, InnerRect.Min.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); // bottom Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, InnerRect.Max.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); // left Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, InnerRect.Min.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); // right Context.RHICmdList.SetScissorRect(true, InnerRect.Max.X, ViewRect.Min.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); Context.RHICmdList.SetScissorRect(false, 0, 0, 0, 0); } } // Resolve to the output Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessDeferredDecals::Process(FRenderingCompositePassContext& Context) { FRHICommandListImmediate& RHICmdList = Context.RHICmdList; const bool bShaderComplexity = Context.View.Family->EngineShowFlags.ShaderComplexity; const bool bDBuffer = IsDBufferEnabled(); const bool bStencilSizeThreshold = CVarStencilSizeThreshold.GetValueOnRenderThread() >= 0; SCOPED_DRAW_EVENT(RHICmdList, PostProcessDeferredDecals); if(RenderStage == 0) { // before BasePass, only if DBuffer is enabled check(bDBuffer); // DBuffer: Decal buffer FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(GSceneRenderTargets.GBufferA->GetDesc().Extent, PF_B8G8R8A8, TexCreate_None, TexCreate_ShaderResource | TexCreate_RenderTargetable, false)); if(!GSceneRenderTargets.DBufferA) { GRenderTargetPool.FindFreeElement(Desc, GSceneRenderTargets.DBufferA, TEXT("DBufferA")); } if(!GSceneRenderTargets.DBufferB) { GRenderTargetPool.FindFreeElement(Desc, GSceneRenderTargets.DBufferB, TEXT("DBufferB")); } Desc.Format = PF_R8G8; if(!GSceneRenderTargets.DBufferC) { GRenderTargetPool.FindFreeElement(Desc, GSceneRenderTargets.DBufferC, TEXT("DBufferC")); } // we assume views are non overlapping, then we need to clear only once in the beginning, otherwise we would need to set scissor rects // and don't get FastClear any more. bool bFirstView = Context.View.Family->Views[0] == &Context.View; if(bFirstView) { SCOPED_DRAW_EVENT(RHICmdList, DBufferClear); // could be optimized SetRenderTarget(RHICmdList, GSceneRenderTargets.DBufferA->GetRenderTargetItem().TargetableTexture, FTextureRHIParamRef()); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); SetRenderTarget(RHICmdList, GSceneRenderTargets.DBufferB->GetRenderTargetItem().TargetableTexture, FTextureRHIParamRef()); // todo: some hardware would like to have 0 or 1 for faster clear, we chose 128/255 to represent 0 (8 bit cannot represent 0.5f) RHICmdList.Clear(true, FLinearColor(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); SetRenderTarget(RHICmdList, GSceneRenderTargets.DBufferC->GetRenderTargetItem().TargetableTexture, FTextureRHIParamRef()); // R:roughness, G:roughness opacity RHICmdList.Clear(true, FLinearColor(0, 1, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); } } // this cast is safe as only the dedicated server implements this differently and this pass should not be executed on the dedicated server const FViewInfo& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FScene& Scene = *(FScene*)ViewFamily.Scene; if(!Scene.Decals.Num()) { // to avoid the stats showing up return; } TArray<FTransientDecalRenderData, SceneRenderingAllocator> SortedDecals; SortedDecals.Empty(Scene.Decals.Num()); // Build a list of decals that need to be rendered for this view in SortedDecals for (TSparseArray<FDeferredDecalProxy*>::TConstIterator It(Scene.Decals); It; ++It) { FDeferredDecalProxy* DecalProxy = *It; bool bIsShown = true; // Handle the decal actor having bHidden set when we are in the editor, in G mode #if WITH_EDITOR if (View.Family->EngineShowFlags.Editor) #endif { if (!DecalProxy->DrawInGame) { bIsShown = false; } } const FMatrix ComponentToWorldMatrix = DecalProxy->ComponentTrans.ToMatrixWithScale(); // can be optimized as we test against a sphere around the box instead of the box itself const float ConservativeRadius = FMath::Sqrt( ComponentToWorldMatrix.GetScaledAxis( EAxis::X ).SizeSquared() * FMath::Square(GDefaultDecalSize.X) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Y ).SizeSquared() * FMath::Square(GDefaultDecalSize.Y) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Z ).SizeSquared() * FMath::Square(GDefaultDecalSize.Z)); // can be optimized as the test is too conservative (sphere instead of OBB) if(ConservativeRadius < SMALL_NUMBER || !View.ViewFrustum.IntersectSphere(ComponentToWorldMatrix.GetOrigin(), ConservativeRadius)) { bIsShown = false; } if (bIsShown) { FTransientDecalRenderData Data(Scene, DecalProxy); uint32 DecalRenderStage = ComputeRenderStage(Data.DecalBlendMode); // we could do this test earlier to avoid the decal intersection but getting DecalBlendMode also costs if (Context.View.Family->EngineShowFlags.ShaderComplexity || RenderStage == DecalRenderStage) { SortedDecals.Add(Data); } } } if(SortedDecals.Num() > 0) { FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; bool bStencilDecals = true; #if DBUFFER_DONT_USE_STENCIL_YET if(RenderStage == 0) { bStencilDecals = false; } #endif // Setup a stencil mask to prevent certain pixels from receiving deferred decals if(bStencilDecals) { StencilDecalMask(RHICmdList, View); } // Sort by sort order to allow control over composited result // Then sort decals by state to reduce render target switches // Also sort by component since Sort() is not stable struct FCompareFTransientDecalRenderData { FORCEINLINE bool operator()( const FTransientDecalRenderData& A, const FTransientDecalRenderData& B ) const { if (B.DecalProxy->SortOrder != A.DecalProxy->SortOrder) { return A.DecalProxy->SortOrder < B.DecalProxy->SortOrder; } if (B.DecalBlendMode != A.DecalBlendMode) { return (int32)B.DecalBlendMode < (int32)A.DecalBlendMode; } if (B.bHasNormal != A.bHasNormal) { return B.bHasNormal < A.bHasNormal; } // Batch decals with the same material together if (B.MaterialProxy != A.MaterialProxy ) { return B.MaterialProxy < A.MaterialProxy; } return (PTRINT)B.DecalProxy->Component < (PTRINT)A.DecalProxy->Component; } }; // Sort decals by blend mode to reduce render target switches SortedDecals.Sort( FCompareFTransientDecalRenderData() ); // optimization to have less state changes int32 LastDecalBlendMode = -1; int32 LastDecalHasNormal = -1; // Decal state can change based on its normal property.(SM5) ERenderTargetMode LastRenderTargetMode = RTM_Unknown; int32 WasInsideDecal = -1; const ERHIFeatureLevel::Type SMFeatureLevel = Context.GetFeatureLevel(); SCOPED_DRAW_EVENT(RHICmdList, Decals); INC_DWORD_STAT_BY(STAT_Decals, SortedDecals.Num()); enum EDecalResolveBufferIndex { SceneColorIndex, GBufferAIndex, GBufferBIndex, GBufferCIndex, DBufferAIndex, DBufferBIndex, DBufferCIndex, ResolveBufferMax, }; FTextureRHIParamRef TargetsToResolve[ResolveBufferMax] = { nullptr }; for (int32 DecalIndex = 0, DecalCount = SortedDecals.Num(); DecalIndex < DecalCount; DecalIndex++) { const FTransientDecalRenderData& DecalData = SortedDecals[DecalIndex]; const FDeferredDecalProxy& DecalProxy = *DecalData.DecalProxy; const FMatrix ComponentToWorldMatrix = DecalProxy.ComponentTrans.ToMatrixWithScale(); // Set vertex shader params const FMaterialShaderMap* MaterialShaderMap = DecalData.MaterialResource->GetRenderingThreadShaderMap(); FScaleMatrix DecalScaleTransform(GDefaultDecalSize); FTranslationMatrix PreViewTranslation(View.ViewMatrices.PreViewTranslation); FMatrix FrustumComponentToClip = DecalScaleTransform * ComponentToWorldMatrix * PreViewTranslation * View.ViewMatrices.TranslatedViewProjectionMatrix; // can be optimized as we test against a sphere around the box instead of the box itself const float ConservativeRadius = FMath::Sqrt( ComponentToWorldMatrix.GetScaledAxis( EAxis::X ).SizeSquared() * FMath::Square(GDefaultDecalSize.X) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Y ).SizeSquared() * FMath::Square(GDefaultDecalSize.Y) + ComponentToWorldMatrix.GetScaledAxis( EAxis::Z ).SizeSquared() * FMath::Square(GDefaultDecalSize.Z)); EDecalBlendMode DecalBlendMode = DecalData.DecalBlendMode; bool bStencilThisDecal = bStencilDecals; #if DBUFFER_DONT_USE_STENCIL_YET if(ComputeRenderStage(DecalBlendMode) == 0) { bStencilThisDecal = false; } #endif ERenderTargetMode CurrentRenderTargetMode = ComputeRenderTargetMode(DecalBlendMode); if(bShaderComplexity) { CurrentRenderTargetMode = RTM_SceneColor; // we want additive blending for the ShaderComplexity mode DecalBlendMode = DBM_Emissive; } // fewer rendertarget switches if possible if(CurrentRenderTargetMode != LastRenderTargetMode) { LastRenderTargetMode = CurrentRenderTargetMode; switch(CurrentRenderTargetMode) { case RTM_SceneColorAndGBuffer: { TargetsToResolve[SceneColorIndex] = GSceneRenderTargets.GetSceneColor()->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferAIndex] = GSceneRenderTargets.GBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferBIndex] = GSceneRenderTargets.GBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[GBufferCIndex] = GSceneRenderTargets.GBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 4, TargetsToResolve, GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; case RTM_GBufferNormal: TargetsToResolve[GBufferAIndex] = GSceneRenderTargets.GBufferA->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[GBufferAIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case RTM_SceneColor: TargetsToResolve[SceneColorIndex] = GSceneRenderTargets.GetSceneColor()->GetRenderTargetItem().TargetableTexture; SetRenderTarget(RHICmdList, TargetsToResolve[SceneColorIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); break; case RTM_DBuffer: { TargetsToResolve[DBufferAIndex] = GSceneRenderTargets.DBufferA->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferBIndex] = GSceneRenderTargets.DBufferB->GetRenderTargetItem().TargetableTexture; TargetsToResolve[DBufferCIndex] = GSceneRenderTargets.DBufferC->GetRenderTargetItem().TargetableTexture; SetRenderTargets(RHICmdList, 3, &TargetsToResolve[DBufferAIndex], GSceneRenderTargets.GetSceneDepthSurface(), ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilWrite); } break; default: check(0); break; } Context.SetViewportAndCallRHI(DestRect); // we need to reset the stream source after any call to SetRenderTarget (at least for Metal, which doesn't queue up VB assignments) RHICmdList.SetStreamSource(0, GUnitCubeVertexBuffer.VertexBufferRHI, sizeof(FVector4), 0); } bool bThisDecalUsesStencil = false; if (bStencilThisDecal) { if (bStencilSizeThreshold) { // note this is after a SetStreamSource (in if CurrentRenderTargetMode != LastRenderTargetMode) call as it needs to get the VB input bThisDecalUsesStencil = RenderPreStencil(Context, MaterialShaderMap, ComponentToWorldMatrix, FrustumComponentToClip); WasInsideDecal = -1; LastDecalBlendMode = -1; } } const bool bBlendStateChange = DecalBlendMode != LastDecalBlendMode;// Has decal mode changed. const bool bDecalNormalChanged = GSupportsSeparateRenderTargetBlendState && // has normal changed for SM5 stain/translucent decals? (DecalBlendMode == DBM_Translucent || DecalBlendMode == DBM_Stain) && (int32)DecalData.bHasNormal != LastDecalHasNormal; // fewer blend state changes if possible if (bBlendStateChange || bDecalNormalChanged) { LastDecalBlendMode = DecalBlendMode; LastDecalHasNormal = (int32)DecalData.bHasNormal; SetDecalBlendState(RHICmdList, SMFeatureLevel, RenderStage, (EDecalBlendMode)LastDecalBlendMode, DecalData.bHasNormal); } { TShaderMapRef<FDeferredDecalVS> VertexShader(Context.GetShaderMap()); SetShader(Context, bShaderComplexity, DecalData, *VertexShader); VertexShader->SetParameters(RHICmdList, View, FrustumComponentToClip); const int32 IsInsideDecal = ((FVector)View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).SizeSquared() < FMath::Square(ConservativeRadius * 1.05f + View.NearClippingDistance * 2.0f) + ( bThisDecalUsesStencil ) ? 2 : 0; if ( WasInsideDecal != IsInsideDecal ) { WasInsideDecal = IsInsideDecal; if ( !(IsInsideDecal & 1) ) { // Render backfaces with depth tests disabled since the camera is inside (or close to inside) the light function geometry RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI()); if(bStencilDecals) { // Enable stencil testing, only write to pixels with stencil of 0 if ( bThisDecalUsesStencil ) { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_Always, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, 0xff, 0x7f >::GetRHI(), 1); } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_Always, true,CF_Equal,SO_Keep,SO_Keep,SO_Keep, false,CF_Always,SO_Keep,SO_Keep,SO_Keep, 0x80,0x00>::GetRHI(), 0); } } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always, true>::GetRHI(), 0); } } else { // Render frontfaces with depth tests on to get the speedup from HiZ since the camera is outside the light function geometry if(bStencilDecals) { // Render frontfaces with depth tests on to get the speedup from HiZ since the camera is outside the light function geometry // Enable stencil testing, only write to pixels with stencil of 0 if ( bThisDecalUsesStencil ) { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_DepthNearOrEqual, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, true,CF_Equal,SO_Zero,SO_Zero,SO_Zero, 0xff, 0x7f >::GetRHI(), 1); } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false,CF_DepthNearOrEqual, true,CF_Equal,SO_Keep,SO_Keep,SO_Keep, false,CF_Always,SO_Keep,SO_Keep,SO_Keep, 0x80,0x00>::GetRHI(), 0); } RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI()); } else { RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_DepthNearOrEqual>::GetRHI(), 0); } RHICmdList.SetRasterizerState(View.bReverseCulling ? TStaticRasterizerState<FM_Solid, CM_CW>::GetRHI() : TStaticRasterizerState<FM_Solid, CM_CCW>::GetRHI()); } } RHICmdList.DrawIndexedPrimitive(GUnitCubeIndexBuffer.IndexBufferRHI, PT_TriangleList, 0, 0, 8, 0, GUnitCubeIndexBuffer.GetIndexCount() / 3, 1); } } // we don't modify stencil but if out input was having stencil for us (after base pass - we need to clear) // Clear stencil to 0, which is the assumed default by other passes RHICmdList.Clear(false, FLinearColor::White, false, (float)ERHIZBuffer::FarPlane, true, 0, FIntRect()); // resolve the targets we wrote to. FResolveParams ResolveParams; for (int32 i = 0; i < ResolveBufferMax; ++i) { if (TargetsToResolve[i]) { RHICmdList.CopyToResolveTarget(TargetsToResolve[i], TargetsToResolve[i], true, ResolveParams); } } } if(RenderStage == 0) { // before BasePass GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, GSceneRenderTargets.DBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, GSceneRenderTargets.DBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, GSceneRenderTargets.DBufferC); } }