1// 2// Copyright 2022 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6// EGLSyncTestMetalSharedEvent: 7// Tests pertaining to EGL_ANGLE_sync_mtl_shared_event extension. 8// 9 10#include <gtest/gtest.h> 11 12#include "test_utils/ANGLETest.h" 13#include "util/EGLWindow.h" 14 15#include <Metal/Metal.h> 16 17using namespace angle; 18 19static inline EGLAttrib Uint64HighPart(uint64_t value) 20{ 21 return value >> 32; 22} 23 24static inline EGLAttrib Uint64LowPart(uint64_t value) 25{ 26 return value & 0xFFFFFFFF; 27} 28 29class EGLSyncTestMetalSharedEvent : public ANGLETest<> 30{ 31 protected: 32 id<MTLSharedEvent> createMetalSharedEvent() const 33 { 34 id<MTLDevice> device = getMetalDevice(); 35 id<MTLSharedEvent> sharedEvent = [device newSharedEvent]; 36 sharedEvent.label = @"TestSharedEvent"; 37 return sharedEvent; 38 } 39 40 id<MTLDevice> getMetalDevice() const 41 { 42 EGLAttrib angleDevice = 0; 43 EXPECT_EGL_TRUE( 44 eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); 45 46 EGLAttrib device = 0; 47 EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), 48 EGL_METAL_DEVICE_ANGLE, &device)); 49 50 return (__bridge id<MTLDevice>)reinterpret_cast<void *>(device); 51 } 52 53 bool hasEGLDisplayExtension(const char *extname) const 54 { 55 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), extname); 56 } 57 58 bool hasSyncMetalSharedEventExtension() const 59 { 60 return hasEGLDisplayExtension("EGL_ANGLE_metal_shared_event_sync"); 61 } 62 63 EGLAttrib sharedEventAsAttrib(id<MTLSharedEvent> sharedEvent) const 64 { 65 return reinterpret_cast<EGLAttrib>(sharedEvent); 66 } 67 68 id<MTLSharedEvent> sharedEventFromVoidPtr(void *ptr) const 69 { 70 return (__bridge id<MTLSharedEvent>)ptr; 71 } 72}; 73 74// Test existing fence is created unsignaled 75TEST_P(EGLSyncTestMetalSharedEvent, BasicEGLSync) 76{ 77 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 78 79 EGLDisplay display = getEGLWindow()->getDisplay(); 80 81 EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr); 82 EXPECT_NE(sync, EGL_NO_SYNC_KHR); 83 84 constexpr EGLint kSentinelAttribValue = 123456789; 85 EGLint signaledValue = kSentinelAttribValue; 86 EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &signaledValue)); 87 EXPECT_EQ(signaledValue, EGL_UNSIGNALED_KHR); 88 89 glClearColor(1.0f, 0.0f, 1.0f, 1.0f); 90 91 glClear(GL_COLOR_BUFFER_BIT); 92 EXPECT_EGL_TRUE(eglWaitSyncKHR(display, sync, 0)); 93 94 glFinish(); 95 96 // Don't wait forever to make sure the test terminates 97 constexpr GLuint64 kTimeout = 1000'000'000ul; // 1 second 98 EXPECT_EQ(EGL_CONDITION_SATISFIED_KHR, 99 eglClientWaitSyncKHR(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, kTimeout)); 100 101 signaledValue = kSentinelAttribValue; 102 EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &signaledValue)); 103 EXPECT_EQ(signaledValue, EGL_SIGNALED_KHR); 104 105 EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync)); 106} 107 108// Test usage of eglGetSyncAttrib 109TEST_P(EGLSyncTestMetalSharedEvent, GetSyncAttrib) 110{ 111 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 112 113 id<MTLSharedEvent> sharedEvent = createMetalSharedEvent(); 114 EXPECT_EQ([sharedEvent retainCount], 1ul); 115 uint64_t initialSignalValue = sharedEvent.signaledValue; 116 EXPECT_EQ(initialSignalValue, 0u); 117 118 EGLDisplay display = getEGLWindow()->getDisplay(); 119 EGLAttrib syncAttribs[] = {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, 120 sharedEventAsAttrib(sharedEvent), EGL_NONE}; 121 EXPECT_EQ([sharedEvent retainCount], 1ul); 122 123 EGLSync sync = eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs); 124 EXPECT_NE(sync, EGL_NO_SYNC); 125 // sharedEvent, sync, mtlCommandBuffer 126 EXPECT_GT([sharedEvent retainCount], 1ul); 127 128 // Fence sync attributes are: 129 // 130 // EGL_SYNC_TYPE: EGL_SYNC_METAL_SHARED_EVENT_ANGLE 131 // EGL_SYNC_STATUS: EGL_UNSIGNALED or EGL_SIGNALED 132 // EGL_SYNC_CONDITION: EGL_SYNC_PRIOR_COMMANDS_COMPLETE 133 134 constexpr EGLAttrib kSentinelAttribValue = 123456789; 135 EGLAttrib attribValue = kSentinelAttribValue; 136 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_TYPE, &attribValue)); 137 EXPECT_EQ(attribValue, EGL_SYNC_METAL_SHARED_EVENT_ANGLE); 138 139 attribValue = kSentinelAttribValue; 140 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_CONDITION, &attribValue)); 141 EXPECT_EQ(attribValue, EGL_SYNC_PRIOR_COMMANDS_COMPLETE); 142 143 attribValue = kSentinelAttribValue; 144 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_STATUS, &attribValue)); 145 EXPECT_EQ(attribValue, EGL_UNSIGNALED); 146 EXPECT_GT([sharedEvent retainCount], 1ul); 147 148 glFinish(); 149 150 attribValue = kSentinelAttribValue; 151 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_STATUS, &attribValue)); 152 EXPECT_EQ(attribValue, EGL_SIGNALED); 153 EXPECT_EQ(sharedEvent.signaledValue, initialSignalValue + 1); 154 EXPECT_GT([sharedEvent retainCount], 1ul); 155 156 EXPECT_EGL_TRUE(eglDestroySync(display, sync)); 157 EXPECT_EQ([sharedEvent retainCount], 1ul); 158 159 sharedEvent = nil; 160} 161 162// Test usage of eglGetSyncAttrib with explicit sync condition 163TEST_P(EGLSyncTestMetalSharedEvent, GetSyncAttrib_ExplicitSyncCondition) 164{ 165 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 166 167 id<MTLSharedEvent> sharedEvent = createMetalSharedEvent(); 168 EXPECT_EQ(sharedEvent.signaledValue, 0u); 169 170 EGLDisplay display = getEGLWindow()->getDisplay(); 171 EGLAttrib syncAttribs[3][5] = { 172 {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, sharedEventAsAttrib(sharedEvent), EGL_NONE}, 173 {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, sharedEventAsAttrib(sharedEvent), 174 EGL_SYNC_CONDITION, EGL_SYNC_PRIOR_COMMANDS_COMPLETE, EGL_NONE}, 175 {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, sharedEventAsAttrib(sharedEvent), 176 EGL_SYNC_CONDITION, EGL_SYNC_METAL_SHARED_EVENT_SIGNALED_ANGLE, EGL_NONE}}; 177 178 EGLAttrib expectedSyncCondition[3] = {EGL_SYNC_PRIOR_COMMANDS_COMPLETE, 179 EGL_SYNC_PRIOR_COMMANDS_COMPLETE, 180 EGL_SYNC_METAL_SHARED_EVENT_SIGNALED_ANGLE}; 181 182 for (int i = 0; i < 3; ++i) 183 { 184 uint64_t initialSignalValue = sharedEvent.signaledValue; 185 186 EGLSync sync = eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs[i]); 187 EXPECT_NE(sync, EGL_NO_SYNC); 188 189 constexpr EGLAttrib kSentinelAttribValue = 123456789; 190 EGLAttrib attribValue = kSentinelAttribValue; 191 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_TYPE, &attribValue)); 192 EXPECT_EQ(attribValue, EGL_SYNC_METAL_SHARED_EVENT_ANGLE); 193 194 attribValue = kSentinelAttribValue; 195 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_CONDITION, &attribValue)); 196 EXPECT_EQ(attribValue, expectedSyncCondition[i]); 197 198 attribValue = kSentinelAttribValue; 199 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_STATUS, &attribValue)); 200 EXPECT_EQ(attribValue, EGL_UNSIGNALED); 201 202 glFinish(); 203 204 if (i == 2) 205 { 206 sharedEvent.signaledValue += 1; 207 } 208 209 attribValue = kSentinelAttribValue; 210 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, sync, EGL_SYNC_STATUS, &attribValue)); 211 EXPECT_EQ(attribValue, EGL_SIGNALED); 212 EXPECT_EQ(sharedEvent.signaledValue, initialSignalValue + 1); 213 214 EXPECT_EGL_TRUE(eglDestroySync(display, sync)); 215 } 216 217 sharedEvent = nil; 218} 219 220// Verify CreateSync and ClientWait for EGL_ANGLE_metal_shared_event_sync 221TEST_P(EGLSyncTestMetalSharedEvent, AngleMetalSharedEventSync_ClientWait) 222{ 223 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 224 225 id<MTLSharedEvent> sharedEvent = createMetalSharedEvent(); 226 227 EGLDisplay display = getEGLWindow()->getDisplay(); 228 EGLAttrib syncAttribs[] = {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, 229 sharedEventAsAttrib(sharedEvent), EGL_NONE}; 230 231 // We can ClientWait on this 232 EGLSync syncWithSharedEvent = 233 eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs); 234 EXPECT_NE(syncWithSharedEvent, EGL_NO_SYNC); 235 236 // Create work to do 237 glClearColor(0.0f, 1.0f, 1.0f, 1.0f); 238 glClear(GL_COLOR_BUFFER_BIT); 239 glFlush(); 240 241 // Wait for the draw to complete 242 glClear(GL_COLOR_BUFFER_BIT); 243 244 // Don't wait forever to make sure the test terminates 245 constexpr GLuint64 kTimeout = 1000000000; // 1 second 246 EGLAttrib value = 0; 247 EXPECT_EQ(EGL_CONDITION_SATISFIED, eglClientWaitSync(display, syncWithSharedEvent, 248 EGL_SYNC_FLUSH_COMMANDS_BIT, kTimeout)); 249 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent, EGL_SYNC_STATUS, &value)); 250 EXPECT_EQ(value, EGL_SIGNALED); 251 252 // Clean up created objects. 253 EXPECT_EGL_TRUE(eglDestroySync(display, syncWithSharedEvent)); 254 sharedEvent = nil; 255} 256 257// Verify CreateSync and ClientWait for EGL_ANGLE_metal_shared_event_sync 258TEST_P(EGLSyncTestMetalSharedEvent, AngleMetalSharedEventSync_ClientWait_WithSignalValue) 259{ 260 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 261 262 id<MTLSharedEvent> sharedEvent = createMetalSharedEvent(); 263 264 constexpr uint64_t kSignalValue = 0xDEADBEEFCAFE; 265 EGLDisplay display = getEGLWindow()->getDisplay(); 266 EGLAttrib syncAttribs[] = {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, 267 sharedEventAsAttrib(sharedEvent), 268 EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_HI_ANGLE, 269 Uint64HighPart(kSignalValue), 270 EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_LO_ANGLE, 271 Uint64LowPart(kSignalValue), 272 EGL_NONE}; 273 274 // We can ClientWait on this 275 EGLSync syncWithSharedEvent = 276 eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs); 277 EXPECT_NE(syncWithSharedEvent, EGL_NO_SYNC); 278 279 // Create work to do 280 glClearColor(0.0f, 1.0f, 1.0f, 1.0f); 281 glClear(GL_COLOR_BUFFER_BIT); 282 glFlush(); 283 284 // Wait for the draw to complete 285 glClear(GL_COLOR_BUFFER_BIT); 286 287 // Don't wait forever to make sure the test terminates 288 constexpr GLuint64 kTimeout = 1000000000; // 1 second 289 EGLAttrib value = 0; 290 EXPECT_EQ(EGL_CONDITION_SATISFIED, eglClientWaitSync(display, syncWithSharedEvent, 291 EGL_SYNC_FLUSH_COMMANDS_BIT, kTimeout)); 292 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent, EGL_SYNC_STATUS, &value)); 293 EXPECT_EQ(value, EGL_SIGNALED); 294 EXPECT_EQ(sharedEvent.signaledValue, kSignalValue); 295 296 // Clean up created objects. 297 EXPECT_EGL_TRUE(eglDestroySync(display, syncWithSharedEvent)); 298 sharedEvent = nil; 299} 300 301// Verify eglCopyMetalSharedEventANGLE for EGL_ANGLE_metal_shared_event_sync 302TEST_P(EGLSyncTestMetalSharedEvent, AngleMetalSharedEventSync_CopyMetalSharedEventANGLE) 303{ 304 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 305 306 EGLDisplay display = getEGLWindow()->getDisplay(); 307 308 // We can ClientWait on this 309 EGLSync syncWithGeneratedEvent = 310 eglCreateSyncKHR(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, nullptr); 311 EXPECT_NE(syncWithGeneratedEvent, EGL_NO_SYNC_KHR); 312 313 id<MTLSharedEvent> sharedEvent = 314 sharedEventFromVoidPtr(eglCopyMetalSharedEventANGLE(display, syncWithGeneratedEvent)); 315 EXPECT_EGL_SUCCESS(); 316 EXPECT_GT([sharedEvent retainCount], 1ul); 317 318 glFinish(); 319 EXPECT_EGL_TRUE(eglDestroySync(display, syncWithGeneratedEvent)); 320 321 // Clean up created objects. 322 EXPECT_EQ([sharedEvent retainCount], 1ul); 323 [sharedEvent release]; 324} 325 326// Verify WaitSync with EGL_ANGLE_metal_shared_event_sync 327// Simulate passing shared events across processes by passing across Contexts. 328TEST_P(EGLSyncTestMetalSharedEvent, AngleMetalSharedEventSync_WaitSync) 329{ 330 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 331 332 id<MTLSharedEvent> sharedEvent = createMetalSharedEvent(); 333 334 EGLAttrib value = 0; 335 EGLDisplay display = getEGLWindow()->getDisplay(); 336 EGLSurface surface = getEGLWindow()->getSurface(); 337 338 /*- First Context ------------------------*/ 339 340 EGLAttrib syncAttribs[] = {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, 341 sharedEventAsAttrib(sharedEvent), EGL_NONE}; 342 // We can ClientWait on this 343 344 EGLSync syncWithSharedEvent1 = 345 eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs); 346 EXPECT_NE(syncWithSharedEvent1, EGL_NO_SYNC); 347 if (syncWithSharedEvent1 == EGL_NO_SYNC) 348 { 349 // Unable to continue with test. 350 return; 351 } 352 353 // Create work to do 354 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 355 glClear(GL_COLOR_BUFFER_BIT); 356 glFlush(); 357 358 /*- Second Context ------------------------*/ 359 EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); 360 361 EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT, nullptr); 362 EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2)); 363 364 EGLSync syncWithSharedEvent2 = 365 eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs); 366 EXPECT_NE(syncWithSharedEvent2, EGL_NO_SYNC); 367 if (syncWithSharedEvent2 == EGL_NO_SYNC) 368 { 369 // Unable to continue with test. 370 return; 371 } 372 373 // Second draw waits for first to complete. May already be signaled - ignore error. 374 if (eglWaitSync(display, syncWithSharedEvent2, 0) == EGL_TRUE) 375 { 376 // Create work to do 377 glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 378 glClear(GL_COLOR_BUFFER_BIT); 379 glFlush(); 380 } 381 382 // Wait for second draw to complete 383 EXPECT_EQ(EGL_CONDITION_SATISFIED, eglClientWaitSync(display, syncWithSharedEvent2, 384 EGL_SYNC_FLUSH_COMMANDS_BIT, 1000000000)); 385 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent2, EGL_SYNC_STATUS, &value)); 386 EXPECT_EQ(value, EGL_SIGNALED); 387 388 // Reset to default context and surface. 389 EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); 390 EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, getEGLWindow()->getContext())); 391 392 // Clean up created objects. 393 EXPECT_EGL_TRUE(eglDestroySync(display, syncWithSharedEvent2)); 394 EXPECT_EGL_TRUE(eglDestroyContext(display, context2)); 395 396 // Wait for first draw to complete 397 EXPECT_EQ(EGL_CONDITION_SATISFIED, eglClientWaitSync(display, syncWithSharedEvent1, 398 EGL_SYNC_FLUSH_COMMANDS_BIT, 1000000000)); 399 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent1, EGL_SYNC_STATUS, &value)); 400 EXPECT_EQ(value, EGL_SIGNALED); 401 402 // Clean up created objects. 403 EXPECT_EGL_TRUE(eglDestroySync(display, syncWithSharedEvent1)); 404 sharedEvent = nil; 405} 406 407// Verify WaitSync with EGL_ANGLE_metal_shared_event_sync 408// Simulate passing shared events across processes by passing across Contexts. 409TEST_P(EGLSyncTestMetalSharedEvent, AngleMetalSharedEventSync_WaitSync_ExternallySignaled) 410{ 411 ANGLE_SKIP_TEST_IF(!hasSyncMetalSharedEventExtension()); 412 413 id<MTLSharedEvent> sharedEvent = createMetalSharedEvent(); 414 415 EGLAttrib value = 0; 416 EGLDisplay display = getEGLWindow()->getDisplay(); 417 418 EGLAttrib syncAttribs[] = {EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, 419 sharedEventAsAttrib(sharedEvent), EGL_SYNC_CONDITION, 420 EGL_SYNC_METAL_SHARED_EVENT_SIGNALED_ANGLE, EGL_NONE}; 421 422 // We can ClientWait on this 423 EGLSync syncWithSharedEvent = 424 eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs); 425 EXPECT_NE(syncWithSharedEvent, EGL_NO_SYNC); 426 if (syncWithSharedEvent == EGL_NO_SYNC) 427 { 428 // Unable to continue with test. 429 return; 430 } 431 432 constexpr EGLAttrib kSentinelAttribValue = 123456789; 433 value = kSentinelAttribValue; 434 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent, EGL_SYNC_CONDITION, &value)); 435 EXPECT_EQ(value, EGL_SYNC_METAL_SHARED_EVENT_SIGNALED_ANGLE); 436 437 EXPECT_EQ(EGL_TIMEOUT_EXPIRED, 438 eglClientWaitSync(display, syncWithSharedEvent, EGL_SYNC_FLUSH_COMMANDS_BIT, 0)); 439 440 value = kSentinelAttribValue; 441 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent, EGL_SYNC_STATUS, &value)); 442 EXPECT_EQ(value, EGL_UNSIGNALED); 443 444 // Wait for previous work to complete before drawing 445 EXPECT_EGL_TRUE(eglWaitSync(display, syncWithSharedEvent, 0)); 446 447 // Create work to do 448 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 449 glClear(GL_COLOR_BUFFER_BIT); 450 glFlush(); 451 452 // After explicit flush, should still time out 453 // TODO(djg): flushing here causes a 5s stall in `CommandBuffer::wait` 454 // (mtl_command_buffer.mm:765) EXPECT_EQ(EGL_TIMEOUT_EXPIRED, 455 // eglClientWaitSync(display, syncWithSharedEvent, EGL_SYNC_FLUSH_COMMANDS_BIT, 0)); 456 EXPECT_EQ(EGL_TIMEOUT_EXPIRED, eglClientWaitSync(display, syncWithSharedEvent, 0, 0)); 457 458 value = kSentinelAttribValue; 459 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent, EGL_SYNC_STATUS, &value)); 460 EXPECT_EQ(value, EGL_UNSIGNALED); 461 462 // Signal the MTLSharedEvent 463 sharedEvent.signaledValue += 1; 464 465 // Wait for draw to complete. This will be satisfied since the signalValue 466 // was incremented on sharedEvent. 467 EXPECT_EQ(EGL_CONDITION_SATISFIED, 468 eglClientWaitSync(display, syncWithSharedEvent, EGL_SYNC_FLUSH_COMMANDS_BIT, 0)); 469 EXPECT_EGL_TRUE(eglGetSyncAttrib(display, syncWithSharedEvent, EGL_SYNC_STATUS, &value)); 470 EXPECT_EQ(value, EGL_SIGNALED); 471 472 // Clean up created objects. 473 EXPECT_EGL_TRUE(eglDestroySync(display, syncWithSharedEvent)); 474 sharedEvent = nil; 475} 476 477ANGLE_INSTANTIATE_TEST(EGLSyncTestMetalSharedEvent, ES2_METAL(), ES3_METAL()); 478// This test suite is not instantiated on non-Metal backends and OSes. 479GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSyncTestMetalSharedEvent); 480