|
|
|
|
@ -32,6 +32,7 @@
|
|
|
|
|
#include <Corrade/TestSuite/Tester.h> |
|
|
|
|
|
|
|
|
|
#include "Magnum/Renderer.h" |
|
|
|
|
#include "Magnum/TimeQuery.h" |
|
|
|
|
|
|
|
|
|
#ifdef MAGNUM_TARGET_HEADLESS |
|
|
|
|
#include "Magnum/Platform/WindowlessEglApplication.h" |
|
|
|
|
@ -95,9 +96,56 @@ output. While it is possible, the tester class doesn't abort the test cases
|
|
|
|
|
upon encountering a GL error -- this should be done explicitly with |
|
|
|
|
@ref MAGNUM_VERIFY_NO_ERROR() instead, as the debug output is not available on |
|
|
|
|
all platforms and not all GL errors are fatal. |
|
|
|
|
|
|
|
|
|
## GPU time benchmarks |
|
|
|
|
|
|
|
|
|
This class adds @ref BenchmarkType::GpuTime to the benchmark type enum, |
|
|
|
|
allowing you to measure time spent on GPU as opposed to CPU or wall clock time. |
|
|
|
|
*/ |
|
|
|
|
class OpenGLTester: public TestSuite::Tester { |
|
|
|
|
public: |
|
|
|
|
/**
|
|
|
|
|
* @brief Benchmark type |
|
|
|
|
* |
|
|
|
|
* Extends @ref Corrade::TestSuite::Tester::BenchmarkType with GPU |
|
|
|
|
* benchmark types. |
|
|
|
|
* @see @ref addBenchmarks(), @ref addInstancedBenchmarks() |
|
|
|
|
*/ |
|
|
|
|
enum class BenchmarkType { |
|
|
|
|
/**
|
|
|
|
|
* See @ref Corrade::TestSuite::Tester::BenchmarkType::Default for |
|
|
|
|
* details. |
|
|
|
|
*/ |
|
|
|
|
Default = Int(Tester::BenchmarkType::Default), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See @ref Corrade::TestSuite::Tester::BenchmarkType::WallTime for |
|
|
|
|
* details. |
|
|
|
|
*/ |
|
|
|
|
WallTime = Int(Tester::BenchmarkType::WallTime), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See @ref Corrade::TestSuite::Tester::BenchmarkType::CpuTime for |
|
|
|
|
* details. |
|
|
|
|
*/ |
|
|
|
|
CpuTime = Int(Tester::BenchmarkType::CpuTime), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See @ref Corrade::TestSuite::Tester::BenchmarkType::CpuCycles |
|
|
|
|
* for details. |
|
|
|
|
*/ |
|
|
|
|
CpuCycles = Int(Tester::BenchmarkType::CpuCycles), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GPU time, measured using @ref TimeQuery::Target::TimeElapsed. |
|
|
|
|
* Note that the result of the query is retrieved synchronously and |
|
|
|
|
* thus may cause pipeline bubble. Increase number of iterations |
|
|
|
|
* passed to @ref CORRADE_BENCHMARK() to amortize the measurement |
|
|
|
|
* error. |
|
|
|
|
*/ |
|
|
|
|
GpuTime = 32 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Constructor |
|
|
|
|
* |
|
|
|
|
@ -107,7 +155,62 @@ class OpenGLTester: public TestSuite::Tester {
|
|
|
|
|
|
|
|
|
|
~OpenGLTester(); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add benchmarks |
|
|
|
|
* |
|
|
|
|
* Extends @ref Corrade::TestSuite::Tester::addBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, BenchmarkType) with support |
|
|
|
|
* for GPU benchmark types. |
|
|
|
|
*/ |
|
|
|
|
template<class Derived> void addBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, BenchmarkType benchmarkType = BenchmarkType::Default) { |
|
|
|
|
if(benchmarkType == BenchmarkType::GpuTime) |
|
|
|
|
addCustomBenchmarks<Derived>(benchmarks, batchCount, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, BenchmarkUnits::Nanoseconds); |
|
|
|
|
else |
|
|
|
|
Tester::addBenchmarks(benchmarks, batchCount, Tester::BenchmarkType(Int(benchmarkType))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add benchmarks with explicit setup and teardown functions |
|
|
|
|
* |
|
|
|
|
* Extends @ref Corrade::TestSuite::Tester::addBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, void(Derived::*)(), void(Derived::*)(), BenchmarkType) with support |
|
|
|
|
* for GPU benchmark types. |
|
|
|
|
*/ |
|
|
|
|
template<class Derived> void addBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) { |
|
|
|
|
if(benchmarkType == BenchmarkType::GpuTime) |
|
|
|
|
addCustomBenchmarks<Derived>(benchmarks, batchCount, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, setup, teardown, BenchmarkUnits::Nanoseconds); |
|
|
|
|
else |
|
|
|
|
Tester::addBenchmarks(benchmarks, batchCount, setup, teardown, Tester::BenchmarkType(Int(benchmarkType))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add instanced benchmarks |
|
|
|
|
* |
|
|
|
|
* Extends @ref Corrade::TestSuite::Tester::addInstancedBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, std::size_t, BenchmarkType) with support for GPU |
|
|
|
|
* benchmark types. |
|
|
|
|
*/ |
|
|
|
|
template<class Derived> void addInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, BenchmarkType benchmarkType = BenchmarkType::Default) { |
|
|
|
|
if(benchmarkType == BenchmarkType::GpuTime) |
|
|
|
|
addCustomInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, BenchmarkUnits::Nanoseconds); |
|
|
|
|
else |
|
|
|
|
Tester::addInstancedBenchmarks(benchmarks, batchCount, instanceCount, Tester::BenchmarkType(Int(benchmarkType))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Add instanced benchmarks with explicit setup and teardown functions |
|
|
|
|
* |
|
|
|
|
* Extends @ref Corrade::TestSuite::Tester::addInstancedBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, std::size_t, void(Derived::*)(), void(Derived::*)(), BenchmarkType) |
|
|
|
|
* with support for GPU benchmark types. |
|
|
|
|
*/ |
|
|
|
|
template<class Derived> void addInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) { |
|
|
|
|
if(benchmarkType == BenchmarkType::GpuTime) |
|
|
|
|
addCustomInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, setup, teardown, BenchmarkUnits::Nanoseconds); |
|
|
|
|
else |
|
|
|
|
Tester::addInstancedBenchmarks(benchmarks, batchCount, instanceCount, setup, teardown, Tester::BenchmarkType(Int(benchmarkType))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
void gpuTimeBenchmarkBegin(); |
|
|
|
|
std::uint64_t gpuTimeBenchmarkEnd(); |
|
|
|
|
|
|
|
|
|
struct WindowlessApplication: Platform::WindowlessApplication { |
|
|
|
|
explicit WindowlessApplication(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} {} |
|
|
|
|
int exec() override final { return 0; } |
|
|
|
|
@ -116,6 +219,8 @@ class OpenGLTester: public TestSuite::Tester {
|
|
|
|
|
using Platform::WindowlessApplication::createContext; |
|
|
|
|
|
|
|
|
|
} _windowlessApplication; |
|
|
|
|
|
|
|
|
|
TimeQuery _gpuTimeQuery{NoCreate}; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** @hideinitializer
|
|
|
|
|
|