Commit 2570bf33 authored by David C. Lonie's avatar David C. Lonie

Add vtkOpenGLRenderTimer.

Uses GL_TIMESTAMP queries to provide asynch, nestable GPU timings.
parent c3f96385
Pipeline #27030 passed with stage
...@@ -50,6 +50,7 @@ set(Module_SRCS ...@@ -50,6 +50,7 @@ set(Module_SRCS
vtkOpenGLPolyDataMapper2D.cxx vtkOpenGLPolyDataMapper2D.cxx
vtkOpenGLProperty.cxx vtkOpenGLProperty.cxx
vtkOpenGLRenderPass.cxx vtkOpenGLRenderPass.cxx
vtkOpenGLRenderTimer.cxx
vtkOpenGLRenderUtilities.cxx vtkOpenGLRenderUtilities.cxx
vtkOpenGLRenderWindow.cxx vtkOpenGLRenderWindow.cxx
vtkOpenGLRenderer.cxx vtkOpenGLRenderer.cxx
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "vtkOpenGLBufferObject.h" #include "vtkOpenGLBufferObject.h"
#include "vtkOpenGLError.h" #include "vtkOpenGLError.h"
#include "vtkOpenGLRenderer.h" #include "vtkOpenGLRenderer.h"
#include "vtkOpenGLRenderTimer.h"
#include "vtkOpenGLRenderUtilities.h" #include "vtkOpenGLRenderUtilities.h"
#include "vtkOpenGLRenderWindow.h" #include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLShaderCache.h" #include "vtkOpenGLShaderCache.h"
...@@ -97,21 +98,17 @@ void vtkOpenGLFXAAFilter::Execute(vtkOpenGLRenderer *ren) ...@@ -97,21 +98,17 @@ void vtkOpenGLFXAAFilter::Execute(vtkOpenGLRenderer *ren)
assert(ren); assert(ren);
this->Renderer = ren; this->Renderer = ren;
this->StartTimeQuery(this->PreparationTimeQuery, this->StartTimeQuery(this->PreparationTimer);
this->PreparationTimeQueryActive);
this->Prepare(); this->Prepare();
this->LoadInput(); this->LoadInput();
this->EndTimeQuery(this->PreparationTimer);
this->EndTimeQuery(this->PreparationTimeQuery, this->StartTimeQuery(this->FXAATimer);
this->PreparationTimeQueryActive);
this->StartTimeQuery(this->FXAATimeQuery, this->FXAATimeQueryActive);
this->ApplyFilter(); this->ApplyFilter();
this->EndTimeQuery(this->FXAATimer);
this->EndTimeQuery(this->FXAATimeQuery, this->FXAATimeQueryActive);
this->Finalize(); this->Finalize();
this->PrintBenchmark();
this->Renderer = NULL; this->Renderer = NULL;
} }
...@@ -162,12 +159,8 @@ void vtkOpenGLFXAAFilter::SetDebugOptionValue(vtkFXAAOptions::DebugOption opt) ...@@ -162,12 +159,8 @@ void vtkOpenGLFXAAFilter::SetDebugOptionValue(vtkFXAAOptions::DebugOption opt)
vtkOpenGLFXAAFilter::vtkOpenGLFXAAFilter() vtkOpenGLFXAAFilter::vtkOpenGLFXAAFilter()
: BlendState(false), : BlendState(false),
DepthTestState(false), DepthTestState(false),
PreparationTimeQueryActive(false), PreparationTimer(new vtkOpenGLRenderTimer),
FXAATimeQueryActive(false), FXAATimer(new vtkOpenGLRenderTimer),
PreparationTimeQuery(0),
FXAATimeQuery(0),
PreparationTime(0),
FXAATime(0),
RelativeContrastThreshold(1.f/8.f), RelativeContrastThreshold(1.f/8.f),
HardContrastThreshold(1.f/16.f), HardContrastThreshold(1.f/16.f),
SubpixelBlendLimit(3.f/4.f), SubpixelBlendLimit(3.f/4.f),
...@@ -189,6 +182,8 @@ vtkOpenGLFXAAFilter::vtkOpenGLFXAAFilter() ...@@ -189,6 +182,8 @@ vtkOpenGLFXAAFilter::vtkOpenGLFXAAFilter()
vtkOpenGLFXAAFilter::~vtkOpenGLFXAAFilter() vtkOpenGLFXAAFilter::~vtkOpenGLFXAAFilter()
{ {
this->FreeGLObjects(); this->FreeGLObjects();
delete PreparationTimer;
delete FXAATimer;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -243,17 +238,6 @@ void vtkOpenGLFXAAFilter::FreeGLObjects() ...@@ -243,17 +238,6 @@ void vtkOpenGLFXAAFilter::FreeGLObjects()
// DeleteHelper(this->Program); // Managed by the shader cache // DeleteHelper(this->Program); // Managed by the shader cache
DeleteHelper(this->VAO); DeleteHelper(this->VAO);
DeleteHelper(this->VBO); DeleteHelper(this->VBO);
if (this->FXAATimeQuery > 0)
{
glDeleteQueries(1, &this->FXAATimeQuery);
this->FXAATimeQuery = 0;
}
if (this->PreparationTimeQuery > 0)
{
glDeleteQueries(1, &this->PreparationTimeQuery);
this->PreparationTimeQuery = 0;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -393,116 +377,60 @@ void vtkOpenGLFXAAFilter::Finalize() ...@@ -393,116 +377,60 @@ void vtkOpenGLFXAAFilter::Finalize()
} }
vtkOpenGLCheckErrorMacro("Error after restoring GL state."); vtkOpenGLCheckErrorMacro("Error after restoring GL state.");
#ifdef FXAA_BENCHMARK
if (this->GetTimeQueryResult(this->PreparationTimeQuery,
this->PreparationTime) ||
this->GetTimeQueryResult(this->FXAATimeQuery,
this->FXAATime))
{
this->PrintBenchmark();
}
#endif // FXAA_BENCHMARK
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void vtkOpenGLFXAAFilter::StartTimeQuery(unsigned int &queryId, bool &tracker) void vtkOpenGLFXAAFilter::StartTimeQuery(vtkOpenGLRenderTimer *timer)
{ {
#ifdef FXAA_BENCHMARK // Since it may take a few frames for the results to become available,
// Don't start a new query until the old results are in: // check if we've started the timer already.
if (tracker || queryId != 0) if (!timer->Started())
{ {
return; timer->Start();
}
glGenQueries(1, &queryId);
glBeginQuery(GL_TIME_ELAPSED, queryId);
tracker = true;
vtkOpenGLCheckErrorMacro("Error after starting GL_TIME_ELAPSED query.");
#else // FXAA_BENCHMARK
(void)queryId;
(void)tracker;
#endif // FXAA_BENCHMARK
}
//------------------------------------------------------------------------------
void vtkOpenGLFXAAFilter::EndTimeQuery(unsigned int &queryId, bool &tracker)
{
#ifdef FXAA_BENCHMARK
if (!tracker || queryId == 0)
{ // Shouldn't happen, but just in case...
return;
} }
glEndQuery(GL_TIME_ELAPSED);
tracker = false;
vtkOpenGLCheckErrorMacro("Error after ending GL_TIME_ELAPSED query.");
#else // FXAA_BENCHMARK
(void)queryId;
(void)tracker;
#endif // FXAA_BENCHMARK
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool vtkOpenGLFXAAFilter::GetTimeQueryResult(unsigned int &queryId, void vtkOpenGLFXAAFilter::EndTimeQuery(vtkOpenGLRenderTimer *timer)
unsigned int &result)
{ {
#ifdef FXAA_BENCHMARK // Since it may take a few frames for the results to become available,
if (queryId == 0) // check if we've stopped the timer already.
if (!timer->Stopped())
{ {
return false; timer->Stop();
} }
GLint ready;
glGetQueryObjectiv(queryId, GL_QUERY_RESULT_AVAILABLE, &ready);
vtkOpenGLCheckErrorMacro("Error after checking GL_TIME_ELAPSED status.");
if (!ready)
{
return false;
}
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, &result);
vtkOpenGLCheckErrorMacro("Error after checking GL_TIME_ELAPSED result.");
// Free the query:
glDeleteQueries(1, &queryId);
queryId = 0;
return true;
#else // FXAA_BENCHMARK
(void)queryId;
(void)result;
return false;
#endif // FXAA_BENCHMARK
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void vtkOpenGLFXAAFilter::PrintBenchmark() void vtkOpenGLFXAAFilter::PrintBenchmark()
{ {
if (this->PreparationTimer->Ready() &&
this->FXAATimer->Ready())
{
#ifdef FXAA_BENCHMARK #ifdef FXAA_BENCHMARK
int numPixels = this->Input->GetWidth() * this->Input->GetHeight(); int numPixels = this->Input->GetWidth() * this->Input->GetHeight();
float ptime = static_cast<float>(this->PreparationTime); float ptime = this->PreparationTimer->GetElapsedMilliseconds();
float ftime = static_cast<float>(this->FXAATime); float ftime = this->FXAATimer->GetElapsedMilliseconds();
float ttime = ptime + ftime; float ttime = ptime + ftime;
float ptimePerPixel = ptime / numPixels; float ptimePerPixel = (this->PreparationTimer->GetElapsedNanoseconds() /
float ftimePerPixel = ftime / numPixels; static_cast<float>(numPixels));
float ttimePerPixel = ttime / numPixels; float ftimePerPixel = (this->FXAATimer->GetElapsedNanoseconds() /
static_cast<float>(numPixels));
// Convert the non-per-pixel times to ms: float ttimePerPixel = ptimePerPixel + ftimePerPixel;
ptime *= 1e-6f;
ftime *= 1e-6f; std::cerr << "FXAA Info:\n"
ttime *= 1e-6f; << " - Number of pixels: " << numPixels << "\n"
<< " - Preparation time: " << ptime << "ms ("
std::cerr << "FXAA Info:\n" << ptimePerPixel << "ns per pixel)\n"
<< " - Number of pixels: " << numPixels << "\n" << " - FXAA time: " << ftime << "ms ("
<< " - Preparation time: " << ptime << "ms (" << ftimePerPixel << "ns per pixel)\n"
<< ptimePerPixel << "ns per pixel)\n" << " - Total time: " << ttime << "ms ("
<< " - FXAA time: " << ftime << "ms (" << ttimePerPixel << "ns per pixel)\n";
<< ftimePerPixel << "ns per pixel)\n"
<< " - Total time: " << ttime << "ms ("
<< ttimePerPixel << "ns per pixel)\n";
#endif // FXAA_BENCHMARK #endif // FXAA_BENCHMARK
this->PreparationTimer->Reset();
this->FXAATimer->Reset();
}
} }
...@@ -45,6 +45,7 @@ class vtkFXAAOptions; ...@@ -45,6 +45,7 @@ class vtkFXAAOptions;
class vtkOpenGLBufferObject; class vtkOpenGLBufferObject;
class vtkOpenGLVertexArrayObject; class vtkOpenGLVertexArrayObject;
class vtkOpenGLRenderer; class vtkOpenGLRenderer;
class vtkOpenGLRenderTimer;
class vtkShaderProgram; class vtkShaderProgram;
class vtkTextureObject; class vtkTextureObject;
...@@ -100,9 +101,8 @@ protected: ...@@ -100,9 +101,8 @@ protected:
void SubstituteFragmentShader(std::string &fragShader); void SubstituteFragmentShader(std::string &fragShader);
void Finalize(); void Finalize();
void StartTimeQuery(unsigned int &queryId, bool &tracker); void StartTimeQuery(vtkOpenGLRenderTimer *timer);
void EndTimeQuery(unsigned int &queryId, bool &tracker); void EndTimeQuery(vtkOpenGLRenderTimer *timer);
bool GetTimeQueryResult(unsigned int &queryId, unsigned int &result);
void PrintBenchmark(); void PrintBenchmark();
// Cache GL state that we modify // Cache GL state that we modify
...@@ -112,12 +112,8 @@ protected: ...@@ -112,12 +112,8 @@ protected:
int Viewport[4]; // x, y, width, height int Viewport[4]; // x, y, width, height
// Used to measure execution time: // Used to measure execution time:
bool PreparationTimeQueryActive; vtkOpenGLRenderTimer *PreparationTimer;
bool FXAATimeQueryActive; vtkOpenGLRenderTimer *FXAATimer;
unsigned int PreparationTimeQuery;
unsigned int FXAATimeQuery;
unsigned int PreparationTime;
unsigned int FXAATime;
// Parameters: // Parameters:
float RelativeContrastThreshold; float RelativeContrastThreshold;
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenGLRenderTimer.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkOpenGLRenderTimer.h"
#include "vtkObjectFactory.h"
#include "vtk_glew.h"
//------------------------------------------------------------------------------
vtkOpenGLRenderTimer::vtkOpenGLRenderTimer()
: StartReady(false),
EndReady(false),
StartQuery(0),
EndQuery(0),
StartTime(0),
EndTime(0)
{
}
//------------------------------------------------------------------------------
vtkOpenGLRenderTimer::~vtkOpenGLRenderTimer()
{
this->Reset();
}
//------------------------------------------------------------------------------
void vtkOpenGLRenderTimer::Reset()
{
if (this->StartQuery != 0)
{
glDeleteQueries(1, static_cast<GLuint*>(&this->StartQuery));
this->StartQuery = 0;
}
if (this->EndQuery != 0)
{
glDeleteQueries(1, static_cast<GLuint*>(&this->EndQuery));
this->EndQuery = 0;
}
this->StartReady = false;
this->EndReady = false;
this->StartTime = 0;
this->EndTime = 0;
}
//------------------------------------------------------------------------------
void vtkOpenGLRenderTimer::Start()
{
this->Reset();
glGenQueries(1, static_cast<GLuint*>(&this->StartQuery));
glQueryCounter(static_cast<GLuint>(this->StartQuery), GL_TIMESTAMP);
}
//------------------------------------------------------------------------------
void vtkOpenGLRenderTimer::Stop()
{
if (this->EndQuery != 0)
{
vtkGenericWarningMacro("vtkOpenGLRenderTimer::Stop called before "
"resetting. Ignoring.");
return;
}
if (this->StartQuery == 0)
{
vtkGenericWarningMacro("vtkOpenGLRenderTimer::Stop called before "
"vtkOpenGLRenderTimer::Start. Ignoring.");
return;
}
glGenQueries(1, static_cast<GLuint*>(&this->EndQuery));
glQueryCounter(static_cast<GLuint>(this->EndQuery), GL_TIMESTAMP);
}
//------------------------------------------------------------------------------
bool vtkOpenGLRenderTimer::Started()
{
return this->StartQuery != 0;
}
//------------------------------------------------------------------------------
bool vtkOpenGLRenderTimer::Stopped()
{
return this->EndQuery != 0;
}
//------------------------------------------------------------------------------
bool vtkOpenGLRenderTimer::Ready()
{
if (!this->StartReady)
{
GLint ready;
glGetQueryObjectiv(static_cast<GLuint>(this->StartQuery),
GL_QUERY_RESULT_AVAILABLE, &ready);
if (!ready)
{
return false;
}
this->StartReady = true;
glGetQueryObjectui64v(static_cast<GLuint>(this->StartQuery),
GL_QUERY_RESULT,
reinterpret_cast<GLuint64*>(&this->StartTime));
}
if (!this->EndReady)
{
GLint ready;
glGetQueryObjectiv(static_cast<GLuint>(this->EndQuery),
GL_QUERY_RESULT_AVAILABLE, &ready);
if (!ready)
{
return false;
}
this->EndReady = true;
glGetQueryObjectui64v(static_cast<GLuint>(this->EndQuery),
GL_QUERY_RESULT,
reinterpret_cast<GLuint64*>(&this->EndTime));
}
return true;
}
//------------------------------------------------------------------------------
float vtkOpenGLRenderTimer::GetElapsedSeconds()
{
if (!this->Ready())
{
return 0.f;
}
return (this->EndTime - this->StartTime) * 1e-9f;
}
//------------------------------------------------------------------------------
float vtkOpenGLRenderTimer::GetElapsedMilliseconds()
{
if (!this->Ready())
{
return 0.f;
}
return (this->EndTime - this->StartTime) * 1e-6f;
}
//------------------------------------------------------------------------------
vtkTypeUInt64 vtkOpenGLRenderTimer::GetElapsedNanoseconds()
{
if (!this->Ready())
{
return 0;
}
return (this->EndTime - this->StartTime);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenGLRenderTimer.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkOpenGLRenderTimer - Asynchronously measures GPU execution time.
//
// .SECTION Description
// This class posts events to the OpenGL server to measure execution times
// of GPU processes. The queries are asynchronous and multiple
// vtkOpenGLRenderTimers may overlap / be nested.
//
// This uses GL_TIMESTAMP rather than GL_ELAPSED_TIME, since only one
// GL_ELAPSED_TIME query may be active at a time.
#ifndef vtkOpenGLRenderTimer_h
#define vtkOpenGLRenderTimer_h
#include "vtkRenderingOpenGL2Module.h" // For export macro
#include "vtkType.h" // For vtkTypeUint64, etc
class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLRenderTimer
{
public:
vtkOpenGLRenderTimer();
~vtkOpenGLRenderTimer();
// Description:
// Clear out any previous results and prepare for a new query.
void Reset();
// Description:
// Mark the start of a timed event.
void Start();
// Description:
// Mark the end of a timed event.
void Stop();
// Description:
// Returns true if the timer has been started. The query may not be ready yet.
bool Started();
// Description:
// Returns true if the timer has been stopped. The query may not be ready yet.
bool Stopped();
// Description:
// Returns true when the timing results are available.
bool Ready();
// Description:
// If Ready() returns true, get the elapsed time in the requested units.
float GetElapsedSeconds();
float GetElapsedMilliseconds();
vtkTypeUInt64 GetElapsedNanoseconds();
protected:
bool StartReady;
bool EndReady;
vtkTypeUInt32 StartQuery;
vtkTypeUInt32 EndQuery;
vtkTypeUInt64 StartTime;
vtkTypeUInt64 EndTime;
private:
vtkOpenGLRenderTimer(const vtkOpenGLRenderTimer&) VTK_DELETE_FUNCTION;
void operator=(const vtkOpenGLRenderTimer&) VTK_DELETE_FUNCTION;
};
#endif // vtkOpenGLRenderTimer_h
// VTK-HeaderTest-Exclude: vtkOpenGLRenderTimer.h
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment