- Revision
- 279883
- Author
- [email protected]
- Date
- 2021-07-13 12:28:19 -0700 (Tue, 13 Jul 2021)
Log Message
rAF driven WebGL submits excessive amount of GPU work when frames are slow
https://bugs.webkit.org/show_bug.cgi?id=227059
Reviewed by Dean Jackson.
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.
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.
Source/ThirdParty/ANGLE:
An additional change ensures that Nvidia configs, which do not support MTLEvents
to a level of conformance required (See http://crbug.com/1136673), continue to run. The more powerful eGPUs will not experience throttling to the same level as integrated GPUS.
* src/libANGLE/renderer/metal/DisplayMtl.mm:
(rx::DisplayMtl::initializeExtensions const):
Source/WebCore:
An additional change ensures that Nvidia configs, which do not support MTLEvents
to a level of conformance required (See http://crbug.com/1136673), continue to run. The more powerful eGPUs will not experience throttling to the same level as integrated GPUS.
* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/GraphicsContextGLAttributes.h:
* platform/graphics/angle/GraphicsContextGLANGLE.cpp:
(WebCore::GraphicsContextGLOpenGL::waitAndUpdateOldestFrame):
* platform/graphics/angle/GraphicsContextGLANGLEUtilities.h:
(WebCore::ScopedGLFence::ScopedGLFence):
(WebCore::ScopedGLFence::~ScopedGLFence):
(WebCore::ScopedGLFence::operator=):
(WebCore::ScopedGLFence::reset):
(WebCore::ScopedGLFence::abandon):
(WebCore::ScopedGLFence::fenceSync):
(WebCore::ScopedGLFence::operator GLsync const):
(WebCore::ScopedGLFence::operator bool const):
* platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
(WebCore::InitializeEGLDisplay):
(WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
(WebCore::GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL):
(WebCore::GraphicsContextGLOpenGL::prepareForDisplay):
* platform/graphics/opengl/GraphicsContextGLOpenGL.h:
Modified Paths
Diff
Modified: trunk/Source/ThirdParty/ANGLE/ChangeLog (279882 => 279883)
--- trunk/Source/ThirdParty/ANGLE/ChangeLog 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/ThirdParty/ANGLE/ChangeLog 2021-07-13 19:28:19 UTC (rev 279883)
@@ -1,3 +1,26 @@
+2021-07-13 Kyle Piddington <[email protected]>
+
+ rAF driven WebGL submits excessive amount of GPU work when frames are slow
+ https://bugs.webkit.org/show_bug.cgi?id=227059
+
+ Reviewed by Dean Jackson.
+
+ 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.
+
+ 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.
+
+ An additional change ensures that Nvidia configs, which do not support MTLEvents
+ to a level of conformance required (See http://crbug.com/1136673), continue to run. The more powerful eGPUs will not experience throttling to the same level as integrated GPUS.
+ * src/libANGLE/renderer/metal/DisplayMtl.mm:
+ (rx::DisplayMtl::initializeExtensions const):
+
2021-07-07 Kyle Piddington <[email protected]>
WebGL shader link error in iOS 15 beta: "Internal error compiling shader with Metal backend"
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/DisplayMtl.mm (279882 => 279883)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/DisplayMtl.mm 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/metal/DisplayMtl.mm 2021-07-13 19:28:19 UTC (rev 279883)
@@ -884,6 +884,9 @@
// GL_OES_EGL_sync
mNativeExtensions.eglSyncOES = true;
+
+ // GL_ARB_sync
+ mNativeExtensions.glSyncARB = true;
}
}
Modified: trunk/Source/WebCore/ChangeLog (279882 => 279883)
--- trunk/Source/WebCore/ChangeLog 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/ChangeLog 2021-07-13 19:28:19 UTC (rev 279883)
@@ -1,3 +1,46 @@
+2021-07-13 Kyle Piddington <[email protected]>
+
+ rAF driven WebGL submits excessive amount of GPU work when frames are slow
+ https://bugs.webkit.org/show_bug.cgi?id=227059
+
+ Reviewed by Dean Jackson.
+
+ 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.
+
+ 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.
+
+ An additional change ensures that Nvidia configs, which do not support MTLEvents
+ to a level of conformance required (See http://crbug.com/1136673), continue to run. The more powerful eGPUs will not experience throttling to the same level as integrated GPUS.
+
+
+ * Headers.cmake:
+ * WebCore.xcodeproj/project.pbxproj:
+ * platform/graphics/GraphicsContextGLAttributes.h:
+ * platform/graphics/angle/GraphicsContextGLANGLE.cpp:
+ (WebCore::GraphicsContextGLOpenGL::waitAndUpdateOldestFrame):
+ * platform/graphics/angle/GraphicsContextGLANGLEUtilities.h:
+ (WebCore::ScopedGLFence::ScopedGLFence):
+ (WebCore::ScopedGLFence::~ScopedGLFence):
+ (WebCore::ScopedGLFence::operator=):
+ (WebCore::ScopedGLFence::reset):
+ (WebCore::ScopedGLFence::abandon):
+ (WebCore::ScopedGLFence::fenceSync):
+ (WebCore::ScopedGLFence::operator GLsync const):
+ (WebCore::ScopedGLFence::operator bool const):
+ * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
+ (WebCore::InitializeEGLDisplay):
+ (WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
+ (WebCore::GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL):
+ (WebCore::GraphicsContextGLOpenGL::prepareForDisplay):
+ * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+
2021-07-13 Chris Dumez <[email protected]>
Revoking Blob URL after calling XMLHttpRequest::open() causes the XHR to fail
Modified: trunk/Source/WebCore/Headers.cmake (279882 => 279883)
--- trunk/Source/WebCore/Headers.cmake 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/Headers.cmake 2021-07-13 19:28:19 UTC (rev 279883)
@@ -1330,6 +1330,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 (279882 => 279883)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-07-13 19:28:19 UTC (rev 279883)
@@ -715,7 +715,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, ); }; };
@@ -2323,7 +2323,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/GraphicsContextGLAttributes.h (279882 => 279883)
--- trunk/Source/WebCore/platform/graphics/GraphicsContextGLAttributes.h 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContextGLAttributes.h 2021-07-13 19:28:19 UTC (rev 279883)
@@ -62,7 +62,8 @@
using WebGLVersion = GraphicsContextGLWebGLVersion;
WebGLVersion webGLVersion { WebGLVersion::WebGL1 };
#if PLATFORM(COCOA)
- bool useMetal { false };
+ bool useMetal { true };
+ bool hasFenceSync { false };
#endif
#if ENABLE(WEBXR)
bool xrCompatible { false };
Modified: trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp (279882 => 279883)
--- trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp 2021-07-13 19:28:19 UTC (rev 279883)
@@ -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)
{
@@ -2854,6 +2852,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 doeØs 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 (279882 => 279883)
--- trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLEUtilities.h 2021-07-13 19:28:19 UTC (rev 279883)
@@ -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 (279882 => 279883)
--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm 2021-07-13 19:28:19 UTC (rev 279883)
@@ -116,13 +116,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.\n", attrs.useMetal && canUseMetal ? "Metal" : "OpenGL");
+ LOG(WebGL, "Attempting to use ANGLE's %s backend.\n", attrs.useMetal ? "Metal" : "OpenGL");
if (attrs.powerPreference != GraphicsContextGLAttributes::PowerPreference::Default) {
displayAttributes.append(EGL_POWER_PREFERENCE_ANGLE);
if (attrs.powerPreference == GraphicsContextGLAttributes::PowerPreference::LowPower)
@@ -132,7 +130,6 @@
displayAttributes.append(EGL_HIGH_POWER_ANGLE);
}
}
-
displayAttributes.append(EGL_NONE);
display = EGL_GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), displayAttributes.data());
@@ -210,6 +207,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)
@@ -306,8 +307,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) {
@@ -317,6 +317,15 @@
}
extensions.ensureEnabled(extension);
}
+ if (contextAttributes().useMetal) {
+ // The implementation uses GLsync objects. Enable the functionality for WebGL 1.0 contexts
+ // that use OpenGL ES 2.0.
+ if (extensions.supports("GL_ARB_sync"_s)) {
+ attrs.hasFenceSync = true;
+ extensions.ensureEnabled("GL_ARB_sync"_s);
+ setContextAttributes(attrs);
+ }
+ }
validateAttributes();
attrs = contextAttributes(); // They may have changed during validation.
@@ -398,6 +407,12 @@
gl::DeleteTextures(1, &m_preserveDrawingBufferTexture);
if (m_preserveDrawingBufferFBO)
gl::DeleteFramebuffers(1, &m_preserveDrawingBufferFBO);
+ // If fences are not enabled, this loop will not execute.
+ for (auto& fence : m_frameCompletionFences)
+ fence.reset();
+ } else {
+ for (auto& fence : m_frameCompletionFences)
+ fence.abandon();
}
if (m_displayBufferPbuffer) {
EGL_DestroySurface(m_displayObj, m_displayBufferPbuffer);
@@ -782,6 +797,13 @@
allocateAndBindDisplayBufferBacking();
markLayerComposited();
+
+ if (contextAttributes().useMetal && contextAttributes().hasFenceSync) {
+ // 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 (279882 => 279883)
--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h 2021-07-13 19:20:46 UTC (rev 279882)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h 2021-07-13 19:28:19 UTC (rev 279883)
@@ -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)
@@ -578,6 +580,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 };
@@ -791,6 +797,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