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 Flush and finish tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es3fFlushFinishTests.hpp" 25 26#include "gluRenderContext.hpp" 27#include "gluObjectWrapper.hpp" 28#include "gluShaderProgram.hpp" 29#include "gluDrawUtil.hpp" 30 31#include "glsCalibration.hpp" 32 33#include "tcuTestLog.hpp" 34#include "tcuRenderTarget.hpp" 35#include "tcuCPUWarmup.hpp" 36 37#include "glwEnums.hpp" 38#include "glwFunctions.hpp" 39 40#include "deRandom.hpp" 41#include "deStringUtil.hpp" 42#include "deClock.h" 43#include "deThread.h" 44#include "deMath.h" 45 46#include <algorithm> 47 48namespace deqp 49{ 50namespace gles3 51{ 52namespace Functional 53{ 54 55using std::vector; 56using std::string; 57using tcu::TestLog; 58using tcu::Vec2; 59using deqp::gls::theilSenLinearRegression; 60using deqp::gls::LineParameters; 61 62namespace 63{ 64 65enum 66{ 67 MAX_VIEWPORT_SIZE = 256, 68 MAX_SAMPLE_DURATION_US = 150*1000, 69 WAIT_TIME_MS = 200, 70 MIN_DRAW_CALL_COUNT = 10, 71 MAX_DRAW_CALL_COUNT = 1<<20, 72 MAX_SHADER_ITER_COUNT = 1<<10, 73 NUM_SAMPLES = 50, 74 NUM_VERIFICATION_SAMPLES = 3, 75 MAX_CALIBRATION_ATTEMPTS = 5 76}; 77 78DE_STATIC_ASSERT(MAX_SAMPLE_DURATION_US < 1000*WAIT_TIME_MS); 79 80const float NO_CORR_COEF_THRESHOLD = 0.1f; 81const float FLUSH_COEF_THRESHOLD = 0.2f; 82const float CORRELATED_COEF_THRESHOLD = 0.5f; 83const float CALIBRATION_VERIFICATION_THRESHOLD = 0.10f; // Rendering time needs to be within 10% of MAX_SAMPLE_DURATION_US 84 85static void busyWait (int milliseconds) 86{ 87 const deUint64 startTime = deGetMicroseconds(); 88 float v = 2.0f; 89 90 for (;;) 91 { 92 for (int i = 0; i < 10; i++) 93 v = deFloatSin(v); 94 95 if (deGetMicroseconds()-startTime >= deUint64(1000*milliseconds)) 96 break; 97 } 98} 99 100class CalibrationFailedException : public std::runtime_error 101{ 102public: 103 CalibrationFailedException (const std::string& reason) : std::runtime_error(reason) {} 104}; 105 106class FlushFinishCase : public TestCase 107{ 108public: 109 enum ExpectedBehavior 110 { 111 EXPECT_COEF_LESS_THAN = 0, 112 EXPECT_COEF_GREATER_THAN, 113 }; 114 115 FlushFinishCase (Context& context, 116 const char* name, 117 const char* description, 118 ExpectedBehavior waitBehavior, 119 float waitThreshold, 120 ExpectedBehavior readBehavior, 121 float readThreshold); 122 ~FlushFinishCase (void); 123 124 void init (void); 125 void deinit (void); 126 IterateResult iterate (void); 127 128 struct Sample 129 { 130 int numDrawCalls; 131 deUint64 submitTime; 132 deUint64 waitTime; 133 deUint64 readPixelsTime; 134 }; 135 136 struct CalibrationParams 137 { 138 int numItersInShader; 139 int maxDrawCalls; 140 }; 141 142protected: 143 virtual void waitForGL (void) = 0; 144 145private: 146 FlushFinishCase (const FlushFinishCase&); 147 FlushFinishCase& operator= (const FlushFinishCase&); 148 149 CalibrationParams calibrate (void); 150 void verifyCalibration (const CalibrationParams& params); 151 152 void analyzeResults (const std::vector<Sample>& samples, const CalibrationParams& calibrationParams); 153 154 void setupRenderState (void); 155 void setShaderIterCount (int numIters); 156 void render (int numDrawCalls); 157 void readPixels (void); 158 159 const ExpectedBehavior m_waitBehavior; 160 const float m_waitThreshold; 161 const ExpectedBehavior m_readBehavior; 162 const float m_readThreshold; 163 164 glu::ShaderProgram* m_program; 165 int m_iterCountLoc; 166}; 167 168FlushFinishCase::FlushFinishCase (Context& context, const char* name, const char* description, ExpectedBehavior waitBehavior, float waitThreshold, ExpectedBehavior readBehavior, float readThreshold) 169 : TestCase (context, name, description) 170 , m_waitBehavior (waitBehavior) 171 , m_waitThreshold (waitThreshold) 172 , m_readBehavior (readBehavior) 173 , m_readThreshold (readThreshold) 174 , m_program (DE_NULL) 175 , m_iterCountLoc (0) 176{ 177} 178 179FlushFinishCase::~FlushFinishCase (void) 180{ 181 FlushFinishCase::deinit(); 182} 183 184void FlushFinishCase::init (void) 185{ 186 DE_ASSERT(!m_program); 187 188 m_program = new glu::ShaderProgram(m_context.getRenderContext(), 189 glu::ProgramSources() 190 << glu::VertexSource( 191 "#version 300 es\n" 192 "in highp vec4 a_position;\n" 193 "out highp vec4 v_coord;\n" 194 "void main (void)\n" 195 "{\n" 196 " gl_Position = a_position;\n" 197 " v_coord = a_position;\n" 198 "}\n") 199 << glu::FragmentSource( 200 "#version 300 es\n" 201 "uniform highp int u_numIters;\n" 202 "in highp vec4 v_coord;\n" 203 "out mediump vec4 o_color;\n" 204 "void main (void)\n" 205 "{\n" 206 " highp vec4 color = v_coord;\n" 207 " for (int i = 0; i < u_numIters; i++)\n" 208 " color = sin(color);\n" 209 " o_color = color;\n" 210 "}\n")); 211 212 if (!m_program->isOk()) 213 { 214 m_testCtx.getLog() << *m_program; 215 delete m_program; 216 m_program = DE_NULL; 217 TCU_FAIL("Compile failed"); 218 } 219 220 m_iterCountLoc = m_context.getRenderContext().getFunctions().getUniformLocation(m_program->getProgram(), "u_numIters"); 221 TCU_CHECK(m_iterCountLoc >= 0); 222} 223 224void FlushFinishCase::deinit (void) 225{ 226 delete m_program; 227 m_program = DE_NULL; 228} 229 230tcu::TestLog& operator<< (tcu::TestLog& log, const FlushFinishCase::Sample& sample) 231{ 232 log << TestLog::Message << sample.numDrawCalls << " calls:\t" << sample.submitTime << " us submit,\t" << sample.waitTime << " us wait,\t" << sample.readPixelsTime << " us read" << TestLog::EndMessage; 233 return log; 234} 235 236void FlushFinishCase::setupRenderState (void) 237{ 238 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 239 const int posLoc = gl.getAttribLocation(m_program->getProgram(), "a_position"); 240 const int viewportW = de::min<int>(m_context.getRenderTarget().getWidth(), MAX_VIEWPORT_SIZE); 241 const int viewportH = de::min<int>(m_context.getRenderTarget().getHeight(), MAX_VIEWPORT_SIZE); 242 243 static const float s_positions[] = 244 { 245 -1.0f, -1.0f, 246 +1.0f, -1.0f, 247 -1.0f, +1.0f, 248 +1.0f, +1.0f 249 }; 250 251 TCU_CHECK(posLoc >= 0); 252 253 gl.viewport(0, 0, viewportW, viewportH); 254 gl.useProgram(m_program->getProgram()); 255 gl.enableVertexAttribArray(posLoc); 256 gl.vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, &s_positions[0]); 257 gl.enable(GL_BLEND); 258 gl.blendFunc(GL_ONE, GL_ONE); 259 gl.blendEquation(GL_FUNC_ADD); 260 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up render state"); 261} 262 263void FlushFinishCase::setShaderIterCount (int numIters) 264{ 265 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 266 gl.uniform1i(m_iterCountLoc, numIters); 267} 268 269void FlushFinishCase::render (int numDrawCalls) 270{ 271 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 272 273 const deUint8 indices[] = { 0, 1, 2, 2, 1, 3 }; 274 275 gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 276 277 for (int ndx = 0; ndx < numDrawCalls; ndx++) 278 gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, &indices[0]); 279} 280 281void FlushFinishCase::readPixels (void) 282{ 283 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 284 deUint8 tmp[4]; 285 286 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &tmp); 287} 288 289FlushFinishCase::CalibrationParams FlushFinishCase::calibrate (void) 290{ 291 tcu::ScopedLogSection section (m_testCtx.getLog(), "CalibrationInfo", "Calibration info"); 292 CalibrationParams params; 293 294 // Step 1: find iteration count that results in rougly 1/10th of target maximum sample duration. 295 { 296 const deUint64 targetDurationUs = MAX_SAMPLE_DURATION_US/100; 297 deUint64 prevDuration = 0; 298 int prevIterCount = 1; 299 int curIterCount = 1; 300 301 m_testCtx.getLog() << TestLog::Message << "Calibrating shader iteration count, target duration = " << targetDurationUs << " us" << TestLog::EndMessage; 302 303 for (;;) 304 { 305 deUint64 curDuration; 306 307 setShaderIterCount(curIterCount); 308 render(1); // \note Submit time is ignored 309 310 { 311 const deUint64 startTime = deGetMicroseconds(); 312 readPixels(); 313 curDuration = deGetMicroseconds()-startTime; 314 } 315 316 m_testCtx.getLog() << TestLog::Message << "Duration with " << curIterCount << " iterations = " << curDuration << " us" << TestLog::EndMessage; 317 318 if (curDuration > targetDurationUs) 319 { 320 if (curIterCount > 1) 321 { 322 // Compute final count by using linear estimation. 323 const float a = float(curDuration - prevDuration) / float(curIterCount - prevIterCount); 324 const float b = float(prevDuration) - a*float(prevIterCount); 325 const float est = (float(targetDurationUs) - b) / a; 326 327 curIterCount = de::clamp(deFloorFloatToInt32(est), 1, int(MAX_SHADER_ITER_COUNT)); 328 } 329 // else: Settle on 1. 330 331 break; 332 } 333 else if (curIterCount >= MAX_SHADER_ITER_COUNT) 334 break; // Settle on maximum. 335 else 336 { 337 prevIterCount = curIterCount; 338 prevDuration = curDuration; 339 curIterCount = curIterCount*2; 340 } 341 } 342 343 params.numItersInShader = curIterCount; 344 345 m_testCtx.getLog() << TestLog::Integer("ShaderIterCount", "Shader iteration count", "", QP_KEY_TAG_NONE, params.numItersInShader); 346 } 347 348 // Step 2: Find draw call count that results in desired maximum time. 349 { 350 deUint64 prevDuration = 0; 351 int prevDrawCount = 1; 352 int curDrawCount = 1; 353 354 m_testCtx.getLog() << TestLog::Message << "Calibrating maximum draw call count, target duration = " << int(MAX_SAMPLE_DURATION_US) << " us" << TestLog::EndMessage; 355 356 setShaderIterCount(params.numItersInShader); 357 358 for (;;) 359 { 360 deUint64 curDuration; 361 362 render(curDrawCount); // \note Submit time is ignored 363 364 { 365 const deUint64 startTime = deGetMicroseconds(); 366 readPixels(); 367 curDuration = deGetMicroseconds()-startTime; 368 } 369 370 m_testCtx.getLog() << TestLog::Message << "Duration with " << curDrawCount << " draw calls = " << curDuration << " us" << TestLog::EndMessage; 371 372 if (curDuration > MAX_SAMPLE_DURATION_US) 373 { 374 if (curDrawCount > 1) 375 { 376 // Compute final count by using linear estimation. 377 const float a = float(curDuration - prevDuration) / float(curDrawCount - prevDrawCount); 378 const float b = float(prevDuration) - a*float(prevDrawCount); 379 const float est = (float(MAX_SAMPLE_DURATION_US) - b) / a; 380 381 curDrawCount = de::clamp(deFloorFloatToInt32(est), 1, int(MAX_DRAW_CALL_COUNT)); 382 } 383 // else: Settle on 1. 384 385 break; 386 } 387 else if (curDrawCount >= MAX_DRAW_CALL_COUNT) 388 break; // Settle on maximum. 389 else 390 { 391 prevDrawCount = curDrawCount; 392 prevDuration = curDuration; 393 curDrawCount = curDrawCount*2; 394 } 395 } 396 397 params.maxDrawCalls = curDrawCount; 398 399 m_testCtx.getLog() << TestLog::Integer("MaxDrawCalls", "Maximum number of draw calls", "", QP_KEY_TAG_NONE, params.maxDrawCalls); 400 } 401 402 // Sanity check. 403 if (params.maxDrawCalls < MIN_DRAW_CALL_COUNT) 404 throw CalibrationFailedException("Calibration failed, maximum draw call count is too low"); 405 406 return params; 407} 408 409void FlushFinishCase::verifyCalibration (const CalibrationParams& params) 410{ 411 setShaderIterCount(params.numItersInShader); 412 413 for (int sampleNdx = 0; sampleNdx < NUM_VERIFICATION_SAMPLES; sampleNdx++) 414 { 415 deUint64 readStartTime; 416 417 render(params.maxDrawCalls); 418 419 readStartTime = deGetMicroseconds(); 420 readPixels(); 421 422 { 423 const deUint64 renderDuration = deGetMicroseconds()-readStartTime; 424 const float relativeDelta = float(double(renderDuration) / double(MAX_SAMPLE_DURATION_US)) - 1.0f; 425 426 if (!de::inBounds(relativeDelta, -CALIBRATION_VERIFICATION_THRESHOLD, CALIBRATION_VERIFICATION_THRESHOLD)) 427 { 428 std::ostringstream msg; 429 msg << "ERROR: Unstable performance, got " << renderDuration << " us read time, " 430 << de::floatToString(relativeDelta*100.0f, 1) << "% diff to estimated " << (int)MAX_SAMPLE_DURATION_US << " us"; 431 throw CalibrationFailedException(msg.str()); 432 } 433 } 434 } 435} 436 437struct CompareSampleDrawCount 438{ 439 bool operator() (const FlushFinishCase::Sample& a, const FlushFinishCase::Sample& b) const { return a.numDrawCalls < b.numDrawCalls; } 440}; 441 442std::vector<Vec2> getPointsFromSamples (const std::vector<FlushFinishCase::Sample>& samples, const deUint64 FlushFinishCase::Sample::*field) 443{ 444 vector<Vec2> points(samples.size()); 445 446 for (size_t ndx = 0; ndx < samples.size(); ndx++) 447 points[ndx] = Vec2(float(samples[ndx].numDrawCalls), float(samples[ndx].*field)); 448 449 return points; 450} 451 452template<typename T> 453T getMaximumValue (const std::vector<FlushFinishCase::Sample>& samples, const T FlushFinishCase::Sample::*field) 454{ 455 DE_ASSERT(!samples.empty()); 456 457 T maxVal = samples[0].*field; 458 459 for (size_t ndx = 1; ndx < samples.size(); ndx++) 460 maxVal = de::max(maxVal, samples[ndx].*field); 461 462 return maxVal; 463} 464 465void FlushFinishCase::analyzeResults (const std::vector<Sample>& samples, const CalibrationParams& calibrationParams) 466{ 467 const vector<Vec2> waitTimes = getPointsFromSamples(samples, &Sample::waitTime); 468 const vector<Vec2> readTimes = getPointsFromSamples(samples, &Sample::readPixelsTime); 469 const LineParameters waitLine = theilSenLinearRegression(waitTimes); 470 const LineParameters readLine = theilSenLinearRegression(readTimes); 471 const float normWaitCoef = waitLine.coefficient * float(calibrationParams.maxDrawCalls) / float(MAX_SAMPLE_DURATION_US); 472 const float normReadCoef = readLine.coefficient * float(calibrationParams.maxDrawCalls) / float(MAX_SAMPLE_DURATION_US); 473 bool allOk = true; 474 475 { 476 tcu::ScopedLogSection section (m_testCtx.getLog(), "Samples", "Samples"); 477 vector<Sample> sortedSamples (samples.begin(), samples.end()); 478 479 std::sort(sortedSamples.begin(), sortedSamples.end(), CompareSampleDrawCount()); 480 481 for (vector<Sample>::const_iterator iter = sortedSamples.begin(); iter != sortedSamples.end(); ++iter) 482 m_testCtx.getLog() << *iter; 483 } 484 485 m_testCtx.getLog() << TestLog::Float("WaitCoefficient", "Wait coefficient", "", QP_KEY_TAG_NONE, waitLine.coefficient) 486 << TestLog::Float("ReadCoefficient", "Read coefficient", "", QP_KEY_TAG_NONE, readLine.coefficient) 487 << TestLog::Float("NormalizedWaitCoefficient", "Normalized wait coefficient", "", QP_KEY_TAG_NONE, normWaitCoef) 488 << TestLog::Float("NormalizedReadCoefficient", "Normalized read coefficient", "", QP_KEY_TAG_NONE, normReadCoef); 489 490 { 491 const bool waitCorrelated = normWaitCoef > CORRELATED_COEF_THRESHOLD; 492 const bool readCorrelated = normReadCoef > CORRELATED_COEF_THRESHOLD; 493 const bool waitNotCorr = normWaitCoef < NO_CORR_COEF_THRESHOLD; 494 const bool readNotCorr = normReadCoef < NO_CORR_COEF_THRESHOLD; 495 496 if (waitCorrelated || waitNotCorr) 497 m_testCtx.getLog() << TestLog::Message << "Wait time is" << (waitCorrelated ? "" : " NOT") << " correlated to rendering workload size." << TestLog::EndMessage; 498 else 499 m_testCtx.getLog() << TestLog::Message << "Warning: Wait time correlation to rendering workload size is unclear." << TestLog::EndMessage; 500 501 if (readCorrelated || readNotCorr) 502 m_testCtx.getLog() << TestLog::Message << "Read time is" << (readCorrelated ? "" : " NOT") << " correlated to rendering workload size." << TestLog::EndMessage; 503 else 504 m_testCtx.getLog() << TestLog::Message << "Warning: Read time correlation to rendering workload size is unclear." << TestLog::EndMessage; 505 } 506 507 for (int ndx = 0; ndx < 2; ndx++) 508 { 509 const float coef = ndx == 0 ? normWaitCoef : normReadCoef; 510 const char* name = ndx == 0 ? "wait" : "read"; 511 const ExpectedBehavior behavior = ndx == 0 ? m_waitBehavior : m_readBehavior; 512 const float threshold = ndx == 0 ? m_waitThreshold : m_readThreshold; 513 const bool isOk = behavior == EXPECT_COEF_GREATER_THAN ? coef > threshold : 514 behavior == EXPECT_COEF_LESS_THAN ? coef < threshold : false; 515 const char* cmpName = behavior == EXPECT_COEF_GREATER_THAN ? "greater than" : 516 behavior == EXPECT_COEF_LESS_THAN ? "less than" : DE_NULL; 517 518 if (!isOk) 519 { 520 m_testCtx.getLog() << TestLog::Message << "ERROR: Expected " << name << " coefficient to be " << cmpName << " " << threshold << TestLog::EndMessage; 521 allOk = false; 522 } 523 } 524 525 m_testCtx.setTestResult(allOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 526 allOk ? "Pass" : "Suspicious performance behavior"); 527} 528 529FlushFinishCase::IterateResult FlushFinishCase::iterate (void) 530{ 531 vector<Sample> samples (NUM_SAMPLES); 532 CalibrationParams params; 533 534 tcu::warmupCPU(); 535 536 setupRenderState(); 537 538 // Do one full render cycle. 539 { 540 setShaderIterCount(1); 541 render(1); 542 readPixels(); 543 } 544 545 // Calibrate. 546 for (int calibrationRoundNdx = 0; /* until done */; calibrationRoundNdx++) 547 { 548 try 549 { 550 m_testCtx.touchWatchdog(); 551 params = calibrate(); 552 verifyCalibration(params); 553 break; 554 } 555 catch (const CalibrationFailedException& e) 556 { 557 m_testCtx.getLog() << e; 558 559 if (calibrationRoundNdx < MAX_CALIBRATION_ATTEMPTS) 560 { 561 m_testCtx.getLog() << TestLog::Message 562 << "Retrying calibration (" << (calibrationRoundNdx+1) << " / " << (int)MAX_CALIBRATION_ATTEMPTS << ")" 563 << TestLog::EndMessage; 564 } 565 else 566 { 567 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, e.what()); 568 return STOP; 569 } 570 } 571 } 572 573 // Do measurement. 574 { 575 de::Random rnd (123); 576 577 setShaderIterCount(params.numItersInShader); 578 579 for (size_t ndx = 0; ndx < samples.size(); ndx++) 580 { 581 const int drawCallCount = rnd.getInt(1, params.maxDrawCalls); 582 const deUint64 submitStartTime = deGetMicroseconds(); 583 deUint64 waitStartTime; 584 deUint64 readStartTime; 585 deUint64 readFinishTime; 586 587 render(drawCallCount); 588 589 waitStartTime = deGetMicroseconds(); 590 waitForGL(); 591 592 readStartTime = deGetMicroseconds(); 593 readPixels(); 594 readFinishTime = deGetMicroseconds(); 595 596 samples[ndx].numDrawCalls = drawCallCount; 597 samples[ndx].submitTime = waitStartTime-submitStartTime; 598 samples[ndx].waitTime = readStartTime-waitStartTime; 599 samples[ndx].readPixelsTime = readFinishTime-readStartTime; 600 601 m_testCtx.touchWatchdog(); 602 } 603 } 604 605 // Analyze - sets test case result. 606 analyzeResults(samples, params); 607 608 return STOP; 609} 610 611class WaitOnlyCase : public FlushFinishCase 612{ 613public: 614 WaitOnlyCase (Context& context) 615 : FlushFinishCase(context, "wait", "Wait only", EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD, EXPECT_COEF_GREATER_THAN, -1000.0f /* practically nothing is expected */) 616 { 617 } 618 619 void init (void) 620 { 621 m_testCtx.getLog() << TestLog::Message << int(WAIT_TIME_MS) << " ms busy wait" << TestLog::EndMessage; 622 FlushFinishCase::init(); 623 } 624 625protected: 626 void waitForGL (void) 627 { 628 busyWait(WAIT_TIME_MS); 629 } 630}; 631 632class FlushOnlyCase : public FlushFinishCase 633{ 634public: 635 FlushOnlyCase (Context& context) 636 : FlushFinishCase(context, "flush", "Flush only", EXPECT_COEF_LESS_THAN, FLUSH_COEF_THRESHOLD, EXPECT_COEF_GREATER_THAN, CORRELATED_COEF_THRESHOLD) 637 { 638 } 639 640 void init (void) 641 { 642 m_testCtx.getLog() << TestLog::Message << "Single call to glFlush()" << TestLog::EndMessage; 643 FlushFinishCase::init(); 644 } 645 646protected: 647 void waitForGL (void) 648 { 649 m_context.getRenderContext().getFunctions().flush(); 650 } 651}; 652 653class FlushWaitCase : public FlushFinishCase 654{ 655public: 656 FlushWaitCase (Context& context) 657 : FlushFinishCase(context, "flush_wait", "Wait after flushing", EXPECT_COEF_LESS_THAN, FLUSH_COEF_THRESHOLD, EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD) 658 { 659 } 660 661 void init (void) 662 { 663 m_testCtx.getLog() << TestLog::Message << "glFlush() followed by " << int(WAIT_TIME_MS) << " ms busy wait" << TestLog::EndMessage; 664 FlushFinishCase::init(); 665 } 666 667protected: 668 void waitForGL (void) 669 { 670 m_context.getRenderContext().getFunctions().flush(); 671 busyWait(WAIT_TIME_MS); 672 } 673}; 674 675class FinishOnlyCase : public FlushFinishCase 676{ 677public: 678 FinishOnlyCase (Context& context) 679 : FlushFinishCase(context, "finish", "Finish only", EXPECT_COEF_GREATER_THAN, CORRELATED_COEF_THRESHOLD, EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD) 680 { 681 } 682 683 void init (void) 684 { 685 m_testCtx.getLog() << TestLog::Message << "Single call to glFinish()" << TestLog::EndMessage; 686 FlushFinishCase::init(); 687 } 688 689protected: 690 void waitForGL (void) 691 { 692 m_context.getRenderContext().getFunctions().finish(); 693 } 694}; 695 696class FinishWaitCase : public FlushFinishCase 697{ 698public: 699 FinishWaitCase (Context& context) 700 : FlushFinishCase(context, "finish_wait", "Finish and wait", EXPECT_COEF_GREATER_THAN, CORRELATED_COEF_THRESHOLD, EXPECT_COEF_LESS_THAN, NO_CORR_COEF_THRESHOLD) 701 { 702 } 703 704 void init (void) 705 { 706 m_testCtx.getLog() << TestLog::Message << "glFinish() followed by " << int(WAIT_TIME_MS) << " ms busy wait" << TestLog::EndMessage; 707 FlushFinishCase::init(); 708 } 709 710protected: 711 void waitForGL (void) 712 { 713 m_context.getRenderContext().getFunctions().finish(); 714 busyWait(WAIT_TIME_MS); 715 } 716}; 717 718} // anonymous 719 720FlushFinishTests::FlushFinishTests (Context& context) 721 : TestCaseGroup(context, "flush_finish", "Flush and Finish tests") 722{ 723} 724 725FlushFinishTests::~FlushFinishTests (void) 726{ 727} 728 729void FlushFinishTests::init (void) 730{ 731 addChild(new WaitOnlyCase (m_context)); 732 addChild(new FlushOnlyCase (m_context)); 733 addChild(new FlushWaitCase (m_context)); 734 addChild(new FinishOnlyCase (m_context)); 735 addChild(new FinishWaitCase (m_context)); 736} 737 738} // Functional 739} // gles3 740} // deqp 741