Report GPU arch on Metal devices with no vendorID
This change attempts to better classify devices with a Metal backend
that aren't currently reporting vendor/device ID. In practice this
mostly means Apple-produced GPUs, like the M1 series.
Bug: dawn:1443
Change-Id: I9e8467a50c9f8eeccc00863f6dee32c0f91380dd
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/92123
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: Brandon Jones <bajones@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/common/BUILD.gn b/src/dawn/common/BUILD.gn
index a9ecded..c843e86 100644
--- a/src/dawn/common/BUILD.gn
+++ b/src/dawn/common/BUILD.gn
@@ -192,7 +192,7 @@
script = "${dawn_root}/generator/dawn_gpu_info_generator.py"
args = [
"--gpu-info-json",
- rebase_path("${dawn_root}/gpu_info.json", root_build_dir),
+ rebase_path("${dawn_root}/src/dawn/gpu_info.json", root_build_dir),
]
outputs = [
"src/dawn/common/GPUInfo_autogen.h",
diff --git a/src/dawn/common/CMakeLists.txt b/src/dawn/common/CMakeLists.txt
index 7e1c373..a2741d1 100644
--- a/src/dawn/common/CMakeLists.txt
+++ b/src/dawn/common/CMakeLists.txt
@@ -24,7 +24,7 @@
SCRIPT "${Dawn_SOURCE_DIR}/generator/dawn_gpu_info_generator.py"
PRINT_NAME "Dawn GPU info utilities"
ARGS "--gpu-info-json"
- "${Dawn_SOURCE_DIR}/gpu_info.json"
+ "${Dawn_SOURCE_DIR}/src/dawn/gpu_info.json"
RESULT_VARIABLE "DAWN_GPU_INFO_AUTOGEN_SOURCES"
)
diff --git a/gpu_info.json b/src/dawn/gpu_info.json
similarity index 86%
rename from gpu_info.json
rename to src/dawn/gpu_info.json
index d969962..6a1ddc0 100644
--- a/gpu_info.json
+++ b/src/dawn/gpu_info.json
@@ -33,7 +33,15 @@
},
"Apple": {
- "id": "0x106b"
+ "id": "0x106b",
+
+ "_comment": [
+ "Apple GPUs do not report a DeviceID via the Metal API, and as such the typical device",
+ "pattern matching does not work for them. The recommended approach is to find the highest",
+ "supported 'common' family supported and report it as the architecture.",
+ "Examples: 'common-1', 'common-3'",
+ "https://developer.apple.com/documentation/metal/gpu_devices_and_work_submission/detecting_gpu_features_and_metal_software_versions"
+ ]
},
"ARM": {
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 53580aa..b1c015d 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -33,6 +33,8 @@
MaybeError AdapterBase::Initialize() {
DAWN_TRY_CONTEXT(InitializeImpl(), "initializing adapter (backend=%s)", mBackend);
+ InitializeVendorArchitectureImpl();
+
DAWN_TRY_CONTEXT(
InitializeSupportedFeaturesImpl(),
"gathering supported features for \"%s\" - \"%s\" (vendorId=%#06x deviceId=%#06x "
@@ -44,9 +46,6 @@
"backend=%s type=%s)",
mName, mDriverDescription, mVendorId, mDeviceId, mBackend, mAdapterType);
- mVendorName = gpu_info::GetVendorName(mVendorId);
- mArchitectureName = gpu_info::GetArchitectureName(mVendorId, mDeviceId);
-
// Enforce internal Dawn constants.
mLimits.v1.maxVertexBufferArrayStride =
std::min(mLimits.v1.maxVertexBufferArrayStride, kMaxVertexBufferArrayStride);
@@ -138,6 +137,11 @@
callback(status, ToAPI(device.Detach()), nullptr, userdata);
}
+void AdapterBase::InitializeVendorArchitectureImpl() {
+ mVendorName = gpu_info::GetVendorName(mVendorId);
+ mArchitectureName = gpu_info::GetArchitectureName(mVendorId, mDeviceId);
+}
+
uint32_t AdapterBase::GetVendorId() const {
return mVendorId;
}
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index a02e77c..ba69b38 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -86,6 +86,8 @@
// Check base WebGPU limits and populate supported limits.
virtual MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) = 0;
+ virtual void InitializeVendorArchitectureImpl();
+
ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor);
virtual MaybeError ResetInternalDeviceForTestingImpl();
diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm
index 4d5d854..e142b2b 100644
--- a/src/dawn/native/metal/BackendMTL.mm
+++ b/src/dawn/native/metal/BackendMTL.mm
@@ -47,11 +47,10 @@
};
#if DAWN_PLATFORM_IS(MACOS)
-const Vendor kVendors[] = {{"AMD", gpu_info::kVendorID_AMD},
- {"Radeon", gpu_info::kVendorID_AMD},
- {"Intel", gpu_info::kVendorID_Intel},
- {"Geforce", gpu_info::kVendorID_Nvidia},
- {"Quadro", gpu_info::kVendorID_Nvidia}};
+const Vendor kVendors[] = {
+ {"AMD", gpu_info::kVendorID_AMD}, {"Apple", gpu_info::kVendorID_Apple},
+ {"Radeon", gpu_info::kVendorID_AMD}, {"Intel", gpu_info::kVendorID_Intel},
+ {"Geforce", gpu_info::kVendorID_Nvidia}, {"Quadro", gpu_info::kVendorID_Nvidia}};
// Find vendor ID from MTLDevice name.
MaybeError GetVendorIdFromVendors(id<MTLDevice> device, PCIIDs* ids) {
@@ -147,10 +146,16 @@
// [device registryID] is introduced on macOS 10.13+, otherwise workaround to get vendor
// id by vendor name on old macOS
if (@available(macos 10.13, *)) {
- return GetDeviceIORegistryPCIInfo(device, ids);
- } else {
- return GetVendorIdFromVendors(device, ids);
+ auto result = GetDeviceIORegistryPCIInfo(device, ids);
+ if (result.IsError()) {
+ dawn::WarningLog() << "GetDeviceIORegistryPCIInfo failed: "
+ << result.AcquireError()->GetFormattedMessage();
+ } else if (ids->vendorId != 0) {
+ return result;
+ }
}
+
+ return GetVendorIdFromVendors(device, ids);
}
bool IsMetalSupported() {
@@ -391,6 +396,33 @@
return {};
}
+ void InitializeVendorArchitectureImpl() override {
+ if (@available(macOS 10.15, iOS 13.0, *)) {
+ // According to Apple's documentation:
+ // https://developer.apple.com/documentation/metal/gpu_devices_and_work_submission/detecting_gpu_features_and_metal_software_versions
+ // - "Use the Common family to create apps that target a range of GPUs on multiple
+ // platforms.""
+ // - "A GPU can be a member of more than one family; in most cases, a GPU supports one
+ // of the Common families and then one or more families specific to the build target."
+ // So we'll use the highest supported common family as the reported "architecture" on
+ // devices where a deviceID isn't available.
+ if (mDeviceId == 0) {
+ if ([*mDevice supportsFamily:MTLGPUFamilyCommon3]) {
+ mArchitectureName = "common-3";
+ } else if ([*mDevice supportsFamily:MTLGPUFamilyCommon2]) {
+ mArchitectureName = "common-2";
+ } else if ([*mDevice supportsFamily:MTLGPUFamilyCommon1]) {
+ mArchitectureName = "common-1";
+ }
+ }
+ }
+
+ mVendorName = gpu_info::GetVendorName(mVendorId);
+ if (mDeviceId != 0) {
+ mArchitectureName = gpu_info::GetArchitectureName(mVendorId, mDeviceId);
+ }
+ };
+
enum class MTLGPUFamily {
Apple1,
Apple2,
diff --git a/src/dawn/tests/DawnTest.cpp b/src/dawn/tests/DawnTest.cpp
index c88ccf9..49386e8 100644
--- a/src/dawn/tests/DawnTest.cpp
+++ b/src/dawn/tests/DawnTest.cpp
@@ -649,6 +649,11 @@
<< ", backend: " << ParamName(properties.backendType) << "\n"
<< " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
<< (properties.selected ? " [Selected]" : "") << "\n";
+
+ if (strlen(properties.vendorName) || strlen(properties.architecture)) {
+ log << " vendorName: " << properties.vendorName
+ << ", architecture: " << properties.architecture << "\n";
+ }
}
}