bool IsIndirectLightingCacheAllowed(ERHIFeatureLevel::Type InFeatureLevel) { static const auto AllowStaticLightingVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AllowStaticLighting")); const bool bAllowStaticLighting = (!AllowStaticLightingVar || AllowStaticLightingVar->GetValueOnRenderThread() != 0); return GIndirectLightingCache != 0 && bAllowStaticLighting; }
void SetPS(const FRenderingCompositePassContext& Context) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(ShaderRHI, Context.View); PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI()); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.GPUBusyWait")); uint32 PixelCount = Context.View.ViewRect.Size().X * Context.View.ViewRect.Size().Y; float CVarValue = FMath::Clamp(CVar->GetValueOnRenderThread(), 0.0f, 500.0f); // multiply with large number to get more human friendly number range // calibrated on a NV580 to be roughly a millisecond // divide by viewport pixel count uint32 Value = (uint32)(CVarValue * 1000000000.0 / 6.12 / PixelCount); SetShaderValue(ShaderRHI, GPUBusyWait, Value); } #endif }
float GetSubsurfaceRadiusScale() { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.SSS.Scale")); check(CVar); float Ret = CVar->GetValueOnRenderThread(); return FMath::Max(0.0f, Ret); }
int32 GetMotionBlurQualityFromCVar() { int32 MotionBlurQuality; static const auto ICVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MotionBlurQuality")); MotionBlurQuality = FMath::Clamp(ICVar->GetValueOnRenderThread(), 0, 4); return MotionBlurQuality; }
static bool IsPoolingEnabled() { if (GRHIThread && IsInRenderingThread() && GRHICommandList.IsRHIThreadActive()) { return false; // we can't currently use pooling if the RHI thread is active. } static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.UniformBufferPooling")); int32 CVarValue = CVar->GetValueOnRenderThread(); return CVarValue != 0; };
// Convert f-stop and focal distance into projected size in half resolution pixels. // Setup depth based blur. FVector4 CircleDofHalfCoc(const FSceneView& View) { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.DepthOfFieldQuality")); bool bDepthOfField = View.Family->EngineShowFlags.DepthOfField && CVar->GetValueOnRenderThread() > 0; FVector4 Ret(0, 1, 0, 0); if(bDepthOfField && View.FinalPostProcessSettings.DepthOfFieldMethod == DOFM_CircleDOF) { float FocalLengthInMM = ComputeFocalLengthFromFov(View); // Convert focal distance in world position to mm (from cm to mm) float FocalDistanceInMM = View.FinalPostProcessSettings.DepthOfFieldFocalDistance * 10.0f; // Convert f-stop, focal length, and focal distance to // projected circle of confusion size at infinity in mm. // // coc = f * f / (n * (d - f)) // where, // f = focal length // d = focal distance // n = fstop (where n is the "n" in "f/n") float Radius = FMath::Square(FocalLengthInMM) / (View.FinalPostProcessSettings.DepthOfFieldFstop * (FocalDistanceInMM - FocalLengthInMM)); // Convert mm to pixels. float const Width = (float)View.ViewRect.Width(); float const SensorWidth = View.FinalPostProcessSettings.DepthOfFieldSensorWidth; Radius = Radius * Width * (1.0f / SensorWidth); // Convert diameter to radius at half resolution (algorithm radius is at half resolution). Radius *= 0.25f; // Comment out for now, allowing settings which the algorithm cannot cleanly do. #if 0 // Limit to algorithm max size. if(Radius > 6.0f) { Radius = 6.0f; } #endif // The DepthOfFieldDepthBlurAmount = km at which depth blur is 50%. // Need to convert to cm here. Ret = FVector4( Radius, 1.0f / (View.FinalPostProcessSettings.DepthOfFieldDepthBlurAmount * 100000.0f), View.FinalPostProcessSettings.DepthOfFieldDepthBlurRadius * Width / 1920.0f, Width / 1920.0f); } return Ret; }
//============================================================================= void UGripMotionControllerComponent::FViewExtension::PreRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& InViewFamily) { if (!MotionControllerComponent) { return; } FScopeLock ScopeLock(&CritSect); if (MotionControllerComponent->bDisableLowLatencyUpdate || !CVarEnableMotionControllerLateUpdate->GetValueOnRenderThread()) { return; } // Poll state for the most recent controller transform FVector Position; FRotator Orientation; //bool bRenderTracked = bRenderTracked = MotionControllerComponent->PollControllerState(Position, Orientation); if (!MotionControllerComponent->PollControllerState(Position, Orientation)) { return; } if (LateUpdatePrimitives.Num()) { // Calculate the late update transform that will rebase all children proxies within the frame of reference FTransform OldLocalToWorldTransform = MotionControllerComponent->CalcNewComponentToWorld(MotionControllerComponent->GetRelativeTransform()); FTransform NewLocalToWorldTransform = MotionControllerComponent->CalcNewComponentToWorld(FTransform(Orientation, Position)); FMatrix LateUpdateTransform = (OldLocalToWorldTransform.Inverse() * NewLocalToWorldTransform).ToMatrixWithScale(); FPrimitiveSceneInfo* RetrievedSceneInfo; FPrimitiveSceneInfo* CachedSceneInfo; // Apply delta to the affected scene proxies for (auto PrimitiveInfo : LateUpdatePrimitives) { RetrievedSceneInfo = InViewFamily.Scene->GetPrimitiveSceneInfo(*PrimitiveInfo.IndexAddress); CachedSceneInfo = PrimitiveInfo.SceneInfo; // If the retrieved scene info is different than our cached scene info then the primitive was removed from the scene if (CachedSceneInfo == RetrievedSceneInfo && CachedSceneInfo->Proxy) { CachedSceneInfo->Proxy->ApplyLateUpdateTransform(LateUpdateTransform); } } LateUpdatePrimitives.Reset(); } }
void FD3D11DynamicRHI::CheckIfSRVIsResolved(ID3D11ShaderResourceView* SRV) { #if CHECK_SRV_TRANSITIONS if (GRHIThread || !SRV) { return; } static const auto CheckSRVCVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.CheckSRVTransitions")); if (!CheckSRVCVar->GetValueOnRenderThread()) { return; } ID3D11Resource* SRVResource = nullptr; SRV->GetResource(&SRVResource); int32 MipLevel; int32 NumMips; int32 ArraySlice; int32 NumSlices; GetMipAndSliceInfoFromSRV(SRV, MipLevel, NumMips, ArraySlice, NumSlices); //d3d uses -1 to mean 'all mips' int32 LastMip = MipLevel + NumMips - 1; int32 LastSlice = ArraySlice + NumSlices - 1; TArray<FUnresolvedRTInfo> RTInfoArray; UnresolvedTargets.MultiFind(SRVResource, RTInfoArray); for (int32 InfoIndex = 0; InfoIndex < RTInfoArray.Num(); ++InfoIndex) { const FUnresolvedRTInfo& RTInfo = RTInfoArray[InfoIndex]; int32 RTLastMip = RTInfo.MipLevel + RTInfo.NumMips - 1; ensureMsgf((MipLevel == -1 || NumMips == -1) || (LastMip < RTInfo.MipLevel || MipLevel > RTLastMip), TEXT("SRV is set to read mips in range %i to %i. Target %s is unresolved for mip %i"), MipLevel, LastMip, *RTInfo.ResourceName.ToString(), RTInfo.MipLevel); ensureMsgf(NumMips != -1, TEXT("SRV is set to read all mips. Target %s is unresolved for mip %i"), *RTInfo.ResourceName.ToString(), RTInfo.MipLevel); int32 RTLastSlice = RTInfo.ArraySlice + RTInfo.ArraySize - 1; ensureMsgf((ArraySlice == -1 || LastSlice == -1) || (LastSlice < RTInfo.ArraySlice || ArraySlice > RTLastSlice), TEXT("SRV is set to read slices in range %i to %i. Target %s is unresolved for mip %i"), ArraySlice, LastSlice, *RTInfo.ResourceName.ToString(), RTInfo.ArraySlice); ensureMsgf(ArraySlice == -1 || NumSlices != -1, TEXT("SRV is set to read all slices. Target %s is unresolved for slice %i")); } SRVResource->Release(); #endif }
// @return 0:off, 0..4 static uint32 ComputeAmbientOcclusionPassCount(FPostprocessContext& Context) { uint32 Ret = 0; bool bEnabled = true; if(!IsLpvIndirectPassRequired(Context)) { bEnabled = Context.View.FinalPostProcessSettings.AmbientOcclusionIntensity > 0 && Context.View.FinalPostProcessSettings.AmbientOcclusionRadius >= 0.1f && (IsBasePassAmbientOcclusionRequired(Context) || IsAmbientCubemapPassRequired(Context) || IsReflectionEnvironmentActive(Context) || IsSkylightActive(Context) || Context.View.Family->EngineShowFlags.VisualizeBuffer ) && !IsSimpleDynamicLightingEnabled(); } if(bEnabled) { static const auto ICVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AmbientOcclusionLevels")); Ret = FMath::Clamp(ICVar->GetValueOnRenderThread(), 0, 4); } return Ret; }
/** * Finishes the view family rendering. */ void FDeferredShadingSceneRenderer::RenderFinish() { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { static const auto ICVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.VisualizeTexturePool")); if(ICVar->GetValueOnRenderThread()) { RenderVisualizeTexturePool(); } } #endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST) FSceneRenderer::RenderFinish(); //grab the new transform out of the proxies for next frame if(ViewFamily.EngineShowFlags.MotionBlur) { Scene->MotionBlurInfoData.UpdateMotionBlurCache(); } }
void SetPS(const FRenderingCompositePassContext& Context) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View); DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View); const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings; const FSceneViewFamily& ViewFamily = *(Context.View.Family); FSceneViewState* ViewState = (FSceneViewState*)Context.View.State; PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI()); // PostprocessInput1MS and EditorPrimitivesStencil { FRenderingCompositeOutputRef* OutputRef = Context.Pass->GetInput(ePId_Input1); check(OutputRef); FRenderingCompositeOutput* Input = OutputRef->GetOutput(); check(Input); TRefCountPtr<IPooledRenderTarget> InputPooledElement = Input->RequestInput(); check(InputPooledElement); FTexture2DRHIRef& TargetableTexture = (FTexture2DRHIRef&)InputPooledElement->GetRenderTargetItem().TargetableTexture; SetTextureParameter(Context.RHICmdList, ShaderRHI, PostprocessInput1MS, TargetableTexture); if(EditorPrimitivesStencil.IsBound()) { // cache the stencil SRV to avoid create calls each frame (the cache element is stored in the state) if(ViewState->SelectionOutlineCacheKey != TargetableTexture) { // release if not the right one (as the internally SRV stores a pointer to the texture we cannot get a false positive) ViewState->SelectionOutlineCacheKey.SafeRelease(); ViewState->SelectionOutlineCacheValue.SafeRelease(); } if(!ViewState->SelectionOutlineCacheValue) { // create if needed ViewState->SelectionOutlineCacheKey = TargetableTexture; ViewState->SelectionOutlineCacheValue = RHICreateShaderResourceView(TargetableTexture, 0, 1, PF_X24_G8); } SetSRVParameter(Context.RHICmdList, ShaderRHI, EditorPrimitivesStencil, ViewState->SelectionOutlineCacheValue); } } #if WITH_EDITOR { FLinearColor OutlineColorValue = Context.View.SelectionOutlineColor; FLinearColor SubduedOutlineColorValue = Context.View.SubduedSelectionOutlineColor; OutlineColorValue.A = GEngine->SelectionHighlightIntensity; SetShaderValue(Context.RHICmdList, ShaderRHI, OutlineColor, OutlineColorValue); SetShaderValue(Context.RHICmdList, ShaderRHI, SubduedOutlineColor, SubduedOutlineColorValue); SetShaderValue(Context.RHICmdList, ShaderRHI, BSPSelectionIntensity, GEngine->BSPSelectionHighlightIntensity); } #else check(!"This shader is not used outside of the Editor."); #endif { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.Editor.MovingPattern")); FLinearColor Value(0, CVar->GetValueOnRenderThread(), 0, 0); if(!ViewFamily.bRealtimeUpdate) { // no animation if realtime update is disabled Value.G = 0; } SetShaderValue(Context.RHICmdList, ShaderRHI, EditorRenderParams, Value); } }
void FOpenGLDynamicRHI::RHIEndDrawingViewport(FViewportRHIParamRef ViewportRHI,bool bPresent,bool bLockToVsync) { VERIFY_GL_SCOPE(); DYNAMIC_CAST_OPENGLRESOURCE(Viewport,Viewport); SCOPE_CYCLE_COUNTER(STAT_OpenGLPresentTime); check(DrawingViewport.GetReference() == Viewport); FOpenGLTexture2D* BackBuffer = Viewport->GetBackBuffer(); uint32 IdleStart = FPlatformTime::Cycles(); PlatformBlitToViewport(PlatformDevice, Viewport->OpenGLContext, BackBuffer->GetSizeX(), BackBuffer->GetSizeY(), bPresent, bLockToVsync, RHIOpenGLConsoleVariables::SyncInterval ); DrawingViewport = NULL; // Don't wait on the GPU when using SLI, let the driver determine how many frames behind the GPU should be allowed to get if (GNumActiveGPUsForRendering == 1) { static const auto CFinishFrameVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.FinishCurrentFrame")); if (!CFinishFrameVar->GetValueOnRenderThread()) { // Wait for the GPU to finish rendering the previous frame before finishing this frame. Viewport->WaitForFrameEventCompletion(); Viewport->IssueFrameEvent(); } else { // Finish current frame immediately to reduce latency Viewport->IssueFrameEvent(); Viewport->WaitForFrameEventCompletion(); } // If the input latency timer has been triggered, block until the GPU is completely // finished displaying this frame and calculate the delta time. if ( GInputLatencyTimer.RenderThreadTrigger ) { Viewport->WaitForFrameEventCompletion(); uint32 EndTime = FPlatformTime::Cycles(); GInputLatencyTimer.DeltaTime = EndTime - GInputLatencyTimer.StartTime; GInputLatencyTimer.RenderThreadTrigger = false; } } GRenderThreadIdle[ERenderThreadIdleTypes::WaitingForGPUPresent] += FPlatformTime::Cycles() - IdleStart; if (bRevertToSharedContextAfterDrawingViewport) { PlatformSharedContextSetup(PlatformDevice); bRevertToSharedContextAfterDrawingViewport = false; } }
static FORCEINLINE bool IsWritingHDRImage(const bool bCaptureHDR) { static const auto CVarDumpFramesAsHDR = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.BufferVisualizationDumpFramesAsHDR")); return bCaptureHDR || CVarDumpFramesAsHDR->GetValueOnRenderThread(); }
void SetParameters( FRHICommandList& RHICmdList, const FSceneView& View, int32 ViewIndex, int32 NumViews, const TArray<FSortedLightSceneInfo, SceneRenderingAllocator>& SortedLights, int32 NumLightsToRenderInSortedLights, const FSimpleLightArray& SimpleLights, int32 StartIndex, int32 NumThisPass, IPooledRenderTarget& InTextureValue, IPooledRenderTarget& OutTextureValue) { FComputeShaderRHIParamRef ShaderRHI = GetComputeShader(); FGlobalShader::SetParameters(RHICmdList, ShaderRHI, View); DeferredParameters.Set(RHICmdList, ShaderRHI, View); SetTextureParameter(RHICmdList, ShaderRHI, InTexture, InTextureValue.GetRenderTargetItem().ShaderResourceTexture); FUnorderedAccessViewRHIParamRef OutUAV = OutTextureValue.GetRenderTargetItem().UAV; RHICmdList.TransitionResources(EResourceTransitionAccess::ERWBarrier, EResourceTransitionPipeline::EGfxToCompute, &OutUAV, 1); OutTexture.SetTexture(RHICmdList, ShaderRHI, 0, OutUAV); SetShaderValue(RHICmdList, ShaderRHI, ViewDimensions, View.ViewRect); SetTextureParameter( RHICmdList, ShaderRHI, PreIntegratedBRDF, PreIntegratedBRDFSampler, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), GEngine->PreIntegratedSkinBRDFTexture->Resource->TextureRHI ); static const auto AllowStaticLightingVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AllowStaticLighting")); const bool bAllowStaticLighting = (!AllowStaticLightingVar || AllowStaticLightingVar->GetValueOnRenderThread() != 0); FTiledDeferredLightData LightData; FTiledDeferredLightData2 LightData2; for (int32 LightIndex = 0; LightIndex < NumThisPass; LightIndex++) { if (StartIndex + LightIndex < NumLightsToRenderInSortedLights) { const FSortedLightSceneInfo& SortedLightInfo = SortedLights[StartIndex + LightIndex]; const FLightSceneInfoCompact& LightSceneInfoCompact = SortedLightInfo.SceneInfo; const FLightSceneInfo* const LightSceneInfo = LightSceneInfoCompact.LightSceneInfo; FVector NormalizedLightDirection; FVector2D SpotAngles; float SourceRadius; float SourceLength; float MinRoughness; // Get the light parameters LightSceneInfo->Proxy->GetParameters( LightData.LightPositionAndInvRadius[LightIndex], LightData.LightColorAndFalloffExponent[LightIndex], NormalizedLightDirection, SpotAngles, SourceRadius, SourceLength, MinRoughness); if (LightSceneInfo->Proxy->IsInverseSquared()) { // Correction for lumen units LightData.LightColorAndFalloffExponent[LightIndex].X *= 16.0f; LightData.LightColorAndFalloffExponent[LightIndex].Y *= 16.0f; LightData.LightColorAndFalloffExponent[LightIndex].Z *= 16.0f; LightData.LightColorAndFalloffExponent[LightIndex].W = 0; } // When rendering reflection captures, the direct lighting of the light is actually the indirect specular from the main view if (View.bIsReflectionCapture) { LightData.LightColorAndFalloffExponent[LightIndex].X *= LightSceneInfo->Proxy->GetIndirectLightingScale(); LightData.LightColorAndFalloffExponent[LightIndex].Y *= LightSceneInfo->Proxy->GetIndirectLightingScale(); LightData.LightColorAndFalloffExponent[LightIndex].Z *= LightSceneInfo->Proxy->GetIndirectLightingScale(); } { // SpotlightMaskAndMinRoughness, >0:Spotlight, MinRoughness = abs(); float W = FMath::Max(0.0001f, MinRoughness) * ((LightSceneInfo->Proxy->GetLightType() == LightType_Spot) ? 1 : -1); LightData2.LightDirectionAndSpotlightMaskAndMinRoughness[LightIndex] = FVector4(NormalizedLightDirection, W); } LightData2.SpotAnglesAndSourceRadiusAndSimpleLighting[LightIndex] = FVector4(SpotAngles.X, SpotAngles.Y, SourceRadius, 0); int32 ShadowMapChannel = LightSceneInfo->Proxy->GetShadowMapChannel(); if (!bAllowStaticLighting) { ShadowMapChannel = INDEX_NONE; } LightData2.ShadowMapChannelMask[LightIndex] = FVector4( ShadowMapChannel == 0 ? 1 : 0, ShadowMapChannel == 1 ? 1 : 0, ShadowMapChannel == 2 ? 1 : 0, ShadowMapChannel == 3 ? 1 : 0); } else { int32 SimpleLightIndex = StartIndex + LightIndex - NumLightsToRenderInSortedLights; const FSimpleLightEntry& SimpleLight = SimpleLights.InstanceData[SimpleLightIndex]; const FSimpleLightPerViewEntry& SimpleLightPerViewData = SimpleLights.GetViewDependentData(SimpleLightIndex, ViewIndex, NumViews); LightData.LightPositionAndInvRadius[LightIndex] = FVector4(SimpleLightPerViewData.Position, 1.0f / FMath::Max(SimpleLight.Radius, KINDA_SMALL_NUMBER)); LightData.LightColorAndFalloffExponent[LightIndex] = FVector4(SimpleLight.Color, SimpleLight.Exponent); LightData2.LightDirectionAndSpotlightMaskAndMinRoughness[LightIndex] = FVector4(FVector(1, 0, 0), 0); LightData2.SpotAnglesAndSourceRadiusAndSimpleLighting[LightIndex] = FVector4(-2, 1, 0, 1); LightData2.ShadowMapChannelMask[LightIndex] = FVector4(0, 0, 0, 0); if( SimpleLight.Exponent == 0.0f ) { // Correction for lumen units LightData.LightColorAndFalloffExponent[LightIndex] *= 16.0f; } } } SetUniformBufferParameterImmediate(RHICmdList, ShaderRHI, GetUniformBufferParameter<FTiledDeferredLightData>(), LightData); SetUniformBufferParameterImmediate(RHICmdList, ShaderRHI, GetUniformBufferParameter<FTiledDeferredLightData2>(), LightData2); SetShaderValue(RHICmdList, ShaderRHI, NumLights, NumThisPass); }
/** * Renders the view family. */ void FDeferredShadingSceneRenderer::Render() { if(!ViewFamily.EngineShowFlags.Rendering) { return; } SCOPED_DRAW_EVENT(Scene,DEC_SCENE_ITEMS); // Initialize global system textures (pass-through if already initialized). GSystemTextures.InitializeTextures(); // Allocate the maximum scene render target space for the current view family. GSceneRenderTargets.Allocate(ViewFamily); // Find the visible primitives. InitViews(); const bool bIsWireframe = ViewFamily.EngineShowFlags.Wireframe; static const auto ClearMethodCVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.ClearSceneMethod")); bool bRequiresRHIClear = true; bool bRequiresFarZQuadClear = false; if (ClearMethodCVar) { switch (ClearMethodCVar->GetValueOnRenderThread()) { case 0: // No clear { bRequiresRHIClear = false; bRequiresFarZQuadClear = false; break; } case 1: // RHIClear { bRequiresRHIClear = true; bRequiresFarZQuadClear = false; break; } case 2: // Clear using far-z quad { bRequiresFarZQuadClear = true; bRequiresRHIClear = false; break; } } } // Always perform a full buffer clear for wireframe, shader complexity view mode, and stationary light overlap viewmode. if (bIsWireframe || ViewFamily.EngineShowFlags.ShaderComplexity || ViewFamily.EngineShowFlags.StationaryLightOverlap) { bRequiresRHIClear = true; } // force using occ queries for wireframe if rendering is parented or frozen in the first view check(Views.Num()); #if (UE_BUILD_SHIPPING || UE_BUILD_TEST) const bool bIsViewFrozen = false; const bool bHasViewParent = false; #else const bool bIsViewFrozen = Views[0].State && ((FSceneViewState*)Views[0].State)->bIsFrozen; const bool bHasViewParent = Views[0].State && ((FSceneViewState*)Views[0].State)->HasViewParent(); #endif const bool bIsOcclusionTesting = DoOcclusionQueries() && (!bIsWireframe || bIsViewFrozen || bHasViewParent); // Dynamic vertex and index buffers need to be committed before rendering. FGlobalDynamicVertexBuffer::Get().Commit(); FGlobalDynamicIndexBuffer::Get().Commit(); // Notify the FX system that the scene is about to be rendered. if (Scene->FXSystem) { Scene->FXSystem->PreRender(); } // Draw the scene pre-pass / early z pass, populating the scene depth buffer and HiZ RenderPrePass(); // Clear scene color buffer if necessary. if ( bRequiresRHIClear ) { ClearView(); // Only clear once. bRequiresRHIClear = false; } // Clear LPVs for all views if ( IsFeatureLevelSupported(GRHIShaderPlatform, ERHIFeatureLevel::SM5) ) { ClearLPVs(); } // only temporarily available after early z pass and until base pass check(!GSceneRenderTargets.DBufferA); check(!GSceneRenderTargets.DBufferB); check(!GSceneRenderTargets.DBufferC); if(IsDBufferEnabled()) { GSceneRenderTargets.ResolveSceneDepthTexture(); // Resolve the scene depth to an auxiliary texture when SM3/SM4 is in use. This needs to happen so the auxiliary texture can be bound as a shader parameter // while the primary scene depth texture can be bound as the target. Simultaneously binding a single DepthStencil resource as a parameter and target // is unsupported in d3d feature level 10. if(!(GRHIFeatureLevel >= ERHIFeatureLevel::SM5) && GRHIFeatureLevel >= ERHIFeatureLevel::SM4) { GSceneRenderTargets.ResolveSceneDepthToAuxiliaryTexture(); } // e.g. ambient cubemaps, ambient occlusion, deferred decals for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++) { SCOPED_CONDITIONAL_DRAW_EVENTF(EventView,Views.Num() > 1, DEC_SCENE_ITEMS, TEXT("View%d"), ViewIndex); GCompositionLighting.ProcessBeforeBasePass(Views[ViewIndex]); } } if(bIsWireframe && FDeferredShadingSceneRenderer::ShouldCompositeEditorPrimitives(Views[0])) { // In Editor we want wire frame view modes to be MSAA for better quality. Resolve will be done with EditorPrimitives RHISetRenderTarget(GSceneRenderTargets.GetEditorPrimitivesColor(), GSceneRenderTargets.GetEditorPrimitivesDepth()); RHIClear(true, FLinearColor(0, 0, 0, 0), true, 0.0f, false, 0, FIntRect()); } else { // Begin rendering to scene color GSceneRenderTargets.BeginRenderingSceneColor(true); } RenderBasePass(); if(ViewFamily.EngineShowFlags.VisualizeLightCulling) { // clear out emissive and baked lighting (not too efficient but simple and only needed for this debug view) GSceneRenderTargets.BeginRenderingSceneColor(false); RHIClear(true, FLinearColor(0, 0, 0, 0), false, 0, false, 0, FIntRect()); } GSceneRenderTargets.DBufferA.SafeRelease(); GSceneRenderTargets.DBufferB.SafeRelease(); GSceneRenderTargets.DBufferC.SafeRelease(); // only temporarily available after early z pass and until base pass check(!GSceneRenderTargets.DBufferA); check(!GSceneRenderTargets.DBufferB); check(!GSceneRenderTargets.DBufferC); if (bRequiresFarZQuadClear) { // Clears view by drawing quad at maximum Z // TODO: if all the platforms have fast color clears, we can replace this with an RHIClear. ClearGBufferAtMaxZ(); bRequiresFarZQuadClear = false; } GSceneRenderTargets.ResolveSceneColor(FResolveRect(0, 0, ViewFamily.FamilySizeX, ViewFamily.FamilySizeY)); GSceneRenderTargets.ResolveSceneDepthTexture(); // Resolve the scene depth to an auxiliary texture when SM3/SM4 is in use. This needs to happen so the auxiliary texture can be bound as a shader parameter // while the primary scene depth texture can be bound as the target. Simultaneously binding a single DepthStencil resource as a parameter and target // is unsupported in d3d feature level 10. if(!GSupportsDepthFetchDuringDepthTest) { GSceneRenderTargets.ResolveSceneDepthToAuxiliaryTexture(); } RenderCustomDepthPass(); // Notify the FX system that opaque primitives have been rendered and we now have a valid depth buffer. if (Scene->FXSystem && Views.IsValidIndex(0)) { Scene->FXSystem->PostRenderOpaque( Views.GetTypedData(), GSceneRenderTargets.GetSceneDepthTexture(), GSceneRenderTargets.GetGBufferATexture() ); } // Update the quarter-sized depth buffer with the current contents of the scene depth texture. // This needs to happen before occlusion tests, which makes use of the small depth buffer. UpdateDownsampledDepthSurface(); // Issue occlusion queries // This is done after the downsampled depth buffer is created so that it can be used for issuing queries if ( bIsOcclusionTesting ) { BeginOcclusionTests(); } // Render lighting. if (ViewFamily.EngineShowFlags.Lighting && GRHIFeatureLevel >= ERHIFeatureLevel::SM4 && ViewFamily.EngineShowFlags.DeferredLighting ) { // Pre-lighting composition lighting stage // e.g. deferred decals, blurred GBuffer for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++) { SCOPED_CONDITIONAL_DRAW_EVENTF(EventView,Views.Num() > 1, DEC_SCENE_ITEMS, TEXT("View%d"), ViewIndex); GCompositionLighting.ProcessAfterBasePass(Views[ViewIndex]); } // Clear the translucent lighting volumes before we accumulate ClearTranslucentVolumeLighting(); RenderLights(); InjectAmbientCubemapTranslucentVolumeLighting(); CompositeIndirectTranslucentVolumeLighting(); // Filter the translucency lighting volume now that it is complete FilterTranslucentVolumeLighting(); // Clear LPVs for all views if ( IsFeatureLevelSupported(GRHIShaderPlatform, ERHIFeatureLevel::SM5) ) { PropagateLPVs(); } // Render reflections that only operate on opaque pixels RenderDeferredReflections(); // Post-lighting composition lighting stage // e.g. ambient cubemaps, ambient occlusion, LPV indirect for(int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex) { SCOPED_CONDITIONAL_DRAW_EVENTF(EventView,Views.Num() > 1, DEC_SCENE_ITEMS, TEXT("View%d"), ViewIndex); GCompositionLighting.ProcessLighting(Views[ViewIndex]); } } if( ViewFamily.EngineShowFlags.StationaryLightOverlap && GRHIFeatureLevel >= ERHIFeatureLevel::SM4) { RenderStationaryLightOverlap(); } FLightShaftsOutput LightShaftOutput; // Draw Lightshafts if (ViewFamily.EngineShowFlags.LightShafts) { LightShaftOutput = RenderLightShaftOcclusion(); } // Draw atmosphere if(ShouldRenderAtmosphere(ViewFamily)) { if (Scene->AtmosphericFog) { // Update RenderFlag based on LightShaftTexture is valid or not if (LightShaftOutput.bRendered) { Scene->AtmosphericFog->RenderFlag &= EAtmosphereRenderFlag::E_LightShaftMask; } else { Scene->AtmosphericFog->RenderFlag |= EAtmosphereRenderFlag::E_DisableLightShaft; } #if WITH_EDITOR if (Scene->bIsEditorScene) { // Precompute Atmospheric Textures Scene->AtmosphericFog->PrecomputeTextures(Views.GetTypedData(), &ViewFamily); } #endif RenderAtmosphere(LightShaftOutput); } } // Draw fog. if(ShouldRenderFog(ViewFamily)) { RenderFog(LightShaftOutput); } // No longer needed, release LightShaftOutput.LightShaftOcclusion = NULL; // Draw translucency. if(ViewFamily.EngineShowFlags.Translucency) { SCOPE_CYCLE_COUNTER(STAT_TranslucencyDrawTime); if(ViewFamily.EngineShowFlags.Refraction) { // to apply refraction effect by distorting the scene color RenderDistortion(); } RenderTranslucency(); } if (ViewFamily.EngineShowFlags.LightShafts) { RenderLightShaftBloom(); } // Resolve the scene color for post processing. GSceneRenderTargets.ResolveSceneColor(FResolveRect(0, 0, ViewFamily.FamilySizeX, ViewFamily.FamilySizeY)); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if(CVarTestUIBlur.GetValueOnRenderThread() > 0) { Views[0].UIBlurOverrideRectangles.Add(FIntRect(20, 20, 400, 400)); } #endif // Finish rendering for each view. if(ViewFamily.bResolveScene) { SCOPED_DRAW_EVENT(FinishRendering, DEC_SCENE_ITEMS); SCOPE_CYCLE_COUNTER(STAT_FinishRenderViewTargetTime); for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++) { SCOPED_CONDITIONAL_DRAW_EVENTF(EventView, Views.Num() > 1, DEC_SCENE_ITEMS, TEXT("View%d"), ViewIndex); FinishRenderViewTarget(&Views[ViewIndex], ViewIndex == (Views.Num() - 1)); } } RenderFinish(); }
void FD3D11DynamicRHI::RHIEndDrawingViewport(FViewportRHIParamRef ViewportRHI,bool bPresent,bool bLockToVsync) { DYNAMIC_CAST_D3D11RESOURCE(Viewport,Viewport); SCOPE_CYCLE_COUNTER(STAT_D3D11PresentTime); check(DrawingViewport.GetReference() == Viewport); DrawingViewport = NULL; // Clear references the device might have to resources. CurrentDepthTexture = NULL; CurrentDepthStencilTarget = NULL; CurrentDSVAccessType = DSAT_Writable; CurrentRenderTargets[0] = NULL; for(uint32 RenderTargetIndex = 1;RenderTargetIndex < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;++RenderTargetIndex) { CurrentRenderTargets[RenderTargetIndex] = NULL; } ClearAllShaderResources(); CommitRenderTargetsAndUAVs(); StateCache.SetVertexShader(nullptr); for(uint32 StreamIndex = 0;StreamIndex < 16;StreamIndex++) { StateCache.SetStreamSource(nullptr, StreamIndex, 0, 0); } StateCache.SetIndexBuffer(nullptr, DXGI_FORMAT_R16_UINT, 0); StateCache.SetPixelShader(nullptr); StateCache.SetHullShader(nullptr); StateCache.SetDomainShader(nullptr); StateCache.SetGeometryShader(nullptr); // Compute Shader is set to NULL after each Dispatch call, so no need to clear it here bool bNativelyPresented = Viewport->Present(bLockToVsync); // Don't wait on the GPU when using SLI, let the driver determine how many frames behind the GPU should be allowed to get if (GNumActiveGPUsForRendering == 1) { if (bNativelyPresented) { static const auto CFinishFrameVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.FinishCurrentFrame")); if (!CFinishFrameVar->GetValueOnRenderThread()) { // Wait for the GPU to finish rendering the previous frame before finishing this frame. Viewport->WaitForFrameEventCompletion(); Viewport->IssueFrameEvent(); } else { // Finish current frame immediately to reduce latency Viewport->IssueFrameEvent(); Viewport->WaitForFrameEventCompletion(); } } // If the input latency timer has been triggered, block until the GPU is completely // finished displaying this frame and calculate the delta time. if ( GInputLatencyTimer.RenderThreadTrigger ) { Viewport->WaitForFrameEventCompletion(); uint32 EndTime = FPlatformTime::Cycles(); GInputLatencyTimer.DeltaTime = EndTime - GInputLatencyTimer.StartTime; GInputLatencyTimer.RenderThreadTrigger = false; } } }
void SetParameters(const FRenderingCompositePassContext& Context) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(ShaderRHI, Context.View); DeferredParameters.Set(ShaderRHI, Context.View); { bool bFiltered = false; #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MotionBlurFiltering")); bFiltered = CVar->GetValueOnRenderThread() != 0; #endif // !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if(bFiltered) { PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Border,AM_Border,AM_Clamp>::GetRHI()); } else { PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Border,AM_Border,AM_Clamp>::GetRHI()); } } if( Context.View.Family->EngineShowFlags.CameraInterpolation ) { // Instead of finding the world space position of the current pixel, calculate the world space position offset by the camera position, // then translate by the difference between last frame's camera position and this frame's camera position, // then apply the rest of the transforms. This effectively avoids precision issues near the extents of large levels whose world space position is very large. FVector ViewOriginDelta = Context.View.ViewMatrices.ViewOrigin - Context.View.PrevViewMatrices.ViewOrigin; SetShaderValue(ShaderRHI, PrevViewProjMatrix, FTranslationMatrix(ViewOriginDelta) * Context.View.PrevViewRotationProjMatrix); } else { SetShaderValue( ShaderRHI, PrevViewProjMatrix, Context.View.ViewMatrices.GetViewRotationProjMatrix() ); } TRefCountPtr<IPooledRenderTarget> InputPooledElement = Context.Pass->GetInput(ePId_Input0)->GetOutput()->RequestInput(); // to mask out samples from outside of the view { FIntPoint BufferSize = GSceneRenderTargets.GetBufferSizeXY(); FVector2D InvBufferSize(1.0f / BufferSize.X, 1.0f / BufferSize.Y); FIntRect ClipRect = Context.View.ViewRect; // to avoid leaking in content from the outside because of bilinear filtering, shrink ClipRect.InflateRect(-1); FVector2D MinUV(ClipRect.Min.X * InvBufferSize.X, ClipRect.Min.Y * InvBufferSize.Y); FVector2D MaxUV(ClipRect.Max.X * InvBufferSize.X, ClipRect.Max.Y * InvBufferSize.Y); FVector2D SizeUV = MaxUV - MinUV; FVector2D Mul(1.0f / SizeUV.X, 1.0f / SizeUV.Y); FVector2D Add = - MinUV * Mul; FVector4 TextureViewMadValue(Mul.X, Mul.Y, Add.X, Add.Y); SetShaderValue(ShaderRHI, TextureViewMad, TextureViewMadValue); } { const float SizeX = Context.View.ViewRect.Width(); const float SizeY = Context.View.ViewRect.Height(); const float AspectRatio = SizeX / SizeY; const float InvAspectRatio = SizeY / SizeX; const FSceneViewState* ViewState = (FSceneViewState*) Context.View.State; float MotionBlurTimeScale = ViewState ? ViewState->MotionBlurTimeScale : 1.0f; float ViewMotionBlurScale = 0.5f * MotionBlurTimeScale * Context.View.FinalPostProcessSettings.MotionBlurAmount; // MotionBlurInstanceScale was needed to hack some cases where motion blur wasn't working well, this shouldn't be needed any more, can clean this up later float MotionBlurInstanceScale = 1; float ObjectMotionBlurScale = MotionBlurInstanceScale * ViewMotionBlurScale; // 0:no 1:full screen width, percent conversion float MaxVelocity = Context.View.FinalPostProcessSettings.MotionBlurMax / 100.0f; float InvMaxVelocity = 1.0f / MaxVelocity; // *2 to convert to -1..1 -1..1 screen space // / MaxFraction to map screenpos to -1..1 normalized MaxFraction FVector4 MotionBlurParametersValue( ObjectMotionBlurScale * InvMaxVelocity, - ObjectMotionBlurScale * InvMaxVelocity * InvAspectRatio, MaxVelocity * 2, - MaxVelocity * 2 * AspectRatio); SetShaderValue(ShaderRHI, MotionBlurParameters, MotionBlurParametersValue); } }