diff --git a/Makefile b/Makefile index f60cf98..4bdc3b5 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,8 @@ DEMO = \ texture.o \ rendertarget.o \ raymarcher.o \ - bloom.o + bloom.o \ + profiling.o DEMO_DEPS = $(DEMO:%.o=.%.d) diff --git a/bloom.cc b/bloom.cc index 6159d8e..7c86933 100644 --- a/bloom.cc +++ b/bloom.cc @@ -3,6 +3,14 @@ #include "texture.hh" #include "rendertarget.hh" #include "bloom.hh" +#include "profiling.hh" + +namespace { + static const std::string Name_( "BLOOOOM!" ); +} + +#define PSTART() T_Profiler::Profiler.start( Name_ ) +#define PEND() do { glFinish( ); T_Profiler::Profiler.end( Name_ ); } while ( 0 ) T_BloomPass::T_BloomPass( @@ -44,6 +52,8 @@ T_BloomPass::T_BloomPass( void T_BloomPass::render( ) { + PSTART( ); + if ( spHighpass_.activate( ) ) { enum { U_TEXTURE = 0 , @@ -117,6 +127,8 @@ void T_BloomPass::render( ) glRectf( -1, -1 , 1 , 1 ); glBindTexture( GL_TEXTURE_2D , 0 ); } + + PEND( ); } void T_BloomPass::makeUI( ) diff --git a/externals.hh b/externals.hh index 1e4f849..678f39b 100644 --- a/externals.hh +++ b/externals.hh @@ -18,6 +18,7 @@ #include #include #include +#include // ImGui #include diff --git a/main.cc b/main.cc index acb7a30..681e469 100644 --- a/main.cc +++ b/main.cc @@ -6,6 +6,7 @@ #include "rendertarget.hh" #include "bloom.hh" #include "raymarcher.hh" +#include "profiling.hh" /*= T_Main ===================================================================*/ @@ -71,13 +72,24 @@ T_Main::T_Main( ) void T_Main::mainLoop( ) { + T_Profiler::Profiler.clear( ); while ( !done ) { + T_Profiler::Profiler.start( "Full frame" ); startIteration( ); if ( !done ) { handleCapture( ); makeUI( ); watcher.check( ); render( ); + T_Profiler::Profiler.end( "Full frame" ); + SDL_GL_SwapWindow( window ); + + auto const& p( T_Profiler::Profiler ); + const auto n( p.sections( ) ); + for ( auto i = 0u ; i < n ; i ++ ) { + printf( "%s: %fms\n" , p.nameOf( i ).c_str( ) , + p.resultOf( i ) ); + } } } } @@ -164,12 +176,13 @@ void T_Main::makeUI( ) void T_Main::render( ) { + T_Profiler::Profiler.start( "Effects" ); raymarcher->render( ); bloomPass->render( ); + glFinish( ); T_Profiler::Profiler.end( "Effects" ); glUseProgram( 0 ); ImGui::Render( ); - SDL_GL_SwapWindow( window ); } diff --git a/profiling.cc b/profiling.cc new file mode 100644 index 0000000..e42df8a --- /dev/null +++ b/profiling.cc @@ -0,0 +1,90 @@ +#include "externals.hh" +#include "utilities.hh" +#include "profiling.hh" + +#include +#include + + +T_Profiler T_Profiler::Profiler; + + +void T_Profiler::clear( ) +{ + sections_.clear( ); + samples_.clear( ); + starts_.clear( ); +} + +void T_Profiler::startFrame( ) +{ +} + +void T_Profiler::start( + __rd__ std::string const& section ) +{ + const auto n( sections_.size( ) ); + const auto pos( find( section ) ); + if ( pos == n ) { + sections_.push_back( section ); + samples_.push_back( T_SamplesList_{ } ); + starts_.push_back( 0u ); + } + + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC , &ts ); + starts_[ pos ] = ts.tv_sec * 1000000000 + ts.tv_nsec; +} + +void T_Profiler::end( + __rd__ std::string const& section ) +{ + const auto pos( find( section ) ); + const auto n( sections_.size( ) ); + if ( pos == n ) { + return; + } + + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC , &ts ); + + const uint64_t ended = ts.tv_sec * 1000000000 + ts.tv_nsec; + const uint64_t duration = ended - starts_[ pos ]; + auto& samples( samples_[ pos ] ); + if ( samples.size( ) == 0 || ( samples.size( ) < History + && samples[ 0 ].nSamples == Samples ) ) { + samples.insert( samples.begin( ) , T_ProfilerSamples{ 0 , 0 } ); + } else if ( samples.size( ) == History && samples[ 0 ].nSamples == Samples ) { + for ( auto i = 1u ; i < History ; i ++ ) { + samples[ i ] = samples[ i - 1 ]; + } + samples[ 0 ].sum = 0; + samples[ 0 ].nSamples = 0; + } + samples[ 0 ].sum += float( duration ) * 1e-6; + samples[ 0 ].nSamples ++; +} + +float T_Profiler::resultOf( + __rd__ const uint32_t section ) const +{ + auto const& samples( samples_[ section ] ); + float total = 0; + float nSamples = 0; + for ( auto const& entry : samples ) { + total += entry.sum; + nSamples += entry.nSamples; + } + return total / nSamples; +} + +uint32_t T_Profiler::find( + __rd__ std::string const& section ) const +{ + const auto n( sections_.size( ) ); + auto pos( 0u ); + while ( pos < n && sections_[ pos ] != section ) { + pos ++; + } + return pos; +} diff --git a/profiling.hh b/profiling.hh new file mode 100644 index 0000000..313e3db --- /dev/null +++ b/profiling.hh @@ -0,0 +1,47 @@ +#pragma once +#ifndef REAL_BUILD +# define REAL_BUILD +# include "externals.hh" +# include "utilities.hh" +# undef REAL_BUILD +#endif + + +struct T_ProfilerSamples +{ + float sum; + uint32_t nSamples; +}; + + +struct T_Profiler +{ + static constexpr uint32_t Samples = 4; + static constexpr uint32_t History = 4; + static T_Profiler Profiler; + + void clear( ); + + void startFrame( ); + void start( __rd__ std::string const& section ); + void end( __rd__ std::string const& section ); + + uint32_t sections( ) const noexcept + { return sections_.size( ); } + + std::string const& nameOf( + __rd__ const uint32_t section ) const + { return sections_[ section ]; } + + float resultOf( __rd__ const uint32_t section ) const; + + private: + using T_SamplesList_ = std::vector< T_ProfilerSamples >; + using T_Data_ = std::vector< T_SamplesList_ >; + + uint32_t find( __rd__ std::string const& section ) const; + + std::vector< std::string > sections_; + T_Data_ samples_; + std::vector< uint64_t > starts_; +}; diff --git a/raymarcher.cc b/raymarcher.cc index a6a6653..0ab310d 100644 --- a/raymarcher.cc +++ b/raymarcher.cc @@ -3,7 +3,14 @@ #include "texture.hh" #include "rendertarget.hh" #include "raymarcher.hh" +#include "profiling.hh" +namespace { + static const std::string Name_( "Raymarcher" ); +} + +#define PSTART() T_Profiler::Profiler.start( Name_ ) +#define PEND() do { glFinish( ); T_Profiler::Profiler.end( Name_ ); } while ( 0 ) T_Raymarcher::T_Raymarcher( __rw__ T_FilesWatcher& watcher , @@ -22,9 +29,12 @@ T_Raymarcher::T_Raymarcher( void T_Raymarcher::render( ) { + PSTART( ); if ( !( program_.activate( ) && rtOutput_.activate( ) ) ) { + PEND( ); return; } + glClearColor( 0 , 1 , 1 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); enum { @@ -52,6 +62,8 @@ void T_Raymarcher::render( ) rmEpsilon , rmMaxDist ); glRectf( -1, -1 , 1 , 1 ); + + PEND( ); } void T_Raymarcher::makeUI( )