/** Returns true if the Material and Vertex Factory combination require adjacency information. */ bool RequiresAdjacencyInformation( UMaterialInterface* Material, const FVertexFactoryType* VertexFactoryType, ERHIFeatureLevel::Type InFeatureLevel ) { EMaterialTessellationMode TessellationMode = MTM_NoTessellation; bool bEnableCrackFreeDisplacement = false; if ( RHISupportsTessellation(GShaderPlatformForFeatureLevel[InFeatureLevel]) && VertexFactoryType->SupportsTessellationShaders() && Material ) { if ( IsInRenderingThread() ) { FMaterialRenderProxy* MaterialRenderProxy = Material->GetRenderProxy( false, false ); check( MaterialRenderProxy ); const FMaterial* MaterialResource = MaterialRenderProxy->GetMaterial(InFeatureLevel); check( MaterialResource ); TessellationMode = MaterialResource->GetTessellationMode(); bEnableCrackFreeDisplacement = MaterialResource->IsCrackFreeDisplacementEnabled(); } else if ( IsInGameThread() ) { UMaterial* BaseMaterial = Material->GetMaterial(); check( BaseMaterial ); TessellationMode = (EMaterialTessellationMode)BaseMaterial->D3D11TessellationMode; bEnableCrackFreeDisplacement = BaseMaterial->bEnableCrackFreeDisplacement; } else { UMaterialInterface::TMicRecursionGuard RecursionGuard; const UMaterial* BaseMaterial = Material->GetMaterial_Concurrent(RecursionGuard); check( BaseMaterial ); TessellationMode = (EMaterialTessellationMode)BaseMaterial->D3D11TessellationMode; bEnableCrackFreeDisplacement = BaseMaterial->bEnableCrackFreeDisplacement; } } return TessellationMode == MTM_PNTriangles || ( TessellationMode == MTM_FlatTessellation && bEnableCrackFreeDisplacement ); }
void FRHIResource::FlushPendingDeletes() { SCOPE_CYCLE_COUNTER(STAT_DeleteResources); check(IsInRenderingThread()); FRHICommandListExecutor::CheckNoOutstandingCmdLists(); FRHICommandListExecutor::GetImmediateCommandList().ImmediateFlush(EImmediateFlushType::FlushRHIThread); while (1) { TArray<FRHIResource*> ToDelete; PendingDeletes.PopAll(ToDelete); if (!ToDelete.Num()) { break; } for (int32 Index = 0; Index < ToDelete.Num(); Index++) { FRHIResource* Ref = ToDelete[Index]; check(Ref->MarkedForDelete == 1); if (Ref->GetRefCount() == 0) // caches can bring dead objects back to life { CurrentlyDeleting = Ref; delete Ref; CurrentlyDeleting = nullptr; } else { Ref->MarkedForDelete = 0; FPlatformMisc::MemoryBarrier(); } } } }
void FSteamVRHMD::RenderTexture_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIParamRef BackBuffer, FTexture2DRHIParamRef SrcTexture) const { check(IsInRenderingThread()); if (WindowMirrorMode == 0) { return; } const uint32 ViewportWidth = BackBuffer->GetSizeX(); const uint32 ViewportHeight = BackBuffer->GetSizeY(); SetRenderTarget(RHICmdList, BackBuffer, FTextureRHIRef()); RHICmdList.SetViewport(0, 0, 0, ViewportWidth, ViewportHeight, 1.0f); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); const auto FeatureLevel = GMaxRHIFeatureLevel; auto ShaderMap = GetGlobalShaderMap(FeatureLevel); TShaderMapRef<FScreenVS> VertexShader(ShaderMap); TShaderMapRef<FScreenPS> PixelShader(ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, FeatureLevel, BoundShaderState, RendererModule->GetFilterVertexDeclaration().VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, TStaticSamplerState<SF_Bilinear>::GetRHI(), SrcTexture); if (WindowMirrorMode == 1) { // need to clear when rendering only one eye since the borders won't be touched by the DrawRect below RHICmdList.Clear(true, FLinearColor::Black, false, 0, false, 0, FIntRect()); RendererModule->DrawRectangle( RHICmdList, ViewportWidth / 4, 0, ViewportWidth / 2, ViewportHeight, 0.1f, 0.2f, 0.3f, 0.6f, FIntPoint(ViewportWidth, ViewportHeight), FIntPoint(1, 1), *VertexShader, EDRF_Default); } else if (WindowMirrorMode == 2) { RendererModule->DrawRectangle( RHICmdList, 0, 0, ViewportWidth, ViewportHeight, 0.0f, 0.0f, 1.0f, 1.0f, FIntPoint(ViewportWidth, ViewportHeight), FIntPoint(1, 1), *VertexShader, EDRF_Default); } }
bool FD3D11DynamicRHI::RHIGetRenderQueryResult(FRenderQueryRHIParamRef QueryRHI,uint64& OutResult,bool bWait) { check(IsInRenderingThread()); FD3D11RenderQuery* Query = ResourceCast(QueryRHI); bool bSuccess = true; if(!Query->bResultIsCached) { bSuccess = GetQueryData(Query->Resource,&Query->Result,sizeof(Query->Result),bWait, Query->QueryType); Query->bResultIsCached = bSuccess; } if(Query->QueryType == RQT_AbsoluteTime) { // GetTimingFrequency is the number of ticks per second uint64 Div = FGPUTiming::GetTimingFrequency() / (1000 * 1000); // convert from GPU specific timestamp to micro sec (1 / 1 000 000 s) which seems a reasonable resolution OutResult = Query->Result / Div; } else { OutResult = Query->Result; } return bSuccess; }
void FIndirectLightingCache::FinalizeUpdateInternal_RenderThread(FScene* Scene, FSceneRenderer& Renderer, TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate, const TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate) { check(IsInRenderingThread()); if (IndirectLightingAllowed(Scene, Renderer)) { { SCOPE_CYCLE_COUNTER(STAT_UpdateIndirectLightingCacheBlocks); UpdateBlocks(Scene, Renderer.Views.GetData(), BlocksToUpdate); } { SCOPE_CYCLE_COUNTER(STAT_UpdateIndirectLightingCacheTransitions); UpdateTransitionsOverTime(TransitionsOverTimeToUpdate, Renderer.ViewFamily.DeltaWorldTime); } } if (GCacheDrawLightingSamples || Renderer.ViewFamily.EngineShowFlags.VolumeLightingSamples || GCacheDrawDirectionalShadowing) { FViewElementPDI DebugPDI(Renderer.Views.GetData(), NULL); for (int32 VolumeIndex = 0; VolumeIndex < Scene->PrecomputedLightVolumes.Num(); VolumeIndex++) { const FPrecomputedLightVolume* PrecomputedLightVolume = Scene->PrecomputedLightVolumes[VolumeIndex]; PrecomputedLightVolume->DebugDrawSamples(&DebugPDI, GCacheDrawDirectionalShadowing != 0); } } }
void FCompositionLighting::ProcessLpvIndirect(FRHICommandListImmediate& RHICmdList, FViewInfo& View) { check(IsInRenderingThread()); FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); FPostprocessContext Context(CompositeContext.Graph, View); if(IsLpvIndirectPassRequired(Context)) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); FRenderingCompositePass* SSAO = Context.Graph.RegisterPass(new FRCPassPostProcessInput(SceneContext.ScreenSpaceAO)); FRenderingCompositePass* Pass = Context.Graph.RegisterPass(new FRCPassPostProcessLpvIndirect()); Pass->SetInput(ePId_Input0, Context.FinalOutput); Pass->SetInput(ePId_Input1, SSAO ); Context.FinalOutput = FRenderingCompositeOutputRef(Pass); } // The graph setup should be finished before this line ---------------------------------------- SCOPED_DRAW_EVENT(RHICmdList, CompositionLpvIndirect); // we don't replace the final element with the scenecolor because this is what those passes should do by themself CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("CompositionLighting")); }
void FCompositionLighting::ProcessBeforeBasePass(FRHICommandListImmediate& RHICmdList, FViewInfo& View) { check(IsInRenderingThread()); // so that the passes can register themselves to the graph { FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); FPostprocessContext Context(CompositeContext.Graph, View); // Add the passes we want to add to the graph (commenting a line means the pass is not inserted into the graph) ---------- // decals are before AmbientOcclusion so the decal can output a normal that AO is affected by if (Context.View.Family->EngineShowFlags.Decals && !Context.View.Family->EngineShowFlags.ShaderComplexity && IsDBufferEnabled()) { FRenderingCompositePass* Pass = Context.Graph.RegisterPass(new(FMemStack::Get()) FRCPassPostProcessDeferredDecals(DRS_BeforeBasePass)); Pass->SetInput(ePId_Input0, Context.FinalOutput); Context.FinalOutput = FRenderingCompositeOutputRef(Pass); } // The graph setup should be finished before this line ---------------------------------------- SCOPED_DRAW_EVENT(RHICmdList, CompositionBeforeBasePass); CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("Composition_BeforeBasePass")); } }
void FGearVRSplash::Tick(float DeltaTime) { check(IsInRenderingThread()); FCustomPresent* pCustomPresent = pPlugin->GetCustomPresent_Internal(); if (pCustomPresent && pPlugin->HasValidOvrMobile()) { static double LastHighFreqTime = FPlatformTime::Seconds(); const double CurTime = FPlatformTime::Seconds(); const double DeltaSecondsHighFreq = CurTime - LastHighFreqTime; if (!IsLoadingIconMode()) { bool bNeedToPushFrame = false; FScopeLock ScopeLock2(&RenderSplashScreensLock); FGameFrame* pCurrentFrame = static_cast<FGameFrame*>(RenderFrame.Get()); check(pCurrentFrame); for (int32 i = 0; i < RenderSplashScreens.Num(); ++i) { FRenderSplashInfo& Splash = RenderSplashScreens[i]; // Let update only each 2nd frame if rotation is needed if ((!Splash.Desc.DeltaRotation.Equals(FQuat::Identity) && DeltaSecondsHighFreq > 2.f * DisplayRefreshRate)) { if (pCurrentFrame) { const FHMDLayerDesc* pLayerDesc = LayerMgr->GetLayerDesc(Splash.SplashLID); if (pLayerDesc) { FHMDLayerDesc layerDesc = *pLayerDesc; FTransform transform(layerDesc.GetTransform()); if (!Splash.Desc.DeltaRotation.Equals(FQuat::Identity)) { const FQuat prevRotation(transform.GetRotation()); const FQuat resultRotation(Splash.Desc.DeltaRotation * prevRotation); transform.SetRotation(resultRotation); layerDesc.SetTransform(transform); } LayerMgr->UpdateLayer(layerDesc); bNeedToPushFrame = true; } } } } if (bNeedToPushFrame || DeltaSecondsHighFreq > .5f) // also call push frame once in half second { ++pCurrentFrame->FrameNumber; // = pPlugin->GetCurrentFrameNumber(); FLayerManager* pGearVRLayerMgr = (FLayerManager*)LayerMgr.Get(); pGearVRLayerMgr->PreSubmitUpdate_RenderThread(FRHICommandListExecutor::GetImmediateCommandList(), pCurrentFrame, false); pCustomPresent->PushFrame(pGearVRLayerMgr, pCurrentFrame); LastHighFreqTime = CurTime; } } else if (DeltaSecondsHighFreq > 1.f / 3.f) { pPlugin->RenderLoadingIcon_RenderThread(); LastHighFreqTime = CurTime; } } }
/** Initialization */ void Init(const FArrowVertexBuffer* VertexBuffer) { if (IsInRenderingThread()) { // Initialize the vertex factory's stream components. FDataType NewData; NewData.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, Position, VET_Float3); NewData.TextureCoordinates.Add( FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FDynamicMeshVertex, TextureCoordinate), sizeof(FDynamicMeshVertex), VET_Float2) ); NewData.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, TangentX, VET_PackedNormal); NewData.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, TangentZ, VET_PackedNormal); SetData(NewData); } else { ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( InitArrowVertexFactory, FArrowVertexFactory*, VertexFactory, this, const FArrowVertexBuffer*, VertexBuffer, VertexBuffer, { // Initialize the vertex factory's stream components. FDataType NewData; NewData.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, Position, VET_Float3); NewData.TextureCoordinates.Add( FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FDynamicMeshVertex, TextureCoordinate), sizeof(FDynamicMeshVertex), VET_Float2) ); NewData.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, TangentX, VET_PackedNormal); NewData.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, TangentZ, VET_PackedNormal); VertexFactory->SetData(NewData); }); }
FLightPrimitiveInteraction::~FLightPrimitiveInteraction() { check(IsInRenderingThread()); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) // Update the game thread's counter of number of uncached static lighting interactions. if(bUncachedStaticLighting) { LightSceneInfo->NumUnbuiltInteractions--; FPlatformAtomics::InterlockedDecrement(&PrimitiveSceneInfo->Scene->NumUncachedStaticLightingInteractions); #if WITH_EDITOR PrimitiveSceneInfo->Proxy->NumUncachedStaticLightingInteractions--; #endif } #endif // Remove the interaction from the light's interaction list. if(NextPrimitive) { NextPrimitive->PrevPrimitiveLink = PrevPrimitiveLink; } *PrevPrimitiveLink = NextPrimitive; // Remove the interaction from the primitive's interaction list. if(NextLight) { NextLight->PrevLightLink = PrevLightLink; } *PrevLightLink = NextLight; }
void FSsPartsVertexFactory::Init(const FSsPartsVertexBuffer* VertexBuffer) { if(IsInRenderingThread()) { FLocalVertexFactory::DataType Data; Data.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, Position, VET_Float3); Data.TextureCoordinates.Add(FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FSsPartVertex,TexCoord), sizeof(FSsPartVertex), VET_Float2)); Data.ColorComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, Color, VET_Color); Data.TextureCoordinates.Add(FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FSsPartVertex,ColorBlend), sizeof(FSsPartVertex), VET_Float2)); Data.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, TangentX, VET_PackedNormal); Data.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, TangentZ, VET_PackedNormal); SetData(Data); } else { ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( FInitSsPartsVertexFactory, FSsPartsVertexFactory*, VertexFactory, this, const FSsPartsVertexBuffer*, VertexBuffer, VertexBuffer, { DataType Data; Data.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, Position, VET_Float3); Data.TextureCoordinates.Add(FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FSsPartVertex,TexCoord), sizeof(FSsPartVertex), VET_Float2)); Data.ColorComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, Color, VET_Color); Data.TextureCoordinates.Add(FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FSsPartVertex,ColorBlend), sizeof(FSsPartVertex), VET_Float2)); Data.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, TangentX, VET_PackedNormal); Data.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FSsPartVertex, TangentZ, VET_PackedNormal); VertexFactory->SetData(Data); }); }
void FSlateElementIndexBuffer::FillBuffer( const TArray<SlateIndex>& InIndices, bool bShrinkToFit ) { check( IsInRenderingThread() ); if( InIndices.Num() ) { uint32 NumIndices = InIndices.Num(); uint32 RequiredBufferSize = NumIndices*sizeof(SlateIndex); // resize if needed if( RequiredBufferSize > GetBufferSize() || bShrinkToFit ) { // Use array resize techniques for the vertex buffer ResizeBuffer( InIndices.GetAllocatedSize() ); } BufferUsageSize += RequiredBufferSize; void* IndicesPtr = RHILockIndexBuffer( IndexBufferRHI, 0, RequiredBufferSize, RLM_WriteOnly ); FMemory::Memcpy( IndicesPtr, InIndices.GetData(), RequiredBufferSize ); RHIUnlockIndexBuffer(IndexBufferRHI); } }
void FCompositionLighting::ProcessAsyncSSAO(FRHICommandListImmediate& RHICmdList, TArray<FViewInfo>& Views) { check(IsInRenderingThread()); PrepareAsyncSSAO(RHICmdList, Views); // so that the passes can register themselves to the graph for (int32 i = 0; i < Views.Num(); ++i) { FViewInfo& View = Views[i]; FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); // Add the passes we want to add to the graph (commenting a line means the pass is not inserted into the graph) ---------- uint32 Levels = ComputeAmbientOcclusionPassCount(View); if (FSSAOHelper::IsAmbientOcclusionAsyncCompute(View, Levels)) { FPostprocessContext Context(RHICmdList, CompositeContext.Graph, View); FRenderingCompositeOutputRef AmbientOcclusion = AddPostProcessingAmbientOcclusion(RHICmdList, Context, Levels); Context.FinalOutput = FRenderingCompositeOutputRef(AmbientOcclusion); // The graph setup should be finished before this line ---------------------------------------- CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("Composition_ProcessAsyncSSAO")); } } FinishAsyncSSAO(RHICmdList); }
void FSlateRHIRenderingPolicy::EndDrawingWindows() { check( IsInRenderingThread() ); bShouldShrinkResources = false; uint32 TotalVertexBufferMemory = 0; uint32 TotalIndexBufferMemory = 0; uint32 TotalVertexBufferUsage = 0; uint32 TotalIndexBufferUsage = 0; for( int32 BufferIndex = 0; BufferIndex < 2; ++BufferIndex ) { TotalVertexBufferMemory += VertexBuffers[BufferIndex].GetBufferSize(); TotalVertexBufferUsage += VertexBuffers[BufferIndex].GetBufferUsageSize(); TotalIndexBufferMemory += IndexBuffers[BufferIndex].GetBufferSize(); TotalIndexBufferUsage += IndexBuffers[BufferIndex].GetBufferUsageSize(); } // How much larger the buffers can be than the required size. // @todo Slate probably could be more intelligent about this const uint32 MaxSizeMultiplier = 2; if( TotalVertexBufferMemory > TotalVertexBufferUsage*MaxSizeMultiplier || TotalIndexBufferMemory > TotalIndexBufferUsage*MaxSizeMultiplier ) { // The vertex buffer or index is more than twice the size of what is required. Shrink it bShouldShrinkResources = true; } SET_MEMORY_STAT( STAT_SlateVertexBufferMemory, TotalVertexBufferMemory ); SET_MEMORY_STAT( STAT_SlateIndexBufferMemory, TotalIndexBufferMemory ); }
void FSlateRHIRenderingPolicy::EndDrawingWindows() { check( IsInRenderingThread() ); uint32 TotalVertexBufferMemory = 0; uint32 TotalIndexBufferMemory = 0; uint32 TotalVertexBufferUsage = 0; uint32 TotalIndexBufferUsage = 0; uint32 MinVertexBufferSize = VertexBuffers[0].GetMinBufferSize(); uint32 MinIndexBufferSize = IndexBuffers[0].GetMinBufferSize(); for( int32 BufferIndex = 0; BufferIndex < SlateRHIConstants::NumBuffers; ++BufferIndex ) { TotalVertexBufferMemory += VertexBuffers[BufferIndex].GetBufferSize(); TotalVertexBufferUsage += VertexBuffers[BufferIndex].GetBufferUsageSize(); TotalIndexBufferMemory += IndexBuffers[BufferIndex].GetBufferSize(); TotalIndexBufferUsage += IndexBuffers[BufferIndex].GetBufferUsageSize(); } SET_MEMORY_STAT( STAT_SlateVertexBufferMemory, TotalVertexBufferMemory ); SET_MEMORY_STAT( STAT_SlateIndexBufferMemory, TotalIndexBufferMemory ); }
FD3D11UniformBuffer::~FD3D11UniformBuffer() { // Do not return the allocation to the pool if it is in the dynamic constant buffer! if (!RingAllocation.IsValid() && Resource != nullptr) { check(IsInRenderingThread()); D3D11_BUFFER_DESC Desc; Resource->GetDesc(&Desc); // Return this uniform buffer to the free pool if (Desc.CPUAccessFlags == D3D11_CPU_ACCESS_WRITE && Desc.Usage == D3D11_USAGE_DYNAMIC) { check(IsValidRef(Resource)); FPooledUniformBuffer NewEntry; NewEntry.Buffer = Resource; NewEntry.FrameFreed = GFrameNumberRenderThread; NewEntry.CreatedSize = Desc.ByteWidth; // Add to this frame's array of free uniform buffers const int32 SafeFrameIndex = (GFrameNumberRenderThread - 1) % NumSafeFrames; const uint32 BucketIndex = GetPoolBucketIndex(Desc.ByteWidth); int32 LastNum = SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Num(); check(Desc.ByteWidth <= GetPoolBucketSize(Desc.ByteWidth)); SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Add(NewEntry); INC_DWORD_STAT(STAT_D3D11NumFreeUniformBuffers); INC_MEMORY_STAT_BY(STAT_D3D11FreeUniformBufferMemory, Desc.ByteWidth); FPlatformMisc::MemoryBarrier(); // check for unwanted concurrency check(SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Num() == LastNum + 1); } } }
void FOculusRiftHMD::RenderTexture_RenderThread(class FRHICommandListImmediate& RHICmdList, class FRHITexture2D* BackBuffer, class FRHITexture2D* SrcTexture) const { check(IsInRenderingThread()); check(pCustomPresent); auto RenderContext = pCustomPresent->GetRenderContext(); if (RenderContext && RenderContext->GetFrameSettings()->Flags.bMirrorToWindow) { if (RenderContext->GetFrameSettings()->MirrorWindowMode == FSettings::eMirrorWindow_Distorted) { FTexture2DRHIRef MirrorTexture = pCustomPresent->GetMirrorTexture(); if (MirrorTexture) { CopyTexture_RenderThread(RHICmdList, BackBuffer, MirrorTexture); } } else if (RenderContext->GetFrameSettings()->MirrorWindowMode == FSettings::eMirrorWindow_Undistorted) { auto FrameSettings = RenderContext->GetFrameSettings(); FIntRect destRect(0, 0, BackBuffer->GetSizeX() / 2, BackBuffer->GetSizeY()); for (int i = 0; i < 2; ++i) { CopyTexture_RenderThread(RHICmdList, BackBuffer, SrcTexture, destRect, FrameSettings->EyeRenderViewport[i]); destRect.Min.X += BackBuffer->GetSizeX() / 2; destRect.Max.X += BackBuffer->GetSizeX() / 2; } } else if (RenderContext->GetFrameSettings()->MirrorWindowMode == FSettings::eMirrorWindow_SingleEye) { auto FrameSettings = RenderContext->GetFrameSettings(); CopyTexture_RenderThread(RHICmdList, BackBuffer, SrcTexture, FIntRect(), FrameSettings->EyeRenderViewport[0]); } } }
/** * Creates a bound shader state instance which encapsulates a decl, vertex shader, and pixel shader * @param VertexDeclaration - existing vertex decl * @param StreamStrides - optional stream strides * @param VertexShader - existing vertex shader * @param HullShader - existing hull shader * @param DomainShader - existing domain shader * @param PixelShader - existing pixel shader * @param GeometryShader - existing geometry shader */ FBoundShaderStateRHIRef FD3D11DynamicRHI::RHICreateBoundShaderState( FVertexDeclarationRHIParamRef VertexDeclarationRHI, FVertexShaderRHIParamRef VertexShaderRHI, FHullShaderRHIParamRef HullShaderRHI, FDomainShaderRHIParamRef DomainShaderRHI, FPixelShaderRHIParamRef PixelShaderRHI, FGeometryShaderRHIParamRef GeometryShaderRHI ) { check(IsInRenderingThread()); SCOPE_CYCLE_COUNTER(STAT_D3D11CreateBoundShaderStateTime); checkf(GIsRHIInitialized && Direct3DDeviceIMContext,(TEXT("Bound shader state RHI resource was created without initializing Direct3D first"))); // Check for an existing bound shader state which matches the parameters FCachedBoundShaderStateLink* CachedBoundShaderStateLink = GetCachedBoundShaderState( VertexDeclarationRHI, VertexShaderRHI, PixelShaderRHI, HullShaderRHI, DomainShaderRHI, GeometryShaderRHI ); if(CachedBoundShaderStateLink) { // If we've already created a bound shader state with these parameters, reuse it. return CachedBoundShaderStateLink->BoundShaderState; } else { SCOPE_CYCLE_COUNTER(STAT_D3D11NewBoundShaderStateTime); return new FD3D11BoundShaderState(VertexDeclarationRHI,VertexShaderRHI,PixelShaderRHI,HullShaderRHI,DomainShaderRHI,GeometryShaderRHI,Direct3DDevice); } }
void FPrimitiveSceneInfo::RemoveFromScene(bool bUpdateStaticDrawLists) { check(IsInRenderingThread()); // implicit linked list. The destruction will update this "head" pointer to the next item in the list. while(LightList) { FLightPrimitiveInteraction::Destroy(LightList); } // Remove the primitive from the octree. check(OctreeId.IsValidId()); check(Scene->PrimitiveOctree.GetElementById(OctreeId).PrimitiveSceneInfo == this); Scene->PrimitiveOctree.RemoveElement(OctreeId); OctreeId = FOctreeElementId(); IndirectLightingCacheAllocation = NULL; DEC_MEMORY_STAT_BY(STAT_PrimitiveInfoMemory, sizeof(*this) + StaticMeshes.GetAllocatedSize() + Proxy->GetMemoryFootprint()); if (bUpdateStaticDrawLists) { RemoveStaticMeshes(); } }
void FRuntimeMeshProxy::DeleteSection_RenderThread(int32 SectionId) { check(IsInRenderingThread()); bool bChangedState = false; if (SectionId == INDEX_NONE) { Sections.Empty(); bChangedState = true; } else { // Remove the section if it exists if (Sections.Remove(SectionId) > 0) { bChangedState = true; } } if (bChangedState) { // Update the cached values for rendering. UpdateCachedValues(); } }
void FViewExtension::PreRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& ViewFamily) { check(IsInRenderingThread()); FViewExtension& RenderContext = *this; FGameFrame* CurrentFrame = static_cast<FGameFrame*>(RenderContext.RenderFrame.Get()); if (bFrameBegun || !CurrentFrame || !CurrentFrame->Settings->IsStereoEnabled() || !ViewFamily.RenderTarget->GetRenderTargetTexture()) { return; } FSettings* FrameSettings = CurrentFrame->GetSettings(); RenderContext.ShowFlags = ViewFamily.EngineShowFlags; RenderContext.CurHeadPose = CurrentFrame->HeadPose; if (FrameSettings->TexturePaddingPerEye != 0) { // clear the padding between two eyes const int32 GapMinX = ViewFamily.Views[0]->ViewRect.Max.X; const int32 GapMaxX = ViewFamily.Views[1]->ViewRect.Min.X; const int ViewportSizeY = (ViewFamily.RenderTarget->GetRenderTargetTexture()) ? ViewFamily.RenderTarget->GetRenderTargetTexture()->GetSizeY() : ViewFamily.RenderTarget->GetSizeXY().Y; RHICmdList.SetViewport(GapMinX, 0, 0, GapMaxX, ViewportSizeY, 1.0f); RHICmdList.Clear(true, FLinearColor::Black, false, 0, false, 0, FIntRect()); } check(ViewFamily.RenderTarget->GetRenderTargetTexture()); FrameSettings->EyeLayer.EyeFov.Viewport[0] = ToOVRRecti(FrameSettings->EyeRenderViewport[0]); FrameSettings->EyeLayer.EyeFov.Viewport[1] = ToOVRRecti(FrameSettings->EyeRenderViewport[1]); pPresentBridge->BeginRendering(RenderContext, ViewFamily.RenderTarget->GetRenderTargetTexture()); ovrHmd_GetFrameTiming(Hmd, RenderContext.RenderFrame->FrameNumber); RenderContext.bFrameBegun = true; if (RenderContext.ShowFlags.Rendering) { // get latest orientation/position and cache it ovrTrackingState ts; ovrPosef EyeRenderPose[2]; CurrentFrame->GetEyePoses(Hmd, EyeRenderPose, ts); // Take new EyeRenderPose is bUpdateOnRT. // if !bOrientationChanged && !bPositionChanged then we still need to use new eye pose (for timewarp) if (FrameSettings->Flags.bUpdateOnRT || (!CurrentFrame->Flags.bOrientationChanged && !CurrentFrame->Flags.bPositionChanged)) { RenderContext.CurHeadPose = ts.HeadPose.ThePose; FMemory::Memcpy(RenderContext.CurEyeRenderPose, EyeRenderPose); } else { FMemory::Memcpy<ovrPosef[2]>(RenderContext.CurEyeRenderPose, CurrentFrame->EyeRenderPose); } } }
const FTexture2DRHIRef& FSceneViewport::GetRenderTargetTexture() const { if (IsInRenderingThread()) { return RenderTargetTextureRenderThreadRHI; } return RenderTargetTextureRHI; }
FSlateShaderResource* FSceneViewport::GetViewportRenderTargetTexture() { if (IsInRenderingThread()) { return RenderThreadSlateTexture; } return (BufferedSlateHandles.Num() != 0) ? BufferedSlateHandles[CurrentBufferedTargetIndex] : nullptr; }
bool FSteamVRHMD::D3D11Bridge::Present(int& SyncInterval) { check(IsInRenderingThread()); FinishRendering(); return true; }
void FCompositionLighting::ProcessAfterBasePass(FRHICommandListImmediate& RHICmdList, FViewInfo& View) { check(IsInRenderingThread()); FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); // might get renamed to refracted or ...WithAO SceneContext.GetSceneColor()->SetDebugName(TEXT("SceneColor")); // to be able to observe results with VisualizeTexture GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GetSceneColor()); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferA); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferB); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferC); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferD); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferE); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.GBufferVelocity); GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, SceneContext.ScreenSpaceAO); // so that the passes can register themselves to the graph { FMemMark Mark(FMemStack::Get()); FRenderingCompositePassContext CompositeContext(RHICmdList, View); FPostprocessContext Context(CompositeContext.Graph, View); // Add the passes we want to add to the graph (commenting a line means the pass is not inserted into the graph) ---------- // decals are before AmbientOcclusion so the decal can output a normal that AO is affected by if( Context.View.Family->EngineShowFlags.Decals && !Context.View.Family->EngineShowFlags.VisualizeLightCulling) // decal are distracting when looking at LightCulling { AddDeferredDecalsBeforeLighting(Context); } FRenderingCompositeOutputRef AmbientOcclusion; if(uint32 Levels = ComputeAmbientOcclusionPassCount(Context)) { AmbientOcclusion = AddPostProcessingAmbientOcclusion(RHICmdList, Context, Levels); } if(IsAmbientCubemapPassRequired(Context)) { AddPostProcessingAmbientCubemap(Context, AmbientOcclusion); } // The graph setup should be finished before this line ---------------------------------------- SCOPED_DRAW_EVENT(RHICmdList, LightCompositionTasks_PreLighting); TRefCountPtr<IPooledRenderTarget>& SceneColor = SceneContext.GetSceneColor(); Context.FinalOutput.GetOutput()->RenderTargetDesc = SceneColor->GetDesc(); Context.FinalOutput.GetOutput()->PooledRenderTarget = SceneColor; CompositeContext.Process(Context.FinalOutput.GetPass(), TEXT("CompositionLighting_AfterBasePass")); } }
void FSteamVRHMD::PreRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& ViewFamily) { check(IsInRenderingThread()); GetActiveRHIBridgeImpl()->BeginRendering(); FVector CurrentPosition; FQuat CurrentOrientation; GetCurrentPose(CurrentOrientation, CurrentPosition, vr::k_unTrackedDeviceIndex_Hmd, true); }
void FBoneDataVertexBuffer::UnlockData() { check(IsValidRef(BoneBuffer)); check(IsInRenderingThread() && AllocBlock && AllocSize); FRHICommandListExecutor::GetImmediateCommandList().UpdateVertexBuffer(BoneBuffer.VertexBufferRHI, AllocBlock, AllocSize); FMemory::Free(AllocBlock); AllocBlock = nullptr; AllocSize = 0; }
void FOculusRiftHMD::ShutdownRendering() { check(IsInRenderingThread()); if (pCustomPresent.GetReference()) { pCustomPresent->Shutdown(); pCustomPresent = NULL; } }
void FSteamVRHMD::PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& View) { check(IsInRenderingThread()); // The last view location used to set the view will be in BaseHmdOrientation. We need to calculate the delta from that, so that // cameras that rely on game objects (e.g. other components) for their positions don't need to be updated on the render thread. const FQuat DeltaOrient = View.BaseHmdOrientation.Inverse() * TrackingFrame.DeviceOrientation[vr::k_unTrackedDeviceIndex_Hmd]; View.ViewRotation = FRotator(View.ViewRotation.Quaternion() * DeltaOrient); View.UpdateViewMatrix(); }
void FSteamVRHMD::D3D11Bridge::BeginRendering() { check(IsInRenderingThread()); static bool Inited = false; if (!Inited) { Inited = true; } }