From 49b7ce025d6d1e3adb70c28b276a9b7378f57a9f Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 19 Aug 2021 21:53:52 +0300
Subject: [PATCH] SL-7934 Driver version from wrong GPU

---
 indra/llwindow/lldxhardware.cpp | 78 +++++++++++++++++++++++++++++----
 indra/llwindow/lldxhardware.h   | 10 ++++-
 indra/newview/llappviewer.cpp   | 23 +++++++++-
 3 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index 12a6baa3e69..81e938edbe7 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -229,7 +229,7 @@ S32 LLDXHardware::getMBVideoMemoryViaWMI()
 }
 
 //Getting the version of graphics controller driver via WMI
-std::string LLDXHardware::getDriverVersionWMI()
+std::string LLDXHardware::getDriverVersionWMI(EGPUVendor vendor)
 {
 	std::string mDriverVersion;
 	HRESULT hrCoInitialize = S_OK;
@@ -325,15 +325,68 @@ std::string LLDXHardware::getDriverVersionWMI()
 		{
 			break;               // If quantity less then 1.
 		}
+        
+        if (vendor != GPU_ANY)
+        {
+            VARIANT vtCaptionProp;
+            // Might be preferable to check "AdapterCompatibility" here instead of caption.
+            hr = pclsObj->Get(L"Caption", 0, &vtCaptionProp, 0, 0);
+
+            if (FAILED(hr))
+            {
+                LL_WARNS("AppInit") << "Query for Caption property failed." << " Error code = 0x" << hr << LL_ENDL;
+                pSvc->Release();
+                pLoc->Release();
+                CoUninitialize();
+                return std::string();               // Program has failed.
+            }
+
+            // use characters in the returned driver version
+            BSTR caption(vtCaptionProp.bstrVal);
+
+            //convert BSTR to std::string
+            std::wstring ws(caption, SysStringLen(caption));
+            std::string caption_str(ws.begin(), ws.end());
+            LLStringUtil::toLower(caption_str);
+
+            bool found = false;
+            switch (vendor)
+            {
+            case GPU_INTEL:
+                found = caption_str.find("intel") != std::string::npos;
+                break;
+            case GPU_NVIDIA:
+                found = caption_str.find("nvidia") != std::string::npos;
+                break;
+            case GPU_AMD:
+                found = caption_str.find("amd") != std::string::npos
+                        || caption_str.find("ati ") != std::string::npos
+                        || caption_str.find("radeon") != std::string::npos;
+                break;
+            default:
+                break;
+            }
 
-		VARIANT vtProp;
+            if (found)
+            {
+                VariantClear(&vtCaptionProp);
+            }
+            else
+            {
+                VariantClear(&vtCaptionProp);
+                pclsObj->Release();
+                continue;
+            }
+        }
 
-		// Get the value of the Name property
-		hr = pclsObj->Get(L"DriverVersion", 0, &vtProp, 0, 0);
+        VARIANT vtVersionProp;
+
+		// Get the value of the DriverVersion property
+		hr = pclsObj->Get(L"DriverVersion", 0, &vtVersionProp, 0, 0);
 
 		if (FAILED(hr))
 		{
-			LL_WARNS("AppInit") << "Query for name property failed." << " Error code = 0x" << hr << LL_ENDL;
+			LL_WARNS("AppInit") << "Query for DriverVersion property failed." << " Error code = 0x" << hr << LL_ENDL;
 			pSvc->Release();
 			pLoc->Release();
 			CoUninitialize();
@@ -341,7 +394,7 @@ std::string LLDXHardware::getDriverVersionWMI()
 		}
 
 		// use characters in the returned driver version
-		BSTR driverVersion(vtProp.bstrVal);
+		BSTR driverVersion(vtVersionProp.bstrVal);
 
 		//convert BSTR to std::string
 		std::wstring ws(driverVersion, SysStringLen(driverVersion));
@@ -354,10 +407,19 @@ std::string LLDXHardware::getDriverVersionWMI()
 		}
 		else if (mDriverVersion != str)
 		{
-			LL_WARNS("DriverVersion") << "Different versions of drivers. Version of second driver : " << str << LL_ENDL;
+            if (vendor == GPU_ANY)
+            {
+                // Expected from systems with gpus from different vendors
+                LL_INFOS("DriverVersion") << "Multiple video drivers detected. Version of second driver: " << str << LL_ENDL;
+            }
+            else
+            {
+                // Not Expected!
+                LL_WARNS("DriverVersion") << "Multiple video drivers detected from same vendor. Version of second driver : " << str << LL_ENDL;
+            }
 		}
 
-		VariantClear(&vtProp);
+		VariantClear(&vtVersionProp);
 		pclsObj->Release();
 	}
 
diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h
index 1cb687e3b6d..9cec3e2f1bf 100644
--- a/indra/llwindow/lldxhardware.h
+++ b/indra/llwindow/lldxhardware.h
@@ -88,7 +88,15 @@ class LLDXHardware
 	// vram_only TRUE does a "light" probe.
 	BOOL getInfo(BOOL vram_only);
 
-	std::string getDriverVersionWMI();
+    // WMI can return multiple GPU drivers
+    // specify which one to output
+    typedef enum {
+        GPU_INTEL,
+        GPU_NVIDIA,
+        GPU_AMD,
+        GPU_ANY
+    } EGPUVendor;
+	std::string getDriverVersionWMI(EGPUVendor vendor);
 
 	S32 getVRAM() const { return mVRAM; }
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 891722e1bd1..65db910c087 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3165,7 +3165,28 @@ LLSD LLAppViewer::getViewerInfo() const
 	info["GRAPHICS_CARD"] = ll_safe_string((const char*)(glGetString(GL_RENDERER)));
 
 #if LL_WINDOWS
-	std::string drvinfo = gDXHardware.getDriverVersionWMI();
+    std::string drvinfo;
+
+    if (gGLManager.mIsIntel)
+    {
+        drvinfo = gDXHardware.getDriverVersionWMI(LLDXHardware::GPU_INTEL);
+    }
+    else if (gGLManager.mIsNVIDIA)
+    {
+        drvinfo = gDXHardware.getDriverVersionWMI(LLDXHardware::GPU_NVIDIA);
+    }
+    else if (gGLManager.mIsATI)
+    {
+        drvinfo = gDXHardware.getDriverVersionWMI(LLDXHardware::GPU_AMD);
+    }
+
+    if (drvinfo.empty())
+    {
+        // Generic/substitute windows driver? Unknown vendor?
+        LL_WARNS("DriverVersion") << "Vendor based driver search failed, searching for any driver" << LL_ENDL;
+        drvinfo = gDXHardware.getDriverVersionWMI(LLDXHardware::GPU_ANY);
+    }
+
 	if (!drvinfo.empty())
 	{
 		info["GRAPHICS_DRIVER_VERSION"] = drvinfo;
-- 
GitLab