1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL (ES) 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 State change performance tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "glsStateChangePerfTestCases.hpp" 25 26#include "tcuTestLog.hpp" 27 28#include "gluDefs.hpp" 29#include "gluRenderContext.hpp" 30#include "gluShaderProgram.hpp" 31 32#include "glwFunctions.hpp" 33#include "glwEnums.hpp" 34 35#include "deStringUtil.hpp" 36 37#include "deClock.h" 38 39#include <vector> 40#include <algorithm> 41 42using std::vector; 43using std::string; 44using tcu::TestLog; 45using namespace glw; 46 47namespace deqp 48{ 49namespace gls 50{ 51 52namespace 53{ 54 55struct ResultStats 56{ 57 double median; 58 double mean; 59 double variance; 60 61 deUint64 min; 62 deUint64 max; 63}; 64 65ResultStats calculateStats (const vector<deUint64>& values) 66{ 67 ResultStats result = { 0.0, 0.0, 0.0, 0xFFFFFFFFFFFFFFFFu, 0 }; 68 69 deUint64 sum = 0; 70 71 for (int i = 0; i < (int)values.size(); i++) 72 sum += values[i]; 73 74 result.mean = ((double)sum) / (double)values.size(); 75 76 for (int i = 0; i < (int)values.size(); i++) 77 { 78 const double val = (double)values[i]; 79 result.variance += (val - result.mean) * (val - result.mean); 80 } 81 82 result.variance /= (double)values.size(); 83 84 { 85 const int n = (int)(values.size()/2); 86 87 vector<deUint64> sortedValues = values; 88 89 std::sort(sortedValues.begin(), sortedValues.end()); 90 91 result.median = (double)sortedValues[n]; 92 } 93 94 for (int i = 0; i < (int)values.size(); i++) 95 { 96 result.min = std::min(result.min, values[i]); 97 result.max = std::max(result.max, values[i]); 98 } 99 100 return result; 101} 102 103 104void genIndices (vector<GLushort>& indices, int triangleCount) 105{ 106 indices.reserve(triangleCount*3); 107 108 for (int triangleNdx = 0; triangleNdx < triangleCount; triangleNdx++) 109 { 110 indices.push_back((GLushort)(triangleNdx*3)); 111 indices.push_back((GLushort)(triangleNdx*3+1)); 112 indices.push_back((GLushort)(triangleNdx*3+2)); 113 } 114} 115 116void genCoords (vector<GLfloat>& coords, int triangleCount) 117{ 118 coords.reserve(triangleCount * 3 * 2); 119 120 for (int triangleNdx = 0; triangleNdx < triangleCount; triangleNdx++) 121 { 122 if ((triangleNdx % 2) == 0) 123 { 124 // CW 125 coords.push_back(-1.0f); 126 coords.push_back(-1.0f); 127 128 coords.push_back( 1.0f); 129 coords.push_back(-1.0f); 130 131 coords.push_back( 1.0f); 132 coords.push_back( 1.0f); 133 } 134 else 135 { 136 // CCW 137 coords.push_back(-1.0f); 138 coords.push_back(-1.0f); 139 140 coords.push_back(-1.0f); 141 coords.push_back( 1.0f); 142 143 coords.push_back( 1.0f); 144 coords.push_back( 1.0f); 145 } 146 } 147} 148 149void genTextureData (vector<deUint8>& data, int width, int height) 150{ 151 data.clear(); 152 data.reserve(width*height*4); 153 154 for (int x = 0; x < width; x++) 155 { 156 for (int y = 0; y < height; y++) 157 { 158 data.push_back((deUint8)((255*x)/width)); 159 data.push_back((deUint8)((255*y)/width)); 160 data.push_back((deUint8)((255*x*y)/(width*height))); 161 data.push_back(255); 162 } 163 } 164} 165 166double calculateVariance (const vector<deUint64>& values, double avg) 167{ 168 double sum = 0.0; 169 170 for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++) 171 { 172 double value = (double)values[valueNdx]; 173 sum += (value - avg) * (value - avg); 174 } 175 176 return sum / (double)values.size(); 177} 178 179deUint64 findMin (const vector<deUint64>& values) 180{ 181 deUint64 min = ~0ull; 182 183 for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++) 184 min = std::min(values[valueNdx], min); 185 186 return min; 187} 188 189deUint64 findMax (const vector<deUint64>& values) 190{ 191 deUint64 max = 0; 192 193 for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++) 194 max = std::max(values[valueNdx], max); 195 196 return max; 197} 198 199deUint64 findMedian (const vector<deUint64>& v) 200{ 201 vector<deUint64> values = v; 202 size_t n = values.size() / 2; 203 204 std::nth_element(values.begin(), values.begin() + n, values.end()); 205 206 return values[n]; 207} 208 209} // anonymous 210 211StateChangePerformanceCase::StateChangePerformanceCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, DrawType drawType, int drawCallCount, int triangleCount) 212 : tcu::TestCase (testCtx, tcu::NODETYPE_PERFORMANCE, name, description) 213 , m_renderCtx (renderCtx) 214 , m_drawType (drawType) 215 , m_iterationCount (100) 216 , m_callCount (drawCallCount) 217 , m_triangleCount (triangleCount) 218{ 219} 220 221StateChangePerformanceCase::~StateChangePerformanceCase (void) 222{ 223 StateChangePerformanceCase::deinit(); 224} 225 226void StateChangePerformanceCase::init (void) 227{ 228 if (m_drawType == DRAWTYPE_INDEXED_USER_PTR) 229 genIndices(m_indices, m_triangleCount); 230} 231 232void StateChangePerformanceCase::requireIndexBuffers (int count) 233{ 234 const glw::Functions& gl = m_renderCtx.getFunctions(); 235 236 if ((int)m_indexBuffers.size() >= count) 237 return; 238 239 m_indexBuffers.reserve(count); 240 241 vector<GLushort> indices; 242 genIndices(indices, m_triangleCount); 243 244 while ((int)m_indexBuffers.size() < count) 245 { 246 GLuint buffer; 247 248 gl.genBuffers(1, &buffer); 249 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()"); 250 251 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); 252 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); 253 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(indices.size() * sizeof(GLushort)), &(indices[0]), GL_STATIC_DRAW); 254 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()"); 255 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 256 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); 257 258 m_indexBuffers.push_back(buffer); 259 } 260} 261 262void StateChangePerformanceCase::requireCoordBuffers (int count) 263{ 264 const glw::Functions& gl = m_renderCtx.getFunctions(); 265 266 if ((int)m_coordBuffers.size() >= count) 267 return; 268 269 m_coordBuffers.reserve(count); 270 271 vector<GLfloat> coords; 272 genCoords(coords, m_triangleCount); 273 274 while ((int)m_coordBuffers.size() < count) 275 { 276 GLuint buffer; 277 278 gl.genBuffers(1, &buffer); 279 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()"); 280 281 gl.bindBuffer(GL_ARRAY_BUFFER, buffer); 282 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); 283 gl.bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(coords.size() * sizeof(GLfloat)), &(coords[0]), GL_STATIC_DRAW); 284 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()"); 285 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 286 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()"); 287 288 m_coordBuffers.push_back(buffer); 289 } 290} 291 292void StateChangePerformanceCase::requirePrograms (int count) 293{ 294 if ((int)m_programs.size() >= count) 295 return; 296 297 m_programs.reserve(count); 298 299 while ((int)m_programs.size() < count) 300 { 301 string vertexShaderSource = 302 "attribute mediump vec2 a_coord;\n" 303 "varying mediump vec2 v_texCoord;\n" 304 "void main (void)\n" 305 "{\n" 306 "\tv_texCoord = vec2(0.5) + 0.5" + de::toString(m_programs.size()) + " * a_coord.xy;\n" 307 "\tgl_Position = vec4(a_coord, 0.5, 1.0);\n" 308 "}"; 309 310 string fragmentShaderSource = 311 "uniform sampler2D u_sampler;\n" 312 "varying mediump vec2 v_texCoord;\n" 313 "void main (void)\n" 314 "{\n" 315 "\tgl_FragColor = vec4(1.0" + de::toString(m_programs.size()) + " * texture2D(u_sampler, v_texCoord).xyz, 1.0);\n" 316 "}"; 317 318 glu::ShaderProgram* program = new glu::ShaderProgram(m_renderCtx, glu::ProgramSources() << glu::VertexSource(vertexShaderSource) << glu::FragmentSource(fragmentShaderSource)); 319 320 if (!program->isOk()) 321 { 322 m_testCtx.getLog() << *program; 323 delete program; 324 TCU_FAIL("Compile failed"); 325 } 326 327 m_programs.push_back(program); 328 } 329} 330 331void StateChangePerformanceCase::requireTextures (int count) 332{ 333 const glw::Functions& gl = m_renderCtx.getFunctions(); 334 335 const int textureWidth = 64; 336 const int textureHeight = 64; 337 338 if ((int)m_textures.size() >= count) 339 return; 340 341 m_textures.reserve(count); 342 343 vector<deUint8> textureData; 344 genTextureData(textureData, textureWidth, textureHeight); 345 346 DE_ASSERT(textureData.size() == textureWidth * textureHeight * 4); 347 348 while ((int)m_textures.size() < count) 349 { 350 GLuint texture; 351 352 gl.genTextures(1, &texture); 353 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures()"); 354 355 gl.bindTexture(GL_TEXTURE_2D, texture); 356 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()"); 357 358 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(textureData[0])); 359 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D()"); 360 361 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 362 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()"); 363 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 364 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()"); 365 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 366 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()"); 367 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 368 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri()"); 369 370 gl.bindTexture(GL_TEXTURE_2D, 0); 371 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()"); 372 373 m_textures.push_back(texture); 374 } 375} 376 377void StateChangePerformanceCase::requireFramebuffers (int count) 378{ 379 const glw::Functions& gl = m_renderCtx.getFunctions(); 380 381 if ((int)m_framebuffers.size() >= count) 382 return; 383 384 m_framebuffers.reserve(count); 385 386 requireRenderbuffers(count); 387 388 while ((int)m_framebuffers.size() < count) 389 { 390 GLuint framebuffer; 391 392 gl.genFramebuffers(1, &framebuffer); 393 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers()"); 394 395 gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer); 396 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer()"); 397 398 gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffers[m_framebuffers.size()]); 399 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()"); 400 401 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffers[m_framebuffers.size()]); 402 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer()"); 403 404 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 405 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()"); 406 407 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 408 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer()"); 409 410 m_framebuffers.push_back(framebuffer); 411 } 412} 413 414void StateChangePerformanceCase::requireRenderbuffers (int count) 415{ 416 const glw::Functions& gl = m_renderCtx.getFunctions(); 417 418 if ((int)m_renderbuffers.size() >= count) 419 return; 420 421 m_renderbuffers.reserve(count); 422 423 while ((int)m_renderbuffers.size() < count) 424 { 425 GLuint renderbuffer; 426 427 gl.genRenderbuffers(1, &renderbuffer); 428 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers()"); 429 430 gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 431 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()"); 432 433 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 24, 24); 434 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage()"); 435 436 gl.bindRenderbuffer(GL_RENDERBUFFER, 0); 437 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer()"); 438 439 m_renderbuffers.push_back(renderbuffer); 440 } 441} 442 443void StateChangePerformanceCase::requireSamplers (int count) 444{ 445 const glw::Functions& gl = m_renderCtx.getFunctions(); 446 447 if ((int)m_samplers.size() >= count) 448 return; 449 450 m_samplers.reserve(count); 451 452 while ((int)m_samplers.size() < count) 453 { 454 GLuint sampler; 455 gl.genSamplers(1, &sampler); 456 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenSamplers()"); 457 m_samplers.push_back(sampler); 458 } 459} 460 461void StateChangePerformanceCase::requireVertexArrays (int count) 462{ 463 const glw::Functions& gl = m_renderCtx.getFunctions(); 464 465 if ((int)m_vertexArrays.size() >= count) 466 return; 467 468 m_vertexArrays.reserve(count); 469 470 while ((int)m_vertexArrays.size() < count) 471 { 472 GLuint vertexArray; 473 gl.genVertexArrays(1, &vertexArray); 474 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays()"); 475 m_vertexArrays.push_back(vertexArray); 476 } 477} 478 479void StateChangePerformanceCase::deinit (void) 480{ 481 m_indices.clear(); 482 m_interleavedResults.clear(); 483 m_batchedResults.clear(); 484 485 { 486 const glw::Functions& gl = m_renderCtx.getFunctions(); 487 488 if (!m_indexBuffers.empty()) 489 { 490 gl.deleteBuffers((GLsizei)m_indexBuffers.size(), &(m_indexBuffers[0])); 491 m_indexBuffers.clear(); 492 } 493 494 if (!m_coordBuffers.empty()) 495 { 496 gl.deleteBuffers((GLsizei)m_coordBuffers.size(), &(m_coordBuffers[0])); 497 m_coordBuffers.clear(); 498 } 499 500 if (!m_textures.empty()) 501 { 502 gl.deleteTextures((GLsizei)m_textures.size(), &(m_textures[0])); 503 m_textures.clear(); 504 } 505 506 if (!m_framebuffers.empty()) 507 { 508 gl.deleteFramebuffers((GLsizei)m_framebuffers.size(), &(m_framebuffers[0])); 509 m_framebuffers.clear(); 510 } 511 512 if (!m_renderbuffers.empty()) 513 { 514 gl.deleteRenderbuffers((GLsizei)m_renderbuffers.size(), &(m_renderbuffers[0])); 515 m_renderbuffers.clear(); 516 } 517 518 if (!m_samplers.empty()) 519 { 520 gl.deleteSamplers((GLsizei)m_samplers.size(), &m_samplers[0]); 521 m_samplers.clear(); 522 } 523 524 if (!m_vertexArrays.empty()) 525 { 526 gl.deleteVertexArrays((GLsizei)m_vertexArrays.size(), &m_vertexArrays[0]); 527 m_vertexArrays.clear(); 528 } 529 530 for (int programNdx = 0; programNdx < (int)m_programs.size(); programNdx++) 531 { 532 delete m_programs[programNdx]; 533 m_programs[programNdx] = NULL; 534 } 535 m_programs.clear(); 536 } 537} 538 539void StateChangePerformanceCase::logAndSetTestResult (void) 540{ 541 TestLog& log = m_testCtx.getLog(); 542 543 ResultStats interleaved = calculateStats(m_interleavedResults); 544 ResultStats batched = calculateStats(m_batchedResults); 545 546 log << TestLog::Message << "Interleaved mean: " << interleaved.mean << TestLog::EndMessage; 547 log << TestLog::Message << "Interleaved median: " << interleaved.median << TestLog::EndMessage; 548 log << TestLog::Message << "Interleaved variance: " << interleaved.variance << TestLog::EndMessage; 549 log << TestLog::Message << "Interleaved min: " << interleaved.min << TestLog::EndMessage; 550 log << TestLog::Message << "Interleaved max: " << interleaved.max << TestLog::EndMessage; 551 552 log << TestLog::Message << "Batched mean: " << batched.mean << TestLog::EndMessage; 553 log << TestLog::Message << "Batched median: " << batched.median << TestLog::EndMessage; 554 log << TestLog::Message << "Batched variance: " << batched.variance << TestLog::EndMessage; 555 log << TestLog::Message << "Batched min: " << batched.min << TestLog::EndMessage; 556 log << TestLog::Message << "Batched max: " << batched.max << TestLog::EndMessage; 557 558 log << TestLog::Message << "Batched/Interleaved mean ratio: " << (interleaved.mean/batched.mean) << TestLog::EndMessage; 559 log << TestLog::Message << "Batched/Interleaved median ratio: " << (interleaved.median/batched.median) << TestLog::EndMessage; 560 561 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)(((double)interleaved.median) / batched.median), 2).c_str()); 562} 563 564tcu::TestCase::IterateResult StateChangePerformanceCase::iterate (void) 565{ 566 if (m_interleavedResults.empty() && m_batchedResults.empty()) 567 { 568 TestLog& log = m_testCtx.getLog(); 569 570 log << TestLog::Message << "Draw call count: " << m_callCount << TestLog::EndMessage; 571 log << TestLog::Message << "Per call triangle count: " << m_triangleCount << TestLog::EndMessage; 572 } 573 574 // \note [mika] Interleave sampling to balance effects of powerstate etc. 575 if ((int)m_interleavedResults.size() < m_iterationCount && m_batchedResults.size() >= m_interleavedResults.size()) 576 { 577 const glw::Functions& gl = m_renderCtx.getFunctions(); 578 deUint64 resBeginUs = 0; 579 deUint64 resEndUs = 0; 580 581 setupInitialState(gl); 582 gl.finish(); 583 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()"); 584 585 // Render result 586 resBeginUs = deGetMicroseconds(); 587 588 renderTest(gl); 589 590 gl.finish(); 591 resEndUs = deGetMicroseconds(); 592 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()"); 593 594 m_interleavedResults.push_back(resEndUs - resBeginUs); 595 596 return CONTINUE; 597 } 598 else if ((int)m_batchedResults.size() < m_iterationCount) 599 { 600 const glw::Functions& gl = m_renderCtx.getFunctions(); 601 deUint64 refBeginUs = 0; 602 deUint64 refEndUs = 0; 603 604 setupInitialState(gl); 605 gl.finish(); 606 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()"); 607 608 // Render reference 609 refBeginUs = deGetMicroseconds(); 610 611 renderReference(gl); 612 613 gl.finish(); 614 refEndUs = deGetMicroseconds(); 615 GLU_EXPECT_NO_ERROR(gl.getError(), "glFinish()"); 616 617 m_batchedResults.push_back(refEndUs - refBeginUs); 618 619 return CONTINUE; 620 } 621 else 622 { 623 logAndSetTestResult(); 624 return STOP; 625 } 626} 627 628void StateChangePerformanceCase::callDraw (const glw::Functions& gl) 629{ 630 switch (m_drawType) 631 { 632 case DRAWTYPE_NOT_INDEXED: gl.drawArrays(GL_TRIANGLES, 0, m_triangleCount * 3); break; 633 case DRAWTYPE_INDEXED_USER_PTR: gl.drawElements(GL_TRIANGLES, m_triangleCount * 3, GL_UNSIGNED_SHORT, &m_indices[0]); break; 634 case DRAWTYPE_INDEXED_BUFFER: gl.drawElements(GL_TRIANGLES, m_triangleCount * 3, GL_UNSIGNED_SHORT, NULL); break; 635 default: 636 DE_ASSERT(false); 637 } 638} 639 640// StateChangeCallPerformanceCase 641 642StateChangeCallPerformanceCase::StateChangeCallPerformanceCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description) 643 : tcu::TestCase (testCtx, tcu::NODETYPE_PERFORMANCE, name, description) 644 , m_renderCtx (renderCtx) 645 , m_iterationCount (100) 646 , m_callCount (1000) 647{ 648} 649 650StateChangeCallPerformanceCase::~StateChangeCallPerformanceCase (void) 651{ 652} 653 654void StateChangeCallPerformanceCase::executeTest (void) 655{ 656 const glw::Functions& gl = m_renderCtx.getFunctions(); 657 deUint64 beginTimeUs = 0; 658 deUint64 endTimeUs = 0; 659 660 beginTimeUs = deGetMicroseconds(); 661 662 execCalls(gl, (int)m_results.size(), m_callCount); 663 664 endTimeUs = deGetMicroseconds(); 665 666 m_results.push_back(endTimeUs - beginTimeUs); 667} 668 669void StateChangeCallPerformanceCase::logTestCase (void) 670{ 671 TestLog& log = m_testCtx.getLog(); 672 673 log << TestLog::Message << "Iteration count: " << m_iterationCount << TestLog::EndMessage; 674 log << TestLog::Message << "Per iteration call count: " << m_callCount << TestLog::EndMessage; 675} 676 677double calculateAverage (const vector<deUint64>& values) 678{ 679 deUint64 sum = 0; 680 681 for (int valueNdx = 0; valueNdx < (int)values.size(); valueNdx++) 682 sum += values[valueNdx]; 683 684 return ((double)sum) / (double)values.size(); 685} 686 687void StateChangeCallPerformanceCase::logAndSetTestResult (void) 688{ 689 TestLog& log = m_testCtx.getLog(); 690 691 deUint64 minUs = findMin(m_results); 692 deUint64 maxUs = findMax(m_results); 693 deUint64 medianUs = findMedian(m_results); 694 double avgIterationUs = calculateAverage(m_results); 695 double avgCallUs = avgIterationUs / m_callCount; 696 double varIteration = calculateVariance(m_results, avgIterationUs); 697 double avgMedianCallUs = ((double)medianUs)/m_callCount; 698 699 log << TestLog::Message << "Min iteration time: " << minUs << "us" << TestLog::EndMessage; 700 log << TestLog::Message << "Max iteration time: " << maxUs << "us" << TestLog::EndMessage; 701 log << TestLog::Message << "Average iteration time: " << avgIterationUs << "us" << TestLog::EndMessage; 702 log << TestLog::Message << "Iteration variance time: " << varIteration << TestLog::EndMessage; 703 log << TestLog::Message << "Median iteration time: " << medianUs << "us" << TestLog::EndMessage; 704 log << TestLog::Message << "Average call time: " << avgCallUs << "us" << TestLog::EndMessage; 705 log << TestLog::Message << "Average call time for median iteration: " << avgMedianCallUs << "us" << TestLog::EndMessage; 706 707 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)avgMedianCallUs, 3).c_str()); 708} 709 710tcu::TestCase::IterateResult StateChangeCallPerformanceCase::iterate (void) 711{ 712 if (m_results.empty()) 713 logTestCase(); 714 715 if ((int)m_results.size() < m_iterationCount) 716 { 717 executeTest(); 718 GLU_EXPECT_NO_ERROR(m_renderCtx.getFunctions().getError(), "Unexpected error"); 719 return CONTINUE; 720 } 721 else 722 { 723 logAndSetTestResult(); 724 return STOP; 725 } 726} 727 728} // gls 729} // deqp 730