Diff
Modified: trunk/Source/ThirdParty/ANGLE/ChangeLog (279171 => 279172)
--- trunk/Source/ThirdParty/ANGLE/ChangeLog 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/ThirdParty/ANGLE/ChangeLog 2021-06-23 17:08:51 UTC (rev 279172)
@@ -1,3 +1,18 @@
+2021-06-23 Kimmo Kinnunen <[email protected]>
+
+ rAF driven WebGL submits excessive amount of GPU work when frames are slow
+ https://bugs.webkit.org/show_bug.cgi?id=227059
+ <rdar://problem/79385858>
+
+ Reviewed by Kenneth Russell.
+
+ Advertise GL_ARB_sync for the Metal backend.
+ Since GL_ARB_sync is core in OpenGL ES 3.0 and the Metal backend advertises OpenGL ES 3.0,
+ the API must be working already.
+
+ * src/libANGLE/renderer/metal/DisplayMtl.mm:
+ (rx::DisplayMtl::initializeExtensions const):
+
2021-06-22 Dean Jackson <[email protected]>
[ANGLE] Support importing external MTLTextures
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/DisplayMtl.mm (279171 => 279172)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/DisplayMtl.mm 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/DisplayMtl.mm 2021-06-23 17:08:51 UTC (rev 279172)
@@ -883,6 +883,9 @@
// GL_OES_EGL_sync
mNativeExtensions.eglSyncOES = true;
+
+ // GL_ARB_sync
+ mNativeExtensions.glSyncARB = true;
}
}
Modified: trunk/Source/WebCore/ChangeLog (279171 => 279172)
--- trunk/Source/WebCore/ChangeLog 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/ChangeLog 2021-06-23 17:08:51 UTC (rev 279172)
@@ -1,3 +1,37 @@
+2021-06-23 Kimmo Kinnunen <[email protected]>
+
+ rAF driven WebGL submits excessive amount of GPU work when frames are slow
+ https://bugs.webkit.org/show_bug.cgi?id=227059
+ <rdar://problem/79385858>
+
+ Reviewed by Kenneth Russell.
+
+ Limit in-flight WebGL frames to three frames. Do not continue preparation for display
+ until the commands for the oldest frame have been executed by the GPU.
+
+ This limits the impact slow frames have, especially in the
+ case where the compositor skip frames and WebKit would issue a new slow frame
+ on top of the skipped frame.
+
+ No new tests, tested manually with the pages referenced from the bugs.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * platform/graphics/angle/GraphicsContextGLANGLE.cpp:
+ (WebCore::GraphicsContextGLOpenGL::waitAndUpdateOldestFrame):
+ * platform/graphics/angle/GraphicsContextGLANGLEUtilities.h:
+ (WebCore::ScopedGLFence::ScopedGLFence):
+ (WebCore::ScopedGLFence::operator=):
+ (WebCore::ScopedGLFence::~ScopedGLFence):
+ (WebCore::ScopedGLFence::reset):
+ (WebCore::ScopedGLFence::abandon):
+ (WebCore::ScopedGLFence::fenceSync):
+ (WebCore::ScopedGLFence::operator GLsync const):
+ * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
+ (WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
+ (WebCore::GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL):
+ (WebCore::GraphicsContextGLOpenGL::prepareForDisplay):
+ * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+
2021-06-23 Andres Gonzalez <[email protected]>
Accessibility support for image text recognition.
Modified: trunk/Source/WebCore/Headers.cmake (279171 => 279172)
--- trunk/Source/WebCore/Headers.cmake 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/Headers.cmake 2021-06-23 17:08:51 UTC (rev 279172)
@@ -1329,6 +1329,7 @@
platform/graphics/angle/ANGLEHeaders.h
platform/graphics/angle/ExtensionsGLANGLE.h
+ platform/graphics/angle/GraphicsContextGLANGLEUtilities.h
platform/graphics/displaylists/DisplayList.h
platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (279171 => 279172)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-06-23 17:08:51 UTC (rev 279172)
@@ -714,7 +714,7 @@
26F756B51B3B68F20005DD79 /* ImmutableNFANodeBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F756B41B3B68F20005DD79 /* ImmutableNFANodeBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; };
26F9A83818A046AC00AEB88A /* ViewportConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F9A83618A046AC00AEB88A /* ViewportConfiguration.cpp */; };
26F9A83918A046AC00AEB88A /* ViewportConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F9A83718A046AC00AEB88A /* ViewportConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 27E3C808257F5E6E00C986AB /* ANGLEHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E3C806257F5E6E00C986AB /* ANGLEHeaders.h */; };
+ 27E3C808257F5E6E00C986AB /* ANGLEHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E3C806257F5E6E00C986AB /* ANGLEHeaders.h */; settings = {ATTRIBUTES = (Private, ); }; };
2914E3081CAB5A440049966F /* AccessibilityAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 2914E3061CAB5A440049966F /* AccessibilityAttachment.h */; };
2936BF5C21D69E4B004A8FC9 /* AccessibilityObjectInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 2936BF5A21D6999E004A8FC9 /* AccessibilityObjectInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
293EAE1F1356B2FE0067ACF9 /* RuntimeApplicationChecks.h in Headers */ = {isa = PBXBuildFile; fileRef = 293EAE1E1356B2FE0067ACF9 /* RuntimeApplicationChecks.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -2322,7 +2322,7 @@
7B6DC81925712E9200380C70 /* GraphicsContextGLIOSurfaceSwapChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B6DC81725712E9200380C70 /* GraphicsContextGLIOSurfaceSwapChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
7B7311FB25C092B7003B2796 /* ScopedHighPerformanceGPURequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7311FA25C092B7003B2796 /* ScopedHighPerformanceGPURequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
7B90417025501142006EEB8C /* RemoteGraphicsContextGLProxyBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B90416E25501109006EEB8C /* RemoteGraphicsContextGLProxyBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 7BB34A1725345CB200029D08 /* GraphicsContextGLANGLEUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BB34A1625345CB200029D08 /* GraphicsContextGLANGLEUtilities.h */; };
+ 7BB34A1725345CB200029D08 /* GraphicsContextGLANGLEUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BB34A1625345CB200029D08 /* GraphicsContextGLANGLEUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
7BB34A48253776CA00029D08 /* GraphicsContextGLImageExtractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BB34A45253776C600029D08 /* GraphicsContextGLImageExtractor.h */; settings = {ATTRIBUTES = (Private, ); }; };
7BB680BA25BA1BE4002B8738 /* GraphicsChecksMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BB680B825BA1BE4002B8738 /* GraphicsChecksMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
7BE7427381FA906FBB4F0F2C /* JSSVGGraphicsElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 950C4C02BED8936F818E2F99 /* JSSVGGraphicsElement.h */; };
Modified: trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp (279171 => 279172)
--- trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp 2021-06-23 17:08:51 UTC (rev 279172)
@@ -44,6 +44,7 @@
#include <algorithm>
#include <cstring>
#include <wtf/HexNumber.h>
+#include <wtf/Seconds.h>
#include <wtf/ThreadSpecific.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringBuilder.h>
@@ -61,11 +62,8 @@
static const char* packedDepthStencilExtensionName = "GL_OES_packed_depth_stencil";
-namespace {
+static Seconds maxFrameDuration = 5_s;
-
-} // namespace anonymous
-
#if PLATFORM(MAC) || PLATFORM(IOS_FAMILY)
static void wipeAlphaChannelFromPixels(int width, int height, unsigned char* pixels)
{
@@ -2846,6 +2844,27 @@
}
#endif
+bool GraphicsContextGLOpenGL::waitAndUpdateOldestFrame()
+{
+ size_t oldestFrameCompletionFence = m_oldestFrameCompletionFence++ % maxPendingFrames;
+ bool success = true;
+ if (ScopedGLFence fence = WTFMove(m_frameCompletionFences[oldestFrameCompletionFence])) {
+ // Wait so that rendering does not get more than maxPendingFrames frames ahead.
+ GLbitfield flags = GL_SYNC_FLUSH_COMMANDS_BIT;
+#if PLATFORM(COCOA)
+ // Avoid using the GL_SYNC_FLUSH_COMMANDS_BIT because each each frame is ended with a flush
+ // due to external IOSurface access. This particular fence is maxPendingFrames behind.
+ // This means the creation of this fence has already been flushed.
+ flags = 0;
+#endif
+ GLenum result = gl::ClientWaitSync(fence, flags, maxFrameDuration.nanosecondsAs<GLuint64>());
+ ASSERT(result != GL_WAIT_FAILED);
+ success = result != GL_WAIT_FAILED && result != GL_TIMEOUT_EXPIRED;
+ }
+ m_frameCompletionFences[oldestFrameCompletionFence].fenceSync();
+ return success;
}
+}
+
#endif // ENABLE(WEBGL) && USE(ANGLE)
Modified: trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h (279171 => 279172)
--- trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h 2021-06-23 17:08:51 UTC (rev 279172)
@@ -204,6 +204,42 @@
GLuint m_object { 0 };
};
+class ScopedGLFence {
+ WTF_MAKE_NONCOPYABLE(ScopedGLFence);
+public:
+ ScopedGLFence() = default;
+ ScopedGLFence(ScopedGLFence&& other)
+ : m_object(std::exchange(other.m_object, { }))
+ {
+ }
+ ~ScopedGLFence() { reset(); }
+ ScopedGLFence& operator=(ScopedGLFence&& other)
+ {
+ if (this != &other) {
+ reset();
+ m_object = std::exchange(other.m_object, { });
+ }
+ return *this;
+ }
+ void reset()
+ {
+ if (m_object) {
+ gl::DeleteSync(m_object);
+ m_object = { };
+ }
+ }
+ void abandon() { m_object = { }; }
+ void fenceSync()
+ {
+ reset();
+ m_object = gl::FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+ operator GLsync() const { return m_object; }
+ operator bool() const { return m_object; }
+private:
+ GLsync m_object { };
+};
+
}
#endif
Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm (279171 => 279172)
--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm 2021-06-23 17:08:51 UTC (rev 279172)
@@ -115,14 +115,11 @@
displayAttributes.append(EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE);
displayAttributes.append(EGL_TRUE);
}
- bool canUseMetal = platformSupportsMetal();
- if (attrs.useMetal && canUseMetal) {
+ if (attrs.useMetal) {
displayAttributes.append(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
displayAttributes.append(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
}
-
- LOG(WebGL, "Attempting to use ANGLE's %s backend.", attrs.useMetal && canUseMetal ? "Metal" : "OpenGL");
-
+ LOG(WebGL, "Attempting to use ANGLE's %s backend.\n", attrs.useMetal ? "Metal" : "OpenGL");
displayAttributes.append(EGL_NONE);
display = EGL_GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), displayAttributes.data());
@@ -200,6 +197,10 @@
: GraphicsContextGL(attrs, sharedContext)
{
m_isForWebGL2 = attrs.webGLVersion == GraphicsContextGLWebGLVersion::WebGL2;
+ if (attrs.useMetal && !platformSupportsMetal()) {
+ attrs.useMetal = false;
+ setContextAttributes(attrs);
+ }
m_displayObj = InitializeEGLDisplay(attrs);
if (!m_displayObj)
@@ -286,6 +287,12 @@
if (m_isForWebGL2) {
// For WebGL 2.0 occlusion queries to work.
requiredExtensions.append("GL_EXT_occlusion_query_boolean"_s);
+ } else {
+ if (contextAttributes().useMetal) {
+ // The implementation uses GLsync objects. Enable the functionality for WebGL 1.0 contexts
+ // that use OpenGL ES 2.0.
+ requiredExtensions.append("GL_ARB_sync"_s);
+ }
}
#if PLATFORM(MAC) || PLATFORM(MACCATALYST)
if (!needsEAGLOnMac()) {
@@ -293,8 +300,7 @@
requiredExtensions.append("GL_ANGLE_texture_rectangle"_s);
// For creating the EGL surface from an IOSurface.
requiredExtensions.append("GL_EXT_texture_format_BGRA8888"_s);
- }
-
+ }
#endif // PLATFORM(MAC) || PLATFORM(MACCATALYST)
ExtensionsGL& extensions = getExtensions();
for (auto& extension : requiredExtensions) {
@@ -385,6 +391,11 @@
gl::DeleteTextures(1, &m_preserveDrawingBufferTexture);
if (m_preserveDrawingBufferFBO)
gl::DeleteFramebuffers(1, &m_preserveDrawingBufferFBO);
+ for (auto& fence : m_frameCompletionFences)
+ fence.reset();
+ } else {
+ for (auto& fence : m_frameCompletionFences)
+ fence.abandon();
}
if (m_displayBufferPbuffer) {
EGL_DestroySurface(m_displayObj, m_displayBufferPbuffer);
@@ -720,8 +731,14 @@
// Error will be handled by next call to makeContextCurrent() which will notice lack of display buffer.
if (!hasNewBacking)
allocateAndBindDisplayBufferBacking();
+ markLayerComposited();
- markLayerComposited();
+ if (contextAttributes().useMetal) {
+ // OpenGL sync objects are not signaling upon completion on Catalina-era drivers.
+ // OpenGL drivers typically implement some sort of internal throttling.
+ bool success = waitAndUpdateOldestFrame();
+ UNUSED_VARIABLE(success); // FIXME: implement context lost.
+ }
}
std::optional<PixelBuffer> GraphicsContextGLOpenGL::readCompositedResults()
Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h (279171 => 279172)
--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h 2021-06-23 16:59:34 UTC (rev 279171)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h 2021-06-23 17:08:51 UTC (rev 279172)
@@ -45,11 +45,17 @@
#include "PlatformCALayer.h"
#endif
-#if !USE(ANGLE)
+#if USE(ANGLE)
+#include "GraphicsContextGLANGLEUtilities.h"
+#else
#include "ANGLEWebKitBridge.h"
#include "ExtensionsGLOpenGLCommon.h"
#endif
+#if PLATFORM(MAC)
+#include "ScopedHighPerformanceGPURequest.h"
+#endif
+
// FIXME: Find a better way to avoid the name confliction for NO_ERROR.
#if PLATFORM(WIN)
#undef NO_ERROR
@@ -72,10 +78,6 @@
}
#endif
-#if PLATFORM(MAC)
-#include "ScopedHighPerformanceGPURequest.h"
-#endif
-
namespace WebCore {
class ExtensionsGL;
#if USE(ANGLE)
@@ -574,6 +576,10 @@
bool allocateAndBindDisplayBufferBacking();
bool bindDisplayBufferBacking(std::unique_ptr<IOSurface> backing, void* pbuffer);
#endif
+#if USE(ANGLE)
+ // Returns false if context should be lost due to timeout.
+ bool waitAndUpdateOldestFrame() WARN_UNUSED_RETURN;
+#endif
#if PLATFORM(COCOA)
GraphicsContextGLIOSurfaceSwapChain* m_swapChain { nullptr };
@@ -787,6 +793,11 @@
#if ENABLE(VIDEO) && USE(AVFOUNDATION)
std::unique_ptr<GraphicsContextGLCV> m_cv;
#endif
+#if USE(ANGLE)
+ static constexpr size_t maxPendingFrames = 3;
+ size_t m_oldestFrameCompletionFence { 0 };
+ ScopedGLFence m_frameCompletionFences[maxPendingFrames];
+#endif
};
} // namespace WebCore