瀏覽代碼

When logging an error report, log the system information as well

BearishSun 8 年之前
父節點
當前提交
36c515ba66

+ 8 - 0
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -70,6 +70,14 @@ namespace bs { namespace ct
 		mActiveD3DDriver = mDriverList->item(0); // TODO: Always get first driver, for now
 		mVideoModeInfo = mActiveD3DDriver->getVideoModeInfo();
 
+		GPUInfo gpuInfo;
+		gpuInfo.numGPUs = std::min(5U, mDriverList->count());
+
+		for(UINT32 i = 0; i < gpuInfo.numGPUs; i++)
+			gpuInfo.names[i] = mDriverList->item(i)->getDriverName();
+
+		PlatformUtility::_setGPUInfo(gpuInfo);
+
 		IDXGIAdapter* selectedAdapter = mActiveD3DDriver->getDeviceAdapter();
 
 		D3D_FEATURE_LEVEL requestedLevels[] = {

+ 9 - 0
Source/BansheeGLRenderAPI/Source/BsGLRenderAPI.cpp

@@ -141,6 +141,15 @@ namespace bs { namespace ct
 		// Ensure cubemaps are filtered across seams
 		glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
 
+		GPUInfo gpuInfo;
+		gpuInfo.numGPUs = 1;
+
+		const char* vendor = (const char*)glGetString(GL_VENDOR);
+		const char* renderer = (const char*)glGetString(GL_RENDERER);
+		gpuInfo.names[0] = String(vendor) + " " + String(renderer);
+
+		PlatformUtility::_setGPUInfo(gpuInfo);
+
 		mGLInitialised = true;
 
 		RenderAPI::initializeWithWindow(primaryWindow);

+ 38 - 0
Source/BansheeUtility/Include/BsPlatformUtility.h

@@ -24,6 +24,27 @@ namespace bs
 		TypeMask = 0xFFFF
 	};
 
+	/** Contains information about available GPUs on the system. */
+	struct GPUInfo
+	{
+		String names[5];
+		UINT32 numGPUs;
+	};
+
+	/** Contains information about the system hardware and operating system. */
+	struct SystemInfo
+	{
+		String cpuManufacturer;
+		String cpuModel;
+		UINT32 cpuClockSpeedMhz;
+		UINT32 cpuNumCores;
+		UINT32 memoryAmountMb;
+		String osName;
+		bool osIs64Bit;
+
+		GPUInfo gpuInfo;
+	};
+
 	/** Provides access to various operating system specific utility functions. */
 	class BS_UTILITY_EXPORT PlatformUtility
 	{
@@ -68,6 +89,9 @@ namespace bs
 		 */
 		static bool getMACAddress(MACAddress& address);
 
+		/** Returns information about the underlying hardware. */
+		static SystemInfo getSystemInfo();
+
 		/** Creates a new universally unique identifier and returns it as a string. */
 		static String generateUUID();
 
@@ -78,6 +102,20 @@ namespace bs
 		 * @param[in]	path	Absolute path to the file or folder to open.
 		 */
 		static void open(const Path& path);
+
+		/** @name Internal
+		 *  @{
+		 */
+
+		/** 
+		 * Assigns information about GPU hardware. This data will be returned by getSystemInfo() when requested. This is
+		 * expeced to be called by the render API backend when initialized.
+		 */
+		static void _setGPUInfo(GPUInfo gpuInfo) { sGPUInfo = gpuInfo; }
+		/** @} */
+
+	private:
+		static GPUInfo sGPUInfo;
 	};
 
 	/** Represents a MAC (ethernet) address. */

+ 10 - 13
Source/BansheeUtility/Source/BsCrashHandler.cpp

@@ -10,7 +10,7 @@ namespace bs
 	const String CrashHandler::sCrashReportFolder = "CrashReports";
 	const String CrashHandler::sCrashLogName = "log.html";
 	const String CrashHandler::sFatalErrorMsg =
-	    "A fatal error occurred and the program has to terminate!";
+		"A fatal error occurred and the program has to terminate!";
 
 	CrashHandler& gCrashHandler()
 	{
@@ -19,20 +19,20 @@ namespace bs
 
 	const Path& CrashHandler::getCrashFolder()
 	{
-		static const Path path =
-			FileSystem::getWorkingDirectoryPath()
-			+ Path(sCrashReportFolder)
-			+ Path(getCrashTimestamp());
+		static const Path path = FileSystem::getWorkingDirectoryPath() + sCrashReportFolder + 
+			getCrashTimestamp();
+		
 		static bool first = true;
-		if (first) {
+		if (first) 
+		{
 			FileSystem::createDir(path);
 			first = false;
 		}
+
 		return path;
 	}
 
-	void CrashHandler::logErrorAndStackTrace(const String& errorMsg,
-	                                         const String& stackTrace) const
+	void CrashHandler::logErrorAndStackTrace(const String& errorMsg, const String& stackTrace) const
 	{
 		StringStream errorMessage;
 		errorMessage << sFatalErrorMsg << std::endl;
@@ -43,11 +43,8 @@ namespace bs
 		gDebug().logError(errorMessage.str());
 	}
 
-	void CrashHandler::logErrorAndStackTrace(const String& type,
-	                                         const String& description,
-	                                         const String& function,
-	                                         const String& file,
-	                                         UINT32 line) const
+	void CrashHandler::logErrorAndStackTrace(const String& type, const String& description, const String& function,
+		const String& file, UINT32 line) const
 	{
 		StringStream errorMessage;
 		errorMessage << "  - Error: " << type << std::endl;

+ 29 - 2
Source/BansheeUtility/Source/BsDebug.cpp

@@ -191,8 +191,10 @@ table td
 <title>Banshee Engine Log</title>
 </head>
 <body>
-<h1>Banshee Engine Log</h1>
-<table border="1" cellpadding="1" cellspacing="1">
+)";
+
+		static const char* htmlEntriesTableHeader =
+			R"(<table border="1" cellpadding="1" cellspacing="1">
 	<thead>
 		<tr>
 			<th scope="col" style="width:60px">Type</th>
@@ -212,6 +214,31 @@ table td
 		stream << htmlPreStyleHeader;
 		stream << style;
 		stream << htmlPostStyleHeader;
+		stream << "<h1>Banshee Engine Log</h1>\n";
+
+		stream << "<h2>System information</h2>\n";
+
+		// Write header information
+		stream << "<p>Banshee version: " << BS_VERSION_MAJOR << "." << BS_VERSION_MINOR << "</p>\n";
+
+		SystemInfo systemInfo = PlatformUtility::getSystemInfo();
+		stream << "<p>OS version: " << systemInfo.osName << " " << (systemInfo.osIs64Bit ? "64-bit" : "32-bit") << "</p>\n";
+		stream << "<p>CPU vendor: " << systemInfo.cpuManufacturer << "</p>\n";
+		stream << "<p>CPU name: " << systemInfo.cpuModel << "</p>\n";
+		stream << "<p>CPU clock speed: " << systemInfo.cpuClockSpeedMhz << "Mhz</p>\n";
+		stream << "<p>CPU core count: " << systemInfo.cpuNumCores << "</p>\n";
+
+		if(systemInfo.gpuInfo.numGPUs == 1)
+			stream << "<p>GPU: " << systemInfo.gpuInfo.names[0] << "</p>\n";
+		else
+		{
+			for(UINT32 i = 0; i < systemInfo.gpuInfo.numGPUs; i++)
+				stream << "<p>GPU #" << i << ": " << systemInfo.gpuInfo.names[i] << "</p>\n";
+		}
+
+		// Write log entries
+		stream << "<h2>Log entries</h2>\n";
+		stream << htmlEntriesTableHeader;
 
 		bool alternate = false;
 		Vector<LogEntry> entries = mLog.getAllEntries();

+ 3 - 6
Source/BansheeUtility/Source/Win32/BsWin32CrashHandler.cpp

@@ -456,11 +456,8 @@ namespace bs
 		MessageBoxW(nullptr, simpleErrorMessage.c_str(), L"Banshee fatal error!", MB_OK);
 
 	}
-	void CrashHandler::reportCrash(const String& type,
-	                               const String& description,
-	                               const String& function,
-	                               const String& file,
-	                               UINT32 line) const
+	void CrashHandler::reportCrash(const String& type, const String& description, const String& function, 
+		const String& file, UINT32 line) const
 	{
 		// Win32 debug methods are not thread safe
 		Lock(m->mutex);
@@ -485,7 +482,7 @@ namespace bs
 		win32_loadSymbols();
 
 		logErrorAndStackTrace(win32_getExceptionMessage(exceptionData->ExceptionRecord),
-		                      win32_getStackTrace(*exceptionData->ContextRecord, 0));
+			win32_getStackTrace(*exceptionData->ContextRecord, 0));
 		saveCrashLog();
 
 		win32_writeMiniDump(getCrashFolder() + String(sMiniDumpName), exceptionData);

+ 107 - 0
Source/BansheeUtility/Source/Win32/BsWin32PlatformUtility.cpp

@@ -5,9 +5,12 @@
 #include "BsColor.h"
 #include <windows.h>
 #include <iphlpapi.h>
+#include <VersionHelpers.h>
 
 namespace bs
 {
+	GPUInfo PlatformUtility::sGPUInfo;
+
 	void PlatformUtility::terminate(bool force)
 	{
 		if (!force)
@@ -122,6 +125,110 @@ namespace bs
 		return false;
 	}
 
+	typedef LONG NTSTATUS, *PNTSTATUS;
+	typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+
+	RTL_OSVERSIONINFOW GetRealOSVersion() 
+	{
+		HMODULE handle = GetModuleHandleW(L"ntdll.dll");
+		if (handle) 
+		{
+			RtlGetVersionPtr rtlGetVersionFunc = (RtlGetVersionPtr)GetProcAddress(handle, "RtlGetVersion");
+			if (rtlGetVersionFunc != nullptr) 
+			{
+				RTL_OSVERSIONINFOW rovi = { 0 };
+				rovi.dwOSVersionInfoSize = sizeof(rovi);
+				if (rtlGetVersionFunc(&rovi) == 0)
+					return rovi;
+			}
+		}
+
+		RTL_OSVERSIONINFOW rovi = { 0 };
+		return rovi;
+	}
+
+	SystemInfo PlatformUtility::getSystemInfo()
+	{
+		SystemInfo output;
+
+		INT32 CPUInfo[4] = { -1 };
+
+		// Get CPU manufacturer
+		__cpuid(CPUInfo, 0);
+		output.cpuManufacturer = String(12, ' ');
+		memcpy((char*)output.cpuManufacturer.data(), &CPUInfo[1], 4);
+		memcpy((char*)output.cpuManufacturer.data() + 4, &CPUInfo[3], 4);
+		memcpy((char*)output.cpuManufacturer.data() + 8, &CPUInfo[2], 4);
+
+		// Get CPU brand string
+		char brandString[48];
+
+		//// Get the information associated with each extended ID.
+		__cpuid(CPUInfo, 0x80000000);
+		UINT32 numExtensionIds = CPUInfo[0];
+		for (UINT32 i = 0x80000000; i <= numExtensionIds; ++i)
+		{
+			__cpuid(CPUInfo, i);
+
+			if (i == 0x80000002)
+				memcpy(brandString, CPUInfo, sizeof(CPUInfo));
+			else if (i == 0x80000003)
+				memcpy(brandString + 16, CPUInfo, sizeof(CPUInfo));
+			else if (i == 0x80000004)
+				memcpy(brandString + 32, CPUInfo, sizeof(CPUInfo));
+		}
+
+		output.cpuModel = brandString;
+
+		// Get number of CPU cores
+		SYSTEM_INFO sysInfo;
+		GetSystemInfo(&sysInfo);
+		output.cpuNumCores = (UINT32)sysInfo.dwNumberOfProcessors;
+
+		// Get CPU clock speed
+		HKEY hKey;
+
+		long status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, 
+			&hKey);
+
+		if (status == ERROR_SUCCESS)
+		{
+			DWORD mhz;
+			DWORD bufferSize = 4;
+			RegQueryValueEx(hKey, "~MHz", NULL, NULL, (LPBYTE) &mhz, &bufferSize);
+
+			output.cpuClockSpeedMhz = (UINT32)mhz;
+		}
+		else
+			output.cpuClockSpeedMhz = 0;
+
+		// Get amount of system memory
+		MEMORYSTATUSEX statex;
+		statex.dwLength = sizeof(statex);
+		GlobalMemoryStatusEx(&statex);
+
+		output.memoryAmountMb = (UINT32)(statex.ullTotalPhys / (1024 * 1024));
+
+		if (BS_ARCH_TYPE == BS_ARCHITECTURE_x86_64)
+			output.osIs64Bit = true;
+		else
+		{
+			HANDLE process = GetCurrentProcess();
+			BOOL is64Bit = false;
+			IsWow64Process(process, (PBOOL)&is64Bit);
+
+			output.osIs64Bit = is64Bit > 0;
+		}
+
+		// Get OS version
+		output.osName = "Windows " + toString((UINT32)GetRealOSVersion().dwMajorVersion);
+
+		// Get GPU info
+		output.gpuInfo = sGPUInfo;
+
+		return output;
+	}
+
 	String PlatformUtility::generateUUID()
 	{
 		UUID uuid;

+ 8 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanRenderAPI.cpp

@@ -220,6 +220,14 @@ namespace bs { namespace ct
 		static_assert(false, "mVideoModeInfo needs to be created.")
 #endif
 
+		GPUInfo gpuInfo;
+		gpuInfo.numGPUs = std::min(5U, mNumDevices);
+
+		for(UINT32 i = 0; i < gpuInfo.numGPUs; i++)
+			gpuInfo.names[i] = mDevices[i]->getDeviceProperties().deviceName;
+
+		PlatformUtility::_setGPUInfo(gpuInfo);
+
 		// Get required extension functions
 		GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceSupportKHR);
 		GET_INSTANCE_PROC_ADDR(mInstance, GetPhysicalDeviceSurfaceFormatsKHR);