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(nullptr)
87 , m_iterNdx(0)
88 , m_rnd(deStringHash(name))
89 {
90 }
91
~FenceSyncCase(void)92 FenceSyncCase::~FenceSyncCase(void)
93 {
94 FenceSyncCase::deinit();
95 }
96
generateVertices(std::vector<float> & dst,int numPrimitives,de::Random & rnd)97 static void generateVertices(std::vector<float> &dst, int numPrimitives, de::Random &rnd)
98 {
99 int numVertices = 3 * numPrimitives;
100 dst.resize(numVertices * 4);
101
102 for (int i = 0; i < numVertices; i++)
103 {
104 dst[i * 4] = rnd.getFloat(-1.0f, 1.0f); // x
105 dst[i * 4 + 1] = rnd.getFloat(-1.0f, 1.0f); // y
106 dst[i * 4 + 2] = rnd.getFloat(0.0f, 1.0f); // z
107 dst[i * 4 + 3] = 1.0f; // w
108 }
109 }
110
init(void)111 void FenceSyncCase::init(void)
112 {
113 const char *vertShaderSource = "#version 300 es\n"
114 "layout(location = 0) in mediump vec4 a_position;\n"
115 "\n"
116 "void main (void)\n"
117 "{\n"
118 " gl_Position = a_position;\n"
119 "}\n";
120
121 const char *fragShaderSource = "#version 300 es\n"
122 "layout(location = 0) out mediump vec4 o_color;\n"
123 "\n"
124 "void main (void)\n"
125 "{\n"
126 " o_color = vec4(0.25, 0.5, 0.75, 1.0);\n"
127 "}\n";
128
129 DE_ASSERT(!m_program);
130 m_program = new glu::ShaderProgram(m_context.getRenderContext(),
131 glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
132
133 if (!m_program->isOk())
134 {
135 m_testCtx.getLog() << *m_program;
136 TCU_FAIL("Failed to compile shader program");
137 }
138
139 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
140 GLU_CHECK_MSG("Case initialization finished");
141 }
142
deinit(void)143 void FenceSyncCase::deinit(void)
144 {
145 if (m_program)
146 {
147 delete m_program;
148 m_program = nullptr;
149 }
150
151 for (int i = 0; i < (int)m_syncObjects.size(); i++)
152 if (m_syncObjects[i])
153 glDeleteSync(m_syncObjects[i]);
154
155 m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
156 }
157
iterate(void)158 FenceSyncCase::IterateResult FenceSyncCase::iterate(void)
159 {
160 TestLog &log = m_testCtx.getLog();
161 std::vector<float> vertices;
162 bool testOk = true;
163
164 std::string header = "Case iteration " + de::toString(m_iterNdx + 1) + " / " + de::toString(NUM_CASE_ITERATIONS);
165 tcu::ScopedLogSection section(log, header, header);
166
167 enableLogging(true);
168
169 TCU_CHECK(m_program);
170 glUseProgram(m_program->getProgram());
171 glEnable(GL_DEPTH_TEST);
172 glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
173 glClearDepthf(1.0f);
174 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
175
176 // Generate vertices
177
178 glEnableVertexAttribArray(0);
179 generateVertices(vertices, m_numSyncs, m_rnd);
180 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
181 m_syncObjects.resize(m_numSyncs);
182
183 // Perform draws and create sync objects
184
185 enableLogging(false);
186 log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDrawArrays and glFenceSync calls done here."
187 << TestLog::EndMessage;
188
189 for (int i = 0; i < m_numSyncs; i++)
190 {
191 glDrawArrays(GL_TRIANGLES, i * 3, 3);
192 m_syncObjects[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
193 GLU_CHECK_MSG("Sync object created");
194 }
195 enableLogging(true);
196 log << TestLog::Message << "// Draws performed, sync objects created." << TestLog::EndMessage;
197
198 // Wait for sync objects
199
200 m_rnd.shuffle(m_syncObjects.begin(), m_syncObjects.end());
201
202 enableLogging(false);
203 if (m_waitCommand & COMMAND_WAIT_SYNC)
204 log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glWaitSync calls done here."
205 << TestLog::EndMessage;
206 else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
207 log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glClientWaitSync calls done here."
208 << TestLog::EndMessage;
209
210 for (int i = 0; i < m_numSyncs; i++)
211 {
212 GLenum waitValue = 0;
213
214 if (m_waitCommand & COMMAND_WAIT_SYNC)
215 {
216 glWaitSync(m_syncObjects[i], 0, GL_TIMEOUT_IGNORED);
217 GLU_CHECK_MSG("glWaitSync called");
218 }
219 else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
220 {
221 waitValue = glClientWaitSync(m_syncObjects[i], 0, 100);
222 GLU_CHECK_MSG("glClientWaitSync called");
223 switch (waitValue)
224 {
225 case GL_ALREADY_SIGNALED:
226 break;
227 case GL_TIMEOUT_EXPIRED:
228 break;
229 case GL_CONDITION_SATISFIED:
230 break;
231 case GL_WAIT_FAILED:
232 log << TestLog::Message << "// glClientWaitSync returned GL_WAIT_FAILED" << TestLog::EndMessage;
233 testOk = false;
234 break;
235 default:
236 TCU_FAIL("glClientWaitSync returned an unknown return value.");
237 }
238 }
239 }
240 enableLogging(true);
241
242 glFinish();
243
244 // Delete sync objects
245
246 enableLogging(false);
247 log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDeleteSync calls done here."
248 << TestLog::EndMessage;
249
250 for (int i = 0; i < (int)m_syncObjects.size(); i++)
251 {
252 if (m_syncObjects[i])
253 {
254 glDeleteSync(m_syncObjects[i]);
255 GLU_CHECK_MSG("Sync object deleted");
256 }
257 }
258
259 enableLogging(true);
260
261 m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
262
263 // Evaluate test result
264
265 log << TestLog::Message << "// Test result: " << (testOk ? "Passed!" : "Failed!") << TestLog::EndMessage;
266
267 if (!testOk)
268 {
269 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
270 return STOP;
271 }
272
273 log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage;
274
275 return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
276 }
277
SyncTests(Context & context)278 SyncTests::SyncTests(Context &context) : TestCaseGroup(context, "fence_sync", "Fence Sync Tests")
279 {
280 }
281
~SyncTests(void)282 SyncTests::~SyncTests(void)
283 {
284 }
285
init(void)286 void SyncTests::init(void)
287 {
288 // Fence sync stress tests.
289
290 addChild(new FenceSyncCase(m_context, "wait_sync_10_syncs", "", 10, COMMAND_WAIT_SYNC));
291 addChild(new FenceSyncCase(m_context, "wait_sync_1000_syncs", "", 1000, COMMAND_WAIT_SYNC));
292 addChild(new FenceSyncCase(m_context, "wait_sync_10000_syncs", "", 10000, COMMAND_WAIT_SYNC));
293
294 addChild(new FenceSyncCase(m_context, "client_wait_sync_10_syncs", "", 10, COMMAND_CLIENT_WAIT_SYNC));
295 addChild(new FenceSyncCase(m_context, "client_wait_sync_1000_syncs", "", 1000, COMMAND_CLIENT_WAIT_SYNC));
296 addChild(new FenceSyncCase(m_context, "client_wait_sync_10000_syncs", "", 10000, COMMAND_CLIENT_WAIT_SYNC));
297 }
298
299 } // namespace Stress
300 } // namespace gles3
301 } // namespace deqp
302