void FVisualizeTexture::QueryInfo( FQueryVisualizeTexureInfo& Out ) { for(uint32 i = 0; ; ++i) { FPooledRenderTarget* RT = GRenderTargetPool.GetElementById(i); if (!RT) { break; } FPooledRenderTargetDesc Desc = RT->GetDesc(); uint32 SizeInKB = (RT->ComputeMemorySize() + 1023) / 1024; FString Entry = FString::Printf(TEXT("%s %d %s %d"), *Desc.GenerateInfoString(), i + 1, Desc.DebugName ? Desc.DebugName : TEXT("<Unnamed>"), SizeInKB); Out.Entries.Add(Entry); } }
void FVisualizeTexture::DebugLog(bool bExtended) { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) { TArray<FSortedLines> SortedLines; for(uint32 i = 0;; ++i) { FPooledRenderTarget* RT = GRenderTargetPool.GetElementById(i); if(!RT) { break; } FPooledRenderTargetDesc Desc = RT->GetDesc(); if(bFullList || (Desc.Flags & TexCreate_HideInVisualizeTexture) == 0) { uint32 SizeInKB = (RT->ComputeMemorySize() + 1023) / 1024; FString UnusedStr; if(RT->GetUnusedForNFrames() > 0) { if(!bFullList) { continue; } UnusedStr = FString::Printf(TEXT(" unused(%d)"), RT->GetUnusedForNFrames()); } FSortedLines Element; Element.PoolIndex = i; // sort by index Element.SortIndex = i; if(SortOrder == -1) { // sort by index Element.Line = FString::Printf(TEXT("%s %s %d KB%s"), *Desc.GenerateInfoString(), Desc.DebugName, SizeInKB, *UnusedStr); } else if(SortOrder == 0) { // sort by name Element.Line = FString::Printf(TEXT("%s %s %d KB%s"), Desc.DebugName, *Desc.GenerateInfoString(), SizeInKB, *UnusedStr); Element.SortIndex = 0; } else if(SortOrder == 1) { // sort by size (large ones first) Element.Line = FString::Printf(TEXT("%d KB %s %s%s"), SizeInKB, *Desc.GenerateInfoString(), Desc.DebugName, *UnusedStr); Element.SortIndex = -(int32)SizeInKB; } else { check(0); } SortedLines.Add(Element); } } SortedLines.Sort(); { for(int32 Index = 0; Index < SortedLines.Num(); Index++) { const FSortedLines& Entry = SortedLines[Index]; UE_LOG(LogConsoleResponse, Log, TEXT(" %3d = %s"), Entry.PoolIndex + 1, *Entry.Line); } } // clean flags for next use bFullList = false; SortOrder = -1; } UE_LOG(LogConsoleResponse, Log, TEXT("")); // log names (alternative method to look at the rendertargets) if(bExtended) { UE_LOG(LogConsoleResponse, Log, TEXT("CheckpointName (what was rendered this frame, use <Name>@<Number> to get intermediate versions):")); TArray<FString> Entries; // sorted by pointer for efficiency, now we want to print sorted alphabetically for (TMap<FString, uint32>:: TIterator It(GRenderTargetPool.VisualizeTexture.VisualizeTextureCheckpoints); It; ++It) { const FString& Key = It.Key(); uint32 Value = It.Value(); /* if(Value) { // was reused this frame Entries.Add(FString::Printf(TEXT("%s @0..%d"), *Key.GetPlainNameString(), Value - 1)); } else */ { // was not reused this frame but can be referenced Entries.Add(Key); } } Entries.Sort(); // print them sorted, if possible multiple in a line { FString Line; FString Separator = " , "; for(int32 Index=0; Index < Entries.Num(); Index++ ) { const FString& Entry = *Entries[Index]; if(Line.Len() + 2 + Entry.Len() > 80) { UE_LOG(LogConsoleResponse, Log, TEXT(" %s"), *Line); Line.Empty(); } Line += Entry; Line += Separator; } if(!Line.IsEmpty()) { // remove separator in the end Line = Line.Left(Line.Len() - Separator.Len()); UE_LOG(LogConsoleResponse, Log, TEXT(" %s"), *Line); } } } { uint32 WholeCount; uint32 WholePoolInKB; uint32 UsedInKB; GRenderTargetPool.GetStats(WholeCount, WholePoolInKB, UsedInKB); UE_LOG(LogConsoleResponse, Log, TEXT("Pool: %d/%d MB (referenced/allocated)"), (UsedInKB + 1023) / 1024, (WholePoolInKB + 1023) / 1024); } #endif }
void FVisualizeTexture::PresentContent(const FSceneView& View) { if(Mode != 0) { // old mode is used, lets copy the specified texture to do it similar to the new system FPooledRenderTarget* Element = GRenderTargetPool.GetElementById(Mode - 1); if(Element) { GenerateContent(Element->GetRenderTargetItem(), Element->GetDesc()); } } const FTexture2DRHIRef& RenderTargetTexture = View.Family->RenderTarget->GetRenderTargetTexture(); if(!VisualizeTextureContent || !IsValidRef(RenderTargetTexture) || GRHIFeatureLevel < ERHIFeatureLevel::SM3) { // visualize feature is deactivated return; } FPooledRenderTargetDesc Desc = VisualizeTextureDesc; RHISetRenderTarget(View.Family->RenderTarget->GetRenderTargetTexture(),FTextureRHIRef()); RHISetViewport(0, 0, 0.0f, GSceneRenderTargets.GetBufferSizeXY().X, GSceneRenderTargets.GetBufferSizeXY().Y, 1.0f ); RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FVisualizeTexturePresentPS> PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); VertexShader->SetParameters(View); PixelShader->SetParameters(View, *VisualizeTextureContent); FIntRect DestRect = View.ViewRect; FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent); // Draw a quad mapping scene color to the view's render target DrawRectangle( VisualizeTextureRect.Min.X, VisualizeTextureRect.Min.Y, VisualizeTextureRect.Width(), VisualizeTextureRect.Height(), 0, 0, VisualizeTextureRect.Width(), VisualizeTextureRect.Height(), GSceneRenderTargets.GetBufferSizeXY(), VisualizeTextureRect.Size(), EDRF_Default); // this is a helper class for FCanvas to be able to get screen size class FRenderTargetTemp : public FRenderTarget { public: const FSceneView& View; FRenderTargetTemp(const FSceneView& InView) : View(InView) { } virtual FIntPoint GetSizeXY() const { return View.UnscaledViewRect.Size(); }; virtual const FTexture2DRHIRef& GetRenderTargetTexture() const { return View.Family->RenderTarget->GetRenderTargetTexture(); } } TempRenderTarget(View); FCanvas Canvas(&TempRenderTarget, NULL, View.Family->CurrentRealTime, View.Family->CurrentWorldTime, View.Family->DeltaWorldTime); float X = 100 + View.ViewRect.Min.X; float Y = 160 + View.ViewRect.Min.Y; float YStep = 14; { uint32 ReuseCount = ObservedDebugNameReusedCurrent; FString ExtendedName; if(ReuseCount) { uint32 ReuseGoal = FMath::Min(ReuseCount - 1, ObservedDebugNameReusedGoal); // was reused this frame ExtendedName = FString::Printf(TEXT("%s@%d @0..%d"), Desc.DebugName, ReuseGoal, ReuseCount - 1); } else { // was not reused this frame but can be referenced ExtendedName = FString::Printf(TEXT("%s"), Desc.DebugName); } FString Line = FString::Printf(TEXT("VisualizeTexture: %d \"%s\" RGB*%g+A*%g UV%d"), Mode, *ExtendedName, RGBMul, AMul, UVInputMapping); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } { FString Line = FString::Printf(TEXT(" TextureInfoString(): %s"), *(Desc.GenerateInfoString())); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } { FString Line = FString::Printf(TEXT(" BufferSize:(%d,%d)"), GSceneRenderTargets.GetBufferSizeXY().X, GSceneRenderTargets.GetBufferSizeXY().Y); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } const FSceneViewFamily& ViewFamily = *View.Family; for(int32 ViewId = 0; ViewId < ViewFamily.Views.Num(); ++ViewId) { const FSceneView& ViewIt = *ViewFamily.Views[ViewId]; FString Line = FString::Printf(TEXT(" View #%d: (%d,%d)-(%d,%d)"), ViewId + 1, ViewIt.ViewRect.Min.X, ViewIt.ViewRect.Min.Y, ViewIt.ViewRect.Max.X, ViewIt.ViewRect.Max.Y); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } X += 40; Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Red: <0"), GetStatsFont(), FLinearColor(1,0,0)); Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Blue: NAN or Inf"), GetStatsFont(), FLinearColor(0,0,1)); Canvas.Flush(); }