void UpdateSceneCaptureContent_RenderThread(FSceneRenderer* SceneRenderer, FTextureRenderTargetResource* TextureRenderTarget, const FName OwnerName, const FResolveParams& ResolveParams, bool bUseSceneColorTexture) { FMemMark MemStackMark(FMemStack::Get()); // update any resources that needed a deferred update FDeferredUpdateResource::UpdateResources(); { #if WANTS_DRAW_MESH_EVENTS FString EventName; OwnerName.ToString(EventName); SCOPED_DRAW_EVENTF(SceneCapture, DEC_SCENE_ITEMS, TEXT("SceneCapture %s"), *EventName); #endif // Render the scene normally const FRenderTarget* Target = SceneRenderer->ViewFamily.RenderTarget; FIntRect ViewRect = SceneRenderer->Views[0].ViewRect; FIntRect UnconstrainedViewRect = SceneRenderer->Views[0].UnconstrainedViewRect; RHISetRenderTarget(Target->GetRenderTargetTexture(), NULL); RHIClear(true, FLinearColor::Black, false, 1.0f, false, 0, ViewRect); SceneRenderer->Render(); // Copy the captured scene into the destination texture if (bUseSceneColorTexture) { // Copy the captured scene into the destination texture RHISetRenderTarget(Target->GetRenderTargetTexture(), NULL); RHISetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); RHISetBlendState(TStaticBlendState<>::GetRHI()); TShaderMapRef<FScreenVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FScreenPS> PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); FRenderingCompositePassContext Context(SceneRenderer->Views[0]); VertexShader->SetParameters(SceneRenderer->Views[0]); PixelShader->SetParameters(TStaticSamplerState<SF_Point>::GetRHI(), GSceneRenderTargets.GetSceneColorTexture()); FIntPoint TargetSize(UnconstrainedViewRect.Width(), UnconstrainedViewRect.Height()); DrawRectangle( ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), TargetSize, GSceneRenderTargets.GetBufferSizeXY(), EDRF_UseTriangleOptimization); } RHICopyToResolveTarget(TextureRenderTarget->GetRenderTargetTexture(), TextureRenderTarget->TextureRHI, false, ResolveParams); } delete SceneRenderer; }
void FLightSceneInfo::AddToScene() { const FLightSceneInfoCompact& LightSceneInfoCompact = Scene->Lights[Id]; // Only need to create light interactions for lights that can cast a shadow, // As deferred shading doesn't need to know anything about the primitives that a light affects if (Proxy->CastsDynamicShadow() || Proxy->CastsStaticShadow() // Lights that should be baked need to check for interactions to track unbuilt state correctly || Proxy->HasStaticLighting() // ES2 path supports dynamic point lights in the base pass using forward rendering, so we need to know the primitives || (Scene->GetFeatureLevel() < ERHIFeatureLevel::SM4 && Proxy->GetLightType() == LightType_Point && Proxy->IsMovable())) { // Add the light to the scene's light octree. Scene->LightOctree.AddElement(LightSceneInfoCompact); // TODO: Special case directional lights, no need to traverse the octree. // Find primitives that the light affects in the primitive octree. FMemMark MemStackMark(FMemStack::Get()); for(FScenePrimitiveOctree::TConstElementBoxIterator<SceneRenderingAllocator> PrimitiveIt( Scene->PrimitiveOctree, GetBoundingBox() ); PrimitiveIt.HasPendingElements(); PrimitiveIt.Advance()) { CreateLightPrimitiveInteraction(LightSceneInfoCompact, PrimitiveIt.GetCurrentElement()); } } }
void FOcclusionQueryBatcher::Flush(FRHICommandListImmediate& RHICmdList) { if(BatchOcclusionQueries.Num()) { FMemMark MemStackMark(FMemStack::Get()); // Create the indices for MaxBatchedPrimitives boxes. FIndexBufferRHIParamRef IndexBufferRHI = GOcclusionQueryIndexBuffer.IndexBufferRHI; // Draw the batches. for(int32 BatchIndex = 0, NumBatches = BatchOcclusionQueries.Num();BatchIndex < NumBatches;BatchIndex++) { FOcclusionBatch& Batch = BatchOcclusionQueries[BatchIndex]; FRenderQueryRHIParamRef BatchOcclusionQuery = Batch.Query; FVertexBufferRHIParamRef VertexBufferRHI = Batch.VertexAllocation.VertexBuffer->VertexBufferRHI; uint32 VertexBufferOffset = Batch.VertexAllocation.VertexOffset; const int32 NumPrimitivesThisBatch = (BatchIndex != (NumBatches-1)) ? MaxBatchedPrimitives : NumBatchedPrimitives; RHICmdList.BeginRenderQuery(BatchOcclusionQuery); RHICmdList.SetStreamSource(0, VertexBufferRHI, sizeof(FVector), VertexBufferOffset); RHICmdList.DrawIndexedPrimitive( IndexBufferRHI, PT_TriangleList, /*BaseVertexIndex=*/ 0, /*MinIndex=*/ 0, /*NumVertices=*/ 8 * NumPrimitivesThisBatch, /*StartIndex=*/ 0, /*NumPrimitives=*/ 12 * NumPrimitivesThisBatch, /*NumInstances=*/ 1 ); RHICmdList.EndRenderQuery(BatchOcclusionQuery); } INC_DWORD_STAT_BY(STAT_OcclusionQueries,BatchOcclusionQueries.Num()); // Reset the batch state. BatchOcclusionQueries.Empty(BatchOcclusionQueries.Num()); CurrentBatchOcclusionQuery = NULL; } }
bool OSVRHMDDescription::Init(OSVR_ClientContext OSVRClientContext) { Valid = false; static const char* Path = "/display"; #if OSVR_ENABLED size_t Length; if (osvrClientGetStringParameterLength(OSVRClientContext, Path, &Length) == OSVR_RETURN_FAILURE) return false; FMemMark MemStackMark(FMemStack::Get()); char* Buffer = new (FMemStack::Get()) char[Length]; if (osvrClientGetStringParameter(OSVRClientContext, Path, Buffer, Length) == OSVR_RETURN_FAILURE) return false; Valid = GetData(Data).InitFromJSON(Buffer); #endif // OSVR_ENABLED return Valid; }
void FPrimitiveSceneInfo::AddToScene(bool bUpdateStaticDrawLists) { check(IsInRenderingThread()); // If we are attaching a primitive that should be statically lit but has unbuilt lighting, // Allocate space in the indirect lighting cache so that it can be used for previewing indirect lighting if (Proxy->HasStaticLighting() && Proxy->NeedsUnbuiltPreviewLighting() && IsIndirectLightingCacheAllowed()) { FIndirectLightingCacheAllocation* PrimitiveAllocation = Scene->IndirectLightingCache.FindPrimitiveAllocation(PrimitiveComponentId); if (PrimitiveAllocation) { IndirectLightingCacheAllocation = PrimitiveAllocation; PrimitiveAllocation->SetDirty(); } else { PrimitiveAllocation = Scene->IndirectLightingCache.AllocatePrimitive(this, true); PrimitiveAllocation->SetDirty(); IndirectLightingCacheAllocation = PrimitiveAllocation; } } if (bUpdateStaticDrawLists) { AddStaticMeshes(); } // create potential storage for our compact info FPrimitiveSceneInfoCompact LocalCompactPrimitiveSceneInfo; FPrimitiveSceneInfoCompact* CompactPrimitiveSceneInfo = &LocalCompactPrimitiveSceneInfo; // if we are being added directly to the Octree, initialize the temp compact scene info, // and let the Octree make a copy of it LocalCompactPrimitiveSceneInfo.Init(this); // Add the primitive to the octree. check(!OctreeId.IsValidId()); Scene->PrimitiveOctree.AddElement(LocalCompactPrimitiveSceneInfo); check(OctreeId.IsValidId()); // Set bounds. FPrimitiveBounds& PrimitiveBounds = Scene->PrimitiveBounds[PackedIndex]; FBoxSphereBounds BoxSphereBounds = Proxy->GetBounds(); PrimitiveBounds.Origin = BoxSphereBounds.Origin; PrimitiveBounds.SphereRadius = BoxSphereBounds.SphereRadius; PrimitiveBounds.BoxExtent = BoxSphereBounds.BoxExtent; PrimitiveBounds.MinDrawDistanceSq = FMath::Square(Proxy->GetMinDrawDistance()); PrimitiveBounds.MaxDrawDistance = Proxy->GetMaxDrawDistance(); // Store precomputed visibility ID. int32 VisibilityBitIndex = Proxy->GetVisibilityId(); FPrimitiveVisibilityId& VisibilityId = Scene->PrimitiveVisibilityIds[PackedIndex]; VisibilityId.ByteIndex = VisibilityBitIndex / 8; VisibilityId.BitMask = (1 << (VisibilityBitIndex & 0x7)); // Store occlusion flags. uint8 OcclusionFlags = EOcclusionFlags::None; if (Proxy->CanBeOccluded()) { OcclusionFlags |= EOcclusionFlags::CanBeOccluded; } if (Proxy->AllowApproximateOcclusion() // Allow approximate occlusion if attached, even if the parent does not have bLightAttachmentsAsGroup enabled || LightingAttachmentRoot.IsValid()) { OcclusionFlags |= EOcclusionFlags::AllowApproximateOcclusion; } if (VisibilityBitIndex >= 0) { OcclusionFlags |= EOcclusionFlags::HasPrecomputedVisibility; } Scene->PrimitiveOcclusionFlags[PackedIndex] = OcclusionFlags; // Store occlusion bounds. FBoxSphereBounds OcclusionBounds = BoxSphereBounds; if (Proxy->HasCustomOcclusionBounds()) { OcclusionBounds = Proxy->GetCustomOcclusionBounds(); } OcclusionBounds.BoxExtent.X = OcclusionBounds.BoxExtent.X + OCCLUSION_SLOP; OcclusionBounds.BoxExtent.Y = OcclusionBounds.BoxExtent.Y + OCCLUSION_SLOP; OcclusionBounds.BoxExtent.Z = OcclusionBounds.BoxExtent.Z + OCCLUSION_SLOP; OcclusionBounds.SphereRadius = OcclusionBounds.SphereRadius + OCCLUSION_SLOP; Scene->PrimitiveOcclusionBounds[PackedIndex] = OcclusionBounds; // Store the component. Scene->PrimitiveComponentIds[PackedIndex] = PrimitiveComponentId; bNeedsCachedReflectionCaptureUpdate = true; { FMemMark MemStackMark(FMemStack::Get()); // Find lights that affect the primitive in the light octree. for (FSceneLightOctree::TConstElementBoxIterator<SceneRenderingAllocator> LightIt(Scene->LightOctree, Proxy->GetBounds().GetBox()); LightIt.HasPendingElements(); LightIt.Advance()) { const FLightSceneInfoCompact& LightSceneInfoCompact = LightIt.GetCurrentElement(); if (LightSceneInfoCompact.AffectsPrimitive(*CompactPrimitiveSceneInfo)) { FLightPrimitiveInteraction::Create(LightSceneInfoCompact.LightSceneInfo,this); } } } INC_MEMORY_STAT_BY(STAT_PrimitiveInfoMemory, sizeof(*this) + StaticMeshes.GetAllocatedSize() + Proxy->GetMemoryFootprint()); }
static void UpdatePlanarReflectionContents_RenderThread( FRHICommandListImmediate& RHICmdList, FSceneRenderer* MainSceneRenderer, FSceneRenderer* SceneRenderer, const FPlanarReflectionSceneProxy* SceneProxy, FRenderTarget* RenderTarget, FTexture* RenderTargetTexture, const FPlane& MirrorPlane, const FName OwnerName, const FResolveParams& ResolveParams, bool bUseSceneColorTexture) { QUICK_SCOPE_CYCLE_COUNTER(STAT_RenderPlanarReflection); FBox PlanarReflectionBounds = SceneProxy->WorldBounds; bool bIsInAnyFrustum = false; for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; if (View.ViewFrustum.IntersectBox(PlanarReflectionBounds.GetCenter(), PlanarReflectionBounds.GetExtent())) { bIsInAnyFrustum = true; break; } } if (bIsInAnyFrustum) { bool bIsVisibleInAnyView = true; for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; FSceneViewState* ViewState = View.ViewState; if (ViewState) { FIndividualOcclusionHistory& OcclusionHistory = ViewState->PlanarReflectionOcclusionHistories.FindOrAdd(SceneProxy->PlanarReflectionId); // +1 to buffered frames because the query is submitted late into the main frame, but read at the beginning of a reflection capture frame const int32 NumBufferedFrames = FOcclusionQueryHelpers::GetNumBufferedFrames() + 1; // +1 to frame counter because we are operating before the main view's InitViews, which is where OcclusionFrameCounter is incremented uint32 OcclusionFrameCounter = ViewState->OcclusionFrameCounter + 1; FRenderQueryRHIRef& PastQuery = OcclusionHistory.GetPastQuery(OcclusionFrameCounter, NumBufferedFrames); if (IsValidRef(PastQuery)) { uint64 NumSamples = 0; QUICK_SCOPE_CYCLE_COUNTER(STAT_PlanarReflectionOcclusionQueryResults); if (RHIGetRenderQueryResult(PastQuery.GetReference(), NumSamples, true)) { bIsVisibleInAnyView = NumSamples > 0; if (bIsVisibleInAnyView) { break; } } } } } if (bIsVisibleInAnyView) { FMemMark MemStackMark(FMemStack::Get()); // update any resources that needed a deferred update FDeferredUpdateResource::UpdateResources(RHICmdList); { #if WANTS_DRAW_MESH_EVENTS FString EventName; OwnerName.ToString(EventName); SCOPED_DRAW_EVENTF(RHICmdList, SceneCapture, TEXT("PlanarReflection %s"), *EventName); #else SCOPED_DRAW_EVENT(RHICmdList, UpdatePlanarReflectionContent_RenderThread); #endif const FRenderTarget* Target = SceneRenderer->ViewFamily.RenderTarget; SetRenderTarget(RHICmdList, Target->GetRenderTargetTexture(), NULL, true); // Note: relying on GBuffer SceneColor alpha being cleared to 1 in the main scene rendering check(GetSceneColorClearAlpha() == 1.0f); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); // Reflection view late update if (SceneRenderer->Views.Num() > 1) { const FMirrorMatrix MirrorMatrix(MirrorPlane); for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& ReflectionViewToUpdate = SceneRenderer->Views[ViewIndex]; const FViewInfo& UpdatedParentView = MainSceneRenderer->Views[ViewIndex]; ReflectionViewToUpdate.UpdatePlanarReflectionViewMatrix(UpdatedParentView, MirrorMatrix); } } // Render the scene normally { SCOPED_DRAW_EVENT(RHICmdList, RenderScene); SceneRenderer->Render(RHICmdList); } for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; if (MainSceneRenderer->Scene->GetShadingPath() == EShadingPath::Deferred) { PrefilterPlanarReflection<true>(RHICmdList, View, SceneProxy, Target); } else { PrefilterPlanarReflection<false>(RHICmdList, View, SceneProxy, Target); } } RHICmdList.CopyToResolveTarget(RenderTarget->GetRenderTargetTexture(), RenderTargetTexture->TextureRHI, false, ResolveParams); } FSceneRenderer::WaitForTasksClearSnapshotsAndDeleteSceneRenderer(RHICmdList, SceneRenderer); } } }