Home | History | Annotate | Download | only in stress
      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 Occlusion query stress tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3sOcclusionQueryTests.hpp"
     25 
     26 #include "deRandom.hpp"
     27 #include "deStringUtil.hpp"
     28 #include "deString.h"
     29 #include "tcuTestLog.hpp"
     30 #include "tcuVector.hpp"
     31 #include "tcuSurface.hpp"
     32 #include "gluShaderProgram.hpp"
     33 #include "deClock.h"
     34 
     35 #include "glw.h"
     36 
     37 #include <vector>
     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 tcu::Vec4	OCCLUDER_COLOR			= tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
     50 static const tcu::Vec4	TARGET_COLOR			= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
     51 static const int		NUM_CASE_ITERATIONS		= 3;
     52 static const int		NUM_GENERATED_VERTICES	= 100;
     53 static const int		WATCHDOG_INTERVAL		= 50; // Touch watchdog every N iterations.
     54 
     55 class OcclusionQueryStressCase : public TestCase
     56 {
     57 public:
     58 								OcclusionQueryStressCase		(Context& ctx, const char* name, const char* desc, int m_numOccluderDraws, int m_numOccludersPerDraw, int m_numTargetDraws, int m_numTargetsPerDraw, int m_numQueries, deUint32 m_queryMode);
     59 								~OcclusionQueryStressCase		(void);
     60 
     61 	void						init							(void);
     62 	void						deinit							(void);
     63 	IterateResult				iterate							(void);
     64 
     65 private:
     66 								OcclusionQueryStressCase		(const OcclusionQueryStressCase&);
     67 	OcclusionQueryStressCase&	operator=						(const OcclusionQueryStressCase&);
     68 
     69 	int							m_numOccluderDraws;
     70 	int							m_numOccludersPerDraw;
     71 	int							m_numTargetDraws;
     72 	int							m_numTargetsPerDraw;
     73 	int							m_numQueries;
     74 	deUint32					m_queryMode;
     75 
     76 	glu::RenderContext&			m_renderCtx;
     77 	glu::ShaderProgram*			m_program;
     78 	int							m_iterNdx;
     79 	de::Random					m_rnd;
     80 
     81 };
     82 
     83 OcclusionQueryStressCase::OcclusionQueryStressCase (Context& ctx, const char* name, const char* desc, int numOccluderDraws, int numOccludersPerDraw, int numTargetDraws, int numTargetsPerDraw, int numQueries, deUint32 queryMode)
     84 	: TestCase				(ctx, name, desc)
     85 	, m_numOccluderDraws	(numOccluderDraws)
     86 	, m_numOccludersPerDraw	(numOccludersPerDraw)
     87 	, m_numTargetDraws		(numTargetDraws)
     88 	, m_numTargetsPerDraw	(numTargetsPerDraw)
     89 	, m_numQueries			(numQueries)
     90 	, m_queryMode			(queryMode)
     91 	, m_renderCtx			(ctx.getRenderContext())
     92 	, m_program				(DE_NULL)
     93 	, m_iterNdx				(0)
     94 	, m_rnd					(deStringHash(name))
     95 {
     96 }
     97 
     98 OcclusionQueryStressCase::~OcclusionQueryStressCase (void)
     99 {
    100 	OcclusionQueryStressCase::deinit();
    101 }
    102 
    103 void OcclusionQueryStressCase::init (void)
    104 {
    105 	const char*	vertShaderSource =
    106 				"#version 300 es\n"
    107 				"layout(location = 0) in mediump vec4 a_position;\n"
    108 				"\n"
    109 				"void main (void)\n"
    110 				"{\n"
    111 				"	gl_Position = a_position;\n"
    112 				"}\n";
    113 
    114 	const char* fragShaderSource =
    115 				"#version 300 es\n"
    116 				"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
    117 				"uniform mediump vec4 u_color;\n"
    118 				"\n"
    119 				"void main (void)\n"
    120 				"{\n"
    121 				"	mediump float depth_gradient = gl_FragCoord.z;\n"
    122 				"	mediump float bias = 0.1;\n"
    123 				"	dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1.0);\n"
    124 				"}\n";
    125 
    126 	DE_ASSERT(!m_program);
    127 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
    128 
    129 	if (!m_program->isOk())
    130 	{
    131 		m_testCtx.getLog() << *m_program;
    132 		TCU_FAIL("Failed to compile shader program");
    133 	}
    134 
    135 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
    136 	GLU_CHECK_MSG ("Case initialization finished");
    137 }
    138 
    139 void OcclusionQueryStressCase::deinit (void)
    140 {
    141 	delete m_program;
    142 	m_program = DE_NULL;
    143 }
    144 
    145 
    146 OcclusionQueryStressCase::IterateResult OcclusionQueryStressCase::iterate (void)
    147 {
    148 	tcu::TestLog&				log				 = m_testCtx.getLog();
    149 	deUint32					colorUnif		 = glGetUniformLocation(m_program->getProgram(), "u_color");
    150 
    151 	std::vector<float>			vertices;
    152 	std::vector<float>			occluderVertices;
    153 	std::vector<float>			targetVertices;
    154 	std::vector<deUint32>		queryIds		 (m_numQueries, 0);
    155 	std::vector<deUint32>		queryResultReady (m_numQueries, 0);
    156 	std::vector<deUint32>		queryResult		 (m_numQueries, 0);
    157 
    158 	std::string					sectionName		("Case iteration " + de::toString(m_iterNdx+1) + "/" + de::toString(NUM_CASE_ITERATIONS));
    159 	tcu::ScopedLogSection		section			(log, sectionName.c_str(), sectionName.c_str());
    160 
    161 	log << tcu::TestLog::Message << "Parameters:\n"
    162 								 << "- Number of occlusion queries: "		 << m_numQueries		<< ".\n"
    163 								 << "- Number of occluder draws per query: " << m_numOccluderDraws	<< ", primitives per draw: " << m_numOccludersPerDraw << ".\n"
    164 								 << "- Number of target draws per query: "	 << m_numTargetDraws	<< ", primitives per draw: " << m_numTargetsPerDraw	  << ".\n"
    165 		<< tcu::TestLog::EndMessage;
    166 
    167 	int numOccluderIndicesPerDraw = 3*m_numOccludersPerDraw;
    168 	int numTargetIndicesPerDraw = 3*m_numTargetsPerDraw;
    169 
    170 	// Generate vertex data
    171 
    172 	vertices.resize(4*NUM_GENERATED_VERTICES);
    173 
    174 	for (int i = 0; i < NUM_GENERATED_VERTICES; i++)
    175 	{
    176 		vertices[4*i    ] = m_rnd.getFloat(-1.0f, 1.0f);
    177 		vertices[4*i + 1] = m_rnd.getFloat(-1.0f, 1.0f);
    178 		vertices[4*i + 2] = m_rnd.getFloat(0.0f, 1.0f);
    179 		vertices[4*i + 3] = 1.0f;
    180 	}
    181 
    182 	// Generate primitives
    183 
    184 	occluderVertices.resize(4*numOccluderIndicesPerDraw * m_numOccluderDraws);
    185 
    186 	for (int i = 0; i < numOccluderIndicesPerDraw * m_numOccluderDraws; i++)
    187 	{
    188 		int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1);
    189 		occluderVertices[4*i    ] = vertices[4*vtxNdx];
    190 		occluderVertices[4*i + 1] = vertices[4*vtxNdx + 1];
    191 		occluderVertices[4*i + 2] = vertices[4*vtxNdx + 2];
    192 		occluderVertices[4*i + 3] = vertices[4*vtxNdx + 3];
    193 	}
    194 
    195 	targetVertices.resize(4*numTargetIndicesPerDraw * m_numTargetDraws);
    196 
    197 	for (int i = 0; i < numTargetIndicesPerDraw * m_numTargetDraws; i++)
    198 	{
    199 		int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1);
    200 		targetVertices[4*i    ] = vertices[4*vtxNdx];
    201 		targetVertices[4*i + 1] = vertices[4*vtxNdx + 1];
    202 		targetVertices[4*i + 2] = vertices[4*vtxNdx + 2];
    203 		targetVertices[4*i + 3] = vertices[4*vtxNdx + 3];
    204 	}
    205 
    206 	TCU_CHECK(m_program);
    207 
    208 	glClearColor				(0.0f, 0.0f, 0.0f, 1.0f);
    209 	glClearDepthf				(1.0f);
    210 	glClear						(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    211 	glEnable					(GL_DEPTH_TEST);
    212 	glUseProgram				(m_program->getProgram());
    213 	glEnableVertexAttribArray	(0);
    214 
    215 	deUint64 time = deGetMicroseconds();
    216 
    217 	for (int queryIter = 0; queryIter < m_numQueries; queryIter++)
    218 	{
    219 		// Draw occluders
    220 
    221 		glUniform4f	(colorUnif, OCCLUDER_COLOR.x(), OCCLUDER_COLOR.y(), OCCLUDER_COLOR.z(), OCCLUDER_COLOR.w());
    222 
    223 		for (int drawIter = 0; drawIter < m_numOccluderDraws; drawIter++)
    224 		{
    225 			glVertexAttribPointer	(0, 4, GL_FLOAT, GL_FALSE, 0, &occluderVertices[drawIter * numOccluderIndicesPerDraw]);
    226 			glDrawArrays			(GL_TRIANGLES, 0, numOccluderIndicesPerDraw);
    227 		}
    228 
    229 		// Begin occlusion query
    230 
    231 		glGenQueries	(1, &queryIds[queryIter]);
    232 		glBeginQuery	(m_queryMode, queryIds[queryIter]);
    233 
    234 		// Draw targets
    235 
    236 		glUniform4f	(colorUnif, TARGET_COLOR.x(), TARGET_COLOR.y(), TARGET_COLOR.z(), TARGET_COLOR.w());
    237 
    238 		for (int drawIter = 0; drawIter < m_numTargetDraws; drawIter++)
    239 		{
    240 			glVertexAttribPointer	(0, 4, GL_FLOAT, GL_FALSE, 0, &targetVertices[drawIter * numTargetIndicesPerDraw]);
    241 			glDrawArrays			(GL_TRIANGLES, 0, numTargetIndicesPerDraw);
    242 		}
    243 
    244 		// End occlusion query
    245 
    246 		glEndQuery		(m_queryMode);
    247 
    248 		if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog())
    249 			qpWatchDog_touch(m_testCtx.getWatchDog());
    250 	}
    251 
    252 	glFinish();
    253 	glDisable(GL_DEPTH_TEST);
    254 
    255 	deUint64 dTime = deGetMicroseconds() - time;
    256 	log << tcu::TestLog::Message << "Total duration: " << dTime/1000 << " ms" << tcu::TestLog::EndMessage;
    257 
    258 	// Get results
    259 
    260 	for (int queryIter = 0; queryIter < m_numQueries; queryIter++)
    261 	{
    262 		glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT_AVAILABLE, &queryResultReady[queryIter]);
    263 
    264 		if (queryResultReady[queryIter] == GL_TRUE)
    265 		{
    266 			glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT, &queryResult[queryIter]);
    267 		}
    268 		else
    269 			TCU_FAIL("Occlusion query failed to return a result after glFinish()");
    270 
    271 		if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog())
    272 			qpWatchDog_touch(m_testCtx.getWatchDog());
    273 	}
    274 
    275 	glDeleteQueries	(m_numQueries, &queryIds[0]);
    276 	GLU_CHECK_MSG	("Occlusion queries finished");
    277 
    278 	log << tcu::TestLog::Message << "Case passed!" << tcu::TestLog::EndMessage;
    279 
    280 	return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
    281 }
    282 
    283 
    284 OcclusionQueryTests::OcclusionQueryTests (Context& testCtx)
    285 	: TestCaseGroup(testCtx, "occlusion_query", "Occlusion query stress tests")
    286 {
    287 }
    288 
    289 OcclusionQueryTests::~OcclusionQueryTests(void)
    290 {
    291 }
    292 
    293 void OcclusionQueryTests::init (void)
    294 {
    295 	addChild(new OcclusionQueryStressCase(m_context, "10_queries_2500_triangles_per_query",		"10_queries_2500_triangles_per_query",	  49, 50, 1, 50, 10,	GL_ANY_SAMPLES_PASSED));
    296 	addChild(new OcclusionQueryStressCase(m_context, "100_queries_2500_triangles_per_query",	"100_queries_2500_triangles_per_query",	  49, 50, 1, 50, 100,	GL_ANY_SAMPLES_PASSED));
    297 	addChild(new OcclusionQueryStressCase(m_context, "1000_queries_500_triangles_per_query",	"1000_queries_500_triangles_per_query",	  49, 10, 1, 10, 1000,	GL_ANY_SAMPLES_PASSED));
    298 	addChild(new OcclusionQueryStressCase(m_context, "10000_queries_20_triangles_per_query",	"10000_queries_20_triangles_per_query",   1,  19, 1, 1,  10000,	GL_ANY_SAMPLES_PASSED));
    299 }
    300 
    301 } // Stress
    302 } // gles3
    303 } // deqp
    304