aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoff Lang <geofflang@chromium.org>2024-04-23 13:23:04 -0400
committerAngle LUCI CQ <angle-scoped@luci-project-accounts.iam.gserviceaccount.com>2024-04-29 19:07:03 +0000
commit038ad6c755a80ee4350715495755deb33c889bcb (patch)
treee3c1c23f98f5ccaa2117f8ba266aa8bde03523fe
parent978cf07b7363173bb87b32314c761432cb9e07d9 (diff)
downloadangle-038ad6c755a80ee4350715495755deb33c889bcb.tar.gz
EGL: Use unlocked tail calls for surface, sync and img calls
EGL surface and sync calls can be expensive to do while holding the global lock on EGL. They are safe because the parameters are captured by value and the underlying EGL driver is also thread safe. EGL image creation also tends to be expensive and is called freqently by Chrome. Bug: angleproject:8434 Change-Id: I7e554fe2e3700d98469de267f7bbff1e96358c78 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5478229 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
-rw-r--r--scripts/code_generation_hashes/GL_EGL_entry_points.json6
-rwxr-xr-xscripts/generate_entry_points.py30
-rw-r--r--src/libANGLE/renderer/gl/egl/ImageEGL.cpp19
-rw-r--r--src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp31
-rw-r--r--src/libANGLE/renderer/gl/egl/SyncEGL.cpp43
-rw-r--r--src/libGLESv2/entry_points_egl_autogen.cpp10
-rw-r--r--src/libGLESv2/entry_points_egl_ext_autogen.cpp10
7 files changed, 96 insertions, 53 deletions
diff --git a/scripts/code_generation_hashes/GL_EGL_entry_points.json b/scripts/code_generation_hashes/GL_EGL_entry_points.json
index 3161e4b2e0..7a619c02ad 100644
--- a/scripts/code_generation_hashes/GL_EGL_entry_points.json
+++ b/scripts/code_generation_hashes/GL_EGL_entry_points.json
@@ -6,7 +6,7 @@
"scripts/entry_point_packed_gl_enums.json":
"57a3a729fd25032bc336f4b6a55bc238",
"scripts/generate_entry_points.py":
- "c811134a03d12777acd1bb85da21ce92",
+ "359649efbbc776d91eb29bc1d78c737c",
"scripts/gl_angle_ext.xml":
"197e07a917d5bba6dfa2840fb1b58e7e",
"scripts/registry_xml.py":
@@ -130,11 +130,11 @@
"src/libGLESv2/entry_points_cl_autogen.h":
"dde2f94c3004874a7da995dae69da811",
"src/libGLESv2/entry_points_egl_autogen.cpp":
- "7b164c4311aba60564509540b1ed8303",
+ "8348d52dadf5ad12208a4d93864000c3",
"src/libGLESv2/entry_points_egl_autogen.h":
"3bc7a8df9deadd7cfd615d0cfad0c6a8",
"src/libGLESv2/entry_points_egl_ext_autogen.cpp":
- "8fd59c97c30cd561cdecdceaeca065e1",
+ "0409df0bdbbc0fb32a88d5f23a2cb7a5",
"src/libGLESv2/entry_points_egl_ext_autogen.h":
"2d005f4cb16dcdd61e08cfec97a12f86",
"src/libGLESv2/entry_points_gl_1_autogen.cpp":
diff --git a/scripts/generate_entry_points.py b/scripts/generate_entry_points.py
index be01613d38..31f54940e7 100755
--- a/scripts/generate_entry_points.py
+++ b/scripts/generate_entry_points.py
@@ -3111,10 +3111,11 @@ def get_unlocked_tail_call(api, cmd_name):
# - eglPrepareSwapBuffersANGLE -> Calls vkAcquireNextImageKHR in tail call
#
# - eglSwapBuffers, eglSwapBuffersWithDamageKHR and
- # eglSwapBuffersWithFrameTokenANGLE -> May throttle the CPU in tail call
+ # eglSwapBuffersWithFrameTokenANGLE -> May throttle the CPU in tail call or
+ # calls native EGL function
#
# - eglClientWaitSyncKHR, eglClientWaitSync, glClientWaitSync,
- # glFinishFenceNV -> May wait on fence in tail call
+ # glFinishFenceNV -> May wait on fence in tail call or call native EGL function
#
# - glTexImage2D, glTexImage3D, glTexSubImage2D, glTexSubImage3D,
# glCompressedTexImage2D, glCompressedTexImage3D,
@@ -3124,10 +3125,13 @@ def get_unlocked_tail_call(api, cmd_name):
# - glCompileShader and glLinkProgram -> May perform the compilation / link
# in tail call
#
+ # - eglCreateSync, eglCreateImage, eglDestroySync, eglDestroyImage -> Calls
+ # native EGL function in tail call
+ #
if (cmd_name in [
- 'eglDestroySurface', 'eglMakeCurrent', 'eglReleaseThread', 'eglCreateWindowSurface',
- 'eglCreatePlatformWindowSurface', 'eglCreatePlatformWindowSurfaceEXT',
- 'eglPrepareSwapBuffersANGLE', 'eglSwapBuffers', 'eglSwapBuffersWithDamageKHR',
+ 'eglCreateSyncKHR', 'eglDestroySurface', 'eglMakeCurrent', 'eglReleaseThread',
+ 'eglCreateWindowSurface', 'eglCreatePlatformWindowSurface',
+ 'eglCreatePlatformWindowSurfaceEXT', 'eglPrepareSwapBuffersANGLE',
'eglSwapBuffersWithFrameTokenANGLE', 'glFinishFenceNV', 'glCompileShader',
'glLinkProgram'
] or cmd_name.startswith('glTexImage2D') or cmd_name.startswith('glTexImage3D') or
@@ -3138,7 +3142,21 @@ def get_unlocked_tail_call(api, cmd_name):
cmd_name.startswith('glCompressedTexSubImage3D')):
return 'egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);'
- if cmd_name in ['eglClientWaitSyncKHR', 'eglClientWaitSync', 'glClientWaitSync']:
+ if cmd_name in [
+ 'eglClientWaitSyncKHR',
+ 'eglClientWaitSync',
+ 'eglCreateImageKHR',
+ 'eglCreateImage',
+ 'eglCreateSyncKHR',
+ 'eglCreateSync',
+ 'eglDestroySyncKHR',
+ 'eglDestroySync',
+ 'eglSwapBuffers',
+ 'eglSwapBuffersWithDamageKHR',
+ 'eglWaitSyncKHR',
+ 'eglWaitSync',
+ 'glClientWaitSync',
+ ]:
return 'egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);'
# Otherwise assert that no tail calls where generated
diff --git a/src/libANGLE/renderer/gl/egl/ImageEGL.cpp b/src/libANGLE/renderer/gl/egl/ImageEGL.cpp
index 8357845197..be70e7dc16 100644
--- a/src/libANGLE/renderer/gl/egl/ImageEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/ImageEGL.cpp
@@ -10,6 +10,7 @@
#include "common/utilities.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/RenderbufferGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
@@ -99,11 +100,19 @@ egl::Error ImageEGL::initialize(const egl::Display *display)
attributes.push_back(EGL_NONE);
- mImage = mEGL->createImageKHR(mContext, mTarget, buffer, attributes.data());
- if (mImage == EGL_NO_IMAGE)
- {
- return egl::EglBadAlloc() << "eglCreateImage failed with " << egl::Error(mEGL->getError());
- }
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add([egl = mEGL, &image = mImage,
+ context = mContext, target = mTarget,
+ buffer, attributes](void *resultOut) {
+ image = egl->createImageKHR(context, target, buffer, attributes.data());
+
+ // If image creation failed, force the return value of eglCreateImage to EGL_NO_IMAGE. This
+ // won't delete this image object but a driver error is unexpected at this point.
+ if (image == EGL_NO_IMAGE)
+ {
+ ERR() << "eglCreateImage failed with " << gl::FmtHex(egl->getError());
+ *static_cast<EGLImage *>(resultOut) = EGL_NO_IMAGE;
+ }
+ });
return egl::NoError();
}
diff --git a/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp b/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
index 0be9a2caf8..f7cbffc2f3 100644
--- a/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/SurfaceEGL.cpp
@@ -9,6 +9,7 @@
#include "libANGLE/renderer/gl/egl/SurfaceEGL.h"
#include "common/debug.h"
+#include "libANGLE/Display.h"
namespace rx
{
@@ -38,11 +39,12 @@ egl::Error SurfaceEGL::makeCurrent(const gl::Context *context)
egl::Error SurfaceEGL::swap(const gl::Context *context)
{
- EGLBoolean success = mEGL->swapBuffers(mSurface);
- if (success == EGL_FALSE)
- {
- return egl::Error(mEGL->getError(), "eglSwapBuffers failed");
- }
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, surface = mSurface](void *resultOut) {
+ ANGLE_UNUSED_VARIABLE(resultOut);
+ *static_cast<EGLBoolean *>(resultOut) = egl->swapBuffers(surface);
+ });
+
return egl::NoError();
}
@@ -50,19 +52,24 @@ egl::Error SurfaceEGL::swapWithDamage(const gl::Context *context,
const EGLint *rects,
EGLint n_rects)
{
- EGLBoolean success;
if (mHasSwapBuffersWithDamage)
{
- success = mEGL->swapBuffersWithDamageKHR(mSurface, rects, n_rects);
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, surface = mSurface, rects, n_rects](void *resultOut) {
+ ANGLE_UNUSED_VARIABLE(resultOut);
+ *static_cast<EGLBoolean *>(resultOut) =
+ egl->swapBuffersWithDamageKHR(surface, rects, n_rects);
+ });
}
else
{
- success = mEGL->swapBuffers(mSurface);
- }
- if (success == EGL_FALSE)
- {
- return egl::Error(mEGL->getError(), "eglSwapBuffersWithDamageKHR failed");
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, surface = mSurface](void *resultOut) {
+ ANGLE_UNUSED_VARIABLE(resultOut);
+ *static_cast<EGLBoolean *>(resultOut) = egl->swapBuffers(surface);
+ });
}
+
return egl::NoError();
}
diff --git a/src/libANGLE/renderer/gl/egl/SyncEGL.cpp b/src/libANGLE/renderer/gl/egl/SyncEGL.cpp
index b4a19dce32..93e3151eaf 100644
--- a/src/libANGLE/renderer/gl/egl/SyncEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/SyncEGL.cpp
@@ -26,7 +26,10 @@ void SyncEGL::onDestroy(const egl::Display *display)
{
if (mSync != EGL_NO_SYNC_KHR)
{
- mEGL->destroySyncKHR(mSync);
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, sync = mSync](void *resultOut) {
+ *static_cast<EGLBoolean *>(resultOut) = egl->destroySyncKHR(sync);
+ });
mSync = EGL_NO_SYNC_KHR;
}
}
@@ -49,11 +52,18 @@ egl::Error SyncEGL::initialize(const egl::Display *display,
}
nativeAttribs.push_back(EGL_NONE);
- mSync = mEGL->createSyncKHR(type, nativeAttribs.data());
- if (mSync == EGL_NO_SYNC_KHR)
- {
- return egl::Error(mEGL->getError(), "eglCreateSync failed to create sync object");
- }
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, &sync = mSync, type, attribs = nativeAttribs](void *resultOut) {
+ sync = egl->createSyncKHR(type, attribs.data());
+
+ // If sync creation failed, force the return value of eglCreateSync to EGL_NO_SYNC. This
+ // won't delete this sync object but a driver error is unexpected at this point.
+ if (sync == EGL_NO_SYNC_KHR)
+ {
+ ERR() << "eglCreateSync failed with " << gl::FmtHex(egl->getError());
+ *static_cast<EGLSync *>(resultOut) = EGL_NO_SYNC_KHR;
+ }
+ });
return egl::NoError();
}
@@ -65,14 +75,14 @@ egl::Error SyncEGL::clientWait(const egl::Display *display,
EGLint *outResult)
{
ASSERT(mSync != EGL_NO_SYNC_KHR);
- EGLint result = mEGL->clientWaitSyncKHR(mSync, flags, timeout);
- if (result == EGL_FALSE)
- {
- return egl::Error(mEGL->getError(), "eglClientWaitSync failed");
- }
+ // If we need to perform a CPU wait don't set the resultOut parameter passed into the
+ // method, instead set the parameter passed into the unlocked tail call.
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, sync = mSync, flags, timeout](void *resultOut) {
+ *static_cast<EGLint *>(resultOut) = egl->clientWaitSyncKHR(sync, flags, timeout);
+ });
- *outResult = result;
return egl::NoError();
}
@@ -81,12 +91,11 @@ egl::Error SyncEGL::serverWait(const egl::Display *display,
EGLint flags)
{
ASSERT(mSync != EGL_NO_SYNC_KHR);
- EGLint result = mEGL->waitSyncKHR(mSync, flags);
- if (result == EGL_FALSE)
- {
- return egl::Error(mEGL->getError(), "eglWaitSync failed");
- }
+ egl::Display::GetCurrentThreadUnlockedTailCall()->add(
+ [egl = mEGL, sync = mSync, flags](void *resultOut) {
+ *static_cast<EGLBoolean *>(resultOut) = egl->waitSyncKHR(sync, flags);
+ });
return egl::NoError();
}
diff --git a/src/libGLESv2/entry_points_egl_autogen.cpp b/src/libGLESv2/entry_points_egl_autogen.cpp
index 54a0591d67..4325d1dc5d 100644
--- a/src/libGLESv2/entry_points_egl_autogen.cpp
+++ b/src/libGLESv2/entry_points_egl_autogen.cpp
@@ -628,7 +628,7 @@ EGLBoolean EGLAPIENTRY EGL_SwapBuffers(EGLDisplay dpy, EGLSurface surface)
ANGLE_CAPTURE_EGL(SwapBuffers, true, thread, dpyPacked, surfacePacked, returnValue);
}
- egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -1026,7 +1026,7 @@ EGLImage EGLAPIENTRY EGL_CreateImage(EGLDisplay dpy,
ANGLE_CAPTURE_EGL(CreateImage, true, thread, dpyPacked, ctxPacked, target, buffer,
attrib_listPacked, returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -1129,7 +1129,7 @@ EGLSync EGLAPIENTRY EGL_CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib
ANGLE_CAPTURE_EGL(CreateSync, true, thread, dpyPacked, type, attrib_listPacked,
returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -1183,7 +1183,7 @@ EGLBoolean EGLAPIENTRY EGL_DestroySync(EGLDisplay dpy, EGLSync sync)
ANGLE_CAPTURE_EGL(DestroySync, true, thread, dpyPacked, syncPacked, returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -1274,7 +1274,7 @@ EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
ANGLE_CAPTURE_EGL(WaitSync, true, thread, dpyPacked, syncPacked, flags, returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
diff --git a/src/libGLESv2/entry_points_egl_ext_autogen.cpp b/src/libGLESv2/entry_points_egl_ext_autogen.cpp
index 93252ebe4f..405f138781 100644
--- a/src/libGLESv2/entry_points_egl_ext_autogen.cpp
+++ b/src/libGLESv2/entry_points_egl_ext_autogen.cpp
@@ -1451,7 +1451,7 @@ EGLSyncKHR EGLAPIENTRY EGL_CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGL
ANGLE_CAPTURE_EGL(CreateSyncKHR, true, thread, dpyPacked, type, attrib_listPacked,
returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
return returnValue;
}
@@ -1478,7 +1478,7 @@ EGLBoolean EGLAPIENTRY EGL_DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
ANGLE_CAPTURE_EGL(DestroySyncKHR, true, thread, dpyPacked, syncPacked, returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -1549,7 +1549,7 @@ EGLImageKHR EGLAPIENTRY EGL_CreateImageKHR(EGLDisplay dpy,
ANGLE_CAPTURE_EGL(CreateImageKHR, true, thread, dpyPacked, ctxPacked, target, buffer,
attrib_listPacked, returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -2018,7 +2018,7 @@ EGLBoolean EGLAPIENTRY EGL_SwapBuffersWithDamageKHR(EGLDisplay dpy,
ANGLE_CAPTURE_EGL(SwapBuffersWithDamageKHR, true, thread, dpyPacked, surfacePacked, rects,
n_rects, returnValue);
}
- egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}
@@ -2046,7 +2046,7 @@ EGLint EGLAPIENTRY EGL_WaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags
ANGLE_CAPTURE_EGL(WaitSyncKHR, true, thread, dpyPacked, syncPacked, flags, returnValue);
}
- ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
+ egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
return returnValue;
}