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 // MultiThreadSteps.cpp:
7 // Synchronization help for tests that use multiple threads.
8
9 #include "MultiThreadSteps.h"
10
11 #include "angle_test_platform.h"
12 #include "gtest/gtest.h"
13 #include "util/EGLWindow.h"
14
15 namespace angle
16 {
17
RunLockStepThreads(EGLWindow * window,size_t threadCount,LockStepThreadFunc threadFuncs[])18 void RunLockStepThreads(EGLWindow *window, size_t threadCount, LockStepThreadFunc threadFuncs[])
19 {
20 EGLDisplay dpy = window->getDisplay();
21 EGLConfig config = window->getConfig();
22
23 constexpr EGLint kPBufferSize = 256;
24 // Initialize the pbuffer and context
25 EGLint pbufferAttributes[] = {
26 EGL_WIDTH, kPBufferSize, EGL_HEIGHT, kPBufferSize, EGL_NONE, EGL_NONE,
27 };
28
29 std::vector<EGLSurface> surfaces(threadCount);
30 std::vector<EGLContext> contexts(threadCount);
31
32 // Create N surfaces and shared contexts, one for each thread
33 for (size_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
34 {
35 surfaces[threadIndex] = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
36 EXPECT_EQ(eglGetError(), EGL_SUCCESS);
37 EGLint extraAttributes[] = {EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE,
38 static_cast<EGLint>(threadIndex), EGL_NONE};
39 if (!IsEGLDisplayExtensionEnabled(dpy, "EGL_ANGLE_context_virtualization"))
40 {
41 extraAttributes[0] = EGL_NONE;
42 }
43 contexts[threadIndex] =
44 window->createContext(threadIndex == 0 ? EGL_NO_CONTEXT : contexts[0], extraAttributes);
45 EXPECT_NE(EGL_NO_CONTEXT, contexts[threadIndex]) << threadIndex;
46 }
47
48 std::vector<std::thread> threads(threadCount);
49
50 // Run the threads
51 for (size_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
52 {
53 threads[threadIndex] = std::thread(std::move(threadFuncs[threadIndex]), dpy,
54 surfaces[threadIndex], contexts[threadIndex]);
55 }
56
57 // Wait for them to finish
58 for (size_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
59 {
60 threads[threadIndex].join();
61
62 // Clean up
63 eglDestroySurface(dpy, surfaces[threadIndex]);
64 eglDestroyContext(dpy, contexts[threadIndex]);
65 }
66 }
67 } // namespace angle
68