xref: /aosp_15_r20/external/deqp/modules/gles3/stress/es3sSyncTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Sync stress tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3sSyncTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 #include "deRandom.hpp"
28 #include "tcuVector.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluCallLogWrapper.hpp"
31 #include "gluRenderContext.hpp"
32 #include "deStringUtil.hpp"
33 #include "deString.h"
34 
35 #include <vector>
36 
37 #include "glw.h"
38 
39 using std::vector;
40 using tcu::TestLog;
41 
42 namespace deqp
43 {
44 namespace gles3
45 {
46 namespace Stress
47 {
48 
49 static const int NUM_CASE_ITERATIONS = 1;
50 
51 enum WaitCommand
52 {
53     COMMAND_WAIT_SYNC        = 1 << 0,
54     COMMAND_CLIENT_WAIT_SYNC = 1 << 1
55 };
56 
57 class FenceSyncCase : public TestCase, public glu::CallLogWrapper
58 {
59 public:
60     FenceSyncCase(Context &context, const char *name, const char *description, int numPrimitives, uint32_t waitCommand);
61     ~FenceSyncCase(void);
62 
63     void init(void);
64     void deinit(void);
65     IterateResult iterate(void);
66 
67 private:
68     FenceSyncCase(const FenceSyncCase &other);
69     FenceSyncCase &operator=(const FenceSyncCase &other);
70 
71     int m_numSyncs;
72     uint32_t m_waitCommand;
73 
74     glu::ShaderProgram *m_program;
75     vector<GLsync> m_syncObjects;
76     int m_iterNdx;
77     de::Random m_rnd;
78 };
79 
FenceSyncCase(Context & context,const char * name,const char * description,int numSyncs,uint32_t waitCommand)80 FenceSyncCase::FenceSyncCase(Context &context, const char *name, const char *description, int numSyncs,
81                              uint32_t waitCommand)
82     : TestCase(context, name, description)
83     , CallLogWrapper(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
84     , m_numSyncs(numSyncs)
85     , m_waitCommand(waitCommand)
86     , m_program(DE_NULL)
87     , m_syncObjects(DE_NULL)
88     , m_iterNdx(0)
89     , m_rnd(deStringHash(name))
90 {
91 }
92 
~FenceSyncCase(void)93 FenceSyncCase::~FenceSyncCase(void)
94 {
95     FenceSyncCase::deinit();
96 }
97 
generateVertices(std::vector<float> & dst,int numPrimitives,de::Random & rnd)98 static void generateVertices(std::vector<float> &dst, int numPrimitives, de::Random &rnd)
99 {
100     int numVertices = 3 * numPrimitives;
101     dst.resize(numVertices * 4);
102 
103     for (int i = 0; i < numVertices; i++)
104     {
105         dst[i * 4]     = rnd.getFloat(-1.0f, 1.0f); // x
106         dst[i * 4 + 1] = rnd.getFloat(-1.0f, 1.0f); // y
107         dst[i * 4 + 2] = rnd.getFloat(0.0f, 1.0f);  // z
108         dst[i * 4 + 3] = 1.0f;                      // w
109     }
110 }
111 
init(void)112 void FenceSyncCase::init(void)
113 {
114     const char *vertShaderSource = "#version 300 es\n"
115                                    "layout(location = 0) in mediump vec4 a_position;\n"
116                                    "\n"
117                                    "void main (void)\n"
118                                    "{\n"
119                                    "    gl_Position = a_position;\n"
120                                    "}\n";
121 
122     const char *fragShaderSource = "#version 300 es\n"
123                                    "layout(location = 0) out mediump vec4 o_color;\n"
124                                    "\n"
125                                    "void main (void)\n"
126                                    "{\n"
127                                    "    o_color = vec4(0.25, 0.5, 0.75, 1.0);\n"
128                                    "}\n";
129 
130     DE_ASSERT(!m_program);
131     m_program = new glu::ShaderProgram(m_context.getRenderContext(),
132                                        glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
133 
134     if (!m_program->isOk())
135     {
136         m_testCtx.getLog() << *m_program;
137         TCU_FAIL("Failed to compile shader program");
138     }
139 
140     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
141     GLU_CHECK_MSG("Case initialization finished");
142 }
143 
deinit(void)144 void FenceSyncCase::deinit(void)
145 {
146     if (m_program)
147     {
148         delete m_program;
149         m_program = DE_NULL;
150     }
151 
152     for (int i = 0; i < (int)m_syncObjects.size(); i++)
153         if (m_syncObjects[i])
154             glDeleteSync(m_syncObjects[i]);
155 
156     m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
157 }
158 
iterate(void)159 FenceSyncCase::IterateResult FenceSyncCase::iterate(void)
160 {
161     TestLog &log = m_testCtx.getLog();
162     std::vector<float> vertices;
163     bool testOk = true;
164 
165     std::string header = "Case iteration " + de::toString(m_iterNdx + 1) + " / " + de::toString(NUM_CASE_ITERATIONS);
166     tcu::ScopedLogSection section(log, header, header);
167 
168     enableLogging(true);
169 
170     TCU_CHECK(m_program);
171     glUseProgram(m_program->getProgram());
172     glEnable(GL_DEPTH_TEST);
173     glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
174     glClearDepthf(1.0f);
175     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
176 
177     // Generate vertices
178 
179     glEnableVertexAttribArray(0);
180     generateVertices(vertices, m_numSyncs, m_rnd);
181     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
182     m_syncObjects.resize(m_numSyncs);
183 
184     // Perform draws and create sync objects
185 
186     enableLogging(false);
187     log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDrawArrays and glFenceSync calls done here."
188         << TestLog::EndMessage;
189 
190     for (int i = 0; i < m_numSyncs; i++)
191     {
192         glDrawArrays(GL_TRIANGLES, i * 3, 3);
193         m_syncObjects[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
194         GLU_CHECK_MSG("Sync object created");
195     }
196     enableLogging(true);
197     log << TestLog::Message << "// Draws performed, sync objects created." << TestLog::EndMessage;
198 
199     // Wait for sync objects
200 
201     m_rnd.shuffle(m_syncObjects.begin(), m_syncObjects.end());
202 
203     enableLogging(false);
204     if (m_waitCommand & COMMAND_WAIT_SYNC)
205         log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glWaitSync calls done here."
206             << TestLog::EndMessage;
207     else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
208         log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glClientWaitSync calls done here."
209             << TestLog::EndMessage;
210 
211     for (int i = 0; i < m_numSyncs; i++)
212     {
213         GLenum waitValue = 0;
214 
215         if (m_waitCommand & COMMAND_WAIT_SYNC)
216         {
217             glWaitSync(m_syncObjects[i], 0, GL_TIMEOUT_IGNORED);
218             GLU_CHECK_MSG("glWaitSync called");
219         }
220         else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
221         {
222             waitValue = glClientWaitSync(m_syncObjects[i], 0, 100);
223             GLU_CHECK_MSG("glClientWaitSync called");
224             switch (waitValue)
225             {
226             case GL_ALREADY_SIGNALED:
227                 break;
228             case GL_TIMEOUT_EXPIRED:
229                 break;
230             case GL_CONDITION_SATISFIED:
231                 break;
232             case GL_WAIT_FAILED:
233                 log << TestLog::Message << "// glClientWaitSync returned GL_WAIT_FAILED" << TestLog::EndMessage;
234                 testOk = false;
235                 break;
236             default:
237                 TCU_FAIL("glClientWaitSync returned an unknown return value.");
238             }
239         }
240     }
241     enableLogging(true);
242 
243     glFinish();
244 
245     // Delete sync objects
246 
247     enableLogging(false);
248     log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDeleteSync calls done here."
249         << TestLog::EndMessage;
250 
251     for (int i = 0; i < (int)m_syncObjects.size(); i++)
252     {
253         if (m_syncObjects[i])
254         {
255             glDeleteSync(m_syncObjects[i]);
256             GLU_CHECK_MSG("Sync object deleted");
257         }
258     }
259 
260     enableLogging(true);
261 
262     m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
263 
264     // Evaluate test result
265 
266     log << TestLog::Message << "// Test result: " << (testOk ? "Passed!" : "Failed!") << TestLog::EndMessage;
267 
268     if (!testOk)
269     {
270         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
271         return STOP;
272     }
273 
274     log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage;
275 
276     return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
277 }
278 
SyncTests(Context & context)279 SyncTests::SyncTests(Context &context) : TestCaseGroup(context, "fence_sync", "Fence Sync Tests")
280 {
281 }
282 
~SyncTests(void)283 SyncTests::~SyncTests(void)
284 {
285 }
286 
init(void)287 void SyncTests::init(void)
288 {
289     // Fence sync stress tests.
290 
291     addChild(new FenceSyncCase(m_context, "wait_sync_10_syncs", "", 10, COMMAND_WAIT_SYNC));
292     addChild(new FenceSyncCase(m_context, "wait_sync_1000_syncs", "", 1000, COMMAND_WAIT_SYNC));
293     addChild(new FenceSyncCase(m_context, "wait_sync_10000_syncs", "", 10000, COMMAND_WAIT_SYNC));
294 
295     addChild(new FenceSyncCase(m_context, "client_wait_sync_10_syncs", "", 10, COMMAND_CLIENT_WAIT_SYNC));
296     addChild(new FenceSyncCase(m_context, "client_wait_sync_1000_syncs", "", 1000, COMMAND_CLIENT_WAIT_SYNC));
297     addChild(new FenceSyncCase(m_context, "client_wait_sync_10000_syncs", "", 10000, COMMAND_CLIENT_WAIT_SYNC));
298 }
299 
300 } // namespace Stress
301 } // namespace gles3
302 } // namespace deqp
303