void FDrawEvent::Start(FRHICommandList& InRHICmdList, const FColor& Color, const TCHAR* Fmt, ...) { check(IsInParallelRenderingThread() || IsInRHIThread()); { va_list ptr; va_start(ptr, Fmt); TCHAR TempStr[256]; // Build the string in the temp buffer FCString::GetVarArgs(TempStr, ARRAY_COUNT(TempStr), ARRAY_COUNT(TempStr) - 1, Fmt, ptr); InRHICmdList.PushEvent(TempStr); RHICmdList = &InRHICmdList; } }
void FDrawEventRHIExecute::Start(IRHIComputeContext& InRHICommandContext, FColor Color, const TCHAR* Fmt, ...) { check(IsInParallelRenderingThread() || IsInRHIThread() || (!GRHIThread && IsInRenderingThread())); { va_list ptr; va_start(ptr, Fmt); TCHAR TempStr[256]; // Build the string in the temp buffer FCString::GetVarArgs(TempStr, ARRAY_COUNT(TempStr), ARRAY_COUNT(TempStr) - 1, Fmt, ptr); RHICommandContext = &InRHICommandContext; RHICommandContext->RHIPushEvent(TempStr, Color); } }
FPrimitiveViewRelevance FPaperBatchSceneProxy::GetViewRelevance(const FSceneView* View) { checkSlow(IsInParallelRenderingThread()); FPrimitiveViewRelevance Result; Result.bDrawRelevance = IsShown(View) && View->Family->EngineShowFlags.Paper2DSprites; Result.bRenderCustomDepth = ShouldRenderCustomDepth(); Result.bRenderInMainPass = ShouldRenderInMainPass(); Result.bMaskedRelevance = true; //Result.bNormalTranslucencyRelevance = true; Result.bDynamicRelevance = true; Result.bOpaqueRelevance = true; return Result; }
bool FVelocityDrawingPolicy::HasVelocity(const FViewInfo& View, const FPrimitiveSceneInfo* PrimitiveSceneInfo) { checkSlow(IsInParallelRenderingThread()); // No velocity if motionblur is off, or if it's a non-moving object (treat as background in that case) if (View.bCameraCut || !PrimitiveSceneInfo->Proxy->IsMovable()) { return false; } if (PrimitiveSceneInfo->Proxy->AlwaysHasVelocity()) { return true; } if (PrimitiveSceneInfo->bVelocityIsSupressed) { return false; } // check if the primitive has moved { FMatrix PreviousLocalToWorld; // hack FScene* Scene = PrimitiveSceneInfo->Scene; if (Scene->MotionBlurInfoData.GetPrimitiveMotionBlurInfo(PrimitiveSceneInfo, PreviousLocalToWorld)) { check(PrimitiveSceneInfo->Proxy); const FMatrix& LocalToWorld = PrimitiveSceneInfo->Proxy->GetLocalToWorld(); // Hasn't moved (treat as background by not rendering any special velocities)? if (LocalToWorld.Equals(PreviousLocalToWorld, 0.0001f)) { return false; } } else { return false; } } return true; }
void FRenderResource::InitResourceFromPossiblyParallelRendering() { if (IsInRenderingThread()) { InitResource(); } else { check(IsInParallelRenderingThread()); class FInitResourceRenderThreadTask { FRenderResource& Resource; FScopedEvent& Event; public: FInitResourceRenderThreadTask(FRenderResource& InResource, FScopedEvent& InEvent) : Resource(InResource) , Event(InEvent) { } FORCEINLINE TStatId GetStatId() const { RETURN_QUICK_DECLARE_CYCLE_STAT(FInitResourceRenderThreadTask, STATGROUP_TaskGraphTasks); } ENamedThreads::Type GetDesiredThread() { return ENamedThreads::RenderThread_Local; } static ESubsequentsMode::Type GetSubsequentsMode() { return ESubsequentsMode::FireAndForget; } void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) { Resource.InitResource(); Event.Trigger(); } }; { FScopedEvent Event; TGraphTask<FInitResourceRenderThreadTask>::CreateTask().ConstructAndDispatchWhenReady(*this, Event); } } }
bool FVelocityDrawingPolicy::HasVelocityOnBasePass(const FViewInfo& View,const FPrimitiveSceneProxy* PrimitiveSceneProxy, const FPrimitiveSceneInfo* PrimitiveSceneInfo, const FMeshBatch& Mesh, bool& bOutHasTransform, FMatrix& OutTransform) { checkSlow(IsInParallelRenderingThread()); // No velocity if motionblur is off, or if it's a non-moving object (treat as background in that case) if (View.bCameraCut) { return false; } //@todo-rco: Where is this set? if (PrimitiveSceneInfo->bVelocityIsSupressed) { return false; } // hack FScene* Scene = PrimitiveSceneInfo->Scene; if (Scene->MotionBlurInfoData.GetPrimitiveMotionBlurInfo(PrimitiveSceneInfo, OutTransform)) { bOutHasTransform = true; /* const FMatrix& LocalToWorld = PrimitiveSceneProxy->GetLocalToWorld(); // Hasn't moved (treat as background by not rendering any special velocities)? if (LocalToWorld.Equals(OutTransform, 0.0001f)) { return false; } */ return true; } bOutHasTransform = false; if (PrimitiveSceneProxy->IsMovable()) { return true; } //@todo-rco: Optimize finding WPO! auto* Material = Mesh.MaterialRenderProxy->GetMaterial(Scene->GetFeatureLevel()); return Material->MaterialModifiesMeshPosition_RenderThread() && Material->OutputsVelocityOnBasePass(); }
FUniformBufferRHIRef FUniformExpressionSet::CreateUniformBuffer(const FMaterialRenderContext& MaterialRenderContext, FRHICommandList* CommandListIfLocalMode, struct FLocalUniformBuffer* OutLocalUniformBuffer) const { check(UniformBufferStruct); check(IsInParallelRenderingThread()); FUniformBufferRHIRef UniformBuffer; if (UniformBufferStruct->GetSize() > 0) { FMemMark Mark(FMemStack::Get()); void* const TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct->GetSize(),UNIFORM_BUFFER_STRUCT_ALIGNMENT); FLinearColor* TempVectorBuffer = (FLinearColor*)TempBuffer; for(int32 VectorIndex = 0;VectorIndex < UniformVectorExpressions.Num();++VectorIndex) { TempVectorBuffer[VectorIndex] = FLinearColor(0,0,0,0); UniformVectorExpressions[VectorIndex]->GetNumberValue(MaterialRenderContext,TempVectorBuffer[VectorIndex]); } float* TempScalarBuffer = (float*)(TempVectorBuffer + UniformVectorExpressions.Num()); for(int32 ScalarIndex = 0;ScalarIndex < UniformScalarExpressions.Num();++ScalarIndex) { FLinearColor VectorValue(0,0,0,0); UniformScalarExpressions[ScalarIndex]->GetNumberValue(MaterialRenderContext,VectorValue); TempScalarBuffer[ScalarIndex] = VectorValue.R; } void** ResourceTable = (void**)((uint8*)TempBuffer + UniformBufferStruct->GetLayout().ResourceOffset); check(((UPTRINT)ResourceTable & 0x7) == 0); check(UniformBufferStruct->GetLayout().Resources.Num() == Uniform2DTextureExpressions.Num() * 2 + UniformCubeTextureExpressions.Num() * 2 + 2); // Cache 2D texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < Uniform2DTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; ESamplerSourceMode SourceMode; Uniform2DTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value,SourceMode); if (Value && Value->Resource) { //@todo-rco: Help track down a invalid values checkf(Value->IsA(UTexture::StaticClass()), TEXT("Expecting a UTexture! Value='%s' class='%s'"), *Value->GetName(), *Value->GetClass()->GetName()); // UMaterial / UMaterialInstance should have caused all dependent textures to be PostLoaded, which initializes their rendering resource checkf(Value->TextureReference.TextureReferenceRHI, TEXT("Texture %s of class %s had invalid texture reference"), *Value->GetName(), *Value->GetClass()->GetName()); *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; FSamplerStateRHIRef* SamplerSource = &Value->Resource->SamplerStateRHI; if (SourceMode == SSM_Wrap_WorldGroupSettings) { SamplerSource = &Wrap_WorldGroupSettings->SamplerStateRHI; } else if (SourceMode == SSM_Clamp_WorldGroupSettings) { SamplerSource = &Clamp_WorldGroupSettings->SamplerStateRHI; } *ResourceTable++ = *SamplerSource; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } // Cache cube texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < UniformCubeTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; ESamplerSourceMode SourceMode; UniformCubeTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value,SourceMode); if(Value && Value->Resource) { check(Value->TextureReference.TextureReferenceRHI); *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; FSamplerStateRHIRef* SamplerSource = &Value->Resource->SamplerStateRHI; if (SourceMode == SSM_Wrap_WorldGroupSettings) { SamplerSource = &Wrap_WorldGroupSettings->SamplerStateRHI; } else if (SourceMode == SSM_Clamp_WorldGroupSettings) { SamplerSource = &Clamp_WorldGroupSettings->SamplerStateRHI; } *ResourceTable++ = *SamplerSource; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } *ResourceTable++ = Wrap_WorldGroupSettings->SamplerStateRHI; *ResourceTable++ = Clamp_WorldGroupSettings->SamplerStateRHI; if (CommandListIfLocalMode) { check(OutLocalUniformBuffer); *OutLocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct->GetSize(), UniformBufferStruct->GetLayout()); check(OutLocalUniformBuffer->IsValid()); } else { UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct->GetLayout(), UniformBuffer_MultiFrame); check(!OutLocalUniformBuffer->IsValid()); } } return UniformBuffer; }
FUniformBufferRHIRef FUniformExpressionSet::CreateUniformBuffer(const FMaterialRenderContext& MaterialRenderContext, FRHICommandList* CommandListIfLocalMode, struct FLocalUniformBuffer* OutLocalUniformBuffer) const { check(UniformBufferStruct); check(IsInParallelRenderingThread()); FUniformBufferRHIRef UniformBuffer; if (UniformBufferStruct->GetSize() > 0) { FMemMark Mark(FMemStack::Get()); void* const TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct->GetSize(),UNIFORM_BUFFER_STRUCT_ALIGNMENT); FLinearColor* TempVectorBuffer = (FLinearColor*)TempBuffer; for(int32 VectorIndex = 0;VectorIndex < UniformVectorExpressions.Num();++VectorIndex) { TempVectorBuffer[VectorIndex] = FLinearColor(0,0,0,0); UniformVectorExpressions[VectorIndex]->GetNumberValue(MaterialRenderContext,TempVectorBuffer[VectorIndex]); } float* TempScalarBuffer = (float*)(TempVectorBuffer + UniformVectorExpressions.Num()); for(int32 ScalarIndex = 0;ScalarIndex < UniformScalarExpressions.Num();++ScalarIndex) { FLinearColor VectorValue(0,0,0,0); UniformScalarExpressions[ScalarIndex]->GetNumberValue(MaterialRenderContext,VectorValue); TempScalarBuffer[ScalarIndex] = VectorValue.R; } void** ResourceTable = (void**)((uint8*)TempBuffer + UniformBufferStruct->GetLayout().ResourceOffset); check(((UPTRINT)ResourceTable & 0x7) == 0); // Cache 2D texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < Uniform2DTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; Uniform2DTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value); if(Value && Value->Resource) { *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; *ResourceTable++ = Value->Resource->SamplerStateRHI; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } // Cache cube texture uniform expressions. for(int32 ExpressionIndex = 0;ExpressionIndex < UniformCubeTextureExpressions.Num();ExpressionIndex++) { const UTexture* Value; UniformCubeTextureExpressions[ExpressionIndex]->GetTextureValue(MaterialRenderContext,MaterialRenderContext.Material,Value); if(Value && Value->Resource) { *ResourceTable++ = Value->TextureReference.TextureReferenceRHI; *ResourceTable++ = Value->Resource->SamplerStateRHI; } else { *ResourceTable++ = GWhiteTexture->TextureRHI; *ResourceTable++ = GWhiteTexture->SamplerStateRHI; } } if (CommandListIfLocalMode) { check(OutLocalUniformBuffer); *OutLocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct->GetSize(), UniformBufferStruct->GetLayout()); check(OutLocalUniformBuffer->IsValid()); } else { UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct->GetLayout(), UniformBuffer_MultiFrame); check(!OutLocalUniformBuffer->IsValid()); } } return UniformBuffer; }