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>
This commit is contained in:
Brandon Jones 2022-06-10 00:05:32 +00:00 committed by Dawn LUCI CQ
parent b2ce202734
commit d45b920aed
7 changed files with 65 additions and 14 deletions

View File

@ -192,7 +192,7 @@ dawn_generator("dawn_gpu_info_gen") {
script = "${dawn_root}/generator/dawn_gpu_info_generator.py" script = "${dawn_root}/generator/dawn_gpu_info_generator.py"
args = [ args = [
"--gpu-info-json", "--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 = [ outputs = [
"src/dawn/common/GPUInfo_autogen.h", "src/dawn/common/GPUInfo_autogen.h",

View File

@ -24,7 +24,7 @@ DawnGenerator(
SCRIPT "${Dawn_SOURCE_DIR}/generator/dawn_gpu_info_generator.py" SCRIPT "${Dawn_SOURCE_DIR}/generator/dawn_gpu_info_generator.py"
PRINT_NAME "Dawn GPU info utilities" PRINT_NAME "Dawn GPU info utilities"
ARGS "--gpu-info-json" 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" RESULT_VARIABLE "DAWN_GPU_INFO_AUTOGEN_SOURCES"
) )

View File

@ -33,7 +33,15 @@
}, },
"Apple": { "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": { "ARM": {

View File

@ -33,6 +33,8 @@ AdapterBase::AdapterBase(InstanceBase* instance, wgpu::BackendType backend)
MaybeError AdapterBase::Initialize() { MaybeError AdapterBase::Initialize() {
DAWN_TRY_CONTEXT(InitializeImpl(), "initializing adapter (backend=%s)", mBackend); DAWN_TRY_CONTEXT(InitializeImpl(), "initializing adapter (backend=%s)", mBackend);
InitializeVendorArchitectureImpl();
DAWN_TRY_CONTEXT( DAWN_TRY_CONTEXT(
InitializeSupportedFeaturesImpl(), InitializeSupportedFeaturesImpl(),
"gathering supported features for \"%s\" - \"%s\" (vendorId=%#06x deviceId=%#06x " "gathering supported features for \"%s\" - \"%s\" (vendorId=%#06x deviceId=%#06x "
@ -44,9 +46,6 @@ MaybeError AdapterBase::Initialize() {
"backend=%s type=%s)", "backend=%s type=%s)",
mName, mDriverDescription, mVendorId, mDeviceId, mBackend, mAdapterType); mName, mDriverDescription, mVendorId, mDeviceId, mBackend, mAdapterType);
mVendorName = gpu_info::GetVendorName(mVendorId);
mArchitectureName = gpu_info::GetArchitectureName(mVendorId, mDeviceId);
// Enforce internal Dawn constants. // Enforce internal Dawn constants.
mLimits.v1.maxVertexBufferArrayStride = mLimits.v1.maxVertexBufferArrayStride =
std::min(mLimits.v1.maxVertexBufferArrayStride, kMaxVertexBufferArrayStride); std::min(mLimits.v1.maxVertexBufferArrayStride, kMaxVertexBufferArrayStride);
@ -138,6 +137,11 @@ void AdapterBase::APIRequestDevice(const DeviceDescriptor* descriptor,
callback(status, ToAPI(device.Detach()), nullptr, userdata); 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 { uint32_t AdapterBase::GetVendorId() const {
return mVendorId; return mVendorId;
} }

View File

@ -86,6 +86,8 @@ class AdapterBase : public RefCounted {
// Check base WebGPU limits and populate supported limits. // Check base WebGPU limits and populate supported limits.
virtual MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) = 0; virtual MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) = 0;
virtual void InitializeVendorArchitectureImpl();
ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor); ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* descriptor);
virtual MaybeError ResetInternalDeviceForTestingImpl(); virtual MaybeError ResetInternalDeviceForTestingImpl();

View File

@ -47,11 +47,10 @@ struct Vendor {
}; };
#if DAWN_PLATFORM_IS(MACOS) #if DAWN_PLATFORM_IS(MACOS)
const Vendor kVendors[] = {{"AMD", gpu_info::kVendorID_AMD}, const Vendor kVendors[] = {
{"Radeon", gpu_info::kVendorID_AMD}, {"AMD", gpu_info::kVendorID_AMD}, {"Apple", gpu_info::kVendorID_Apple},
{"Intel", gpu_info::kVendorID_Intel}, {"Radeon", gpu_info::kVendorID_AMD}, {"Intel", gpu_info::kVendorID_Intel},
{"Geforce", gpu_info::kVendorID_Nvidia}, {"Geforce", gpu_info::kVendorID_Nvidia}, {"Quadro", gpu_info::kVendorID_Nvidia}};
{"Quadro", gpu_info::kVendorID_Nvidia}};
// Find vendor ID from MTLDevice name. // Find vendor ID from MTLDevice name.
MaybeError GetVendorIdFromVendors(id<MTLDevice> device, PCIIDs* ids) { MaybeError GetVendorIdFromVendors(id<MTLDevice> device, PCIIDs* ids) {
@ -147,12 +146,18 @@ MaybeError GetDevicePCIInfo(id<MTLDevice> device, PCIIDs* ids) {
// [device registryID] is introduced on macOS 10.13+, otherwise workaround to get vendor // [device registryID] is introduced on macOS 10.13+, otherwise workaround to get vendor
// id by vendor name on old macOS // id by vendor name on old macOS
if (@available(macos 10.13, *)) { if (@available(macos 10.13, *)) {
return GetDeviceIORegistryPCIInfo(device, ids); auto result = GetDeviceIORegistryPCIInfo(device, ids);
} else { if (result.IsError()) {
return GetVendorIdFromVendors(device, ids); dawn::WarningLog() << "GetDeviceIORegistryPCIInfo failed: "
<< result.AcquireError()->GetFormattedMessage();
} else if (ids->vendorId != 0) {
return result;
} }
} }
return GetVendorIdFromVendors(device, ids);
}
bool IsMetalSupported() { bool IsMetalSupported() {
// Metal was first introduced in macOS 10.11 // Metal was first introduced in macOS 10.11
// WebGPU is targeted at macOS 10.12+ // WebGPU is targeted at macOS 10.12+
@ -391,6 +396,33 @@ class Adapter : public AdapterBase {
return {}; 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 { enum class MTLGPUFamily {
Apple1, Apple1,
Apple2, Apple2,

View File

@ -649,6 +649,11 @@ void DawnTestEnvironment::PrintTestConfigurationAndAdapterInfo(
<< ", backend: " << ParamName(properties.backendType) << "\n" << ", backend: " << ParamName(properties.backendType) << "\n"
<< " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str() << " vendorId: 0x" << vendorId.str() << ", deviceId: 0x" << deviceId.str()
<< (properties.selected ? " [Selected]" : "") << "\n"; << (properties.selected ? " [Selected]" : "") << "\n";
if (strlen(properties.vendorName) || strlen(properties.architecture)) {
log << " vendorName: " << properties.vendorName
<< ", architecture: " << properties.architecture << "\n";
}
} }
} }