Support ANGLE_PREFERRED_DEVICE on CGL

Add the possibility to test both integrated and discrete GPU
with ANGLE tests. Previously it was using only discrete.

The binaries need the NSSupportsAutomaticGraphicsSwitching bundle
property.

This is needed to test ANGLE_power_preference.

Changes the behavior of test apps:

Previously,
  ./angle_end2end_tests
would use discrete GPU.

After,
  ./angle_end2end_tests
or
  ANGLE_PREFERRED_DEVICE=intel ./angle_end2end_tests
will use integrated GPU.
  ANGLE_PREFERRED_DEVICE=amd ./angle_end2end_tests
will use discrete GPU.

Bug: angleproject:7093
Change-Id: Ia64f6024e3215e69c2a1bde3ba4f67c3ca595476
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3516114
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
This commit is contained in:
Kimmo Kinnunen 2022-03-11 13:58:52 +02:00 коммит произвёл Angle LUCI CQ
Родитель 23558369a5
Коммит ba04fcfd10
8 изменённых файлов: 94 добавлений и 30 удалений

Просмотреть файл

@ -1413,6 +1413,21 @@ if (angle_standalone || build_with_chromium) {
}
}
if (angle_enable_cgl) {
config("supports_automatic_graphics_switching") {
# For discussion about config, inputs, etc, see:
# https://bugs.chromium.org/p/chromium/issues/detail?id=781858
_plist_file = "util/osx/supports_automatic_graphics_switching.plist"
inputs = [ _plist_file ]
ldflags = [
"-sectcreate",
"__TEXT",
"__info_plist",
rebase_path(_plist_file, root_build_dir),
]
}
}
if (is_android && symbol_level != 0) {
action_foreach("compressed_symbols") {
sources = []

Просмотреть файл

@ -478,10 +478,15 @@ if (angle_standalone || build_with_chromium) {
]
}
if (is_mac && angle_enable_metal) {
# On macOS, compiling Metal shader sometimes takes very long time due to internal caching
# mechanism. This hooking library is a way to bypass this caching mechanism.
data_deps += [ "$angle_root/src/libANGLE/renderer/metal/file_hooking:metal_shader_cache_file_hooking" ]
if (is_mac) {
if (angle_enable_metal) {
# On macOS, compiling Metal shader sometimes takes very long time due to internal caching
# mechanism. This hooking library is a way to bypass this caching mechanism.
data_deps += [ "$angle_root/src/libANGLE/renderer/metal/file_hooking:metal_shader_cache_file_hooking" ]
}
if (angle_enable_cgl) {
configs += [ "$angle_root:supports_automatic_graphics_switching" ]
}
}
if ((is_linux && !is_chromeos) ||

Просмотреть файл

@ -12,11 +12,18 @@
#include <iostream>
#include <sstream>
#include "anglebase/no_destructor.h"
#include "common/debug.h"
#include "common/string_utils.h"
#include "common/system_utils.h"
namespace angle
{
namespace
{
constexpr char kANGLEPreferredDeviceEnv[] = "ANGLE_PREFERRED_DEVICE";
}
std::string VendorName(VendorID vendor)
{
switch (vendor)
@ -102,6 +109,22 @@ bool SystemInfo::hasAMDGPU() const
return false;
}
std::optional<size_t> SystemInfo::getPreferredGPUIndex() const
{
std::string device = GetPreferredDeviceString();
if (!device.empty())
{
for (size_t i = 0; i < gpus.size(); ++i)
{
std::string vendor = VendorName(gpus[i].vendorId);
ToLower(&vendor);
if (vendor == device)
return i;
}
}
return std::nullopt;
}
bool IsAMD(VendorID vendorId)
{
return vendorId == kVendorID_AMD;
@ -385,4 +408,11 @@ uint32_t GetSystemDeviceIdLowPart(uint64_t systemDeviceId)
return systemDeviceId & 0xffffffff;
}
std::string GetPreferredDeviceString()
{
std::string device = angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv);
ToLower(&device);
return device;
}
} // namespace angle

Просмотреть файл

@ -10,6 +10,7 @@
#define GPU_INFO_UTIL_SYSTEM_INFO_H_
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
@ -60,6 +61,9 @@ struct SystemInfo
bool hasIntelGPU() const;
bool hasAMDGPU() const;
// Returns the index to `gpus` if the entry matches the preferred device string.
std::optional<size_t> getPreferredGPUIndex() const;
std::vector<GPUDeviceInfo> gpus;
// Index of the GPU expected to be used for 3D graphics. Based on a best-guess heuristic on
@ -162,6 +166,9 @@ uint64_t GetSystemDeviceIdFromParts(uint32_t highPart, uint32_t lowPart);
uint32_t GetSystemDeviceIdHighPart(uint64_t systemDeviceId);
uint32_t GetSystemDeviceIdLowPart(uint64_t systemDeviceId);
// Returns lower-case of ANGLE_PREFERRED_DEVICE environment variable contents.
std::string GetPreferredDeviceString();
} // namespace angle
#endif // GPU_INFO_UTIL_SYSTEM_INFO_H_

Просмотреть файл

@ -209,8 +209,26 @@ egl::Error DisplayCGL::initialize(egl::Display *display)
if (mSupportsGPUSwitching)
{
// Determine the currently active GPU on the system.
mCurrentGPUID = angle::GetGpuIDFromDisplayID(kCGDirectMainDisplay);
auto gpuIndex = info.getPreferredGPUIndex();
if (gpuIndex)
{
auto gpuID = info.gpus[*gpuIndex].systemDeviceId;
auto virtualScreen = GetVirtualScreenByRegistryID(mPixelFormat, gpuID);
if (virtualScreen)
{
CGLError error = CGLSetVirtualScreen(mContext, *virtualScreen);
ASSERT(error == kCGLNoError);
if (error == kCGLNoError)
{
mCurrentGPUID = gpuID;
}
}
}
if (mCurrentGPUID == 0)
{
// Determine the currently active GPU on the system.
mCurrentGPUID = angle::GetGpuIDFromDisplayID(kCGDirectMainDisplay);
}
}
if (CGLSetCurrentContext(mContext) != kCGLNoError)

Просмотреть файл

@ -33,10 +33,6 @@
#include "EGL/eglext.h"
#if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
constexpr char kANGLEPreferredDeviceEnv[] = "ANGLE_PREFERRED_DEVICE";
#endif
namespace rx
{
@ -294,15 +290,13 @@ mtl::AutoObjCPtr<id<MTLDevice>> DisplayMtl::getMetalDeviceMatchingAttribute(
}
}
// Check the ANGLE_PREFERRED_DEVICE environment variable for device preference
const std::string anglePreferredDevice = angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv);
if (anglePreferredDevice != "")
const std::string preferredDeviceString = angle::GetPreferredDeviceString();
if (!preferredDeviceString.empty())
{
for (id<MTLDevice> device in deviceList.get())
{
if ([device.name.lowercaseString
containsString:[NSString stringWithUTF8String:anglePreferredDevice.c_str()]
.lowercaseString])
containsString:[NSString stringWithUTF8String:preferredDeviceString.c_str()]])
{
NSLog(@"Using Metal Device: %@", [device name]);
return device;

Просмотреть файл

@ -19,13 +19,7 @@
#include "util/OSWindow.h"
using namespace angle;
namespace
{
// TODO(anglebug.com/7093): Implement bundling of Info.plist to angle_end2end_tests
// In the mean time, change this manually to true and cp src/tests/end2end_tests/mac/Info.plist
// out/Debug/
const bool testRunnerSupportsAutomaticGraphicsSwitching = false;
} // namespace
class EGLPowerPreferenceTest : public ANGLETest
{
public:
@ -46,7 +40,6 @@ class EGLPowerPreferenceTest : public ANGLETest
TEST_P(EGLPowerPreferenceTest, ForceGPUSwitch)
{
ANGLE_SKIP_TEST_IF(!testRunnerSupportsAutomaticGraphicsSwitching);
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(getDisplay(), "EGL_ANGLE_power_preference"));
size_t lowPower = FindLowPowerGPU(mSystemInfo);
size_t highPower = FindHighPowerGPU(mSystemInfo);
@ -69,14 +62,16 @@ TEST_P(EGLPowerPreferenceTest, ForceGPUSwitch)
TEST_P(EGLPowerPreferenceTest, HandleGPUSwitchAfterForceGPUSwitch)
{
ANGLE_SKIP_TEST_IF(!testRunnerSupportsAutomaticGraphicsSwitching);
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(getDisplay(), "EGL_ANGLE_power_preference"));
size_t initialGPU = FindActiveOpenGLGPU(mSystemInfo);
size_t changedGPU = FindLowPowerGPU(mSystemInfo);
if (initialGPU == changedGPU)
{
changedGPU = FindHighPowerGPU(mSystemInfo);
}
// On all platforms the extension is implemented (e.g. CGL): If we start with integrated, and
// force DGPU, we cannot eglHandleGPUSwitchANGLE() from DGPU to integrated.
// eglHandleGPUSwitchANGLE() will switch to the "default", which will be DGPU.
// If we start with DGPU and switch to integrated, we *can* eglHandleGPUSwitchANGLE() back
// to the default, DGPU.
ANGLE_SKIP_TEST_IF(initialGPU == changedGPU);
EGLint hi = 0;
EGLint lo = 0;
for (int i = 0; i < 5; ++i)

Просмотреть файл

@ -3,9 +3,9 @@
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>angle_end2end_tests</string>
<string>angle_test</string> <!-- Generic name so we don't need per target .plist file.-->
<key>CFBundleIdentifier</key>
<string>org.chromium.angle.angle_end2end_tests</string>
<string>org.chromium.angle.angle_test</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
</dict>