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 tcu::TestLog;
40 using std::vector;
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, deUint32 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 deUint32 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,deUint32 waitCommand)80 FenceSyncCase::FenceSyncCase (Context& context, const char* name, const char* description, int numSyncs, deUint32 waitCommand)
81 : TestCase (context, name, description)
82 , CallLogWrapper (context.getRenderContext().getFunctions(), context.getTestContext().getLog())
83 , m_numSyncs (numSyncs)
84 , m_waitCommand (waitCommand)
85 , m_program (DE_NULL)
86 , m_syncObjects (DE_NULL)
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 =
114 "#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 =
123 "#version 300 es\n"
124 "layout(location = 0) out mediump vec4 o_color;\n"
125 "\n"
126 "void main (void)\n"
127 "{\n"
128 " o_color = vec4(0.25, 0.5, 0.75, 1.0);\n"
129 "}\n";
130
131 DE_ASSERT(!m_program);
132 m_program = new glu::ShaderProgram(m_context.getRenderContext(), 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." << 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." << TestLog::EndMessage;
205 else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
206 log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glClientWaitSync calls done here." << TestLog::EndMessage;
207
208 for (int i = 0; i < m_numSyncs; i++)
209 {
210 GLenum waitValue = 0;
211
212 if (m_waitCommand & COMMAND_WAIT_SYNC)
213 {
214 glWaitSync(m_syncObjects[i], 0, GL_TIMEOUT_IGNORED);
215 GLU_CHECK_MSG("glWaitSync called");
216 }
217 else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
218 {
219 waitValue = glClientWaitSync(m_syncObjects[i], 0, 100);
220 GLU_CHECK_MSG("glClientWaitSync called");
221 switch (waitValue)
222 {
223 case GL_ALREADY_SIGNALED: break;
224 case GL_TIMEOUT_EXPIRED: break;
225 case GL_CONDITION_SATISFIED: break;
226 case GL_WAIT_FAILED: log << TestLog::Message << "// glClientWaitSync returned GL_WAIT_FAILED" << TestLog::EndMessage; testOk = false; break;
227 default: TCU_FAIL("glClientWaitSync returned an unknown return value.");
228 }
229 }
230 }
231 enableLogging(true);
232
233 glFinish();
234
235 // Delete sync objects
236
237 enableLogging(false);
238 log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDeleteSync calls done here." << TestLog::EndMessage;
239
240 for (int i = 0; i < (int)m_syncObjects.size(); i++)
241 {
242 if (m_syncObjects[i])
243 {
244 glDeleteSync(m_syncObjects[i]);
245 GLU_CHECK_MSG("Sync object deleted");
246 }
247 }
248
249 enableLogging(true);
250
251 m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
252
253 // Evaluate test result
254
255 log << TestLog::Message << "// Test result: " << (testOk ? "Passed!" : "Failed!") << TestLog::EndMessage;
256
257 if (!testOk)
258 {
259 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
260 return STOP;
261 }
262
263 log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage;
264
265 return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
266 }
267
SyncTests(Context & context)268 SyncTests::SyncTests (Context& context)
269 : TestCaseGroup(context, "fence_sync", "Fence Sync Tests")
270 {
271 }
272
~SyncTests(void)273 SyncTests::~SyncTests (void)
274 {
275 }
276
init(void)277 void SyncTests::init (void)
278 {
279 // Fence sync stress tests.
280
281 addChild(new FenceSyncCase(m_context, "wait_sync_10_syncs", "", 10, COMMAND_WAIT_SYNC));
282 addChild(new FenceSyncCase(m_context, "wait_sync_1000_syncs", "", 1000, COMMAND_WAIT_SYNC));
283 addChild(new FenceSyncCase(m_context, "wait_sync_10000_syncs", "", 10000, COMMAND_WAIT_SYNC));
284
285 addChild(new FenceSyncCase(m_context, "client_wait_sync_10_syncs", "", 10, COMMAND_CLIENT_WAIT_SYNC));
286 addChild(new FenceSyncCase(m_context, "client_wait_sync_1000_syncs", "", 1000, COMMAND_CLIENT_WAIT_SYNC));
287 addChild(new FenceSyncCase(m_context, "client_wait_sync_10000_syncs", "", 10000, COMMAND_CLIENT_WAIT_SYNC));
288 }
289
290 } // Stress
291 } // gles3
292 } // deqp
293