Hash :
36c3e0f5
Author :
Date :
2023-01-17T17:42:59
Implement "Shared Context Mutex" functionality.
Existing implementation uses single `GlobalMutex` for
- EGL calls
- GL calls for Contexts with concurrent access.
This CL introduces abstract `egl::ContextMutex` with two
implementations:
- SingleContextMutex;
- SharedContextMutex<Mutex>;
Note:
`std::mutex` is used in this commit. It is very easy to change mutex
type either at compile-time or at run-time (single type per Display).
When Context:
- is not Shared;
- does not use `EGLImage`s;
- does not use EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE
- does not use EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE
then it will be using `SingleContextMutex` with minimal overhead.
Before such Context is used as `shareContext` or uses `EGLImage`
its mutex replaced by `SharedContextMutex<Mutex>`.
The `GlobalMutex` is only used for EGL calls, while `egl::ContextMutex`
implementations for GL calls. Because some EGL calls use Context,
explicit `egl::ContextMutex` lock is required. This is implemented by
generating "egl_context_mutex_autogen.h" header, and insertion of
`ANGLE_EGL_SCOPED_CONTEXT_LOCK()` macro before `ANGLE_EGL_VALIDATE()`
in each EGL entry point. Implementation in "egl_context_lock_impl.h"
returns lock for required APIs. Special cases of `egl::ContextMutex`
lock handled separately. `std::unique_lock<>` is not used for
performance reasons.
`egl::ContextMutex` explicitly locked when capturing EGL calls.
Fixes EGLImage problem:
https://chromium.googlesource.com/angle/angle/+/e18240d136d15e5cdfa4fa4a6355ca21c8d807b6
Mark contexts as shared when importing EGL images.
Details:
- EGLImage inherits Context's mutex when created.
Mutex is used when the EGLImage accessed or destroyed.
- When EGLImage is used in Context with other `egl::ContextMutex`,
two mutexes are merged into one.
- After the mutex merge, Context Groups will remain separate,
but will not be able to run in parallel.
Fixes race when checking `context->isShared()` in the
`SCOPED_SHARE_CONTEXT_LOCK()` macro. One Context may start executing GL
call while not "Shared", but become "Shared" inside the call. New
(second) "Shared" Context may immediately start using GL and potentially
corrupt some "Shared" state.
Possible performance benefit: allows parallel execution in some cases,
when single `GlobalMutex` would block.
Important note:
Process of replacing the `SingleContextMutex` by
`SharedContextMutex<Mutex>` is not 100% safe. This mean that
original Context may still be using `SingleContextMutex` after
activating `SharedContextMutex<Mutex>`. However, this was always
the case before introduction of this CL. Old `Context::mShared`
member update was not synchronized in any way at all. In other
words, this solution does not 100% fix the original problem.
For 100% safe solution `SingleContextMutex` should not be used
(always pass `SharedContextMutex<Mutex>` to the `gl::Context`
constructor). See `lockAndActivateSharedContextMutex()` for more
details.
CL adds new build option:
angle_enable_shared_context_mutex = true
Behavior with other build options:
- When:
`angle_enable_shared_context_mutex` is disabled or
`angle_enable_share_context_lock` is disabled or
`angle_force_context_check_every_call` is enabled,
Contexts will always have `SingleContextMutex`, however it will be
only used in special cases. `SCOPED_SHARE_CONTEXT_LOCK()` will use
`GlobalMutex` when applicable.
- Otherwise, `SCOPED_SHARE_CONTEXT_LOCK()` will use `egl::ContextMutex`.
Some GFXBench "1080p Driver Overhead 2 Offscreen" performance numbers.
Tested on S906B (Samsung Galaxy S22+) on old ANGLE base:
https://chromium.googlesource.com/angle/angle/+/807c94ea85e046c6f279d081d99f0fb1bcf1191a
Capture/Replay: Adjust tests do adhere to capture limits
Each test result is an average frame number from 6 runs.
SingleContextMutex 6579 ( +0.13%)
(old) GetContextLock() (mShared is false) 6570
Forced `mShared = true` or NOT using `SingleContextMutex`.
SharedContextMutex<std::mutex> FORCE 5061 (-22.97%)
(old) GetContextLock() FORCE 4766 (-27.46%)
Bug: angleproject:6957
Bug: chromium:1336126
Change-Id: Idcd919f9d4bf482b9ae489bd8b4415ec96048e32
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4374545
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
// GENERATED FILE - DO NOT EDIT.
// Generated by generate_entry_points.py using data from egl.xml and egl_angle_ext.xml.
//
// Copyright 2023 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.
//
// egl_context_lock_autogen.h:
// Context Lock functions for the EGL entry points.
#ifndef LIBGLESV2_EGL_CONTEXT_LOCK_AUTOGEN_H_
#define LIBGLESV2_EGL_CONTEXT_LOCK_AUTOGEN_H_
#include "libGLESv2/global_state.h"
namespace egl
{
// EGL 1.0
ScopedContextMutexLock GetContextLock_ChooseConfig(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CopyBuffers(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreateContext(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID share_contextPacked);
ScopedContextMutexLock GetContextLock_CreatePbufferSurface(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreatePixmapSurface(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreateWindowSurface(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_DestroyContext(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked);
ScopedContextMutexLock GetContextLock_DestroySurface(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetConfigAttrib(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
ScopedContextMutexLock GetContextLock_GetConfigs(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetCurrentDisplay(Thread *thread);
ScopedContextMutexLock GetContextLock_GetCurrentSurface(Thread *thread);
ScopedContextMutexLock GetContextLock_GetDisplay(Thread *thread);
ScopedContextMutexLock GetContextLock_GetError(Thread *thread);
ScopedContextMutexLock GetContextLock_GetProcAddress(Thread *thread);
ScopedContextMutexLock GetContextLock_Initialize(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_MakeCurrent(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked);
ScopedContextMutexLock GetContextLock_QueryContext(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked,
EGLint attribute);
ScopedContextMutexLock GetContextLock_QueryString(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_QuerySurface(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
ScopedContextMutexLock GetContextLock_SwapBuffers(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_Terminate(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_WaitGL(Thread *thread);
ScopedContextMutexLock GetContextLock_WaitNative(Thread *thread);
// EGL 1.1
ScopedContextMutexLock GetContextLock_BindTexImage(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_ReleaseTexImage(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_SurfaceAttrib(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
ScopedContextMutexLock GetContextLock_SwapInterval(Thread *thread, egl::Display *dpyPacked);
// EGL 1.2
ScopedContextMutexLock GetContextLock_BindAPI(Thread *thread);
ScopedContextMutexLock GetContextLock_CreatePbufferFromClientBuffer(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_QueryAPI(Thread *thread);
ScopedContextMutexLock GetContextLock_ReleaseThread(Thread *thread);
ScopedContextMutexLock GetContextLock_WaitClient(Thread *thread);
// EGL 1.4
ScopedContextMutexLock GetContextLock_GetCurrentContext(Thread *thread);
// EGL 1.5
ScopedContextMutexLock GetContextLock_ClientWaitSync(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreateImage(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked);
ScopedContextMutexLock GetContextLock_CreatePlatformPixmapSurface(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreatePlatformWindowSurface(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreateSync(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_DestroyImage(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_DestroySync(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetPlatformDisplay(Thread *thread);
ScopedContextMutexLock GetContextLock_GetSyncAttrib(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
ScopedContextMutexLock GetContextLock_WaitSync(Thread *thread, egl::Display *dpyPacked);
// EGL_ANDROID_blob_cache
ScopedContextMutexLock GetContextLock_SetBlobCacheFuncsANDROID(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANDROID_create_native_client_buffer
ScopedContextMutexLock GetContextLock_CreateNativeClientBufferANDROID(Thread *thread);
// EGL_ANDROID_get_frame_timestamps
ScopedContextMutexLock GetContextLock_GetCompositorTimingSupportedANDROID(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetCompositorTimingANDROID(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetNextFrameIdANDROID(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetFrameTimestampSupportedANDROID(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetFrameTimestampsANDROID(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANDROID_get_native_client_buffer
ScopedContextMutexLock GetContextLock_GetNativeClientBufferANDROID(Thread *thread);
// EGL_ANDROID_native_fence_sync
ScopedContextMutexLock GetContextLock_DupNativeFenceFDANDROID(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANDROID_presentation_time
ScopedContextMutexLock GetContextLock_PresentationTimeANDROID(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANGLE_device_creation
ScopedContextMutexLock GetContextLock_CreateDeviceANGLE(Thread *thread);
ScopedContextMutexLock GetContextLock_ReleaseDeviceANGLE(Thread *thread);
// EGL_ANGLE_feature_control
ScopedContextMutexLock GetContextLock_QueryStringiANGLE(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_QueryDisplayAttribANGLE(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
// EGL_ANGLE_metal_shared_event_sync
ScopedContextMutexLock GetContextLock_CopyMetalSharedEventANGLE(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANGLE_power_preference
ScopedContextMutexLock GetContextLock_ReleaseHighPowerGPUANGLE(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked);
ScopedContextMutexLock GetContextLock_ReacquireHighPowerGPUANGLE(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked);
ScopedContextMutexLock GetContextLock_HandleGPUSwitchANGLE(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_ForceGPUSwitchANGLE(Thread *thread, egl::Display *dpyPacked);
// EGL_ANGLE_prepare_swap_buffers
ScopedContextMutexLock GetContextLock_PrepareSwapBuffersANGLE(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANGLE_program_cache_control
ScopedContextMutexLock GetContextLock_ProgramCacheGetAttribANGLE(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_ProgramCacheQueryANGLE(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_ProgramCachePopulateANGLE(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_ProgramCacheResizeANGLE(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANGLE_query_surface_pointer
ScopedContextMutexLock GetContextLock_QuerySurfacePointerANGLE(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
// EGL_ANGLE_stream_producer_d3d_texture
ScopedContextMutexLock GetContextLock_CreateStreamProducerD3DTextureANGLE(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_StreamPostD3DTextureANGLE(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANGLE_swap_with_frame_token
ScopedContextMutexLock GetContextLock_SwapBuffersWithFrameTokenANGLE(Thread *thread,
egl::Display *dpyPacked);
// EGL_ANGLE_sync_control_rate
ScopedContextMutexLock GetContextLock_GetMscRateANGLE(Thread *thread, egl::Display *dpyPacked);
// EGL_ANGLE_vulkan_image
ScopedContextMutexLock GetContextLock_ExportVkImageANGLE(Thread *thread, egl::Display *dpyPacked);
// EGL_ANGLE_wait_until_work_scheduled
ScopedContextMutexLock GetContextLock_WaitUntilWorkScheduledANGLE(Thread *thread,
egl::Display *dpyPacked);
// EGL_CHROMIUM_sync_control
ScopedContextMutexLock GetContextLock_GetSyncValuesCHROMIUM(Thread *thread,
egl::Display *dpyPacked);
// EGL_EXT_device_query
ScopedContextMutexLock GetContextLock_QueryDeviceAttribEXT(Thread *thread, EGLint attribute);
ScopedContextMutexLock GetContextLock_QueryDeviceStringEXT(Thread *thread);
ScopedContextMutexLock GetContextLock_QueryDisplayAttribEXT(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
// EGL_EXT_image_dma_buf_import_modifiers
ScopedContextMutexLock GetContextLock_QueryDmaBufFormatsEXT(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_QueryDmaBufModifiersEXT(Thread *thread,
egl::Display *dpyPacked);
// EGL_EXT_platform_base
ScopedContextMutexLock GetContextLock_CreatePlatformPixmapSurfaceEXT(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreatePlatformWindowSurfaceEXT(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetPlatformDisplayEXT(Thread *thread);
// EGL_KHR_debug
ScopedContextMutexLock GetContextLock_DebugMessageControlKHR(Thread *thread);
ScopedContextMutexLock GetContextLock_LabelObjectKHR(Thread *thread, egl::Display *displayPacked);
ScopedContextMutexLock GetContextLock_QueryDebugKHR(Thread *thread, EGLint attribute);
// EGL_KHR_fence_sync
ScopedContextMutexLock GetContextLock_ClientWaitSyncKHR(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_CreateSyncKHR(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_DestroySyncKHR(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_GetSyncAttribKHR(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
// EGL_KHR_image
ScopedContextMutexLock GetContextLock_CreateImageKHR(Thread *thread,
egl::Display *dpyPacked,
gl::ContextID ctxPacked);
ScopedContextMutexLock GetContextLock_DestroyImageKHR(Thread *thread, egl::Display *dpyPacked);
// EGL_KHR_lock_surface3
ScopedContextMutexLock GetContextLock_LockSurfaceKHR(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_QuerySurface64KHR(Thread *thread,
egl::Display *dpyPacked,
EGLint attribute);
ScopedContextMutexLock GetContextLock_UnlockSurfaceKHR(Thread *thread, egl::Display *dpyPacked);
// EGL_KHR_partial_update
ScopedContextMutexLock GetContextLock_SetDamageRegionKHR(Thread *thread, egl::Display *dpyPacked);
// EGL_KHR_reusable_sync
ScopedContextMutexLock GetContextLock_SignalSyncKHR(Thread *thread, egl::Display *dpyPacked);
// EGL_KHR_stream
ScopedContextMutexLock GetContextLock_CreateStreamKHR(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_DestroyStreamKHR(Thread *thread, egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_QueryStreamKHR(Thread *thread,
egl::Display *dpyPacked,
EGLenum attribute);
ScopedContextMutexLock GetContextLock_QueryStreamu64KHR(Thread *thread,
egl::Display *dpyPacked,
EGLenum attribute);
ScopedContextMutexLock GetContextLock_StreamAttribKHR(Thread *thread,
egl::Display *dpyPacked,
EGLenum attribute);
// EGL_KHR_stream_consumer_gltexture
ScopedContextMutexLock GetContextLock_StreamConsumerAcquireKHR(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_StreamConsumerGLTextureExternalKHR(Thread *thread,
egl::Display *dpyPacked);
ScopedContextMutexLock GetContextLock_StreamConsumerReleaseKHR(Thread *thread,
egl::Display *dpyPacked);
// EGL_KHR_swap_buffers_with_damage
ScopedContextMutexLock GetContextLock_SwapBuffersWithDamageKHR(Thread *thread,
egl::Display *dpyPacked);
// EGL_KHR_wait_sync
ScopedContextMutexLock GetContextLock_WaitSyncKHR(Thread *thread, egl::Display *dpyPacked);
// EGL_NV_post_sub_buffer
ScopedContextMutexLock GetContextLock_PostSubBufferNV(Thread *thread, egl::Display *dpyPacked);
// EGL_NV_stream_consumer_gltexture_yuv
ScopedContextMutexLock GetContextLock_StreamConsumerGLTextureExternalAttribsNV(
Thread *thread,
egl::Display *dpyPacked);
} // namespace egl
#endif // LIBGLESV2_EGL_CONTEXT_LOCK_AUTOGEN_H_