| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/config/gpu_info_collector.h" |
| |
| #import <Metal/Metal.h> |
| |
| #include "base/metrics/histogram_macros.h" |
| #include "base/trace_event/trace_event.h" |
| #include "third_party/angle/src/gpu_info_util/SystemInfo.h" |
| #include "ui/gl/gl_display.h" |
| #include "ui/gl/gl_utils.h" |
| |
| namespace gpu { |
| |
| namespace { |
| |
| // The enums is used for an UMA histogram so we should never reorder entries or |
| // remove unused values. |
| enum class MetalReadWriteTextureSupportTier { |
| kUnknown = 0, |
| kTier0_NoSupport = 1, |
| kTier1_R32Formats = 2, |
| kTier2_AdditionalFormats = 3, |
| kMaxValue = kTier2_AdditionalFormats, |
| }; |
| |
| // The enums is used for an UMA histogram so we should never reorder entries or |
| // remove unused values. |
| enum class MetalFamilyMac { |
| kMac1 = 0, |
| kMac2 = 1, |
| kMaxValue = kMac2, |
| }; |
| |
| MetalFamilyMac GetMetalFamilyMac(id<MTLDevice> device) { |
| if ([device supportsFamily:MTLGPUFamilyMac2]) { |
| return MetalFamilyMac::kMac2; |
| } |
| return MetalFamilyMac::kMac1; |
| } |
| |
| void RecordHistograms() { |
| // Metal tiers are `MTLReadWriteTextureTier[None|1|2]` which correspond to the |
| // integers 0, 1, and 2. The enum `MetalReadWriteTextureSupportTier` was |
| // written to use integers one higher than the macOS API constants so that it |
| // could support the concept of "unknown". Nowadays, `kUnknown` will only be |
| // logged in the case where `MTLCopyAllDevices()` returns an empty array, |
| // perhaps when running in an environment like VMWare? |
| NSUInteger best_tier = 0; |
| |
| NSArray<id<MTLDevice>>* devices = MTLCopyAllDevices(); |
| for (id<MTLDevice> device in devices) { |
| best_tier = std::max(best_tier, device.readWriteTextureSupport + 1); |
| |
| UMA_HISTOGRAM_ENUMERATION("Gpu.Metal.FamilyMac", GetMetalFamilyMac(device)); |
| } |
| |
| UMA_HISTOGRAM_ENUMERATION( |
| "Gpu.Metal.ReadWriteTextureSupport", |
| static_cast<MetalReadWriteTextureSupportTier>(best_tier)); |
| } |
| |
| bool IsLowPowerGpu(const GPUInfo::GPUDevice& gpu) { |
| // Apple GPUs are considered low power. This may not be the case in the |
| // future. |
| switch (gpu.vendor_id) { |
| case 0x8086: // Intel |
| case 0x106b: // Apple |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| bool IsHighPerformanceGpu(const GPUInfo::GPUDevice& gpu) { |
| return !gpu.IsSoftwareRenderer() && !IsLowPowerGpu(gpu); |
| } |
| } // namespace |
| |
| bool CollectContextGraphicsInfo(GPUInfo* gpu_info) { |
| DCHECK(gpu_info); |
| |
| TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo"); |
| |
| RecordHistograms(); |
| |
| return CollectGraphicsInfoGL(gpu_info, gl::GetDefaultDisplayEGL()); |
| } |
| |
| bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) { |
| DCHECK(gpu_info); |
| |
| angle::SystemInfo system_info; |
| bool success = angle::GetSystemInfo(&system_info); |
| FillGPUInfoFromSystemInfo(gpu_info, &system_info); |
| |
| if (gpu_info->GpuCount() > 1) { |
| if (IsLowPowerGpu(gpu_info->gpu)) |
| gpu_info->gpu.gpu_preference = gl::GpuPreference::kLowPower; |
| else if (IsHighPerformanceGpu(gpu_info->gpu)) |
| gpu_info->gpu.gpu_preference = gl::GpuPreference::kHighPerformance; |
| for (auto& gpu : gpu_info->secondary_gpus) { |
| if (IsLowPowerGpu(gpu)) |
| gpu.gpu_preference = gl::GpuPreference::kLowPower; |
| else if (IsHighPerformanceGpu(gpu)) |
| gpu.gpu_preference = gl::GpuPreference::kHighPerformance; |
| } |
| } |
| |
| return success; |
| } |
| |
| } // namespace gpu |