1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // MultiThreadSteps.cpp:
7*8975f5c5SAndroid Build Coastguard Worker // Synchronization help for tests that use multiple threads.
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "MultiThreadSteps.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include "angle_test_platform.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "gtest/gtest.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "util/EGLWindow.h"
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard Worker namespace angle
16*8975f5c5SAndroid Build Coastguard Worker {
17*8975f5c5SAndroid Build Coastguard Worker
RunLockStepThreads(EGLWindow * window,size_t threadCount,LockStepThreadFunc threadFuncs[])18*8975f5c5SAndroid Build Coastguard Worker void RunLockStepThreads(EGLWindow *window, size_t threadCount, LockStepThreadFunc threadFuncs[])
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker constexpr EGLint kPBufferSize = 256;
21*8975f5c5SAndroid Build Coastguard Worker RunLockStepThreadsWithSize(window, kPBufferSize, kPBufferSize, threadCount, threadFuncs);
22*8975f5c5SAndroid Build Coastguard Worker }
23*8975f5c5SAndroid Build Coastguard Worker
RunLockStepThreadsWithSize(EGLWindow * window,EGLint width,EGLint height,size_t threadCount,LockStepThreadFunc threadFuncs[])24*8975f5c5SAndroid Build Coastguard Worker void RunLockStepThreadsWithSize(EGLWindow *window,
25*8975f5c5SAndroid Build Coastguard Worker EGLint width,
26*8975f5c5SAndroid Build Coastguard Worker EGLint height,
27*8975f5c5SAndroid Build Coastguard Worker size_t threadCount,
28*8975f5c5SAndroid Build Coastguard Worker LockStepThreadFunc threadFuncs[])
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker EGLDisplay dpy = window->getDisplay();
31*8975f5c5SAndroid Build Coastguard Worker EGLConfig config = window->getConfig();
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Worker // Initialize the pbuffer and context
34*8975f5c5SAndroid Build Coastguard Worker EGLint pbufferAttributes[] = {
35*8975f5c5SAndroid Build Coastguard Worker EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE, EGL_NONE,
36*8975f5c5SAndroid Build Coastguard Worker };
37*8975f5c5SAndroid Build Coastguard Worker
38*8975f5c5SAndroid Build Coastguard Worker std::vector<EGLSurface> surfaces(threadCount);
39*8975f5c5SAndroid Build Coastguard Worker std::vector<EGLContext> contexts(threadCount);
40*8975f5c5SAndroid Build Coastguard Worker
41*8975f5c5SAndroid Build Coastguard Worker // Create N surfaces and shared contexts, one for each thread
42*8975f5c5SAndroid Build Coastguard Worker for (size_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker surfaces[threadIndex] = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
45*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(eglGetError(), EGL_SUCCESS);
46*8975f5c5SAndroid Build Coastguard Worker EGLint extraAttributes[] = {EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE,
47*8975f5c5SAndroid Build Coastguard Worker static_cast<EGLint>(threadIndex), EGL_NONE};
48*8975f5c5SAndroid Build Coastguard Worker if (!IsEGLDisplayExtensionEnabled(dpy, "EGL_ANGLE_context_virtualization"))
49*8975f5c5SAndroid Build Coastguard Worker {
50*8975f5c5SAndroid Build Coastguard Worker extraAttributes[0] = EGL_NONE;
51*8975f5c5SAndroid Build Coastguard Worker }
52*8975f5c5SAndroid Build Coastguard Worker contexts[threadIndex] =
53*8975f5c5SAndroid Build Coastguard Worker window->createContext(threadIndex == 0 ? EGL_NO_CONTEXT : contexts[0], extraAttributes);
54*8975f5c5SAndroid Build Coastguard Worker EXPECT_NE(EGL_NO_CONTEXT, contexts[threadIndex]) << threadIndex;
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker std::vector<std::thread> threads(threadCount);
58*8975f5c5SAndroid Build Coastguard Worker
59*8975f5c5SAndroid Build Coastguard Worker // Run the threads
60*8975f5c5SAndroid Build Coastguard Worker for (size_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker threads[threadIndex] = std::thread(std::move(threadFuncs[threadIndex]), dpy,
63*8975f5c5SAndroid Build Coastguard Worker surfaces[threadIndex], contexts[threadIndex]);
64*8975f5c5SAndroid Build Coastguard Worker }
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker // Wait for them to finish
67*8975f5c5SAndroid Build Coastguard Worker for (size_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
68*8975f5c5SAndroid Build Coastguard Worker {
69*8975f5c5SAndroid Build Coastguard Worker threads[threadIndex].join();
70*8975f5c5SAndroid Build Coastguard Worker
71*8975f5c5SAndroid Build Coastguard Worker // Clean up
72*8975f5c5SAndroid Build Coastguard Worker eglDestroySurface(dpy, surfaces[threadIndex]);
73*8975f5c5SAndroid Build Coastguard Worker eglDestroyContext(dpy, contexts[threadIndex]);
74*8975f5c5SAndroid Build Coastguard Worker }
75*8975f5c5SAndroid Build Coastguard Worker }
76*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
77