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();
}