gpu_info.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "gpu/config/gpu_info.h"
  5. #include <stdint.h>
  6. #include "base/logging.h"
  7. #include "base/notreached.h"
  8. #include "build/build_config.h"
  9. #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
  10. #include "gpu/config/gpu_util.h"
  11. #if BUILDFLAG(IS_MAC)
  12. #include <GLES2/gl2.h>
  13. #include <GLES2/gl2extchromium.h>
  14. #endif // BUILDFLAG(IS_MAC)
  15. namespace {
  16. void EnumerateGPUDevice(const gpu::GPUInfo::GPUDevice& device,
  17. gpu::GPUInfo::Enumerator* enumerator) {
  18. enumerator->BeginGPUDevice();
  19. enumerator->AddInt("vendorId", device.vendor_id);
  20. enumerator->AddInt("deviceId", device.device_id);
  21. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
  22. enumerator->AddInt("revision", device.revision);
  23. #endif
  24. #if BUILDFLAG(IS_WIN)
  25. enumerator->AddInt("subSysId", device.sub_sys_id);
  26. #endif // BUILDFLAG(IS_WIN)
  27. enumerator->AddBool("active", device.active);
  28. enumerator->AddString("vendorString", device.vendor_string);
  29. enumerator->AddString("deviceString", device.device_string);
  30. enumerator->AddString("driverVendor", device.driver_vendor);
  31. enumerator->AddString("driverVersion", device.driver_version);
  32. enumerator->AddInt("cudaComputeCapabilityMajor",
  33. device.cuda_compute_capability_major);
  34. enumerator->AddInt("gpuPreference", static_cast<int>(device.gpu_preference));
  35. enumerator->EndGPUDevice();
  36. }
  37. void EnumerateVideoDecodeAcceleratorSupportedProfile(
  38. const gpu::VideoDecodeAcceleratorSupportedProfile& profile,
  39. gpu::GPUInfo::Enumerator* enumerator) {
  40. enumerator->BeginVideoDecodeAcceleratorSupportedProfile();
  41. enumerator->AddInt("profile", profile.profile);
  42. enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
  43. enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
  44. enumerator->AddInt("minResolutionWidth", profile.min_resolution.width());
  45. enumerator->AddInt("minResolutionHeight", profile.min_resolution.height());
  46. enumerator->AddBool("encrypted_only", profile.encrypted_only);
  47. enumerator->EndVideoDecodeAcceleratorSupportedProfile();
  48. }
  49. void EnumerateVideoEncodeAcceleratorSupportedProfile(
  50. const gpu::VideoEncodeAcceleratorSupportedProfile& profile,
  51. gpu::GPUInfo::Enumerator* enumerator) {
  52. enumerator->BeginVideoEncodeAcceleratorSupportedProfile();
  53. enumerator->AddInt("profile", profile.profile);
  54. enumerator->AddInt("minResolutionWidth", profile.min_resolution.width());
  55. enumerator->AddInt("minResolutionHeight", profile.min_resolution.height());
  56. enumerator->AddInt("maxResolutionWidth", profile.max_resolution.width());
  57. enumerator->AddInt("maxResolutionHeight", profile.max_resolution.height());
  58. enumerator->AddInt("maxFramerateNumerator", profile.max_framerate_numerator);
  59. enumerator->AddInt("maxFramerateDenominator",
  60. profile.max_framerate_denominator);
  61. enumerator->EndVideoEncodeAcceleratorSupportedProfile();
  62. }
  63. const char* ImageDecodeAcceleratorTypeToString(
  64. gpu::ImageDecodeAcceleratorType type) {
  65. switch (type) {
  66. case gpu::ImageDecodeAcceleratorType::kJpeg:
  67. return "JPEG";
  68. case gpu::ImageDecodeAcceleratorType::kWebP:
  69. return "WebP";
  70. case gpu::ImageDecodeAcceleratorType::kUnknown:
  71. return "Unknown";
  72. }
  73. NOTREACHED() << "Invalid ImageDecodeAcceleratorType.";
  74. return "";
  75. }
  76. const char* ImageDecodeAcceleratorSubsamplingToString(
  77. gpu::ImageDecodeAcceleratorSubsampling subsampling) {
  78. switch (subsampling) {
  79. case gpu::ImageDecodeAcceleratorSubsampling::k420:
  80. return "4:2:0";
  81. case gpu::ImageDecodeAcceleratorSubsampling::k422:
  82. return "4:2:2";
  83. case gpu::ImageDecodeAcceleratorSubsampling::k444:
  84. return "4:4:4";
  85. }
  86. }
  87. void EnumerateImageDecodeAcceleratorSupportedProfile(
  88. const gpu::ImageDecodeAcceleratorSupportedProfile& profile,
  89. gpu::GPUInfo::Enumerator* enumerator) {
  90. enumerator->BeginImageDecodeAcceleratorSupportedProfile();
  91. enumerator->AddString("imageType",
  92. ImageDecodeAcceleratorTypeToString(profile.image_type));
  93. enumerator->AddString("minEncodedDimensions",
  94. profile.min_encoded_dimensions.ToString());
  95. enumerator->AddString("maxEncodedDimensions",
  96. profile.max_encoded_dimensions.ToString());
  97. std::string subsamplings;
  98. for (size_t i = 0; i < profile.subsamplings.size(); i++) {
  99. if (i > 0)
  100. subsamplings += ", ";
  101. subsamplings +=
  102. ImageDecodeAcceleratorSubsamplingToString(profile.subsamplings[i]);
  103. }
  104. enumerator->AddString("subsamplings", subsamplings);
  105. enumerator->EndImageDecodeAcceleratorSupportedProfile();
  106. }
  107. #if BUILDFLAG(IS_WIN)
  108. void EnumerateOverlayInfo(const gpu::OverlayInfo& info,
  109. gpu::GPUInfo::Enumerator* enumerator) {
  110. enumerator->BeginOverlayInfo();
  111. enumerator->AddBool("directComposition", info.direct_composition);
  112. enumerator->AddBool("supportsOverlays", info.supports_overlays);
  113. enumerator->AddString("yuy2OverlaySupport",
  114. gpu::OverlaySupportToString(info.yuy2_overlay_support));
  115. enumerator->AddString("nv12OverlaySupport",
  116. gpu::OverlaySupportToString(info.nv12_overlay_support));
  117. enumerator->EndOverlayInfo();
  118. }
  119. #endif
  120. } // namespace
  121. namespace gpu {
  122. #if BUILDFLAG(IS_WIN)
  123. const char* OverlaySupportToString(gpu::OverlaySupport support) {
  124. switch (support) {
  125. case gpu::OverlaySupport::kNone:
  126. return "NONE";
  127. case gpu::OverlaySupport::kDirect:
  128. return "DIRECT";
  129. case gpu::OverlaySupport::kScaling:
  130. return "SCALING";
  131. case gpu::OverlaySupport::kSoftware:
  132. return "SOFTWARE";
  133. }
  134. }
  135. #endif // BUILDFLAG(IS_WIN)
  136. #if BUILDFLAG(IS_MAC)
  137. GPU_EXPORT bool ValidateMacOSSpecificTextureTarget(int target) {
  138. switch (target) {
  139. case GL_TEXTURE_2D:
  140. case GL_TEXTURE_RECTANGLE_ARB:
  141. return true;
  142. default:
  143. return false;
  144. }
  145. }
  146. #endif // BUILDFLAG(IS_MAC)
  147. VideoDecodeAcceleratorCapabilities::VideoDecodeAcceleratorCapabilities()
  148. : flags(0) {}
  149. VideoDecodeAcceleratorCapabilities::VideoDecodeAcceleratorCapabilities(
  150. const VideoDecodeAcceleratorCapabilities& other) = default;
  151. VideoDecodeAcceleratorCapabilities::~VideoDecodeAcceleratorCapabilities() =
  152. default;
  153. ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile()
  154. : image_type(ImageDecodeAcceleratorType::kUnknown) {}
  155. ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile(
  156. const ImageDecodeAcceleratorSupportedProfile& other) = default;
  157. ImageDecodeAcceleratorSupportedProfile::ImageDecodeAcceleratorSupportedProfile(
  158. ImageDecodeAcceleratorSupportedProfile&& other) = default;
  159. ImageDecodeAcceleratorSupportedProfile::
  160. ~ImageDecodeAcceleratorSupportedProfile() = default;
  161. ImageDecodeAcceleratorSupportedProfile& ImageDecodeAcceleratorSupportedProfile::
  162. operator=(const ImageDecodeAcceleratorSupportedProfile& other) = default;
  163. ImageDecodeAcceleratorSupportedProfile& ImageDecodeAcceleratorSupportedProfile::
  164. operator=(ImageDecodeAcceleratorSupportedProfile&& other) = default;
  165. GPUInfo::GPUDevice::GPUDevice() = default;
  166. GPUInfo::GPUDevice::GPUDevice(const GPUInfo::GPUDevice& other) = default;
  167. GPUInfo::GPUDevice::GPUDevice(GPUInfo::GPUDevice&& other) noexcept = default;
  168. GPUInfo::GPUDevice::~GPUDevice() noexcept = default;
  169. GPUInfo::GPUDevice& GPUInfo::GPUDevice::operator=(
  170. const GPUInfo::GPUDevice& other) = default;
  171. GPUInfo::GPUDevice& GPUInfo::GPUDevice::operator=(
  172. GPUInfo::GPUDevice&& other) noexcept = default;
  173. bool GPUInfo::GPUDevice::IsSoftwareRenderer() const {
  174. switch (vendor_id) {
  175. case 0x0000: // Info collection failed to identify a GPU
  176. case 0xffff: // Chromium internal flag for software rendering
  177. case 0x15ad: // VMware
  178. case 0x1414: // Microsoft software renderer
  179. return true;
  180. default:
  181. return false;
  182. }
  183. }
  184. GPUInfo::GPUInfo()
  185. : optimus(false),
  186. amd_switchable(false),
  187. gl_reset_notification_strategy(0),
  188. software_rendering(false),
  189. sandboxed(false),
  190. in_process_gpu(true),
  191. passthrough_cmd_decoder(false),
  192. #if BUILDFLAG(IS_MAC)
  193. macos_specific_texture_target(gpu::GetPlatformSpecificTextureTarget()),
  194. #endif // BUILDFLAG(IS_MAC)
  195. jpeg_decode_accelerator_supported(false),
  196. subpixel_font_rendering(true) {
  197. }
  198. GPUInfo::GPUInfo(const GPUInfo& other) = default;
  199. GPUInfo::~GPUInfo() = default;
  200. GPUInfo::GPUDevice& GPUInfo::active_gpu() {
  201. return const_cast<GPUInfo::GPUDevice&>(
  202. const_cast<const GPUInfo&>(*this).active_gpu());
  203. }
  204. const GPUInfo::GPUDevice& GPUInfo::active_gpu() const {
  205. if (gpu.active || secondary_gpus.empty())
  206. return gpu;
  207. for (const auto& secondary_gpu : secondary_gpus) {
  208. if (secondary_gpu.active)
  209. return secondary_gpu;
  210. }
  211. DVLOG(2) << "No active GPU found, returning primary GPU.";
  212. return gpu;
  213. }
  214. bool GPUInfo::IsInitialized() const {
  215. return gpu.vendor_id != 0 || !gl_vendor.empty();
  216. }
  217. bool GPUInfo::UsesSwiftShader() const {
  218. return gl_renderer.find("SwiftShader") != std::string::npos;
  219. }
  220. unsigned int GPUInfo::GpuCount() const {
  221. unsigned int gpu_count = 0;
  222. if (!gpu.IsSoftwareRenderer())
  223. ++gpu_count;
  224. for (const auto& secondary_gpu : secondary_gpus) {
  225. if (!secondary_gpu.IsSoftwareRenderer())
  226. ++gpu_count;
  227. }
  228. return gpu_count;
  229. }
  230. const GPUInfo::GPUDevice* GPUInfo::GetGpuByPreference(
  231. gl::GpuPreference preference) const {
  232. DCHECK(preference == gl::GpuPreference::kHighPerformance ||
  233. preference == gl::GpuPreference::kLowPower);
  234. if (gpu.gpu_preference == preference)
  235. return &gpu;
  236. for (auto& device : secondary_gpus) {
  237. if (device.gpu_preference == preference)
  238. return &device;
  239. }
  240. return nullptr;
  241. }
  242. #if BUILDFLAG(IS_WIN)
  243. GPUInfo::GPUDevice* GPUInfo::FindGpuByLuid(DWORD low_part, LONG high_part) {
  244. if (gpu.luid.LowPart == low_part && gpu.luid.HighPart == high_part)
  245. return &gpu;
  246. for (auto& device : secondary_gpus) {
  247. if (device.luid.LowPart == low_part && device.luid.HighPart == high_part)
  248. return &device;
  249. }
  250. return nullptr;
  251. }
  252. #endif // BUILDFLAG(IS_WIN)
  253. void GPUInfo::EnumerateFields(Enumerator* enumerator) const {
  254. struct GPUInfoKnownFields {
  255. base::TimeDelta initialization_time;
  256. bool optimus;
  257. bool amd_switchable;
  258. GPUDevice gpu;
  259. std::vector<GPUDevice> secondary_gpus;
  260. std::string pixel_shader_version;
  261. std::string vertex_shader_version;
  262. std::string max_msaa_samples;
  263. std::string machine_model_name;
  264. std::string machine_model_version;
  265. std::string gl_version_string;
  266. std::string gl_vendor;
  267. std::string gl_renderer;
  268. std::string gl_extensions;
  269. std::string gl_ws_vendor;
  270. std::string gl_ws_version;
  271. std::string gl_ws_extensions;
  272. uint32_t gl_reset_notification_strategy;
  273. bool software_rendering;
  274. std::string direct_rendering_version;
  275. bool sandboxed;
  276. bool in_process_gpu;
  277. bool passthrough_cmd_decoder;
  278. bool is_asan;
  279. bool can_support_threaded_texture_mailbox;
  280. #if BUILDFLAG(IS_MAC)
  281. uint32_t macos_specific_texture_target;
  282. #endif // BUILDFLAG(IS_MAC)
  283. #if BUILDFLAG(IS_WIN)
  284. DxDiagNode dx_diagnostics;
  285. uint32_t d3d12_feature_level;
  286. uint32_t vulkan_version;
  287. OverlayInfo overlay_info;
  288. #endif
  289. VideoDecodeAcceleratorSupportedProfiles
  290. video_decode_accelerator_supported_profiles;
  291. VideoEncodeAcceleratorSupportedProfiles
  292. video_encode_accelerator_supported_profiles;
  293. bool jpeg_decode_accelerator_supported;
  294. ImageDecodeAcceleratorSupportedProfiles
  295. image_decode_accelerator_supported_profiles;
  296. bool subpixel_font_rendering;
  297. uint32_t visibility_callback_call_count;
  298. #if BUILDFLAG(ENABLE_VULKAN)
  299. absl::optional<VulkanInfo> vulkan_info;
  300. #endif
  301. };
  302. // If this assert fails then most likely something below needs to be updated.
  303. // Note that this assert is only approximate. If a new field is added to
  304. // GPUInfo which fits within the current padding then it will not be caught.
  305. static_assert(
  306. sizeof(GPUInfo) == sizeof(GPUInfoKnownFields),
  307. "fields have changed in GPUInfo, GPUInfoKnownFields must be updated");
  308. // Required fields (according to DevTools protocol) first.
  309. enumerator->AddString("machineModelName", machine_model_name);
  310. enumerator->AddString("machineModelVersion", machine_model_version);
  311. EnumerateGPUDevice(gpu, enumerator);
  312. for (const auto& secondary_gpu : secondary_gpus)
  313. EnumerateGPUDevice(secondary_gpu, enumerator);
  314. enumerator->BeginAuxAttributes();
  315. enumerator->AddTimeDeltaInSecondsF("initializationTime", initialization_time);
  316. enumerator->AddBool("optimus", optimus);
  317. enumerator->AddBool("amdSwitchable", amd_switchable);
  318. enumerator->AddString("pixelShaderVersion", pixel_shader_version);
  319. enumerator->AddString("vertexShaderVersion", vertex_shader_version);
  320. enumerator->AddString("maxMsaaSamples", max_msaa_samples);
  321. enumerator->AddString("glVersion", gl_version);
  322. enumerator->AddString("glVendor", gl_vendor);
  323. enumerator->AddString("glRenderer", gl_renderer);
  324. enumerator->AddString("glExtensions", gl_extensions);
  325. enumerator->AddString("glWsVendor", gl_ws_vendor);
  326. enumerator->AddString("glWsVersion", gl_ws_version);
  327. enumerator->AddString("glWsExtensions", gl_ws_extensions);
  328. enumerator->AddInt(
  329. "glResetNotificationStrategy",
  330. static_cast<int>(gl_reset_notification_strategy));
  331. // TODO(kbr): add performance_stats.
  332. enumerator->AddBool("softwareRendering", software_rendering);
  333. enumerator->AddString("directRenderingVersion", direct_rendering_version);
  334. enumerator->AddBool("sandboxed", sandboxed);
  335. enumerator->AddBool("inProcessGpu", in_process_gpu);
  336. enumerator->AddBool("passthroughCmdDecoder", passthrough_cmd_decoder);
  337. enumerator->AddBool("isAsan", is_asan);
  338. enumerator->AddBool("canSupportThreadedTextureMailbox",
  339. can_support_threaded_texture_mailbox);
  340. #if BUILDFLAG(IS_MAC)
  341. enumerator->AddInt("macOSSpecificTextureTarget",
  342. macos_specific_texture_target);
  343. #endif // BUILDFLAG(IS_MAC)
  344. // TODO(kbr): add dx_diagnostics on Windows.
  345. #if BUILDFLAG(IS_WIN)
  346. EnumerateOverlayInfo(overlay_info, enumerator);
  347. enumerator->AddBool("supportsDx12", d3d12_feature_level != 0);
  348. enumerator->AddBool("supportsVulkan", vulkan_version != 0);
  349. enumerator->AddString("dx12FeatureLevel",
  350. gpu::D3DFeatureLevelToString(d3d12_feature_level));
  351. enumerator->AddString("vulkanVersion",
  352. gpu::VulkanVersionToString(vulkan_version));
  353. #endif
  354. for (const auto& profile : video_decode_accelerator_supported_profiles)
  355. EnumerateVideoDecodeAcceleratorSupportedProfile(profile, enumerator);
  356. for (const auto& profile : video_encode_accelerator_supported_profiles)
  357. EnumerateVideoEncodeAcceleratorSupportedProfile(profile, enumerator);
  358. enumerator->AddBool("jpegDecodeAcceleratorSupported",
  359. jpeg_decode_accelerator_supported);
  360. for (const auto& profile : image_decode_accelerator_supported_profiles)
  361. EnumerateImageDecodeAcceleratorSupportedProfile(profile, enumerator);
  362. enumerator->AddBool("subpixelFontRendering", subpixel_font_rendering);
  363. enumerator->AddInt("visibilityCallbackCallCount",
  364. visibility_callback_call_count);
  365. #if BUILDFLAG(ENABLE_VULKAN)
  366. if (vulkan_info) {
  367. auto blob = vulkan_info->Serialize();
  368. enumerator->AddBinary("vulkanInfo", base::span<const uint8_t>(blob));
  369. }
  370. #endif
  371. enumerator->EndAuxAttributes();
  372. }
  373. } // namespace gpu