0

gpu: Ensure we use a non-software device for GPU testing

This change makes it so GPU unit tests (i.e. tests that do not GpuInit)
will initialize the GPU process with a real GPU in the case that the
first default GPU is considered a "software renderer".

This is useful on Windows, where some specific VM scenarios can list the
WARP device before the physical GPU when enumerating adapters on a DXGI
device.

Change-Id: Ic40554910c9e37f1f1fee021ee525c2c9dfb764a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6311591
Commit-Queue: Michael Tang <tangm@microsoft.com>
Reviewed-by: Rafael Cintron <rafael.cintron@microsoft.com>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1430983}
This commit is contained in:
Michael Tang
2025-03-11 10:30:32 -07:00
committed by Chromium LUCI CQ
parent 7d9ee1c94f
commit 75886e6d4a
10 changed files with 64 additions and 2 deletions

@ -28,6 +28,7 @@
#include "gpu/config/gpu_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/init/gl_factory.h"
@ -39,6 +40,10 @@ const uint8_t GLTestHelper::kCheckClearValue;
#endif
gl::GLDisplay* GLTestHelper::InitializeGL(gl::GLImplementation gl_impl) {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
gpu::EnsureNonSoftwareDeviceForTesting(gl::GpuPreference::kDefault);
#endif
gl::GLDisplay* display = nullptr;
if (gl_impl == gl::GLImplementation::kGLImplementationNone) {
display = gl::init::InitializeGLNoExtensionsOneOff(

@ -285,6 +285,9 @@ void CollectNPUInformation(GPUInfo* gpu_info) {
LUID instance_luid;
if (SUCCEEDED(dxcore_adapter->GetProperty(
DXCoreAdapterProperty::InstanceLuid, &instance_luid))) {
device.system_device_id =
(static_cast<uint64_t>(instance_luid.HighPart) << 32) |
static_cast<uint64_t>(instance_luid.LowPart);
device.luid =
CHROME_LUID{instance_luid.LowPart, instance_luid.HighPart};
}
@ -318,6 +321,9 @@ bool CollectDriverInfoD3D(GPUInfo* gpu_info) {
GPUInfo::GPUDevice device;
device.vendor_id = desc.VendorId;
device.device_id = desc.DeviceId;
device.system_device_id =
(static_cast<uint64_t>(desc.AdapterLuid.HighPart) << 32) |
static_cast<uint64_t>(desc.AdapterLuid.LowPart);
device.sub_sys_id = desc.SubSysId;
device.revision = desc.Revision;
device.luid =

@ -7,6 +7,7 @@
#include <string_view>
#include "build/build_config.h"
#include "ui/gl/gpu_preference.h"
#include "ui/gl/startup_trace.h"
#if BUILDFLAG(IS_WIN)
@ -1066,4 +1067,35 @@ std::string VulkanVersionToString(uint32_t vulkan_version) {
}
}
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
// GPU picking is only effective with ANGLE/Metal backend on Mac and
// on Windows with EGL.
void EnsureNonSoftwareDeviceForTesting(gl::GpuPreference gpu_preference) {
// `SetGpuPreferenceEGL` fails when a preference was previously already set.
if (GetSystemDeviceIdEGLForTesting(gpu_preference) != 0) { // IN-TEST
return;
}
GPUInfo gpu_info;
CHECK(CollectBasicGraphicsInfo(&gpu_info));
uint64_t non_software_renderer_device_id = 0;
if (!gpu_info.active_gpu().IsSoftwareRenderer()) {
non_software_renderer_device_id = gpu_info.active_gpu().system_device_id;
} else if (auto it =
std::ranges::find_if(gpu_info.secondary_gpus,
[](const GPUInfo::GPUDevice& device) {
return !device.IsSoftwareRenderer();
});
it != gpu_info.secondary_gpus.end()) {
non_software_renderer_device_id = it->system_device_id;
} else {
LOG(FATAL) << "No non-software renderer device available.";
}
SetGpuPreferenceEGL(gpu_preference, non_software_renderer_device_id);
}
#endif
} // namespace gpu

@ -101,6 +101,11 @@ GPU_EXPORT std::string D3DFeatureLevelToString(uint32_t d3d_feature_level);
GPU_EXPORT std::string VulkanVersionToString(uint32_t vulkan_version);
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
GPU_EXPORT void EnsureNonSoftwareDeviceForTesting(
gl::GpuPreference gpu_preference);
#endif
} // namespace gpu
#endif // GPU_CONFIG_GPU_UTIL_H_

@ -465,6 +465,7 @@ static_library("test_support") {
]
deps = [
"//base/test:test_support",
"//gpu/config",
"//testing/gtest",
"//third_party/angle:includes",
"//ui/base",

@ -45,6 +45,7 @@
#include "ui/gl/gl_version_info.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/gl/test/gl_test_helper.h"
#include "ui/gl/test/gl_test_support.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/platform_window/win/win_window.h"
@ -235,8 +236,7 @@ class DCompPresenterTestBase : public testing::Test {
void SetUp() override {
enabled_features_.InitWithFeatures(enabled_features_list_,
disabled_features_list_);
display_ = gl::init::InitializeGLNoExtensionsOneOff(
/*init_bindings=*/true, /*gpu_preference=*/gl::GpuPreference::kDefault);
display_ = GLTestSupport::InitializeGL(std::nullopt);
std::tie(gl_surface_, context_) =
GLTestHelper::CreateOffscreenGLSurfaceAndContext();

@ -197,6 +197,10 @@ void SetGpuPreferenceEGL(GpuPreference preference, uint64_t system_device_id) {
system_device_id);
}
uint64_t GetSystemDeviceIdEGLForTesting(GpuPreference preference) {
return GLDisplayManagerEGL::GetInstance()->GetSystemDeviceId(preference);
}
void RemoveGpuPreferenceEGL(GpuPreference preference) {
GLDisplayManagerEGL::GetInstance()->RemoveGpuPreference(preference);
}

@ -85,6 +85,9 @@ GL_EXPORT void LabelSwapChainBuffers(IDXGISwapChain* swap_chain,
GL_EXPORT void SetGpuPreferenceEGL(GpuPreference preference,
uint64_t system_device_id);
// Return the value for the entry at <preference> from GLDisplayManagerEGL.
GL_EXPORT uint64_t GetSystemDeviceIdEGLForTesting(GpuPreference preference);
// Remove the entry at <preference> from GLDisplayManagerEGL.
GL_EXPORT void RemoveGpuPreferenceEGL(GpuPreference preference);

@ -1,4 +1,5 @@
include_rules = [
"+gpu/config/gpu_util.h",
"+ui/base",
"+ui/ozone/public",
"+mojo/core/embedder",

@ -11,6 +11,7 @@
#include "base/check_op.h"
#include "base/notreached.h"
#include "build/build_config.h"
#include "gpu/config/gpu_util.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/half_float.h"
#include "ui/gl/init/gl_factory.h"
@ -67,6 +68,10 @@ UNSAFE_BUFFER_USAGE base::span<uint64_t> ToSpan_uint64(uint8_t* data,
// static
GLDisplay* GLTestSupport::InitializeGL(
std::optional<GLImplementationParts> prefered_impl) {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
gpu::EnsureNonSoftwareDeviceForTesting(gl::GpuPreference ::kDefault);
#endif
#if BUILDFLAG(IS_OZONE)
ui::OzonePlatform::InitParams params;
params.single_process = true;