Home | History | Annotate | Download | only in functional
      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 
     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 
    104 FenceSyncCase::~FenceSyncCase (void)
    105 {
    106 	FenceSyncCase::deinit();
    107 }
    108 
    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 
    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 
    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 
    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 	log << TestLog::Section(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:					 log << TestLog::EndSection; 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 		log << TestLog::EndSection;
    264 		return STOP;
    265 	}
    266 
    267 	log << TestLog::Message << "// Sync objects created and deleted successfully." << TestLog::EndMessage << TestLog::EndSection;
    268 
    269 	return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
    270 }
    271 
    272 SyncTests::SyncTests (Context& context)
    273 	: TestCaseGroup(context, "fence_sync", "Fence Sync Tests")
    274 {
    275 }
    276 
    277 SyncTests::~SyncTests (void)
    278 {
    279 }
    280 
    281 void SyncTests::init (void)
    282 {
    283 	// Fence sync tests.
    284 
    285 	addChild(new FenceSyncCase(m_context, "wait_sync_smalldraw",	"",	10,		COMMAND_WAIT_SYNC,	0, GL_TIMEOUT_IGNORED,	0));
    286 	addChild(new FenceSyncCase(m_context, "wait_sync_largedraw",	"",	100000,	COMMAND_WAIT_SYNC,	0, GL_TIMEOUT_IGNORED,	0));
    287 
    288 	addChild(new FenceSyncCase(m_context, "client_wait_sync_smalldraw",			"",	10,		COMMAND_CLIENT_WAIT_SYNC,	0, 0,	0));
    289 	addChild(new FenceSyncCase(m_context, "client_wait_sync_largedraw",			"",	100000,	COMMAND_CLIENT_WAIT_SYNC,	0, 0,	0));
    290 	addChild(new FenceSyncCase(m_context, "client_wait_sync_timeout_smalldraw",	"",	10,		COMMAND_CLIENT_WAIT_SYNC,	0, 10,	0));
    291 	addChild(new FenceSyncCase(m_context, "client_wait_sync_timeout_largedraw",	"",	100000,	COMMAND_CLIENT_WAIT_SYNC,	0, 10,	0));
    292 
    293 	addChild(new FenceSyncCase(m_context, "client_wait_sync_flush_auto",	"",	100000, COMMAND_CLIENT_WAIT_SYNC,	GL_SYNC_FLUSH_COMMANDS_BIT, 0,	0));
    294 	addChild(new FenceSyncCase(m_context, "client_wait_sync_flush_manual",	"",	100000, COMMAND_CLIENT_WAIT_SYNC,	0,							0,	CASE_FLUSH_BEFORE_WAIT));
    295 	addChild(new FenceSyncCase(m_context, "client_wait_sync_noflush",		"",	100000, COMMAND_CLIENT_WAIT_SYNC,	0,							0,	0));
    296 	addChild(new FenceSyncCase(m_context, "client_wait_sync_finish",		"",	100000, COMMAND_CLIENT_WAIT_SYNC,	0,							0,	CASE_FINISH_BEFORE_WAIT));
    297 }
    298 
    299 } // Functional
    300 } // gles3
    301 } // deqp
    302