xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fSyncTests.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 tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fSyncTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 #include "tcuVector.hpp"
28 #include "gluShaderProgram.hpp"
29 #include "gluCallLogWrapper.hpp"
30 #include "gluRenderContext.hpp"
31 #include "glwEnums.hpp"
32 #include "deRandom.hpp"
33 #include "deStringUtil.hpp"
34 #include "deString.h"
35 
36 #include <vector>
37 
38 using tcu::TestLog;
39 
40 namespace deqp
41 {
42 namespace gles3
43 {
44 namespace Functional
45 {
46 
47 using namespace glw; // GL types
48 
49 static const int NUM_CASE_ITERATIONS = 5;
50 
51 enum WaitCommand
52 {
53     COMMAND_WAIT_SYNC        = 1 << 0,
54     COMMAND_CLIENT_WAIT_SYNC = 1 << 1
55 };
56 
57 enum CaseOptions
58 {
59     CASE_FLUSH_BEFORE_WAIT  = 1 << 0,
60     CASE_FINISH_BEFORE_WAIT = 1 << 1
61 };
62 
63 class FenceSyncCase : public TestCase, private glu::CallLogWrapper
64 {
65 public:
66     FenceSyncCase(Context &context, const char *name, const char *description, int numPrimitives, uint32_t waitCommand,
67                   uint32_t waitFlags, uint64_t timeout, uint32_t options);
68     ~FenceSyncCase(void);
69 
70     void init(void);
71     void deinit(void);
72     IterateResult iterate(void);
73 
74 private:
75     FenceSyncCase(const FenceSyncCase &other);
76     FenceSyncCase &operator=(const FenceSyncCase &other);
77 
78     int m_numPrimitives;
79     uint32_t m_waitCommand;
80     uint32_t m_waitFlags;
81     uint64_t m_timeout;
82     uint32_t m_caseOptions;
83 
84     glu::ShaderProgram *m_program;
85     GLsync m_syncObject;
86     int m_iterNdx;
87     de::Random m_rnd;
88 };
89 
FenceSyncCase(Context & context,const char * name,const char * description,int numPrimitives,uint32_t waitCommand,uint32_t waitFlags,uint64_t timeout,uint32_t options)90 FenceSyncCase::FenceSyncCase(Context &context, const char *name, const char *description, int numPrimitives,
91                              uint32_t waitCommand, uint32_t waitFlags, uint64_t timeout, uint32_t options)
92     : TestCase(context, name, description)
93     , CallLogWrapper(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
94     , m_numPrimitives(numPrimitives)
95     , m_waitCommand(waitCommand)
96     , m_waitFlags(waitFlags)
97     , m_timeout(timeout)
98     , m_caseOptions(options)
99     , m_program(DE_NULL)
100     , m_syncObject(DE_NULL)
101     , m_iterNdx(0)
102     , m_rnd(deStringHash(name))
103 {
104 }
105 
~FenceSyncCase(void)106 FenceSyncCase::~FenceSyncCase(void)
107 {
108     FenceSyncCase::deinit();
109 }
110 
generateVertices(std::vector<float> & dst,int numPrimitives,de::Random & rnd)111 static void generateVertices(std::vector<float> &dst, int numPrimitives, de::Random &rnd)
112 {
113     int numVertices = 3 * numPrimitives;
114     dst.resize(numVertices * 4);
115 
116     for (int i = 0; i < numVertices; i++)
117     {
118         dst[i * 4]     = rnd.getFloat(-1.0f, 1.0f); // x
119         dst[i * 4 + 1] = rnd.getFloat(-1.0f, 1.0f); // y
120         dst[i * 4 + 2] = rnd.getFloat(0.0f, 1.0f);  // z
121         dst[i * 4 + 3] = 1.0f;                      // w
122     }
123 }
124 
init(void)125 void FenceSyncCase::init(void)
126 {
127     const char *vertShaderSource = "#version 300 es\n"
128                                    "layout(location = 0) in mediump vec4 a_position;\n"
129                                    "\n"
130                                    "void main (void)\n"
131                                    "{\n"
132                                    "    gl_Position = a_position;\n"
133                                    "}\n";
134 
135     const char *fragShaderSource = "#version 300 es\n"
136                                    "layout(location = 0) out mediump vec4 o_color;\n"
137                                    "\n"
138                                    "void main (void)\n"
139                                    "{\n"
140                                    "    o_color = vec4(0.25, 0.5, 0.75, 1.0);\n"
141                                    "}\n";
142 
143     DE_ASSERT(!m_program);
144     m_program = new glu::ShaderProgram(m_context.getRenderContext(),
145                                        glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
146 
147     if (!m_program->isOk())
148     {
149         m_testCtx.getLog() << *m_program;
150         TCU_FAIL("Failed to compile shader program");
151     }
152 
153     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
154     GLU_CHECK_MSG("Case initialization finished");
155 }
156 
deinit(void)157 void FenceSyncCase::deinit(void)
158 {
159     if (m_program)
160     {
161         delete m_program;
162         m_program = DE_NULL;
163     }
164 
165     if (m_syncObject)
166     {
167         glDeleteSync(m_syncObject);
168         m_syncObject = DE_NULL;
169     }
170 }
171 
iterate(void)172 FenceSyncCase::IterateResult FenceSyncCase::iterate(void)
173 {
174     TestLog &log = m_testCtx.getLog();
175     std::vector<float> vertices;
176     bool testOk = true;
177 
178     std::string header = "Case iteration " + de::toString(m_iterNdx + 1) + " / " + de::toString(NUM_CASE_ITERATIONS);
179     const tcu::ScopedLogSection section(log, header, header);
180 
181     enableLogging(true);
182 
183     DE_ASSERT(m_program);
184     glUseProgram(m_program->getProgram());
185     glEnable(GL_DEPTH_TEST);
186     glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
187     glClearDepthf(1.0f);
188     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
189 
190     // Generate vertices
191 
192     glEnableVertexAttribArray(0);
193     generateVertices(vertices, m_numPrimitives, m_rnd);
194     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
195 
196     // Draw
197 
198     glDrawArrays(GL_TRIANGLES, 0, (int)vertices.size() / 4);
199     log << TestLog::Message << "// Primitives drawn." << TestLog::EndMessage;
200 
201     // Create sync object
202 
203     m_syncObject = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
204     GLU_CHECK_MSG("Sync object created");
205     log << TestLog::Message << "// Sync object created." << TestLog::EndMessage;
206 
207     if (m_caseOptions & CASE_FLUSH_BEFORE_WAIT)
208         glFlush();
209     if (m_caseOptions & CASE_FINISH_BEFORE_WAIT)
210         glFinish();
211 
212     // Wait for sync object
213 
214     GLenum waitValue = 0;
215 
216     if (m_waitCommand & COMMAND_WAIT_SYNC)
217     {
218         DE_ASSERT(m_timeout == GL_TIMEOUT_IGNORED);
219         DE_ASSERT(m_waitFlags == 0);
220         glWaitSync(m_syncObject, m_waitFlags, m_timeout);
221         GLU_CHECK_MSG("glWaitSync called");
222         log << TestLog::Message << "// Wait command glWaitSync called with GL_TIMEOUT_IGNORED." << TestLog::EndMessage;
223     }
224     if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
225     {
226         waitValue = glClientWaitSync(m_syncObject, m_waitFlags, m_timeout);
227         GLU_CHECK_MSG("glClientWaitSync called");
228         log << TestLog::Message << "// glClientWaitSync return value:" << TestLog::EndMessage;
229         switch (waitValue)
230         {
231         case GL_ALREADY_SIGNALED:
232             log << TestLog::Message << "// GL_ALREADY_SIGNALED" << TestLog::EndMessage;
233             break;
234         case GL_TIMEOUT_EXPIRED:
235             log << TestLog::Message << "// GL_TIMEOUT_EXPIRED" << TestLog::EndMessage;
236             break;
237         case GL_CONDITION_SATISFIED:
238             log << TestLog::Message << "// GL_CONDITION_SATISFIED" << TestLog::EndMessage;
239             break;
240         case GL_WAIT_FAILED:
241             log << TestLog::Message << "// GL_WAIT_FAILED" << TestLog::EndMessage;
242             testOk = false;
243             break;
244         default:
245             TCU_FAIL("// Illegal return value!");
246         }
247     }
248 
249     glFinish();
250 
251     if (m_caseOptions & CASE_FINISH_BEFORE_WAIT && waitValue != GL_ALREADY_SIGNALED)
252     {
253         testOk = false;
254         log << TestLog::Message << "// Expected glClientWaitSync to return GL_ALREADY_SIGNALED." << TestLog::EndMessage;
255     }
256 
257     // Delete sync object
258 
259     if (m_syncObject)
260     {
261         glDeleteSync(m_syncObject);
262         m_syncObject = DE_NULL;
263         GLU_CHECK_MSG("Sync object deleted");
264         log << TestLog::Message << "// Sync object deleted." << TestLog::EndMessage;
265     }
266 
267     // Evaluate test result
268 
269     log << TestLog::Message << "// Test result: " << (testOk ? "Passed!" : "Failed!") << TestLog::EndMessage;
270 
271     if (!testOk)
272     {
273         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
274         return STOP;
275     }
276 
277     log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage;
278 
279     return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
280 }
281 
SyncTests(Context & context)282 SyncTests::SyncTests(Context &context) : TestCaseGroup(context, "fence_sync", "Fence Sync Tests")
283 {
284 }
285 
~SyncTests(void)286 SyncTests::~SyncTests(void)
287 {
288 }
289 
init(void)290 void SyncTests::init(void)
291 {
292     // Fence sync tests.
293 
294     addChild(new FenceSyncCase(m_context, "wait_sync_smalldraw", "", 10, COMMAND_WAIT_SYNC, 0, GL_TIMEOUT_IGNORED, 0));
295     addChild(
296         new FenceSyncCase(m_context, "wait_sync_largedraw", "", 10000, COMMAND_WAIT_SYNC, 0, GL_TIMEOUT_IGNORED, 0));
297 
298     addChild(new FenceSyncCase(m_context, "client_wait_sync_smalldraw", "", 10, COMMAND_CLIENT_WAIT_SYNC, 0, 0, 0));
299     addChild(new FenceSyncCase(m_context, "client_wait_sync_largedraw", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0, 0));
300     addChild(
301         new FenceSyncCase(m_context, "client_wait_sync_timeout_smalldraw", "", 10, COMMAND_CLIENT_WAIT_SYNC, 0, 10, 0));
302     addChild(new FenceSyncCase(m_context, "client_wait_sync_timeout_largedraw", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0,
303                                10, 0));
304 
305     addChild(new FenceSyncCase(m_context, "client_wait_sync_flush_auto", "", 10000, COMMAND_CLIENT_WAIT_SYNC,
306                                GL_SYNC_FLUSH_COMMANDS_BIT, 0, 0));
307     addChild(new FenceSyncCase(m_context, "client_wait_sync_flush_manual", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0,
308                                CASE_FLUSH_BEFORE_WAIT));
309     addChild(new FenceSyncCase(m_context, "client_wait_sync_noflush", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0, 0));
310     addChild(new FenceSyncCase(m_context, "client_wait_sync_finish", "", 10000, COMMAND_CLIENT_WAIT_SYNC, 0, 0,
311                                CASE_FINISH_BEFORE_WAIT));
312 }
313 
314 } // namespace Functional
315 } // namespace gles3
316 } // namespace deqp
317