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"; + } } }