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