Changeset 284669 in webkit


Ignore:
Timestamp:
Oct 22, 2021 12:35:57 AM (9 months ago)
Author:
commit-queue@webkit.org
Message:

WebGL low-power and high-performance contexts should use different ANGLE Metal EGLDisplays
https://bugs.webkit.org/show_bug.cgi?id=231012
<rdar://problem/83971417>

Patch by Kimmo Kinnunen <kkinnunen@apple.com> on 2021-10-22
Reviewed by Dean Jackson.

Source/WebCore:

Use per-power preference EGLDisplay when creating Metal
contexts.

Adds a new API test.

  • platform/RuntimeApplicationChecks.cpp:

(WebCore::setAuxiliaryProcessTypeForTesting):

  • platform/RuntimeApplicationChecks.h:

Add a test function to reset the process type after test has set a specific type and then
run to completion. process for the duration of the test. The volatile context flag in

GraphicsContextGLOpenGL depends on condition isWebProcess
isGPUProcess.
  • platform/graphics/angle/GraphicsContextGLANGLE.cpp:

(WebCore::GraphicsContextGLOpenGL::releaseThreadResources):

  • platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:

(WebCore::initializeEGLDisplay):
(WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
(WebCore::GraphicsContextGLOpenGL::setContextVisibility):
(WebCore::GraphicsContextGLOpenGL::displayWasReconfigured):

  • platform/graphics/opengl/GraphicsContextGLOpenGL.h:

Tools:

Add a API test to test GraphicsContextGLOpenGL
Cocoa implementation regarding the bug where
the GraphicsContextGLOpenGL instances would use
the GPU that was selected by the first instance.

  • TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebCore/cocoa/TestGraphicsContextGLOpenGLCocoa.mm: Added.

(TestWebKitAPI::WebCore::TestedGraphicsContextGLOpenGL::create):
(TestWebKitAPI::WebCore::TestedGraphicsContextGLOpenGL::TestedGraphicsContextGLOpenGL):
(TestWebKitAPI::hasMultipleGPUs):
(TestWebKitAPI::TEST):

  • TestWebKitAPI/WebCoreUtilities.h: Added.

(TestWebKitAPI::ScopedSetAuxiliaryProcessTypeForTesting::ScopedSetAuxiliaryProcessTypeForTesting):
(TestWebKitAPI::ScopedSetAuxiliaryProcessTypeForTesting::~ScopedSetAuxiliaryProcessTypeForTesting):
Add a utility state setter to set the process type for the
duration of a test.

Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r284667 r284669  
     12021-10-22  Kimmo Kinnunen  <kkinnunen@apple.com>
     2
     3        WebGL low-power and high-performance contexts should use different ANGLE Metal EGLDisplays
     4        https://bugs.webkit.org/show_bug.cgi?id=231012
     5        <rdar://problem/83971417>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Use per-power preference EGLDisplay when creating Metal
     10        contexts.
     11
     12        Adds a new API test.
     13
     14        * platform/RuntimeApplicationChecks.cpp:
     15        (WebCore::setAuxiliaryProcessTypeForTesting):
     16        * platform/RuntimeApplicationChecks.h:
     17        Add a test function to reset the process type after test has set a specific type and then
     18        run to completion. process for the duration of the test. The volatile context flag in
     19        GraphicsContextGLOpenGL depends on condition isWebProcess || isGPUProcess.
     20        * platform/graphics/angle/GraphicsContextGLANGLE.cpp:
     21        (WebCore::GraphicsContextGLOpenGL::releaseThreadResources):
     22        * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
     23        (WebCore::initializeEGLDisplay):
     24        (WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
     25        (WebCore::GraphicsContextGLOpenGL::setContextVisibility):
     26        (WebCore::GraphicsContextGLOpenGL::displayWasReconfigured):
     27        * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
     28
    1292021-10-21  Cathie Chen  <cathiechen@igalia.com>
    230
  • trunk/Source/WebCore/platform/RuntimeApplicationChecks.cpp

    r282115 r284669  
    7676}
    7777
     78void setAuxiliaryProcessTypeForTesting(std::optional<AuxiliaryProcessType> type)
     79{
     80    auxiliaryProcessType() = type;
     81}
     82
    7883bool checkAuxiliaryProcessType(AuxiliaryProcessType type)
    7984{
  • trunk/Source/WebCore/platform/RuntimeApplicationChecks.h

    r282115 r284669  
    4747
    4848WEBCORE_EXPORT void setAuxiliaryProcessType(AuxiliaryProcessType);
     49WEBCORE_EXPORT void setAuxiliaryProcessTypeForTesting(std::optional<AuxiliaryProcessType>);
    4950WEBCORE_EXPORT bool checkAuxiliaryProcessType(AuxiliaryProcessType);
    5051WEBCORE_EXPORT std::optional<AuxiliaryProcessType> processType();
  • trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp

    r283979 r284669  
    8787    // context cannot be current on multiple threads.
    8888    if (releaseBehavior == ReleaseThreadResourceBehavior::ReleaseCurrentContext) {
    89         if (EGL_GetCurrentContext() == EGL_NO_CONTEXT)
     89        EGLDisplay display = EGL_GetCurrentDisplay();
     90        if (display == EGL_NO_DISPLAY)
    9091            return true;
    9192        // At the time of writing, ANGLE does not flush on MakeCurrent. Since we are
     
    9495        // we would need to flush each EGL context that has been used.
    9596        gl::Flush();
    96         EGLDisplay display = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
    97         if (display == EGL_NO_DISPLAY)
    98             return true;
    9997        return EGL_MakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    10098    }
    10199    if (releaseBehavior == ReleaseThreadResourceBehavior::TerminateAndReleaseThreadResources) {
    102         EGLDisplay display = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
    103         if (display != EGL_NO_DISPLAY) {
    104             if (EGL_GetCurrentContext() != EGL_NO_CONTEXT) {
    105                 ASSERT_NOT_REACHED(); // All resources must have been destroyed.
    106                 EGL_MakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    107             }
    108             EGL_Terminate(display);
     100        EGLDisplay currentDisplay = EGL_GetCurrentDisplay();
     101        if (currentDisplay != EGL_NO_DISPLAY) {
     102            ASSERT_NOT_REACHED(); // All resources must have been destroyed.
     103            EGL_MakeCurrent(currentDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     104        }
     105        constexpr EGLNativeDisplayType nativeDisplays[] = {
     106            defaultDisplay,
     107#if PLATFORM(COCOA)
     108            lowPowerDisplay,
     109            highPerformanceDisplay
     110#endif
     111        };
     112        for (auto nativeDisplay : nativeDisplays) {
     113            EGLDisplay display = EGL_GetDisplay(nativeDisplay);
     114            if (display != EGL_NO_DISPLAY)
     115                EGL_Terminate(display);
    109116        }
    110117    }
  • trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm

    r284454 r284669  
    147147
    148148    LOG(WebGL, "Attempting to use ANGLE's %s backend.", attrs.useMetal ? "Metal" : "OpenGL");
     149    EGLNativeDisplayType nativeDisplay = GraphicsContextGLOpenGL::defaultDisplay;
    149150    if (attrs.useMetal) {
    150151        displayAttributes.append(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
    151152        displayAttributes.append(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
    152     }
    153 
    154     if (attrs.powerPreference != GraphicsContextGLAttributes::PowerPreference::Default || attrs.forceRequestForHighPerformanceGPU) {
    155         displayAttributes.append(EGL_POWER_PREFERENCE_ANGLE);
    156         if (attrs.powerPreference == GraphicsContextGLAttributes::PowerPreference::LowPower && !attrs.forceRequestForHighPerformanceGPU) {
    157             LOG(WebGL, "Requesting low power GPU.");
     153        // These properties are defined for EGL_ANGLE_power_preference as EGLContext attributes,
     154        // but Metal backend uses EGLDisplay attributes.
     155        auto powerPreference = attrs.forceRequestForHighPerformanceGPU ? GraphicsContextGLAttributes::PowerPreference::HighPerformance : attrs.powerPreference;
     156        if (powerPreference == GraphicsContextGLAttributes::PowerPreference::LowPower) {
     157            displayAttributes.append(EGL_POWER_PREFERENCE_ANGLE);
    158158            displayAttributes.append(EGL_LOW_POWER_ANGLE);
    159         } else {
    160             ASSERT(attrs.powerPreference == GraphicsContextGLAttributes::PowerPreference::HighPerformance || attrs.forceRequestForHighPerformanceGPU);
    161             LOG(WebGL, "Requesting high power GPU if available.");
     159            nativeDisplay = GraphicsContextGLOpenGL::lowPowerDisplay;
     160        } else if (powerPreference == GraphicsContextGLAttributes::PowerPreference::HighPerformance) {
     161            displayAttributes.append(EGL_POWER_PREFERENCE_ANGLE);
    162162            displayAttributes.append(EGL_HIGH_POWER_ANGLE);
     163            nativeDisplay = GraphicsContextGLOpenGL::highPerformanceDisplay;
    163164        }
    164165    }
    165166    displayAttributes.append(EGL_NONE);
    166     display = EGL_GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), displayAttributes.data());
     167    display = EGL_GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void*>(nativeDisplay), displayAttributes.data());
    167168
    168169    if (EGL_Initialize(display, &majorVersion, &minorVersion) == EGL_FALSE) {
     
    173174    if (shouldInitializeWithVolatileContextSupport) {
    174175        // After initialization, EGL_DEFAULT_DISPLAY will return the platform-customized display.
    175         ASSERT(display == EGL_GetDisplay(EGL_DEFAULT_DISPLAY));
     176        ASSERT(display == EGL_GetDisplay(nativeDisplay));
    176177        ASSERT(checkVolatileContextSupportIfDeviceExists(display, "EGL_ANGLE_platform_device_context_volatile_eagl", "EGL_ANGLE_device_eagl", EGL_EAGL_CONTEXT_ANGLE));
    177178        ASSERT(checkVolatileContextSupportIfDeviceExists(display, "EGL_ANGLE_platform_device_context_volatile_cgl", "EGL_ANGLE_device_cgl", EGL_CGL_CONTEXT_ANGLE));
     
    219220        return;
    220221
    221     bool supportsPowerPreference = false;
    222222#if PLATFORM(MAC)
    223     const char *displayExtensions = EGL_QueryString(m_displayObj, EGL_EXTENSIONS);
    224     m_supportsPowerPreference = strstr(displayExtensions, "EGL_ANGLE_power_preference");
    225     supportsPowerPreference = m_supportsPowerPreference;
    226 #endif
    227     if (!supportsPowerPreference && attrs.powerPreference == GraphicsContextGLPowerPreference::HighPerformance) {
    228         attrs.powerPreference = GraphicsContextGLPowerPreference::Default;
    229         setContextAttributes(attrs);
    230     }
     223    if (!attrs.useMetal) {
     224        // For OpenGL, EGL_ANGLE_power_preference is used. The context is initialized with the
     225        // default, low-power device. For high-performance contexts, we request the high-performance
     226        // GPU in setContextVisibility. When the request is fullfilled by the system, we get the
     227        // display reconfiguration callback. Upon this, we update the CGL contexts inside ANGLE.
     228        const char *displayExtensions = EGL_QueryString(m_displayObj, EGL_EXTENSIONS);
     229        bool supportsPowerPreference = strstr(displayExtensions, "EGL_ANGLE_power_preference");
     230        if (supportsPowerPreference) {
     231            m_switchesGPUOnDisplayReconfiguration = attrs.powerPreference == GraphicsContextGLPowerPreference::HighPerformance
     232                || attrs.forceRequestForHighPerformanceGPU;
     233        } else {
     234            if (attrs.powerPreference == GraphicsContextGLPowerPreference::HighPerformance) {
     235                attrs.powerPreference = GraphicsContextGLPowerPreference::Default;
     236                setContextAttributes(attrs);
     237            }
     238        }
     239    }
     240#endif
    231241
    232242    EGLint configAttributes[] = {
     
    512522{
    513523#if PLATFORM(MAC)
    514     if (contextAttributes().powerPreference != GraphicsContextGLPowerPreference::HighPerformance)
     524    if (!m_switchesGPUOnDisplayReconfiguration)
    515525        return;
    516526    if (isVisible)
     
    526536{
    527537#if PLATFORM(MAC)
    528     if (m_supportsPowerPreference)
     538    if (m_switchesGPUOnDisplayReconfiguration)
    529539        EGL_HandleGPUSwitchANGLE(m_displayObj);
    530540#endif
  • trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h

    r284438 r284669  
    535535#endif
    536536
     537#if USE(ANGLE)
     538    constexpr static EGLNativeDisplayType defaultDisplay = EGL_DEFAULT_DISPLAY;
     539#if PLATFORM(COCOA)
     540    constexpr static EGLNativeDisplayType lowPowerDisplay = EGL_CAST(EGLNativeDisplayType, -1);
     541    constexpr static EGLNativeDisplayType highPerformanceDisplay = EGL_CAST(EGLNativeDisplayType, -2);
     542#endif
     543#endif
     544
    537545protected:
    538546    GraphicsContextGLOpenGL(GraphicsContextGLAttributes);
     
    789797#endif
    790798#if PLATFORM(MAC)
    791     bool m_supportsPowerPreference { false };
     799    bool m_switchesGPUOnDisplayReconfiguration { false };
    792800    ScopedHighPerformanceGPURequest m_highPerformanceGPURequest;
    793801#endif
  • trunk/Tools/ChangeLog

    r284657 r284669  
     12021-10-22  Kimmo Kinnunen  <kkinnunen@apple.com>
     2
     3        WebGL low-power and high-performance contexts should use different ANGLE Metal EGLDisplays
     4        https://bugs.webkit.org/show_bug.cgi?id=231012
     5        <rdar://problem/83971417>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Add a API test to test GraphicsContextGLOpenGL
     10        Cocoa implementation regarding the bug where
     11        the GraphicsContextGLOpenGL instances would use
     12        the GPU that was selected by the first instance.
     13
     14        * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
     15        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     16        * TestWebKitAPI/Tests/WebCore/cocoa/TestGraphicsContextGLOpenGLCocoa.mm: Added.
     17        (TestWebKitAPI::WebCore::TestedGraphicsContextGLOpenGL::create):
     18        (TestWebKitAPI::WebCore::TestedGraphicsContextGLOpenGL::TestedGraphicsContextGLOpenGL):
     19        (TestWebKitAPI::hasMultipleGPUs):
     20        (TestWebKitAPI::TEST):
     21        * TestWebKitAPI/WebCoreUtilities.h: Added.
     22        (TestWebKitAPI::ScopedSetAuxiliaryProcessTypeForTesting::ScopedSetAuxiliaryProcessTypeForTesting):
     23        (TestWebKitAPI::ScopedSetAuxiliaryProcessTypeForTesting::~ScopedSetAuxiliaryProcessTypeForTesting):
     24        Add a utility state setter to set the process type for the
     25        duration of a test.
     26
    1272021-10-21  Ryan Haddad  <ryanhaddad@apple.com>
    228
  • trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig

    r282368 r284669  
    9191OTHER_CPLUSPLUSFLAGS = $(inherited) -isystem $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders;
    9292
    93 OTHER_LDFLAGS = $(inherited) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework JavaScriptCore -framework WebKit -lWebCoreTestSupport $(WK_APPSERVERSUPPORT_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SYSTEM_LDFLAGS) $(WK_UIKITMACHELPER_LDFLAGS) $(WK_VISIONKITCORE_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
     93OTHER_LDFLAGS = $(inherited) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework JavaScriptCore -framework WebKit -lWebCoreTestSupport -framework Metal $(WK_APPSERVERSUPPORT_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_SYSTEM_LDFLAGS) $(WK_UIKITMACHELPER_LDFLAGS) $(WK_VISIONKITCORE_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
    9494OTHER_LDFLAGS_PLATFORM_ = -framework Cocoa -framework Carbon;
    9595
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r284654 r284669  
    610610                7B774906267CCE72009873B4 /* TestRunnerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7B774904267CCE68009873B4 /* TestRunnerTests.cpp */; };
    611611                7B7D096A2519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7B7D09692519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm */; };
     612                7BA3936C271EDFCA0015911C /* TestGraphicsContextGLOpenGLCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7BA3936B271EDFCA0015911C /* TestGraphicsContextGLOpenGLCocoa.mm */; };
    612613                7C1AF7951E8DCBAB002645B9 /* PrepareForMoveToWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */; };
    613614                7C3965061CDD74F90094DBB8 /* ColorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C3965051CDD74F90094DBB8 /* ColorTests.cpp */; };
     
    25182519                7B774904267CCE68009873B4 /* TestRunnerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestRunnerTests.cpp; sourceTree = "<group>"; };
    25192520                7B7D09692519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebGLNoCrashOnOtherThreadAccess.mm; sourceTree = "<group>"; };
     2521                7BA3936B271EDFCA0015911C /* TestGraphicsContextGLOpenGLCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestGraphicsContextGLOpenGLCocoa.mm; sourceTree = "<group>"; };
     2522                7BA3936D271EEC530015911C /* WebCoreUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreUtilities.h; sourceTree = "<group>"; };
    25202523                7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PrepareForMoveToWindow.mm; sourceTree = "<group>"; };
    25212524                7C3965051CDD74F90094DBB8 /* ColorTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorTests.cpp; sourceTree = "<group>"; };
     
    33193322                                BCB9E7C711234E3A00A137E0 /* TestsController.h */,
    33203323                                7C83E0361D0A5F7000FEBCF3 /* Utilities.h */,
     3324                                7BA3936D271EEC530015911C /* WebCoreUtilities.h */,
    33213325                                7CBD5A2222DE42A6004A9E32 /* WTFStringUtilities.cpp */,
    33223326                                44A622C114A0E2B60048515B /* WTFStringUtilities.h */,
     
    49864990                                5769C50A1D9B0001000847FB /* SerializedCryptoKeyWrap.mm */,
    49874991                                A17991861E1C994E00A505ED /* SharedBuffer.mm */,
     4992                                7BA3936B271EDFCA0015911C /* TestGraphicsContextGLOpenGLCocoa.mm */,
    49884993                                CD89D0381C4EDB2A00040A04 /* WebCoreNSURLSession.mm */,
    49894994                        );
     
    59115916                                F4E0A2B82122847400AF7C7F /* TestFilePromiseReceiver.mm in Sources */,
    59125917                                F4F5BB5221667BAA002D06B9 /* TestFontOptions.mm in Sources */,
     5918                                7BA3936C271EDFCA0015911C /* TestGraphicsContextGLOpenGLCocoa.mm in Sources */,
    59135919                                F45E15762112CE6200307E82 /* TestInputDelegate.mm in Sources */,
    59145920                                F45D3891215A7B4B002A2979 /* TestInspectorBar.mm in Sources */,
Note: See TracChangeset for help on using the changeset viewer.