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