diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9fb993697..58ca6a9ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -874,6 +874,7 @@ set (PCH_SOURCES d_dehacked.cpp d_iwad.cpp d_main.cpp + d_stats.cpp d_net.cpp d_netinfo.cpp d_protocol.cpp diff --git a/src/d_main.cpp b/src/d_main.cpp index 15fcaada3..6338f9b04 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -118,10 +118,11 @@ #include "vm.h" #include "types.h" #include "r_data/r_vanillatrans.h" -#include "d_stats.cpp" EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); +void D_DoAnonStats(); + // MACROS ------------------------------------------------------------------ diff --git a/src/d_stats.cpp b/src/d_stats.cpp index 797cd3ccc..a2df44318 100644 --- a/src/d_stats.cpp +++ b/src/d_stats.cpp @@ -1,52 +1,131 @@ #if defined(_WIN32) -#include - -EXTERN_CVAR(Bool, gl_legacy_mode) -EXTERN_CVAR(Bool, vid_glswfb) -extern int currentrenderer, sys_ostype, restart; -CVAR(String, sys_statshost, "gzstats.drdteam.org", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -CVAR(Int, sys_statsport, 80, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -void D_DoHTTPRequest(char* request); +#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN +#include +extern int sys_ostype; #endif +#include +#include "c_cvars.h" +#include "x86.h" +#include "version.h" +#include "v_video.h" + +EXTERN_CVAR(Bool, vid_glswfb) +extern int currentrenderer; +CVAR(String, sys_statshost, "gzstats.drdteam.org", CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) +CVAR(Int, sys_statsport, 80, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) + +// Each machine will only send two reports, one when started with hardware rendering and one when started with software rendering. +CVAR(Bool, sentstats_swr, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) +CVAR(Bool, sentstats_hwr, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) + +std::pair gl_getInfo(); +bool I_HTTPRequest(const char* request); + + +static int GetOSVersion() +{ +#ifdef _WIN32 + if (sys_ostype == 1) return 1; + if (sizeof(void*) == 4) // 32 bit + { + BOOL res; + if (IsWow64Process(GetCurrentProcess(), &res)) + { + return 6; + } + if (sys_ostype == 2) return 2; + else return 4; + } + else + { + if (sys_ostype == 2) return 3; + else return 5; + } + +#elif defined __APPLE__ + + if (sizeof(void*) == 4) // 32 bit + { + return 7; + } + else + { + return 8; + } + +#else + + // Todo: PPC + ARM + + if (sizeof(void*) == 4) // 32 bit + { + return 11; + } + else + { + return 12; + } + + +#endif +} + +static int GetCoreInfo() +{ + int cores = std::thread::hardware_concurrency(); + if (CPU.HyperThreading) cores /= 2; + return cores < 2? 0 : cores < 4? 1 : cores < 6? 2 : cores < 8? 3 : 4; +} + +static int GetRenderInfo() +{ + if (currentrenderer == 0) + { + if (!screen->Accel2D) return 0; + if (vid_glswfb) return 2; + if (screen->LegacyHardware()) return 6; + return 1; + } + else + { + auto info = gl_getInfo(); + if (info.first < 3.3) return 3; // Legacy OpenGL. Don't care about Intel HD 3000 on Windows being run in 'risky' mode. + if (!info.second) return 4; + return 5; + } +} + +static void D_DoHTTPRequest(const char *request) +{ + if (I_HTTPRequest(request)) + { + if (currentrenderer == 0) + { + cvar_forceset("sentstats_swr", "1"); + } + else + { + cvar_forceset("sentstats_hwr", "1"); + } + } +} + void D_DoAnonStats() { -#if defined(_WIN32) - uint8_t astat_render, astat_sysbits; - static char* requeststring = new char[512]; - // astat_render: - // 0: Unaccelerated (Software) - // 1: Direct3D (Software) - // 2: OpenGL (Software) - // 3: Legacy OpenGL mode - // 4: Modern OpenGL (>3.3) path + static bool done = false; // do this only once per session. + if (done) return; + done = true; - // sys_ostype: - // 0: unknown/outdated - // 1: legacy (XP/Vista) - // 2: supported (7/8/8.1) - // 3: modern (10+) + // Do not repeat if already sent. + if (currentrenderer == 0 && sentstats_swr) return; + if (currentrenderer == 1 && sentstats_hwr) return; - // astat_sysbits: - // 0: 32-bit - // 1: 64-bit - - if (!restart) - { - astat_render = (currentrenderer == 1) ? - (gl_legacy_mode ? 3 : 4) : // opengl - (!(screen->Accel2D)) ? 0 : (vid_glswfb ? 2 : 1); // software -#ifdef _WIN64 - astat_sysbits = 1; -#else - astat_sysbits = 0; -#endif - sprintf(requeststring, "GET /stats.php?render=%i&bits=%i&os=%i HTTP/1.1\nHost: %s\nConnection: close\nUser-Agent: %s %s\n\n", - astat_render, astat_sysbits, sys_ostype, sys_statshost.GetHumanString(), GAMENAME, VERSIONSTR); - //Printf("%s", requeststring); - std::thread t1(D_DoHTTPRequest, requeststring); - t1.detach(); - } -#endif + FStringf requeststring("GET /stats.php?render=%i&cores=%i&os=%i HTTP/1.1\nHost: %s\nConnection: close\nUser-Agent: %s %s\n\n", + GetRenderInfo(), GetCoreInfo(), GetOSVersion(), sys_statshost.GetHumanString(), GAMENAME, VERSIONSTR); + DPrintf(DMSG_NOTIFY, "Sending %s", requeststring); + std::thread t1(D_DoHTTPRequest, requeststring); + t1.detach(); } diff --git a/src/gl/system/gl_interface.cpp b/src/gl/system/gl_interface.cpp index 1ac8b33fe..3f0fe4dbf 100644 --- a/src/gl/system/gl_interface.cpp +++ b/src/gl/system/gl_interface.cpp @@ -41,6 +41,7 @@ void gl_PatchMenu(); static TArray m_Extensions; RenderContext gl; +static double realglversion; // this is public so the statistics code can access it. EXTERN_CVAR(Bool, gl_legacy_mode) extern int currentrenderer; @@ -59,7 +60,7 @@ static void CollectExtensions() int max = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &max); - if (0 == max) + if (max == 0) { // Try old method to collect extensions const char *supported = (char *)glGetString(GL_EXTENSIONS); @@ -144,6 +145,8 @@ void gl_LoadExtensions() } const char *version = Args->CheckValue("-glversion"); + realglversion = strtod(glversion, NULL); + if (version == NULL) { @@ -152,9 +155,8 @@ void gl_LoadExtensions() else { double v1 = strtod(version, NULL); - double v2 = strtod(glversion, NULL); if (v1 >= 3.0 && v1 < 3.3) v1 = 3.3; // promote '3' to 3.3 to avoid falling back to the legacy path. - if (v2 < v1) version = glversion; + if (realglversion < v1) version = glversion; else Printf("Emulating OpenGL v %s\n", version); } @@ -385,3 +387,9 @@ void gl_PrintStartupLog() } +std::pair gl_getInfo() +{ + // gl_ARB_bindless_texture is the closest we can get to determine Vulkan support from OpenGL. + // This isn't foolproof because Intel doesn't support it but for NVidia and AMD support of this extension means Vulkan support. + return std::make_pair(realglversion, CheckExtension("GL_ARB_bindless_texture")); +} \ No newline at end of file diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index 3be9a067c..4de8047e9 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -386,3 +386,8 @@ TArray I_GetGogPaths() // GOG's Doom games are Windows only at the moment return TArray(); } + +bool I_HTTPRequest(const char* request) +{ + // todo +} diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index f980e2598..b3fa1eda7 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -489,3 +489,9 @@ TArray I_GetGogPaths() // GOG's Doom games are Windows only at the moment return TArray(); } + + +bool I_HTTPRequest(const char* request) +{ + // todo +} diff --git a/src/v_video.h b/src/v_video.h index 1d7abd581..4d30cb0ef 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -405,6 +405,7 @@ public: virtual void SetBlendingRect (int x1, int y1, int x2, int y2); bool Accel2D; // If true, 2D drawing can be accelerated. + virtual bool LegacyHardware() const { return false; } // only for reporting SM1.4 support to the stat collector // Begin 2D drawing operations. This is like Update, but it doesn't end // the scene, and it doesn't present the image yet. If you are going to diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index df0bb3cdb..17da1ff6d 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -515,16 +515,16 @@ CCMD (vid_currentmode) EXTERN_CVAR(String, sys_statshost) EXTERN_CVAR(Int, sys_statsport) -void D_DoHTTPRequest(char* request) +bool I_HTTPRequest(const char* request) { if (sys_statshost.GetHumanString() == NULL) - return; // no host, disable + return false; // no host, disable WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { DPrintf(DMSG_ERROR, "WSAStartup failed.\n"); - return; + return false; } SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct hostent *host; @@ -537,9 +537,9 @@ void D_DoHTTPRequest(char* request) if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) { DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); - return; + return false; } - send(Socket, request, strlen(request), 0); + send(Socket, request, (int)strlen(request), 0); char buffer[1024]; int nDataLength; while ((nDataLength = recv(Socket, buffer, 1024, 0)) > 0) @@ -553,5 +553,5 @@ void D_DoHTTPRequest(char* request) closesocket(Socket); WSACleanup(); DPrintf(DMSG_NOTIFY, "Stats send successful.\n"); - return; + return true; } diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index ba829d959..50bc7d8d0 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -243,7 +243,7 @@ void I_DetectOS(void) if (info.dwMinorVersion == 0) { osname = (info.wProductType == VER_NT_WORKSTATION) ? "Vista" : "Server 2008"; - sys_ostype = 1; // legacy OS + sys_ostype = 2; // legacy OS } else if (info.dwMinorVersion == 1) { diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index d2cea2024..d3523e17b 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -147,6 +147,7 @@ public: HRESULT GetHR (); bool Is8BitMode() { return false; } virtual int GetTrueHeight() { return TrueHeight; } + virtual bool LegacyHardware() const { return SM14; } private: friend class D3DTex; diff --git a/src/x86.cpp b/src/x86.cpp index b8c2d01d0..877bd726d 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -143,6 +143,8 @@ haveid: cpu->FeatureFlags[1] = foo[2]; // Store extended feature flags cpu->FeatureFlags[2] = foo[3]; // Store feature flags + cpu->HyperThreading = (foo[3] & (1 << 28)) > 0; + // If CLFLUSH instruction is supported, get the real cache line size. if (foo[3] & (1 << 19)) { @@ -251,6 +253,7 @@ void DumpCPUInfo(const CPUInfo *cpu) if (cpu->bSSE42) Printf(" SSE4.2"); if (cpu->b3DNow) Printf(" 3DNow!"); if (cpu->b3DNowPlus) Printf(" 3DNow!+"); + if (cpu->HyperThreading) Printf(" HyperThreading"); Printf ("\n"); } } diff --git a/src/x86.h b/src/x86.h index 1839e2c35..9c0f0f170 100644 --- a/src/x86.h +++ b/src/x86.h @@ -20,6 +20,7 @@ struct CPUInfo // 92 bytes uint8_t Model; uint8_t Family; uint8_t Type; + uint8_t HyperThreading; union {