Ejemplo n.º 1
0
FQualityLevels BenchmarkQualityLevels()
{
	// benchmark the system

	FQualityLevels Results;

	FSynthBenchmarkResults SynthBenchmark;
	ISynthBenchmark::Get().Run(SynthBenchmark, true);

	float CPUPerfIndex = SynthBenchmark.ComputeCPUPerfIndex();
	float GPUPerfIndex = SynthBenchmark.ComputeGPUPerfIndex();
	float MinPerfIndex = FMath::Min(CPUPerfIndex, GPUPerfIndex);

	// decide on the actual quality needed

	Results.ResolutionQuality = GetRenderScaleLevelFromQualityLevel(ComputeOptionFromPerfIndex(GPUPerfIndex, 15, 45, 70));
	Results.ViewDistanceQuality = ComputeOptionFromPerfIndex(MinPerfIndex, 20, 50, 70);
	Results.AntiAliasingQuality = ComputeOptionFromPerfIndex(GPUPerfIndex, 15, 50, 70);
	Results.ShadowQuality = ComputeOptionFromPerfIndex(MinPerfIndex, 15, 50, 70);
	Results.PostProcessQuality = ComputeOptionFromPerfIndex(GPUPerfIndex, 20, 50, 70);
	Results.TextureQuality = ComputeOptionFromPerfIndex(GPUPerfIndex, 10, 40, 70);
	Results.EffectsQuality = ComputeOptionFromPerfIndex(MinPerfIndex, 25, 55, 70);

	return Results;
}
void FSynthBenchmark::Run(FSynthBenchmarkResults& InOut, bool bGPUBenchmark, float WorkScale) const
{
	check(WorkScale > 0);

	if(!bGPUBenchmark)
	{
		// run a very quick GPU benchmark (less confidence but at least we get some numbers)
		// it costs little time and we get some stats
		WorkScale = 1.0f;
	}

	const double StartTime = FPlatformTime::Seconds();

	UE_LOG(LogSynthBenchmark, Display, TEXT("FSynthBenchmark (V0.95):  requested WorkScale=%.2f"), WorkScale);
	UE_LOG(LogSynthBenchmark, Display, TEXT("==============="));
	
#if UE_BUILD_DEBUG
	UE_LOG(LogSynthBenchmark, Display, TEXT("         Note: Values are not trustable because this is a DEBUG build!"));
#endif
	
	UE_LOG(LogSynthBenchmark, Display, TEXT("Main Processor:"));

	// developer machine: Intel Xeon E5-2660 2.2GHz
	// divided by the actual value on a developer machine to normalize the results
	// Index should be around 100 +-4 on developer machine in a development build (should be the same in shipping)

	InOut.CPUStats[0] = FSynthBenchmarkStat(TEXT("RayIntersect"), 0.02561f, TEXT("s/Run"), 1.f);
	InOut.CPUStats[0].SetMeasuredTime(RunBenchmark(WorkScale, RayIntersectBenchmark));

	InOut.CPUStats[1] = FSynthBenchmarkStat(TEXT("Fractal"), 0.0286f, TEXT("s/Run"), 1.5f);
	InOut.CPUStats[1].SetMeasuredTime(RunBenchmark(WorkScale, FractalBenchmark));

	for(uint32 i = 0; i < ARRAY_COUNT(InOut.CPUStats); ++i)
	{
		UE_LOG(LogSynthBenchmark, Display, TEXT("         ... %f %s '%s'"), InOut.CPUStats[i].GetNormalizedTime(), InOut.CPUStats[i].GetValueType(), InOut.CPUStats[i].GetDesc());
	}

	UE_LOG(LogSynthBenchmark, Display, TEXT(""));

	bool bAppIs64Bit = (sizeof(void*) == 8);

	UE_LOG(LogSynthBenchmark, Display, TEXT("  CompiledTarget_x_Bits: %s"), bAppIs64Bit ? TEXT("64") : TEXT("32"));
	UE_LOG(LogSynthBenchmark, Display, TEXT("  UE_BUILD_SHIPPING: %d"), UE_BUILD_SHIPPING);
	UE_LOG(LogSynthBenchmark, Display, TEXT("  UE_BUILD_TEST: %d"), UE_BUILD_TEST);
	UE_LOG(LogSynthBenchmark, Display, TEXT("  UE_BUILD_DEBUG: %d"), UE_BUILD_DEBUG);

	UE_LOG(LogSynthBenchmark, Display, TEXT("  TotalPhysicalGBRam: %d"), FPlatformMemory::GetPhysicalGBRam());
	UE_LOG(LogSynthBenchmark, Display, TEXT("  NumberOfCores (physical): %d"), FPlatformMisc::NumberOfCores());
	UE_LOG(LogSynthBenchmark, Display, TEXT("  NumberOfCores (logical): %d"), FPlatformMisc::NumberOfCoresIncludingHyperthreads());

	UE_LOG(LogSynthBenchmark, Display, TEXT("  CPU Perf Index 0: %.1f (weight %.2f)"), InOut.CPUStats[0].ComputePerfIndex(), InOut.CPUStats[0].GetWeight());
	UE_LOG(LogSynthBenchmark, Display, TEXT("  CPU Perf Index 1: %.1f (weight %.2f)"), InOut.CPUStats[1].ComputePerfIndex(), InOut.CPUStats[1].GetWeight());
	
	// separator line
	UE_LOG(LogSynthBenchmark, Display, TEXT(" "));

	UE_LOG(LogSynthBenchmark, Display, TEXT("Graphics:"));

	UE_LOG(LogSynthBenchmark, Display, TEXT("  Adapter Name: '%s'"), *GRHIAdapterName);
	UE_LOG(LogSynthBenchmark, Display, TEXT("  (On Optimus the name might be wrong, memory should be ok)"));
	UE_LOG(LogSynthBenchmark, Display, TEXT("  Vendor Id: 0x%x"), GRHIVendorId);

	{
		FTextureMemoryStats Stats;

		RHIGetTextureMemoryStats(Stats);

		if(Stats.AreHardwareStatsValid())
		{
			UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU Memory: %d/%d/%d MB"), 
				FMath::DivideAndRoundUp(Stats.DedicatedVideoMemory, (int64)(1024 * 1024) ),
				FMath::DivideAndRoundUp(Stats.DedicatedSystemMemory, (int64)(1024 * 1024) ),
				FMath::DivideAndRoundUp(Stats.SharedSystemMemory, (int64)(1024 * 1024) ));
		}
	}

	// not always done - cost some time.
	if(bGPUBenchmark)
	{
		IRendererModule& RendererModule = FModuleManager::LoadModuleChecked<IRendererModule>(TEXT("Renderer"));

		// First we run a quick test. If that shows very bad performance we don't need another test
		// The hardware is slow, we don't need a long test and risk driver TDR (driver recovery).
		// We have seen this problem on very low end GPUs.
		{
			const float fFirstWorkScale = 0.01f;
			const float fSecondWorkScale = 0.1f;

			float GPUTime = 0.0f;

			RendererModule.GPUBenchmark(InOut, fFirstWorkScale);
			GPUTime = InOut.ComputeTotalGPUTime();
			UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU first test: %.2fs"), GPUTime);

			for(uint32 MethodId = 0; MethodId < sizeof(InOut.GPUStats) / sizeof(InOut.GPUStats[0]); ++MethodId)
			{
				UE_LOG(LogSynthBenchmark, Display, TEXT("         ... %.3f GigaPix/s, Confidence=%.0f%% '%s' (likely to be very inaccurate)"),
					1.0f / InOut.GPUStats[MethodId].GetNormalizedTime(), InOut.GPUStats[MethodId].GetConfidence(), InOut.GPUStats[MethodId].GetDesc());
			}

			if(GPUTime < 0.1f)
			{
				RendererModule.GPUBenchmark(InOut, fSecondWorkScale);
				GPUTime = InOut.ComputeTotalGPUTime();
				UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU second test: %.2fs"), GPUTime);

				// for testing
				for(uint32 MethodId = 0; MethodId < sizeof(InOut.GPUStats) / sizeof(InOut.GPUStats[0]); ++MethodId)
				{
					UE_LOG(LogSynthBenchmark, Display, TEXT("         ... %.3f GigaPix/s, Confidence=%.0f%% '%s' (likely to be inaccurate)"),
						1.0f / InOut.GPUStats[MethodId].GetNormalizedTime(), InOut.GPUStats[MethodId].GetConfidence(), InOut.GPUStats[MethodId].GetDesc());
				}

				if(GPUTime < 0.1f)
				{
					RendererModule.GPUBenchmark(InOut, WorkScale);
					GPUTime = InOut.ComputeTotalGPUTime();
					UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU third test: %.2fs"), GPUTime);
				}
			}
		}

		for(uint32 MethodId = 0; MethodId < sizeof(InOut.GPUStats) / sizeof(InOut.GPUStats[0]); ++MethodId)
		{
			UE_LOG(LogSynthBenchmark, Display, TEXT("         ... %.3f GigaPix/s, Confidence=%.0f%% '%s'"),
				1.0f / InOut.GPUStats[MethodId].GetNormalizedTime(), InOut.GPUStats[MethodId].GetConfidence(), InOut.GPUStats[MethodId].GetDesc());
		}
		UE_LOG(LogSynthBenchmark, Display, TEXT(""));

		UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU Perf Index 0: %.1f (weight %.2f)"), InOut.GPUStats[0].ComputePerfIndex(), InOut.GPUStats[0].GetWeight());
		UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU Perf Index 1: %.1f (weight %.2f)"), InOut.GPUStats[1].ComputePerfIndex(), InOut.GPUStats[1].GetWeight());
		UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU Perf Index 2: %.1f (weight %.2f)"), InOut.GPUStats[2].ComputePerfIndex(), InOut.GPUStats[2].GetWeight());
		UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU Perf Index 3: %.1f (weight %.2f)"), InOut.GPUStats[3].ComputePerfIndex(), InOut.GPUStats[3].GetWeight());
		UE_LOG(LogSynthBenchmark, Display, TEXT("  GPU Perf Index 4: %.1f (weight %.2f)"), InOut.GPUStats[4].ComputePerfIndex(), InOut.GPUStats[4].GetWeight());
	}
	
	UE_LOG(LogSynthBenchmark, Display, TEXT("  CPUIndex: %.1f"), InOut.ComputeCPUPerfIndex());

	if(bGPUBenchmark)
	{
		UE_LOG(LogSynthBenchmark, Display, TEXT("  GPUIndex: %.1f"), InOut.ComputeGPUPerfIndex());
	}

	UE_LOG(LogSynthBenchmark, Display, TEXT(""));
	UE_LOG(LogSynthBenchmark, Display, TEXT("         ... Total Time: %f sec"),  (float)(FPlatformTime::Seconds() - StartTime));
}