1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Sync stress tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es3sSyncTests.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
27e5c31af7Sopenharmony_ci#include "deRandom.hpp"
28e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
29e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
30e5c31af7Sopenharmony_ci#include "gluCallLogWrapper.hpp"
31e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp"
32e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
33e5c31af7Sopenharmony_ci#include "deString.h"
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci#include <vector>
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include "glw.h"
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ciusing tcu::TestLog;
40e5c31af7Sopenharmony_ciusing std::vector;
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_cinamespace deqp
43e5c31af7Sopenharmony_ci{
44e5c31af7Sopenharmony_cinamespace gles3
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_cinamespace Stress
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cistatic const int NUM_CASE_ITERATIONS = 1;
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_cienum WaitCommand
52e5c31af7Sopenharmony_ci{
53e5c31af7Sopenharmony_ci	COMMAND_WAIT_SYNC			= 1 << 0,
54e5c31af7Sopenharmony_ci	COMMAND_CLIENT_WAIT_SYNC	= 1 << 1
55e5c31af7Sopenharmony_ci};
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ciclass FenceSyncCase : public TestCase, public glu::CallLogWrapper
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_cipublic:
60e5c31af7Sopenharmony_ci						FenceSyncCase		(Context& context, const char* name, const char* description, int numPrimitives, deUint32 waitCommand);
61e5c31af7Sopenharmony_ci						~FenceSyncCase		(void);
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci	void				init				(void);
64e5c31af7Sopenharmony_ci	void				deinit				(void);
65e5c31af7Sopenharmony_ci	IterateResult		iterate				(void);
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ciprivate:
68e5c31af7Sopenharmony_ci						FenceSyncCase		(const FenceSyncCase& other);
69e5c31af7Sopenharmony_ci	FenceSyncCase&		operator=			(const FenceSyncCase& other);
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci	int					m_numSyncs;
72e5c31af7Sopenharmony_ci	deUint32			m_waitCommand;
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ci	glu::ShaderProgram*	m_program;
75e5c31af7Sopenharmony_ci	vector<GLsync>		m_syncObjects;
76e5c31af7Sopenharmony_ci	int					m_iterNdx;
77e5c31af7Sopenharmony_ci	de::Random			m_rnd;
78e5c31af7Sopenharmony_ci};
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ciFenceSyncCase::FenceSyncCase (Context& context, const char* name, const char* description, int numSyncs, deUint32 waitCommand)
81e5c31af7Sopenharmony_ci	: TestCase			(context, name, description)
82e5c31af7Sopenharmony_ci	, CallLogWrapper	(context.getRenderContext().getFunctions(), context.getTestContext().getLog())
83e5c31af7Sopenharmony_ci	, m_numSyncs		(numSyncs)
84e5c31af7Sopenharmony_ci	, m_waitCommand		(waitCommand)
85e5c31af7Sopenharmony_ci	, m_program			(DE_NULL)
86e5c31af7Sopenharmony_ci	, m_syncObjects		(DE_NULL)
87e5c31af7Sopenharmony_ci	, m_iterNdx			(0)
88e5c31af7Sopenharmony_ci	, m_rnd				(deStringHash(name))
89e5c31af7Sopenharmony_ci{
90e5c31af7Sopenharmony_ci}
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ciFenceSyncCase::~FenceSyncCase (void)
93e5c31af7Sopenharmony_ci{
94e5c31af7Sopenharmony_ci	FenceSyncCase::deinit();
95e5c31af7Sopenharmony_ci}
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_cistatic void generateVertices (std::vector<float>& dst, int numPrimitives, de::Random& rnd)
98e5c31af7Sopenharmony_ci{
99e5c31af7Sopenharmony_ci	int numVertices = 3*numPrimitives;
100e5c31af7Sopenharmony_ci	dst.resize(numVertices * 4);
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci	for (int i = 0; i < numVertices; i++)
103e5c31af7Sopenharmony_ci	{
104e5c31af7Sopenharmony_ci		dst[i*4    ] = rnd.getFloat(-1.0f, 1.0f);	// x
105e5c31af7Sopenharmony_ci		dst[i*4 + 1] = rnd.getFloat(-1.0f, 1.0f);	// y
106e5c31af7Sopenharmony_ci		dst[i*4 + 2] = rnd.getFloat( 0.0f, 1.0f);	// z
107e5c31af7Sopenharmony_ci		dst[i*4 + 3] = 1.0f;						// w
108e5c31af7Sopenharmony_ci	}
109e5c31af7Sopenharmony_ci}
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_civoid FenceSyncCase::init (void)
112e5c31af7Sopenharmony_ci{
113e5c31af7Sopenharmony_ci	const char*	vertShaderSource =
114e5c31af7Sopenharmony_ci				"#version 300 es\n"
115e5c31af7Sopenharmony_ci				"layout(location = 0) in mediump vec4 a_position;\n"
116e5c31af7Sopenharmony_ci				"\n"
117e5c31af7Sopenharmony_ci				"void main (void)\n"
118e5c31af7Sopenharmony_ci				"{\n"
119e5c31af7Sopenharmony_ci				"	gl_Position = a_position;\n"
120e5c31af7Sopenharmony_ci				"}\n";
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_ci	const char* fragShaderSource =
123e5c31af7Sopenharmony_ci				"#version 300 es\n"
124e5c31af7Sopenharmony_ci				"layout(location = 0) out mediump vec4 o_color;\n"
125e5c31af7Sopenharmony_ci				"\n"
126e5c31af7Sopenharmony_ci				"void main (void)\n"
127e5c31af7Sopenharmony_ci				"{\n"
128e5c31af7Sopenharmony_ci				"	o_color = vec4(0.25, 0.5, 0.75, 1.0);\n"
129e5c31af7Sopenharmony_ci				"}\n";
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	DE_ASSERT(!m_program);
132e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	if (!m_program->isOk())
135e5c31af7Sopenharmony_ci	{
136e5c31af7Sopenharmony_ci		m_testCtx.getLog() << *m_program;
137e5c31af7Sopenharmony_ci		TCU_FAIL("Failed to compile shader program");
138e5c31af7Sopenharmony_ci	}
139e5c31af7Sopenharmony_ci
140e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
141e5c31af7Sopenharmony_ci	GLU_CHECK_MSG ("Case initialization finished");
142e5c31af7Sopenharmony_ci}
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_civoid FenceSyncCase::deinit (void)
145e5c31af7Sopenharmony_ci{
146e5c31af7Sopenharmony_ci	if (m_program)
147e5c31af7Sopenharmony_ci	{
148e5c31af7Sopenharmony_ci		delete m_program;
149e5c31af7Sopenharmony_ci		m_program = DE_NULL;
150e5c31af7Sopenharmony_ci	}
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)m_syncObjects.size(); i++)
153e5c31af7Sopenharmony_ci		if (m_syncObjects[i])
154e5c31af7Sopenharmony_ci			glDeleteSync(m_syncObjects[i]);
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
157e5c31af7Sopenharmony_ci}
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ciFenceSyncCase::IterateResult FenceSyncCase::iterate (void)
160e5c31af7Sopenharmony_ci{
161e5c31af7Sopenharmony_ci	TestLog&				log		= m_testCtx.getLog();
162e5c31af7Sopenharmony_ci	std::vector<float>		vertices;
163e5c31af7Sopenharmony_ci	bool					testOk	= true;
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci	std::string				header	= "Case iteration " + de::toString(m_iterNdx+1) + " / " + de::toString(NUM_CASE_ITERATIONS);
166e5c31af7Sopenharmony_ci	tcu::ScopedLogSection	section	(log, header, header);
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_ci	enableLogging(true);
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ci	TCU_CHECK		(m_program);
171e5c31af7Sopenharmony_ci	glUseProgram	(m_program->getProgram());
172e5c31af7Sopenharmony_ci	glEnable		(GL_DEPTH_TEST);
173e5c31af7Sopenharmony_ci	glClearColor	(0.3f, 0.3f, 0.3f, 1.0f);
174e5c31af7Sopenharmony_ci	glClearDepthf	(1.0f);
175e5c31af7Sopenharmony_ci	glClear			(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci	// Generate vertices
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci	glEnableVertexAttribArray	(0);
180e5c31af7Sopenharmony_ci	generateVertices			(vertices, m_numSyncs, m_rnd);
181e5c31af7Sopenharmony_ci	glVertexAttribPointer		(0, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
182e5c31af7Sopenharmony_ci	m_syncObjects.resize		(m_numSyncs);
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	// Perform draws and create sync objects
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci	enableLogging(false);
187e5c31af7Sopenharmony_ci	log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDrawArrays and glFenceSync calls done here." << TestLog::EndMessage;
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci	for (int i = 0; i < m_numSyncs; i++)
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		glDrawArrays(GL_TRIANGLES, i*3, 3);
192e5c31af7Sopenharmony_ci		m_syncObjects[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
193e5c31af7Sopenharmony_ci		GLU_CHECK_MSG("Sync object created");
194e5c31af7Sopenharmony_ci	}
195e5c31af7Sopenharmony_ci	enableLogging(true);
196e5c31af7Sopenharmony_ci	log << TestLog::Message << "// Draws performed, sync objects created." << TestLog::EndMessage;
197e5c31af7Sopenharmony_ci
198e5c31af7Sopenharmony_ci	// Wait for sync objects
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	m_rnd.shuffle(m_syncObjects.begin(), m_syncObjects.end());
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ci	enableLogging(false);
203e5c31af7Sopenharmony_ci	if (m_waitCommand & COMMAND_WAIT_SYNC)
204e5c31af7Sopenharmony_ci		log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glWaitSync calls done here." << TestLog::EndMessage;
205e5c31af7Sopenharmony_ci	else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
206e5c31af7Sopenharmony_ci		log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glClientWaitSync calls done here." << TestLog::EndMessage;
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_ci	for (int i = 0; i < m_numSyncs; i++)
209e5c31af7Sopenharmony_ci	{
210e5c31af7Sopenharmony_ci		GLenum waitValue = 0;
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci		if (m_waitCommand & COMMAND_WAIT_SYNC)
213e5c31af7Sopenharmony_ci		{
214e5c31af7Sopenharmony_ci			glWaitSync(m_syncObjects[i], 0, GL_TIMEOUT_IGNORED);
215e5c31af7Sopenharmony_ci			GLU_CHECK_MSG("glWaitSync called");
216e5c31af7Sopenharmony_ci		}
217e5c31af7Sopenharmony_ci		else if (m_waitCommand & COMMAND_CLIENT_WAIT_SYNC)
218e5c31af7Sopenharmony_ci		{
219e5c31af7Sopenharmony_ci			waitValue = glClientWaitSync(m_syncObjects[i], 0, 100);
220e5c31af7Sopenharmony_ci			GLU_CHECK_MSG("glClientWaitSync called");
221e5c31af7Sopenharmony_ci			switch (waitValue)
222e5c31af7Sopenharmony_ci			{
223e5c31af7Sopenharmony_ci				case GL_ALREADY_SIGNALED:	 break;
224e5c31af7Sopenharmony_ci				case GL_TIMEOUT_EXPIRED:	 break;
225e5c31af7Sopenharmony_ci				case GL_CONDITION_SATISFIED: break;
226e5c31af7Sopenharmony_ci				case GL_WAIT_FAILED:		 log << TestLog::Message << "// glClientWaitSync returned GL_WAIT_FAILED"	<< TestLog::EndMessage; testOk = false; break;
227e5c31af7Sopenharmony_ci				default:					 TCU_FAIL("glClientWaitSync returned an unknown return value.");
228e5c31af7Sopenharmony_ci			}
229e5c31af7Sopenharmony_ci		}
230e5c31af7Sopenharmony_ci	}
231e5c31af7Sopenharmony_ci	enableLogging(true);
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci	glFinish();
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci	// Delete sync objects
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci	enableLogging(false);
238e5c31af7Sopenharmony_ci	log << TestLog::Message << "// NOT LOGGED: " << m_numSyncs << " glDeleteSync calls done here." << TestLog::EndMessage;
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)m_syncObjects.size(); i++)
241e5c31af7Sopenharmony_ci	{
242e5c31af7Sopenharmony_ci		if (m_syncObjects[i])
243e5c31af7Sopenharmony_ci		{
244e5c31af7Sopenharmony_ci			glDeleteSync(m_syncObjects[i]);
245e5c31af7Sopenharmony_ci			GLU_CHECK_MSG("Sync object deleted");
246e5c31af7Sopenharmony_ci		}
247e5c31af7Sopenharmony_ci	}
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_ci	enableLogging(true);
250e5c31af7Sopenharmony_ci
251e5c31af7Sopenharmony_ci	m_syncObjects.erase(m_syncObjects.begin(), m_syncObjects.end());
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	// Evaluate test result
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci	log << TestLog::Message << "// Test result: " << (testOk ? "Passed!" : "Failed!") << TestLog::EndMessage;
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci	if (!testOk)
258e5c31af7Sopenharmony_ci	{
259e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
260e5c31af7Sopenharmony_ci		return STOP;
261e5c31af7Sopenharmony_ci	}
262e5c31af7Sopenharmony_ci
263e5c31af7Sopenharmony_ci	log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage;
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci	return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
266e5c31af7Sopenharmony_ci}
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ciSyncTests::SyncTests (Context& context)
269e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "fence_sync", "Fence Sync Tests")
270e5c31af7Sopenharmony_ci{
271e5c31af7Sopenharmony_ci}
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ciSyncTests::~SyncTests (void)
274e5c31af7Sopenharmony_ci{
275e5c31af7Sopenharmony_ci}
276e5c31af7Sopenharmony_ci
277e5c31af7Sopenharmony_civoid SyncTests::init (void)
278e5c31af7Sopenharmony_ci{
279e5c31af7Sopenharmony_ci	// Fence sync stress tests.
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci	addChild(new FenceSyncCase(m_context, "wait_sync_10_syncs",				"",	10,		COMMAND_WAIT_SYNC));
282e5c31af7Sopenharmony_ci	addChild(new FenceSyncCase(m_context, "wait_sync_1000_syncs",			"",	1000,	COMMAND_WAIT_SYNC));
283e5c31af7Sopenharmony_ci	addChild(new FenceSyncCase(m_context, "wait_sync_10000_syncs",			"",	10000,	COMMAND_WAIT_SYNC));
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci	addChild(new FenceSyncCase(m_context, "client_wait_sync_10_syncs",		"",	10,		COMMAND_CLIENT_WAIT_SYNC));
286e5c31af7Sopenharmony_ci	addChild(new FenceSyncCase(m_context, "client_wait_sync_1000_syncs",	"",	1000,	COMMAND_CLIENT_WAIT_SYNC));
287e5c31af7Sopenharmony_ci	addChild(new FenceSyncCase(m_context, "client_wait_sync_10000_syncs",	"",	10000,	COMMAND_CLIENT_WAIT_SYNC));
288e5c31af7Sopenharmony_ci}
289e5c31af7Sopenharmony_ci
290e5c31af7Sopenharmony_ci} // Stress
291e5c31af7Sopenharmony_ci} // gles3
292e5c31af7Sopenharmony_ci} // deqp
293