Add Adapter::GetDeviceType() (integrate vs. discrete vs. CPU)

BUG=chromium:852089
Change-Id: Ia447448392e09c5d604ae038b4758776ed3e66ee
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/5180
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/Adapter.cpp b/src/dawn_native/Adapter.cpp
index 137a1c7..e108acc 100644
--- a/src/dawn_native/Adapter.cpp
+++ b/src/dawn_native/Adapter.cpp
@@ -26,6 +26,10 @@
         return mBackend;
     }
 
+    DeviceType AdapterBase::GetDeviceType() const {
+        return mDeviceType;
+    }
+
     const PCIInfo& AdapterBase::GetPCIInfo() const {
         return mPCIInfo;
     }
diff --git a/src/dawn_native/Adapter.h b/src/dawn_native/Adapter.h
index bb15e70..6f1c0b2 100644
--- a/src/dawn_native/Adapter.h
+++ b/src/dawn_native/Adapter.h
@@ -29,6 +29,7 @@
         virtual ~AdapterBase() = default;
 
         BackendType GetBackendType() const;
+        DeviceType GetDeviceType() const;
         const PCIInfo& GetPCIInfo() const;
         InstanceBase* GetInstance() const;
 
@@ -36,6 +37,7 @@
 
       protected:
         PCIInfo mPCIInfo = {};
+        DeviceType mDeviceType = DeviceType::Unknown;
 
       private:
         virtual ResultOrError<DeviceBase*> CreateDeviceImpl() = 0;
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index 5ae9074..7330f84 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -41,6 +41,10 @@
         return mImpl->GetBackendType();
     }
 
+    DeviceType Adapter::GetDeviceType() const {
+        return mImpl->GetDeviceType();
+    }
+
     const PCIInfo& Adapter::GetPCIInfo() const {
         return mImpl->GetPCIInfo();
     }
diff --git a/src/dawn_native/d3d12/AdapterD3D12.cpp b/src/dawn_native/d3d12/AdapterD3D12.cpp
index 215bd46..61750c5 100644
--- a/src/dawn_native/d3d12/AdapterD3D12.cpp
+++ b/src/dawn_native/d3d12/AdapterD3D12.cpp
@@ -43,6 +43,13 @@
         mPCIInfo.deviceId = adapterDesc.DeviceId;
         mPCIInfo.vendorId = adapterDesc.VendorId;
 
+        if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
+            mDeviceType = DeviceType::CPU;
+        } else {
+            // TODO(cwallez@chromium.org): properly detect integrated vs. discrete.
+            mDeviceType = DeviceType::DiscreteGPU;
+        }
+
         std::wstring_convert<DeletableFacet<std::codecvt<wchar_t, char, std::mbstate_t>>> converter(
             "Error converting");
         mPCIInfo.name = converter.to_bytes(adapterDesc.Description);
diff --git a/src/dawn_native/metal/BackendMTL.mm b/src/dawn_native/metal/BackendMTL.mm
index 7030060..2b2f6e2 100644
--- a/src/dawn_native/metal/BackendMTL.mm
+++ b/src/dawn_native/metal/BackendMTL.mm
@@ -129,6 +129,12 @@
                 mPCIInfo.deviceId = GetEntryProperty(entry, CFSTR("device-id"));
                 IOObjectRelease(entry);
             }
+
+            if ([device isLowPower]) {
+                mDeviceType = DeviceType::IntegratedGPU;
+            } else {
+                mDeviceType = DeviceType::DiscreteGPU;
+            }
         }
 
         ~Adapter() override {
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index 30e501c..3476f1a 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -28,6 +28,7 @@
       public:
         Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::Null) {
             mPCIInfo.name = "Null backend";
+            mDeviceType = DeviceType::CPU;
         }
         virtual ~Adapter() = default;
 
diff --git a/src/dawn_native/vulkan/AdapterVk.cpp b/src/dawn_native/vulkan/AdapterVk.cpp
index 60c350a..d87fdcc 100644
--- a/src/dawn_native/vulkan/AdapterVk.cpp
+++ b/src/dawn_native/vulkan/AdapterVk.cpp
@@ -44,6 +44,21 @@
         mPCIInfo.vendorId = mDeviceInfo.properties.vendorID;
         mPCIInfo.name = mDeviceInfo.properties.deviceName;
 
+        switch (mDeviceInfo.properties.deviceType) {
+            case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
+                mDeviceType = DeviceType::IntegratedGPU;
+                break;
+            case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
+                mDeviceType = DeviceType::DiscreteGPU;
+                break;
+            case VK_PHYSICAL_DEVICE_TYPE_CPU:
+                mDeviceType = DeviceType::CPU;
+                break;
+            default:
+                mDeviceType = DeviceType::Unknown;
+                break;
+        }
+
         return {};
     }
 
diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h
index 82dc006..7d9fa72 100644
--- a/src/include/dawn_native/DawnNative.h
+++ b/src/include/dawn_native/DawnNative.h
@@ -37,6 +37,13 @@
         Vulkan,
     };
 
+    enum class DeviceType {
+        DiscreteGPU,
+        IntegratedGPU,
+        CPU,
+        Unknown,
+    };
+
     class InstanceBase;
     class AdapterBase;
 
@@ -53,6 +60,7 @@
         ~Adapter();
 
         BackendType GetBackendType() const;
+        DeviceType GetDeviceType() const;
         const PCIInfo& GetPCIInfo() const;
 
         explicit operator bool() const;
diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp
index 6747b38..098bcee 100644
--- a/src/tests/DawnTest.cpp
+++ b/src/tests/DawnTest.cpp
@@ -52,6 +52,21 @@
         }
     }
 
+    const char* DeviceTypeName(dawn_native::DeviceType type) {
+        switch (type) {
+            case dawn_native::DeviceType::DiscreteGPU:
+                return "Discrete GPU";
+            case dawn_native::DeviceType::IntegratedGPU:
+                return "Integrated GPU";
+            case dawn_native::DeviceType::CPU:
+                return "CPU";
+            case dawn_native::DeviceType::Unknown:
+                return "Unknown";
+            default:
+                UNREACHABLE();
+        }
+    }
+
     struct MapReadUserdata {
         DawnTest* test;
         size_t slot;
@@ -130,7 +145,9 @@
         deviceId << std::setfill('0') << std::uppercase << std::internal << std::hex << std::setw(4)
                  << pci.deviceId;
 
-        std::cout << " - \"" << pci.name << "\" on " << ParamName(adapter.GetBackendType()) << "\n";
+        std::cout << " - \"" << pci.name << "\"\n";
+        std::cout << "   type: " << DeviceTypeName(adapter.GetDeviceType())
+                  << ", backend: " << ParamName(adapter.GetBackendType()) << "\n";
         std::cout << "   vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
                   << "\n";
     }