diff --git a/base/benchmark.hpp b/base/benchmark.hpp index 9538ead7..b24780c8 100644 --- a/base/benchmark.hpp +++ b/base/benchmark.hpp @@ -17,30 +17,40 @@ namespace vks { class Benchmark { + private: + FILE *stream; public: bool active = false; uint32_t framesPerIteration = 1000; - uint32_t iterations = 10; - std::vector iterationTimes; + uint32_t iterationCount = 10; + //std::vector iterationTimes; + struct Iteration { + std::vector frameTimes; + }; + std::vector iterations; std::string filename = "benchmarkresults.csv"; void run(std::function renderFunc) { active = true; #if defined(_WIN32) AttachConsole(ATTACH_PARENT_PROCESS); - FILE *stream; freopen_s(&stream, "CONOUT$", "w+", stdout); freopen_s(&stream, "CONOUT$", "w+", stderr); #endif - iterationTimes.resize(iterations); - for (uint32_t i = 0; i < iterations; i++) { + // "Warm up" run to get more stable frame rates + for (uint32_t f = 0; f < framesPerIteration; f++) { + renderFunc(); + } + + iterations.resize(iterationCount); + for (uint32_t i = 0; i < iterationCount; i++) { + iterations[i].frameTimes.resize(framesPerIteration); for (uint32_t f = 0; f < framesPerIteration; f++) { auto tStart = std::chrono::high_resolution_clock::now(); renderFunc(); auto tEnd = std::chrono::high_resolution_clock::now(); auto tDiff = std::chrono::duration(tEnd - tStart).count(); - double frameTime = (double)tDiff / 1000.0; - iterationTimes[i] += frameTime; + iterations[i].frameTimes[f] = tDiff; } } } @@ -48,30 +58,42 @@ namespace vks void saveResults(std::string appinfo, std::string deviceinfo) { std::ofstream result(filename, std::ios::out); if (result.is_open()) { + double tMinAll = std::numeric_limits::max(); + double tMaxAll = std::numeric_limits::min(); + double tAvgAll = 0.0; - double tMin = *std::min_element(iterationTimes.begin(), iterationTimes.end()); - double tMax = *std::max_element(iterationTimes.begin(), iterationTimes.end()); - double tAvg = std::accumulate(iterationTimes.begin(), iterationTimes.end(), 0.0) / iterations; - - result << std::fixed << std::setprecision(3); - result << appinfo << std::endl; - result << deviceinfo << std::endl; - result << ",iterations,time(ms),fps" << std::endl;; - for (size_t i = 0; i < iterationTimes.size(); i++) { - result << "," << i << "," << iterationTimes[i] << "," << (framesPerIteration / iterationTimes[i]) << std::endl; + result << std::fixed << std::setprecision(4); + result << "iteration,min(ms),max(ms),avg(ms),min(fps),max(fps),avg(fps)" << std::endl; + uint32_t index = 0; + for (auto iteration : iterations) { + double tMin = *std::min_element(iteration.frameTimes.begin(), iteration.frameTimes.end()); + double tMax = *std::max_element(iteration.frameTimes.begin(), iteration.frameTimes.end()); + double tAvg = std::accumulate(iteration.frameTimes.begin(), iteration.frameTimes.end(), 0.0) / framesPerIteration; + if (tMin < tMinAll) { + tMinAll = tMin; + } + if (tMax > tMaxAll) { + tMaxAll = tMax; + } + tAvgAll += tAvg; + index++; + result << index << "," << tMin << "," << tMax << "," << tAvg << "," << (1000.0 / tMax) << "," << (1000.0 / tMin) << "," << (1000.0 / tAvg) << std::endl; } - result << ",summary" << std::endl; - result << ",,time(ms),fps" << std::endl; - result << ",min," << tMin << "," << (1000.0 / tMin) << std::endl; - result << ",max," << tMax << "," << (1000.0 / tMax) << std::endl; - result << ",avg," << tAvg << "," << (1000.0 / tAvg) << std::endl; + + tAvgAll /= static_cast(iterations.size()); + result << "summary,min(ms),max(ms),avg(ms),min(fps),max(fps),avg(fps)" << std::endl; + result << index << "," << tMinAll << "," << tMaxAll << "," << tAvgAll << "," << (1000.0 / tMaxAll) << "," << (1000.0 / tMinAll) << "," << (1000.0 / tAvgAll) << std::endl; // Output averages to stdout std::cout << std::fixed << std::setprecision(3); - std::cout << "best : " << (1000.0 / tMin) << " fps (" << tMin << " ms)" << std::endl; - std::cout << "worst: " << (1000.0 / tMax) << " fps (" << tMax << " ms)" << std::endl; - std::cout << "avg : " << (1000.0 / tAvg) << " fps (" << tAvg << " ms)" << std::endl; - std::cout << std::flush; + std::cout << "best : " << (1000.0 / tMinAll) << " fps (" << tMinAll << " ms)" << std::endl; + std::cout << "worst: " << (1000.0 / tMaxAll) << " fps (" << tMaxAll << " ms)" << std::endl; + std::cout << "avg : " << (1000.0 / tAvgAll) << " fps (" << tAvgAll << " ms)" << std::endl; + std::cout << std::endl; +#if defined(_WIN32) + fclose(stream); + FreeConsole(); +#endif } } }; diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index cc654e4f..fd3f657c 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -672,7 +672,7 @@ VulkanExampleBase::VulkanExampleBase(bool enableValidation) if (args.size() > i + 2) { char* endptr; uint32_t iterations = strtol(args[i + 2], &endptr, 10); - if (endptr != args[i + 2]) { benchmark.iterations = iterations; }; + if (endptr != args[i + 2]) { benchmark.iterationCount = iterations; }; } } }