• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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