• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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