Skip to content

Commit

Permalink
Add some logic to identify the active GPU in multiple-gpu situation i…
Browse files Browse the repository at this point in the history
…n Linux

BUG=326783
TEST=gpu_unittests
R=kbr@chromium.org

Review URL: https://codereview.chromium.org/94103006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240707 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
zmo@chromium.org committed Dec 13, 2013
1 parent d231b05 commit 86a3377
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 1 deletion.
1 change: 1 addition & 0 deletions content/browser/gpu/gpu_data_manager_impl_private.cc
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
return;

gpu::MergeGPUInfo(&gpu_info_, gpu_info);
gpu::DetermineActiveGPU(&gpu_info_);
complete_gpu_info_already_requested_ =
complete_gpu_info_already_requested_ || gpu_info_.finalized;

Expand Down
7 changes: 7 additions & 0 deletions gpu/config/gpu_info_collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ GPU_EXPORT void MergeGPUInfo(GPUInfo* basic_gpu_info,
GPU_EXPORT void MergeGPUInfoGL(GPUInfo* basic_gpu_info,
const GPUInfo& context_gpu_info);

// If multiple GPUs are detected, use GL_VENDOR string to determine which GPU
// is currently active.
// |gpu_info| is expected to be the merged GPUInfo after full info collection.
// Upon return, |gpu_info->gpu| will contain the active GPU, assuming the
// platform supports it. Return false if it's not supported.
GPU_EXPORT bool DetermineActiveGPU(GPUInfo* gpu_info);

// Advanced Micro Devices has interesting configurations on laptops were
// there are two videocards that can alternatively a given process output.
enum AMDVideoCardType {
Expand Down
9 changes: 9 additions & 0 deletions gpu/config/gpu_info_collector_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,13 @@ void MergeGPUInfo(GPUInfo* basic_gpu_info,
MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
}

bool DetermineActiveGPU(GPUInfo* gpu_info) {
DCHECK(gpu_info);
if (gpu_info->secondary_gpus.size() == 0)
return true;
// TODO(zmo): implement this when Android starts to support more
// than one GPUs.
return false;
}

} // namespace gpu
6 changes: 6 additions & 0 deletions gpu/config/gpu_info_collector_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,10 @@ void MergeGPUInfo(GPUInfo* basic_gpu_info,
MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
}

bool DetermineActiveGPU(GPUInfo* gpu_info) {
DCHECK(gpu_info);
// On mac, during info collection, we've already detected the active gpu.
return true;
}

} // namespace gpu
8 changes: 8 additions & 0 deletions gpu/config/gpu_info_collector_ozone.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,12 @@ void MergeGPUInfo(GPUInfo* basic_gpu_info,
MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
}

bool DetermineActiveGPU(GPUInfo* gpu_info) {
DCHECK(gpu_info);
if (gpu_info->secondary_gpus.size() == 0)
return true;
// TODO(zmo): implement this.
return false;
}

} // namespace gpu_info_collector
66 changes: 66 additions & 0 deletions gpu/config/gpu_info_collector_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,71 @@ TEST_F(GPUInfoCollectorTest, DISABLED_GLExtensionsGL) {
gpu_info.gl_extensions);
}

#if defined(OS_LINUX)
TEST(GPUInfoCollectorUtilTest, DetermineActiveGPU) {
const uint32 kIntelVendorID = 0x8086;
const uint32 kIntelDeviceID = 0x0046;
GPUInfo::GPUDevice intel_gpu;
intel_gpu.vendor_id = kIntelVendorID;
intel_gpu.device_id = kIntelDeviceID;

const uint32 kAMDVendorID = 0x1002;
const uint32 kAMDDeviceID = 0x68c1;
GPUInfo::GPUDevice amd_gpu;
amd_gpu.vendor_id = kAMDVendorID;
amd_gpu.device_id = kAMDDeviceID;

// One GPU, do nothing.
{
GPUInfo gpu_info;
gpu_info.gpu = amd_gpu;
EXPECT_TRUE(DetermineActiveGPU(&gpu_info));
}

// Two GPUs, switched.
{
GPUInfo gpu_info;
gpu_info.gpu = amd_gpu;
gpu_info.secondary_gpus.push_back(intel_gpu);
gpu_info.gl_vendor = "Intel Open Source Technology Center";
EXPECT_TRUE(DetermineActiveGPU(&gpu_info));
EXPECT_EQ(kIntelVendorID, gpu_info.gpu.vendor_id);
EXPECT_EQ(kIntelDeviceID, gpu_info.gpu.device_id);
EXPECT_EQ(kAMDVendorID, gpu_info.secondary_gpus[0].vendor_id);
EXPECT_EQ(kAMDDeviceID, gpu_info.secondary_gpus[0].device_id);
}

// Two GPUs, no switch necessary.
{
GPUInfo gpu_info;
gpu_info.gpu = intel_gpu;
gpu_info.secondary_gpus.push_back(amd_gpu);
gpu_info.gl_vendor = "Intel Open Source Technology Center";
EXPECT_TRUE(DetermineActiveGPU(&gpu_info));
EXPECT_EQ(kIntelVendorID, gpu_info.gpu.vendor_id);
EXPECT_EQ(kIntelDeviceID, gpu_info.gpu.device_id);
EXPECT_EQ(kAMDVendorID, gpu_info.secondary_gpus[0].vendor_id);
EXPECT_EQ(kAMDDeviceID, gpu_info.secondary_gpus[0].device_id);
}

// Two GPUs, empty GL_VENDOR string.
{
GPUInfo gpu_info;
gpu_info.gpu = intel_gpu;
gpu_info.secondary_gpus.push_back(amd_gpu);
EXPECT_FALSE(DetermineActiveGPU(&gpu_info));
}

// Two GPUs, unhandled GL_VENDOR string.
{
GPUInfo gpu_info;
gpu_info.gpu = intel_gpu;
gpu_info.secondary_gpus.push_back(amd_gpu);
gpu_info.gl_vendor = "nouveau";
EXPECT_FALSE(DetermineActiveGPU(&gpu_info));
}
}
#endif

} // namespace gpu

8 changes: 8 additions & 0 deletions gpu/config/gpu_info_collector_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -650,4 +650,12 @@ void MergeGPUInfo(GPUInfo* basic_gpu_info,
basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
}

bool DetermineActiveGPU(GPUInfo* gpu_info) {
DCHECK(gpu_info);
if (gpu_info->secondary_gpus.size() == 0)
return true;
// TODO(zmo): implement this.
return false;
}

} // namespace gpu
51 changes: 50 additions & 1 deletion gpu/config/gpu_info_collector_x11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ std::string CollectDriverVersionNVidia() {
}
int event_base = 0, error_base = 0;
if (!XNVCTRLQueryExtension(display, &event_base, &error_base)) {
LOG(INFO) << "NVCtrl extension does not exist.";
VLOG(1) << "NVCtrl extension does not exist.";
return std::string();
}
int screen_count = ScreenCount(display);
Expand Down Expand Up @@ -162,6 +162,26 @@ bool CollectPCIVideoCardInfo(GPUInfo* gpu_info) {
return (primary_gpu_identified);
}

// Find the first GPU in |secondary_gpus| list that matches |active_vendor|
// and switch it to primary gpu.
// Return false if we cannot find a match.
bool FindAndSetActiveGPU(GPUInfo* gpu_info, uint32 active_vendor) {
DCHECK(gpu_info);
GPUInfo::GPUDevice* device = NULL;
for (size_t ii = 0; ii < gpu_info->secondary_gpus.size(); ++ii) {
if (gpu_info->secondary_gpus[ii].vendor_id == active_vendor) {
device = &(gpu_info->secondary_gpus[ii]);
break;
}
}
if (device == NULL)
return false;
GPUInfo::GPUDevice temp = gpu_info->gpu;
gpu_info->gpu = *device;
*device = temp;
return true;
}

} // namespace anonymous

bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
Expand Down Expand Up @@ -271,4 +291,33 @@ void MergeGPUInfo(GPUInfo* basic_gpu_info,
MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
}

bool DetermineActiveGPU(GPUInfo* gpu_info) {
DCHECK(gpu_info);
if (gpu_info->secondary_gpus.size() == 0)
return true;
if (gpu_info->gl_vendor.empty())
return false;
uint32 active_vendor = 0;
// For now we only handle Intel/NVIDIA/AMD.
if (gpu_info->gl_vendor.find("Intel") != std::string::npos) {
if (gpu_info->gpu.vendor_id == kVendorIDIntel)
return true;
active_vendor = kVendorIDIntel;
}
if (gpu_info->gl_vendor.find("NVIDIA") != std::string::npos) {
if (gpu_info->gpu.vendor_id == kVendorIDNVidia)
return true;
active_vendor = kVendorIDNVidia;
}
if (gpu_info->gl_vendor.find("ATI") != std::string::npos ||
gpu_info->gl_vendor.find("AMD") != std::string::npos) {
if (gpu_info->gpu.vendor_id == kVendorIDAMD)
return true;
active_vendor = kVendorIDAMD;
}
if (active_vendor == 0)
return false;
return FindAndSetActiveGPU(gpu_info, active_vendor);
}

} // namespace gpu

0 comments on commit 86a3377

Please sign in to comment.