Add ForceGPUSwitch to EGL_ANGLE_power_preference

eglHandleGPUSwitch() does not work with WebKit sandbox profile.
The root cause is that we do not know the
primary display, and as such we do not know which GPU drives this.

Add eglForceGPUSwitchANGLE(display, gpuIDHigh, gpuIDLow).
This lets the caller figure out the GPU in another process. Then
the caller can just set the GPU in the sandboxed process.

Add tests that are disabled by default until the runner and the
infrastructure supports running the tests with automatic switching
enabled.

Bug: angleproject:7092
Change-Id: I316ee431156596effbdb89659a5e24291719a204
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3516274
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Kenneth Russell <kbr@chromium.org>
This commit is contained in:
Kimmo Kinnunen 2022-03-10 15:38:13 +02:00 коммит произвёл Angle LUCI CQ
Родитель 7c616871c7
Коммит 9637185c3d
41 изменённых файлов: 464 добавлений и 110 удалений

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

@ -9,6 +9,7 @@ Name Strings
Contributors
Kenneth Russell
Kimmo Kinnunen
Contacts
@ -20,7 +21,7 @@ Status
Version
Version 1, April 16, 2019
Version 3, March 10, 2022
Number
@ -49,6 +50,8 @@ New Procedures and Functions
EGLDisplay dpy,
EGLContext context);
void eglHandleGPUSwitchANGLE(EGLDisplay dpy);
void eglForceGPUSwitchANGLE(EGLDisplay dpy, EGLint gpuIDHigh,
EGLint gpuIDLow);
New Tokens
@ -120,6 +123,31 @@ Additions to the EGL 1.4 Specification
if |dpy| is an uninitialized display, an EGL_NOT_INITIALIZED error
is generated.
eglForceGPUSwitchANGLE should be called with an explicit gpuID to transition
between the low-power and high-power GPUs. This should be called if
the environment is altered in such a way that eglHandleGPUSwitchANGLE
will not work.
On the macOS platform, the sandbox policy might prevent eglHandleGPUSwitchANGLE
from obtaining the current main active GPU. In these cases, the gpuID can
be obtained another way (e.g in other process) and communicated via
eglForceGPUSwitchANGLE to the OpenGL display.
If gpuID does not match any available GPUs in the system,
nothing happens.
For calls to this function:
If |dpy| is not a valid display, an EGL_BAD_DISPLAY error is
generated.
if |dpy| is an uninitialized display, an EGL_NOT_INITIALIZED error
is generated.
|gpuIDHigh| the high 32 bits of the IOKit registry ID of the GPU to
use for all contexts in the display.
|gpuIDLow| the low 32 bits of the IOKit registry ID of the GPU to
use for all contexts in the display.
Issues
None yet.
@ -132,3 +160,4 @@ Revision History
2 June 5, 2020 kbr Add eglReleaseHighPowerGPUANGLE,
eglReacquireHighPowerGPUANGLE, and
eglHandleGPUSwitchANGLE
3 March 10, 2022 kkinnunen Add eglForceGPUSwitchANGLE

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

@ -282,10 +282,12 @@ EGLAPI EGLBoolean EGLAPIENTRY eglGetMscRateANGLE(EGLDisplay dpy,
typedef void(EGLAPIENTRYP PFNEGLRELEASEHIGHPOWERGPUANGLEPROC) (EGLDisplay dpy, EGLContext ctx);
typedef void(EGLAPIENTRYP PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC) (EGLDisplay dpy, EGLContext ctx);
typedef void(EGLAPIENTRYP PFNEGLHANDLEGPUSWITCHANGLEPROC) (EGLDisplay dpy);
typedef void(EGLAPIENTRYP PFNEGLFORCEGPUSWITCHANGLEPROC) (EGLDisplay dpy, EGLint gpuIDHigh, EGLint gpuIDLow);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI void EGLAPIENTRY eglReleaseHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx);
EGLAPI void EGLAPIENTRY eglReacquireHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx);
EGLAPI void EGLAPIENTRY eglHandleGPUSwitchANGLE(EGLDisplay dpy);
EGLAPI void EGLAPIENTRY eglForceGPUSwitchANGLE(EGLDisplay dpy, EGLint gpuIDHigh, EGLint gpuIDLow);
#endif
#endif /* EGL_ANGLE_power_preference */

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

@ -6,7 +6,7 @@
"scripts/egl.xml":
"013c552e6c523abdcf268268ea47e9fe",
"scripts/egl_angle_ext.xml":
"72bf10ed3d23d5cdfa49934a0393b30d",
"3618e835dbe1b28ef5ad20e7e36d1262",
"scripts/extension_data/intel_630_linux.json":
"513dabe561b92b577ec8433d263f8ba6",
"scripts/extension_data/intel_630_win10.json":

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

@ -4,7 +4,7 @@
"scripts/egl.xml":
"013c552e6c523abdcf268268ea47e9fe",
"scripts/egl_angle_ext.xml":
"72bf10ed3d23d5cdfa49934a0393b30d",
"3618e835dbe1b28ef5ad20e7e36d1262",
"scripts/generate_loader.py":
"e67f4da64ba7f5cff39ba4e8926a05f8",
"scripts/gl.xml":
@ -16,21 +16,21 @@
"scripts/wgl.xml":
"c36001431919e1c435f1215a85f7e1db",
"src/libEGL/egl_loader_autogen.cpp":
"cac833213d037fa8d8a81c39b6bb1c56",
"f8e305c5b9defa9ec419cac1a4c2247c",
"src/libEGL/egl_loader_autogen.h":
"6c1243c5956193a13ebc6658646877f2",
"6e1f48d3358bd57cb17e9ca7c8d0f13a",
"src/tests/restricted_traces/trace_egl_loader_autogen.cpp":
"31143ac4b21d32854fa6603673c93937",
"757d54a7afc30f8aa3d285ad2318f68c",
"src/tests/restricted_traces/trace_egl_loader_autogen.h":
"372c734043680041148d75e1810d63c5",
"2a417d513f4ad2892ccc5c66e42e5759",
"src/tests/restricted_traces/trace_gles_loader_autogen.cpp":
"66d09a2dd240c073868fc14118186c69",
"src/tests/restricted_traces/trace_gles_loader_autogen.h":
"e6bdefb58de439b5b38d4d2546ae44e7",
"util/egl_loader_autogen.cpp":
"7134e5535bf520664b33ba5a34e46351",
"6afbbc553222705dd77c48e7510250dd",
"util/egl_loader_autogen.h":
"07612f2570e6ed43f8ccdf32934d73b8",
"3e1e6ea983aa952601d1b6de83161a8a",
"util/gles_loader_autogen.cpp":
"01482c56dd2c4410149feaa8bff21bbe",
"util/gles_loader_autogen.h":

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

@ -4,7 +4,7 @@
"scripts/egl.xml":
"013c552e6c523abdcf268268ea47e9fe",
"scripts/egl_angle_ext.xml":
"72bf10ed3d23d5cdfa49934a0393b30d",
"3618e835dbe1b28ef5ad20e7e36d1262",
"scripts/entry_point_packed_egl_enums.json":
"a72ae855c6b403912103b519139951a1",
"scripts/entry_point_packed_gl_enums.json":
@ -20,9 +20,9 @@
"scripts/wgl.xml":
"c36001431919e1c435f1215a85f7e1db",
"src/common/entry_points_enum_autogen.cpp":
"ecc75a3167c60a45642f44852c921771",
"f882ef34359bd438d01653ec0228b4a8",
"src/common/entry_points_enum_autogen.h":
"c3e69949e19486bed33badcfb9a05805",
"e944a17f832d00a2ac9762ce957f370c",
"src/libANGLE/Context_gl_1_autogen.h":
"115d224fd28b0bc2b2800354bb57fcf3",
"src/libANGLE/Context_gl_2_autogen.h":
@ -76,7 +76,7 @@
"src/libANGLE/validationCL_autogen.h":
"0022d0cdb6a9e2ef4a59b71164f62333",
"src/libANGLE/validationEGL_autogen.h":
"9efb40631ea8b4779167f3ecab1b5794",
"e980833db949005de05ebfda3b65a18b",
"src/libANGLE/validationES1_autogen.h":
"99af5e328690ae78d7724a80e94cfac5",
"src/libANGLE/validationES2_autogen.h":
@ -98,9 +98,9 @@
"src/libANGLE/validationGL4_autogen.h":
"0477150779497ad894973f0e4b830d6b",
"src/libEGL/libEGL_autogen.cpp":
"f94c18dc41b0ce55d56dc002a32bb6b7",
"d2a4716a1e32416b64aa11da7294a2d1",
"src/libEGL/libEGL_autogen.def":
"fdd4a110a95c3a2fed33c4b5f110650d",
"773be535c00e01e343b52561fca73a6b",
"src/libGL/entry_points_gl_1_autogen.cpp":
"8148ccb597c5c77db7d5e532c7152243",
"src/libGL/entry_points_gl_1_autogen.h":
@ -124,7 +124,7 @@
"src/libGLESv2/cl_stubs_autogen.h":
"6d880c6b65284192b5842f0e42ad2741",
"src/libGLESv2/egl_ext_stubs_autogen.h":
"0e33e7ae4c96995f674bff8cf92825ff",
"8614c0f3e9bec09421f557c5bb7826ef",
"src/libGLESv2/egl_get_labeled_object_data.json":
"2f4148b2ddf34e62670e32c5e6da4937",
"src/libGLESv2/egl_stubs_autogen.h":
@ -138,9 +138,9 @@
"src/libGLESv2/entry_points_egl_autogen.h":
"3bc7a8df9deadd7cfd615d0cfad0c6a8",
"src/libGLESv2/entry_points_egl_ext_autogen.cpp":
"c9d5df7d303e13fe9b3f78dafa22eff0",
"9acd4e2c7d4ae61adc2cc01029f1dd08",
"src/libGLESv2/entry_points_egl_ext_autogen.h":
"df2219883f43fc1c7a2b568f4f49185a",
"5ce03067f75c6179d47fe85186dff646",
"src/libGLESv2/entry_points_gles_1_0_autogen.cpp":
"4cb9f5d56c003d1627365cfa34470edc",
"src/libGLESv2/entry_points_gles_1_0_autogen.h":
@ -168,11 +168,11 @@
"src/libGLESv2/libGLESv2_autogen.cpp":
"6a7e775b20563d405005cb1bbcf67e76",
"src/libGLESv2/libGLESv2_autogen.def":
"e49b6127cf3bdd546ed938d9c280bd5f",
"14c09cde5374162e2c3dcd1947804f0d",
"src/libGLESv2/libGLESv2_no_capture_autogen.def":
"60d6dfc9890a30fa862153a9f1ac29e7",
"0f9168c1ebb1f9c044b6249969a8ec0c",
"src/libGLESv2/libGLESv2_with_capture_autogen.def":
"d0915e85df4e78a5384ac1fc5a16b9e6",
"4d77d1e5ceee453bd99a150f6a24aa80",
"src/libOpenCL/libOpenCL_autogen.cpp":
"10849978c910dc1af5dd4f0c815d1581"
}

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

@ -4,7 +4,7 @@
"scripts/egl.xml":
"013c552e6c523abdcf268268ea47e9fe",
"scripts/egl_angle_ext.xml":
"72bf10ed3d23d5cdfa49934a0393b30d",
"3618e835dbe1b28ef5ad20e7e36d1262",
"scripts/gen_proc_table.py":
"8336449da7e36f45dd6d70c44add2ebf",
"scripts/gl.xml":
@ -20,7 +20,7 @@
"src/libGLESv2/proc_table_cl_autogen.cpp":
"ed003b0f041aaaa35b67d3fe07e61f91",
"src/libGLESv2/proc_table_egl_autogen.cpp":
"1fe7444ee1f5b6300d5d02b7eb378cc2",
"c6b5d0b60395ccd33a1d9e38341eeef3",
"src/libOpenCL/libOpenCL_autogen.map":
"bc5f5cf48227149ed321258a16eff1d7"
}

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

@ -113,6 +113,12 @@
<proto><pytpe>void</pytpe> <name>eglHandleGPUSwitchANGLE</name></proto>
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
</command>
<command>
<proto><pytpe>void</pytpe> <name>eglForceGPUSwitchANGLE</name></proto>
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
<param><ptype>EGLint</ptype> <name>gpuIDHigh</name></param>
<param><ptype>EGLint</ptype> <name>gpuIDLow</name></param>
</command>
<command>
<proto><ptype>EGLBoolean</ptype> <name>eglQueryDisplayAttribANGLE</name></proto>
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
@ -180,6 +186,7 @@
<command name="eglReleaseHighPowerGPUANGLE"/>
<command name="eglReacquireHighPowerGPUANGLE"/>
<command name="eglHandleGPUSwitchANGLE"/>
<command name="eglForceGPUSwitchANGLE"/>
</require>
</extension>
<extension name="EGL_ANGLE_display_semaphore_share_group" supported="egl">

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

@ -314,6 +314,8 @@ const char *GetEntryPointName(EntryPoint ep)
return "eglDupNativeFenceFDANDROID";
case EntryPoint::EGLExportVkImageANGLE:
return "eglExportVkImageANGLE";
case EntryPoint::EGLForceGPUSwitchANGLE:
return "eglForceGPUSwitchANGLE";
case EntryPoint::EGLGetCompositorTimingANDROID:
return "eglGetCompositorTimingANDROID";
case EntryPoint::EGLGetCompositorTimingSupportedANDROID:

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

@ -163,6 +163,7 @@ enum class EntryPoint
EGLDestroySyncKHR,
EGLDupNativeFenceFDANDROID,
EGLExportVkImageANGLE,
EGLForceGPUSwitchANGLE,
EGLGetCompositorTimingANDROID,
EGLGetCompositorTimingSupportedANDROID,
EGLGetConfigAttrib,

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

@ -191,7 +191,7 @@ void GetIORegistryDevices(std::vector<GPUDeviceInfo> *devices)
}
}
void SetActiveGPUIndex(SystemInfo *info)
void ForceGPUSwitchIndex(SystemInfo *info)
{
VendorID activeVendor = 0;
DeviceID activeDevice = 0;
@ -373,7 +373,7 @@ bool GetSystemInfo_mac(SystemInfo *info)
// GPU instead of the non-intel GPU
if (@available(macOS 10.13, *))
{
SetActiveGPUIndex(info);
ForceGPUSwitchIndex(info);
}
// Figure out whether this is a dual-GPU system.

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

@ -2372,6 +2372,13 @@ Error Display::handleGPUSwitch()
return NoError();
}
Error Display::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
{
ANGLE_TRY(mImplementation->forceGPUSwitch(gpuIDHigh, gpuIDLow));
initVendorString();
return NoError();
}
bool Display::supportsDmaBufFormat(EGLint format) const
{
return mImplementation->supportsDmaBufFormat(format);

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

@ -303,6 +303,7 @@ class Display final : public LabeledObject,
void returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer);
egl::Error handleGPUSwitch();
egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow);
std::mutex &getDisplayGlobalMutex() { return mDisplayGlobalMutex; }
std::mutex &getProgramCacheMutex() { return mProgramCacheMutex; }

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

@ -74,6 +74,11 @@ egl::Error DisplayImpl::handleGPUSwitch()
return egl::NoError();
}
egl::Error DisplayImpl::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
{
return egl::NoError();
}
egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,

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

@ -120,6 +120,7 @@ class DisplayImpl : public EGLImplFactory, public angle::Subject
const egl::DisplayState &getState() const { return mState; }
virtual egl::Error handleGPUSwitch();
virtual egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow);
virtual bool isX11() const;

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

@ -105,6 +105,7 @@ class DisplayCGL : public DisplayGL
egl::Error referenceDiscreteGPU();
egl::Error unreferenceDiscreteGPU();
egl::Error handleGPUSwitch() override;
egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow) override;
private:
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
@ -113,6 +114,7 @@ class DisplayCGL : public DisplayGL
void generateCaps(egl::Caps *outCaps) const override;
void checkDiscreteGPUStatus();
void setContextToGPU(uint64_t gpuID, GLint virtualScreen);
std::shared_ptr<RendererGL> mRenderer;

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

@ -50,9 +50,8 @@ using IORegistryGPUID = uint64_t;
// Code from WebKit to set an OpenGL context to use a particular GPU by ID.
// https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm
// Used with permission.
static void SetGPUByRegistryID(CGLContextObj contextObj,
CGLPixelFormatObj pixelFormatObj,
IORegistryGPUID preferredGPUID)
static std::optional<GLint> GetVirtualScreenByRegistryID(CGLPixelFormatObj pixelFormatObj,
IORegistryGPUID gpuID)
{
if (@available(macOS 10.13, *))
{
@ -62,51 +61,65 @@ static void SetGPUByRegistryID(CGLContextObj contextObj,
// registryID. CGLSetVirtualScreen can then be used to tell OpenGL which GPU it should be
// using.
if (!contextObj || !preferredGPUID)
return;
GLint virtualScreenCount = 0;
CGLError error = CGLDescribePixelFormat(pixelFormatObj, 0, kCGLPFAVirtualScreenCount,
&virtualScreenCount);
ASSERT(error == kCGLNoError);
GLint firstAcceleratedScreen = -1;
if (error != kCGLNoError)
{
NOTREACHED();
return std::nullopt;
}
for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen)
{
GLint displayMask = 0;
error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFADisplayMask,
&displayMask);
ASSERT(error == kCGLNoError);
auto gpuID = angle::GetGpuIDFromOpenGLDisplayMask(displayMask);
if (gpuID == preferredGPUID)
if (error != kCGLNoError)
{
error = CGLSetVirtualScreen(contextObj, virtualScreen);
ASSERT(error == kCGLNoError);
fprintf(stderr, "Context (%p) set to GPU with ID: (%lld).", contextObj, gpuID);
return;
NOTREACHED();
return std::nullopt;
}
if (firstAcceleratedScreen < 0)
auto virtualScreenGPUID = angle::GetGpuIDFromOpenGLDisplayMask(displayMask);
if (virtualScreenGPUID == gpuID)
{
GLint isAccelerated = 0;
error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFAAccelerated,
&isAccelerated);
ASSERT(error == kCGLNoError);
if (isAccelerated)
firstAcceleratedScreen = virtualScreen;
return virtualScreen;
}
}
// No registryID match found; set to first hardware-accelerated virtual screen.
if (firstAcceleratedScreen >= 0)
{
error = CGLSetVirtualScreen(contextObj, firstAcceleratedScreen);
ASSERT(error == kCGLNoError);
}
}
return std::nullopt;
}
static std::optional<GLint> GetFirstAcceleratedVirtualScreen(CGLPixelFormatObj pixelFormatObj)
{
if (@available(macOS 10.13, *))
{
GLint virtualScreenCount = 0;
CGLError error = CGLDescribePixelFormat(pixelFormatObj, 0, kCGLPFAVirtualScreenCount,
&virtualScreenCount);
if (error != kCGLNoError)
{
NOTREACHED();
return std::nullopt;
}
for (GLint virtualScreen = 0; virtualScreen < virtualScreenCount; ++virtualScreen)
{
GLint isAccelerated = 0;
error = CGLDescribePixelFormat(pixelFormatObj, virtualScreen, kCGLPFAAccelerated,
&isAccelerated);
if (error != kCGLNoError)
{
NOTREACHED();
return std::nullopt;
}
if (isAccelerated)
{
return virtualScreen;
}
}
}
return std::nullopt;
}
} // anonymous namespace
@ -650,22 +663,56 @@ egl::Error DisplayCGL::handleGPUSwitch()
uint64_t gpuID = angle::GetGpuIDFromDisplayID(kCGDirectMainDisplay);
if (gpuID != mCurrentGPUID)
{
SetGPUByRegistryID(mContext, mPixelFormat, gpuID);
// Performing the above operation seems to need a call to CGLSetCurrentContext to make
// the context work properly again. Failing to do this returns null strings for
// GL_VENDOR and GL_RENDERER.
CGLUpdateContext(mContext);
CGLSetCurrentContext(mContext);
onStateChange(angle::SubjectMessage::SubjectChanged);
mCurrentGPUID = gpuID;
mRenderer->handleGPUSwitch();
auto virtualScreen = GetVirtualScreenByRegistryID(mPixelFormat, gpuID);
if (!virtualScreen)
{
virtualScreen = GetFirstAcceleratedVirtualScreen(mPixelFormat);
}
if (virtualScreen)
{
setContextToGPU(gpuID, *virtualScreen);
}
}
}
return egl::NoError();
}
egl::Error DisplayCGL::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
{
if (mSupportsGPUSwitching)
{
uint64_t gpuID = static_cast<uint64_t>(static_cast<uint32_t>(gpuIDHigh)) << 32 |
static_cast<uint32_t>(gpuIDLow);
if (gpuID != mCurrentGPUID)
{
auto virtualScreen = GetVirtualScreenByRegistryID(mPixelFormat, gpuID);
if (virtualScreen)
{
setContextToGPU(gpuID, *virtualScreen);
}
}
}
return egl::NoError();
}
void DisplayCGL::setContextToGPU(uint64_t gpuID, GLint virtualScreen)
{
CGLError error = CGLSetVirtualScreen(mContext, virtualScreen);
ASSERT(error == kCGLNoError);
if (error == kCGLNoError)
{
// Performing the above operation seems to need a call to CGLSetCurrentContext to make
// the context work properly again. Failing to do this returns null strings for
// GL_VENDOR and GL_RENDERER.
CGLUpdateContext(mContext);
CGLSetCurrentContext(mContext);
onStateChange(angle::SubjectMessage::SubjectChanged);
mCurrentGPUID = gpuID;
mRenderer->handleGPUSwitch();
}
}
} // namespace rx
#endif // defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)

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

@ -363,7 +363,6 @@ namespace vk
{
const char *gLoaderLayersPathEnv = "VK_LAYER_PATH";
const char *gLoaderICDFilenamesEnv = "VK_ICD_FILENAMES";
const char *gANGLEPreferredDevice = "ANGLE_PREFERRED_DEVICE";
VkImageAspectFlags GetDepthStencilAspectFlags(const angle::Format &format)
{

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

@ -6234,6 +6234,15 @@ bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const Display *d
return true;
}
bool ValidateForceGPUSwitchANGLE(const ValidationContext *val,
const Display *display,
EGLint gpuIDHigh,
EGLint gpuIDLow)
{
ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
return true;
}
bool ValidateGetCurrentDisplay(const ValidationContext *val)
{
return true;

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

@ -250,6 +250,10 @@ bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
const egl::Display *dpyPacked,
const gl::Context *ctxPacked);
bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const egl::Display *dpyPacked);
bool ValidateForceGPUSwitchANGLE(const ValidationContext *val,
const egl::Display *dpyPacked,
EGLint gpuIDHigh,
EGLint gpuIDLow);
// EGL_ANGLE_prepare_swap_buffers
bool ValidatePrepareSwapBuffersANGLE(const ValidationContext *val,

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

@ -68,6 +68,7 @@ PFNEGLCREATEDEVICEANGLEPROC l_EGL_CreateDeviceANGLE;
PFNEGLRELEASEDEVICEANGLEPROC l_EGL_ReleaseDeviceANGLE;
PFNEGLQUERYDISPLAYATTRIBANGLEPROC l_EGL_QueryDisplayAttribANGLE;
PFNEGLQUERYSTRINGIANGLEPROC l_EGL_QueryStringiANGLE;
PFNEGLFORCEGPUSWITCHANGLEPROC l_EGL_ForceGPUSwitchANGLE;
PFNEGLHANDLEGPUSWITCHANGLEPROC l_EGL_HandleGPUSwitchANGLE;
PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC l_EGL_ReacquireHighPowerGPUANGLE;
PFNEGLRELEASEHIGHPOWERGPUANGLEPROC l_EGL_ReleaseHighPowerGPUANGLE;
@ -213,6 +214,8 @@ void LoadEGL_EGL(LoadProc loadProc)
loadProc("EGL_QueryDisplayAttribANGLE"));
l_EGL_QueryStringiANGLE =
reinterpret_cast<PFNEGLQUERYSTRINGIANGLEPROC>(loadProc("EGL_QueryStringiANGLE"));
l_EGL_ForceGPUSwitchANGLE =
reinterpret_cast<PFNEGLFORCEGPUSWITCHANGLEPROC>(loadProc("EGL_ForceGPUSwitchANGLE"));
l_EGL_HandleGPUSwitchANGLE =
reinterpret_cast<PFNEGLHANDLEGPUSWITCHANGLEPROC>(loadProc("EGL_HandleGPUSwitchANGLE"));
l_EGL_ReacquireHighPowerGPUANGLE = reinterpret_cast<PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC>(

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

@ -73,6 +73,7 @@
#define EGL_ReleaseDeviceANGLE l_EGL_ReleaseDeviceANGLE
#define EGL_QueryDisplayAttribANGLE l_EGL_QueryDisplayAttribANGLE
#define EGL_QueryStringiANGLE l_EGL_QueryStringiANGLE
#define EGL_ForceGPUSwitchANGLE l_EGL_ForceGPUSwitchANGLE
#define EGL_HandleGPUSwitchANGLE l_EGL_HandleGPUSwitchANGLE
#define EGL_ReacquireHighPowerGPUANGLE l_EGL_ReacquireHighPowerGPUANGLE
#define EGL_ReleaseHighPowerGPUANGLE l_EGL_ReleaseHighPowerGPUANGLE
@ -183,6 +184,7 @@ ANGLE_NO_EXPORT extern PFNEGLCREATEDEVICEANGLEPROC l_EGL_CreateDeviceANGLE;
ANGLE_NO_EXPORT extern PFNEGLRELEASEDEVICEANGLEPROC l_EGL_ReleaseDeviceANGLE;
ANGLE_NO_EXPORT extern PFNEGLQUERYDISPLAYATTRIBANGLEPROC l_EGL_QueryDisplayAttribANGLE;
ANGLE_NO_EXPORT extern PFNEGLQUERYSTRINGIANGLEPROC l_EGL_QueryStringiANGLE;
ANGLE_NO_EXPORT extern PFNEGLFORCEGPUSWITCHANGLEPROC l_EGL_ForceGPUSwitchANGLE;
ANGLE_NO_EXPORT extern PFNEGLHANDLEGPUSWITCHANGLEPROC l_EGL_HandleGPUSwitchANGLE;
ANGLE_NO_EXPORT extern PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC l_EGL_ReacquireHighPowerGPUANGLE;
ANGLE_NO_EXPORT extern PFNEGLRELEASEHIGHPOWERGPUANGLEPROC l_EGL_ReleaseHighPowerGPUANGLE;

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

@ -514,6 +514,12 @@ void EGLAPIENTRY eglHandleGPUSwitchANGLE(EGLDisplay dpy)
return EGL_HandleGPUSwitchANGLE(dpy);
}
void EGLAPIENTRY eglForceGPUSwitchANGLE(EGLDisplay dpy, EGLint gpuIDHigh, EGLint gpuIDLow)
{
EnsureEGLLoaded();
return EGL_ForceGPUSwitchANGLE(dpy, gpuIDHigh, gpuIDLow);
}
// EGL_ANGLE_prepare_swap_buffers
EGLBoolean EGLAPIENTRY eglPrepareSwapBuffersANGLE(EGLDisplay dpy, EGLSurface surface)
{

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

@ -92,6 +92,7 @@ EXPORTS
eglQueryStringiANGLE
; EGL_ANGLE_power_preference
eglForceGPUSwitchANGLE
eglHandleGPUSwitchANGLE
eglReacquireHighPowerGPUANGLE
eglReleaseHighPowerGPUANGLE

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

@ -824,6 +824,16 @@ void HandleGPUSwitchANGLE(Thread *thread, Display *display)
thread->setSuccess();
}
void ForceGPUSwitchANGLE(Thread *thread, Display *display, EGLint gpuIDHigh, EGLint gpuIDLow)
{
ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglForceGPUSwitchANGLE",
GetDisplayIfValid(display));
ANGLE_EGL_TRY(thread, display->forceGPUSwitch(gpuIDHigh, gpuIDLow), "eglForceGPUSwitchANGLE",
GetDisplayIfValid(display));
thread->setSuccess();
}
EGLBoolean QueryDisplayAttribANGLE(Thread *thread,
Display *display,
EGLint attribute,

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

@ -246,6 +246,10 @@ EGLBoolean PrepareSwapBuffersANGLE(EGLDisplay dpy, EGLSurface surface);
void ReleaseHighPowerGPUANGLE(Thread *thread, egl::Display *dpyPacked, gl::Context *ctxPacked);
void ReacquireHighPowerGPUANGLE(Thread *thread, egl::Display *dpyPacked, gl::Context *ctxPacked);
void HandleGPUSwitchANGLE(Thread *thread, egl::Display *dpyPacked);
void ForceGPUSwitchANGLE(Thread *thread,
egl::Display *dpyPacked,
EGLint gpuIDHigh,
EGLint gpuIDLow);
EGLBoolean QueryDisplayAttribANGLE(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute,

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

@ -364,6 +364,23 @@ void EGLAPIENTRY EGL_HandleGPUSwitchANGLE(EGLDisplay dpy)
HandleGPUSwitchANGLE(thread, dpyPacked);
}
void EGLAPIENTRY EGL_ForceGPUSwitchANGLE(EGLDisplay dpy, EGLint gpuIDHigh, EGLint gpuIDLow)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EGL_EVENT(ForceGPUSwitchANGLE, "dpy = 0x%016" PRIxPTR ", gpuIDHigh = %d, gpuIDLow = %d",
(uintptr_t)dpy, gpuIDHigh, gpuIDLow);
Thread *thread = egl::GetCurrentThread();
egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
ANGLE_EGL_VALIDATE_VOID(thread, ForceGPUSwitchANGLE, GetDisplayIfValid(dpyPacked), dpyPacked,
gpuIDHigh, gpuIDLow);
ForceGPUSwitchANGLE(thread, dpyPacked, gpuIDHigh, gpuIDLow);
}
// EGL_ANGLE_prepare_swap_buffers
EGLBoolean EGLAPIENTRY EGL_PrepareSwapBuffersANGLE(EGLDisplay dpy, EGLSurface surface)
{

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

@ -78,6 +78,9 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_QueryDisplayAttribANGLE(EGLDisplay dpy,
ANGLE_EXPORT void EGLAPIENTRY EGL_ReleaseHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx);
ANGLE_EXPORT void EGLAPIENTRY EGL_ReacquireHighPowerGPUANGLE(EGLDisplay dpy, EGLContext ctx);
ANGLE_EXPORT void EGLAPIENTRY EGL_HandleGPUSwitchANGLE(EGLDisplay dpy);
ANGLE_EXPORT void EGLAPIENTRY EGL_ForceGPUSwitchANGLE(EGLDisplay dpy,
EGLint gpuIDHigh,
EGLint gpuIDLow);
// EGL_ANGLE_prepare_swap_buffers
ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_PrepareSwapBuffersANGLE(EGLDisplay dpy, EGLSurface surface);

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

@ -1235,6 +1235,7 @@ EXPORTS
EGL_QueryStringiANGLE
; EGL_ANGLE_power_preference
EGL_ForceGPUSwitchANGLE
EGL_HandleGPUSwitchANGLE
EGL_ReacquireHighPowerGPUANGLE
EGL_ReleaseHighPowerGPUANGLE

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

@ -1235,6 +1235,7 @@ EXPORTS
EGL_QueryStringiANGLE
; EGL_ANGLE_power_preference
EGL_ForceGPUSwitchANGLE
EGL_HandleGPUSwitchANGLE
EGL_ReacquireHighPowerGPUANGLE
EGL_ReleaseHighPowerGPUANGLE

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

@ -1235,6 +1235,7 @@ EXPORTS
EGL_QueryStringiANGLE
; EGL_ANGLE_power_preference
EGL_ForceGPUSwitchANGLE
EGL_HandleGPUSwitchANGLE
EGL_ReacquireHighPowerGPUANGLE
EGL_ReleaseHighPowerGPUANGLE

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

@ -62,6 +62,7 @@ const ProcEntry g_procTable[] = {
{"eglDestroySyncKHR", P(EGL_DestroySyncKHR)},
{"eglDupNativeFenceFDANDROID", P(EGL_DupNativeFenceFDANDROID)},
{"eglExportVkImageANGLE", P(EGL_ExportVkImageANGLE)},
{"eglForceGPUSwitchANGLE", P(EGL_ForceGPUSwitchANGLE)},
{"eglGetCompositorTimingANDROID", P(EGL_GetCompositorTimingANDROID)},
{"eglGetCompositorTimingSupportedANDROID", P(EGL_GetCompositorTimingSupportedANDROID)},
{"eglGetConfigAttrib", P(EGL_GetConfigAttrib)},
@ -945,5 +946,5 @@ const ProcEntry g_procTable[] = {
{"glWaitSync", P(GL_WaitSync)},
{"glWeightPointerOES", P(GL_WeightPointerOES)}};
const size_t g_numProcs = 912;
const size_t g_numProcs = 913;
} // namespace egl

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

@ -188,10 +188,13 @@ angle_end2end_tests_sources = [
"test_utils/ANGLETest.h",
"test_utils/MultiviewTest.cpp",
"test_utils/MultiviewTest.h",
"test_utils/system_info_util.cpp",
"test_utils/system_info_util.h",
]
angle_end2end_tests_mac_sources = [
"egl_tests/EGLDeviceCGLTest.cpp",
"egl_tests/EGLIOSurfaceClientBufferTest.cpp",
"egl_tests/EGLPowerPreferenceTest.cpp",
"egl_tests/EGLSurfaceTestMac.mm",
"gl_tests/ImageTestMetal.mm",
]

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

@ -14,6 +14,7 @@
#include "common/string_utils.h"
#include "gpu_info_util/SystemInfo.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/system_info_util.h"
#include "util/OSWindow.h"
using namespace angle;
@ -25,51 +26,15 @@ class EGLDisplaySelectionTest : public ANGLETest
protected:
// Returns the index of the low or high power GPU in SystemInfo depending on the argument.
int findGPU(bool lowPower)
int findGPU(bool lowPower) const
{
if (mSystemInfo.gpus.size() < 2)
{
return 0;
}
for (int i = 0; i < static_cast<int>(mSystemInfo.gpus.size()); ++i)
{
if (lowPower && IsIntel(mSystemInfo.gpus[i].vendorId))
{
return i;
}
// Return the high power GPU, i.e any non-intel GPU
else if (!lowPower && !IsIntel(mSystemInfo.gpus[i].vendorId))
{
return i;
}
}
// Can't find GPU
ASSERT(false);
return 0;
if (lowPower)
return FindLowPowerGPU(mSystemInfo);
return FindHighPowerGPU(mSystemInfo);
}
// Returns the index of the active GPU in SystemInfo based on the renderer string.
int findActiveGPU()
{
char *renderer = (char *)glGetString(GL_RENDERER);
std::string rendererString(renderer);
for (int i = 0; i < static_cast<int>(mSystemInfo.gpus.size()); ++i)
{
std::vector<std::string> vendorTokens;
angle::SplitStringAlongWhitespace(VendorName(mSystemInfo.gpus[i].vendorId),
&vendorTokens);
for (std::string &token : vendorTokens)
{
if (rendererString.find(token) != std::string::npos)
{
return i;
}
}
}
// Can't find active GPU
ASSERT(false);
return 0;
}
int findActiveGPU() const { return FindActiveOpenGLGPU(mSystemInfo); }
SystemInfo mSystemInfo;
};

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

@ -0,0 +1,93 @@
//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EGLPowerPreferenceTest.cpp:
// Checks the implementation of EGL_ANGLE_power_preference.
//
#include <gtest/gtest.h>
#include <tuple>
#include "common/debug.h"
#include "common/string_utils.h"
#include "gpu_info_util/SystemInfo.h"
#include "test_utils/ANGLETest.h"
#include "test_utils/angle_test_platform.h"
#include "test_utils/system_info_util.h"
#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:
void testSetUp() override { (void)GetSystemInfo(&mSystemInfo); }
protected:
auto getGpuIdParts(size_t gpuIndex) const
{
uint64_t deviceId = mSystemInfo.gpus[gpuIndex].systemDeviceId;
return std::make_tuple(GetSystemDeviceIdHighPart(deviceId),
GetSystemDeviceIdLowPart(deviceId));
}
EGLDisplay getDisplay() const { return getEGLWindow()->getDisplay(); }
SystemInfo mSystemInfo;
};
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);
size_t initialGPU = FindActiveOpenGLGPU(mSystemInfo);
ASSERT_TRUE(lowPower == initialGPU || highPower == initialGPU);
EGLint hi = 0;
EGLint lo = 0;
for (int i = 0; i < 5; ++i)
{
std::tie(hi, lo) = getGpuIdParts(lowPower);
eglForceGPUSwitchANGLE(getDisplay(), hi, lo);
EXPECT_EQ(lowPower, FindActiveOpenGLGPU(mSystemInfo));
std::tie(hi, lo) = getGpuIdParts(highPower);
eglForceGPUSwitchANGLE(getDisplay(), hi, lo);
EXPECT_EQ(highPower, FindActiveOpenGLGPU(mSystemInfo));
}
}
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);
}
EGLint hi = 0;
EGLint lo = 0;
for (int i = 0; i < 5; ++i)
{
std::tie(hi, lo) = getGpuIdParts(changedGPU);
eglForceGPUSwitchANGLE(getDisplay(), hi, lo);
ASSERT_EQ(changedGPU, FindActiveOpenGLGPU(mSystemInfo));
eglHandleGPUSwitchANGLE(getDisplay());
ASSERT_EQ(initialGPU, FindActiveOpenGLGPU(mSystemInfo));
}
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLPowerPreferenceTest);
ANGLE_INSTANTIATE_TEST(EGLPowerPreferenceTest, ES2_OPENGL(), ES3_OPENGL());

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

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>angle_end2end_tests</string>
<key>CFBundleIdentifier</key>
<string>org.chromium.angle.angle_end2end_tests</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
</dict>
</plist>

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

@ -72,6 +72,7 @@ ANGLE_TRACE_LOADER_EXPORT PFNEGLCREATEDEVICEANGLEPROC t_eglCreateDeviceANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLRELEASEDEVICEANGLEPROC t_eglReleaseDeviceANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLQUERYDISPLAYATTRIBANGLEPROC t_eglQueryDisplayAttribANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLQUERYSTRINGIANGLEPROC t_eglQueryStringiANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLFORCEGPUSWITCHANGLEPROC t_eglForceGPUSwitchANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLHANDLEGPUSWITCHANGLEPROC t_eglHandleGPUSwitchANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC t_eglReacquireHighPowerGPUANGLE;
ANGLE_TRACE_LOADER_EXPORT PFNEGLRELEASEHIGHPOWERGPUANGLEPROC t_eglReleaseHighPowerGPUANGLE;
@ -219,6 +220,8 @@ void LoadEGL(LoadProc loadProc)
reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBANGLEPROC>(loadProc("eglQueryDisplayAttribANGLE"));
t_eglQueryStringiANGLE =
reinterpret_cast<PFNEGLQUERYSTRINGIANGLEPROC>(loadProc("eglQueryStringiANGLE"));
t_eglForceGPUSwitchANGLE =
reinterpret_cast<PFNEGLFORCEGPUSWITCHANGLEPROC>(loadProc("eglForceGPUSwitchANGLE"));
t_eglHandleGPUSwitchANGLE =
reinterpret_cast<PFNEGLHANDLEGPUSWITCHANGLEPROC>(loadProc("eglHandleGPUSwitchANGLE"));
t_eglReacquireHighPowerGPUANGLE = reinterpret_cast<PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC>(

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

@ -74,6 +74,7 @@
#define eglReleaseDeviceANGLE t_eglReleaseDeviceANGLE
#define eglQueryDisplayAttribANGLE t_eglQueryDisplayAttribANGLE
#define eglQueryStringiANGLE t_eglQueryStringiANGLE
#define eglForceGPUSwitchANGLE t_eglForceGPUSwitchANGLE
#define eglHandleGPUSwitchANGLE t_eglHandleGPUSwitchANGLE
#define eglReacquireHighPowerGPUANGLE t_eglReacquireHighPowerGPUANGLE
#define eglReleaseHighPowerGPUANGLE t_eglReleaseHighPowerGPUANGLE
@ -189,6 +190,7 @@ ANGLE_TRACE_LOADER_EXPORT extern PFNEGLCREATEDEVICEANGLEPROC t_eglCreateDeviceAN
ANGLE_TRACE_LOADER_EXPORT extern PFNEGLRELEASEDEVICEANGLEPROC t_eglReleaseDeviceANGLE;
ANGLE_TRACE_LOADER_EXPORT extern PFNEGLQUERYDISPLAYATTRIBANGLEPROC t_eglQueryDisplayAttribANGLE;
ANGLE_TRACE_LOADER_EXPORT extern PFNEGLQUERYSTRINGIANGLEPROC t_eglQueryStringiANGLE;
ANGLE_TRACE_LOADER_EXPORT extern PFNEGLFORCEGPUSWITCHANGLEPROC t_eglForceGPUSwitchANGLE;
ANGLE_TRACE_LOADER_EXPORT extern PFNEGLHANDLEGPUSWITCHANGLEPROC t_eglHandleGPUSwitchANGLE;
ANGLE_TRACE_LOADER_EXPORT extern PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC
t_eglReacquireHighPowerGPUANGLE;

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

@ -0,0 +1,76 @@
//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// system_info_util.h:
// Implementation of common test utilities for operating with SystemInfo.
//
#include "system_info_util.h"
#include "common/debug.h"
#include "common/string_utils.h"
#include "gpu_info_util/SystemInfo.h"
#include "util/util_gl.h"
using namespace angle;
namespace
{
size_t findGPU(const SystemInfo &systemInfo, bool lowPower)
{
if (systemInfo.gpus.size() < 2)
{
return 0;
}
for (size_t i = 0; i < systemInfo.gpus.size(); ++i)
{
if (lowPower && IsIntel(systemInfo.gpus[i].vendorId))
{
return i;
}
// Return the high power GPU, i.e any non-intel GPU
else if (!lowPower && !IsIntel(systemInfo.gpus[i].vendorId))
{
return i;
}
}
// Can't find GPU
ASSERT(false);
return 0;
}
} // namespace
size_t FindLowPowerGPU(const SystemInfo &systemInfo)
{
return findGPU(systemInfo, true);
}
size_t FindHighPowerGPU(const SystemInfo &systemInfo)
{
return findGPU(systemInfo, false);
}
size_t FindActiveOpenGLGPU(const SystemInfo &systemInfo)
{
char *renderer = (char *)glGetString(GL_RENDERER);
std::string rendererString(renderer);
for (size_t i = 0; i < systemInfo.gpus.size(); ++i)
{
std::vector<std::string> vendorTokens;
angle::SplitStringAlongWhitespace(VendorName(systemInfo.gpus[i].vendorId), &vendorTokens);
for (std::string &token : vendorTokens)
{
if (rendererString.find(token) != std::string::npos)
{
return i;
}
}
}
// Can't find active GPU
ASSERT(false);
return 0;
}

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

@ -0,0 +1,29 @@
//
// Copyright 2022 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// system_info_util.h:
// Implementation of common test utilities for operating with SystemInfo.
//
#ifndef ANGLE_TESTS_SYSTEM_INFO_UTIL_H_
#define ANGLE_TESTS_SYSTEM_INFO_UTIL_H_
#include <stddef.h>
namespace angle
{
struct SystemInfo;
} // namespace angle
// Returns the index of the low power GPU in SystemInfo.
size_t FindLowPowerGPU(const angle::SystemInfo &);
// Returns the index of the high power GPU in SystemInfo.
size_t FindHighPowerGPU(const angle::SystemInfo &);
// Returns the index of the GPU in SystemInfo based on the OpenGL renderer string.
size_t FindActiveOpenGLGPU(const angle::SystemInfo &);
#endif // ANGLE_TESTS_SYSTEM_INFO_UTIL_H_

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

@ -70,6 +70,7 @@ ANGLE_UTIL_EXPORT PFNEGLCREATEDEVICEANGLEPROC l_eglCreateDeviceANGLE;
ANGLE_UTIL_EXPORT PFNEGLRELEASEDEVICEANGLEPROC l_eglReleaseDeviceANGLE;
ANGLE_UTIL_EXPORT PFNEGLQUERYDISPLAYATTRIBANGLEPROC l_eglQueryDisplayAttribANGLE;
ANGLE_UTIL_EXPORT PFNEGLQUERYSTRINGIANGLEPROC l_eglQueryStringiANGLE;
ANGLE_UTIL_EXPORT PFNEGLFORCEGPUSWITCHANGLEPROC l_eglForceGPUSwitchANGLE;
ANGLE_UTIL_EXPORT PFNEGLHANDLEGPUSWITCHANGLEPROC l_eglHandleGPUSwitchANGLE;
ANGLE_UTIL_EXPORT PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC l_eglReacquireHighPowerGPUANGLE;
ANGLE_UTIL_EXPORT PFNEGLRELEASEHIGHPOWERGPUANGLEPROC l_eglReleaseHighPowerGPUANGLE;
@ -214,6 +215,8 @@ void LoadEGL(LoadProc loadProc)
reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBANGLEPROC>(loadProc("eglQueryDisplayAttribANGLE"));
l_eglQueryStringiANGLE =
reinterpret_cast<PFNEGLQUERYSTRINGIANGLEPROC>(loadProc("eglQueryStringiANGLE"));
l_eglForceGPUSwitchANGLE =
reinterpret_cast<PFNEGLFORCEGPUSWITCHANGLEPROC>(loadProc("eglForceGPUSwitchANGLE"));
l_eglHandleGPUSwitchANGLE =
reinterpret_cast<PFNEGLHANDLEGPUSWITCHANGLEPROC>(loadProc("eglHandleGPUSwitchANGLE"));
l_eglReacquireHighPowerGPUANGLE = reinterpret_cast<PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC>(

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

@ -74,6 +74,7 @@
#define eglReleaseDeviceANGLE l_eglReleaseDeviceANGLE
#define eglQueryDisplayAttribANGLE l_eglQueryDisplayAttribANGLE
#define eglQueryStringiANGLE l_eglQueryStringiANGLE
#define eglForceGPUSwitchANGLE l_eglForceGPUSwitchANGLE
#define eglHandleGPUSwitchANGLE l_eglHandleGPUSwitchANGLE
#define eglReacquireHighPowerGPUANGLE l_eglReacquireHighPowerGPUANGLE
#define eglReleaseHighPowerGPUANGLE l_eglReleaseHighPowerGPUANGLE
@ -184,6 +185,7 @@ ANGLE_UTIL_EXPORT extern PFNEGLCREATEDEVICEANGLEPROC l_eglCreateDeviceANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLRELEASEDEVICEANGLEPROC l_eglReleaseDeviceANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLQUERYDISPLAYATTRIBANGLEPROC l_eglQueryDisplayAttribANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLQUERYSTRINGIANGLEPROC l_eglQueryStringiANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLFORCEGPUSWITCHANGLEPROC l_eglForceGPUSwitchANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLHANDLEGPUSWITCHANGLEPROC l_eglHandleGPUSwitchANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLREACQUIREHIGHPOWERGPUANGLEPROC l_eglReacquireHighPowerGPUANGLE;
ANGLE_UTIL_EXPORT extern PFNEGLRELEASEHIGHPOWERGPUANGLEPROC l_eglReleaseHighPowerGPUANGLE;